diff options
author | Daniel Krueger <daniel.krueger@systec-electronic.com> | 2008-12-19 11:41:57 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-06 13:52:36 -0800 |
commit | 9d7164cfdb611c2f864d535ae5794f23db3d84f7 (patch) | |
tree | 046847f7d6432f1f3dc8236f62492503f4c9ebdc /drivers/staging | |
parent | 37bcd24b845abbfd85c838ee9ce07c2b254d3a05 (diff) | |
download | kernel_samsung_smdk4412-9d7164cfdb611c2f864d535ae5794f23db3d84f7.zip kernel_samsung_smdk4412-9d7164cfdb611c2f864d535ae5794f23db3d84f7.tar.gz kernel_samsung_smdk4412-9d7164cfdb611c2f864d535ae5794f23db3d84f7.tar.bz2 |
Staging: add epl stack
This is the openPOWERLINK network stack from systec electronic.
It's a bit messed up as there is a driver mixed into the
middle of it, lots of work needs to be done to unwind the
different portions to make it sane.
Cc: Daniel Krueger <daniel.krueger@systec-electronic.com>
Cc: Ronald Sieber <Ronald.Sieber@systec-electronic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
112 files changed, 56534 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 15f2b11..c063971 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -91,5 +91,7 @@ source "drivers/staging/mimio/Kconfig" source "drivers/staging/frontier/Kconfig" +source "drivers/staging/epl/Kconfig" + endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index d338030..53478e8 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -28,3 +28,4 @@ obj-$(CONFIG_RTL8187SE) += rtl8187se/ obj-$(CONFIG_USB_RSPI) += rspiusb/ obj-$(CONFIG_INPUT_MIMIO) += mimio/ obj-$(CONFIG_TRANZPORT) += frontier/ +obj-$(CONFIG_EPL) += epl/ diff --git a/drivers/staging/epl/Benchmark.h b/drivers/staging/epl/Benchmark.h new file mode 100644 index 0000000..681c1d9 --- /dev/null +++ b/drivers/staging/epl/Benchmark.h @@ -0,0 +1,443 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: header file for benchmarking + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: Benchmark.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + ... + + ------------------------------------------------------------------------- + + Revision History: + + 2006/08/16 d.k.: start of implementation + +****************************************************************************/ + +#ifndef _BENCHMARK_H_ +#define _BENCHMARK_H_ + +#include "global.h" + + +#if (TARGET_SYSTEM == _NO_OS_) && (DEV_SYSTEM == _DEV_GNU_CF548X_) + #include "common.h" + +#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + +// #include <linux/config.h> + #include <linux/kernel.h> + + #ifdef CONFIG_COLDFIRE + #include <asm/coldfire.h> + #include <asm/m5485gpio.h> + + #define BENCHMARK_SET(x) MCF_GPIO_PODR_PCIBG |= (1 << (x)) // (x+1) + #define BENCHMARK_RESET(x) MCF_GPIO_PODR_PCIBG &= ~(1 << (x)) // (x+1) + #define BENCHMARK_TOGGLE(x) MCF_GPIO_PODR_PCIBR ^= (1 << (x - 5)) + #else + #undef BENCHMARK_MODULES + #define BENCHMARK_MODULES 0x00000000 + #endif + +#else + // disable Benchmarking + #undef BENCHMARK_MODULES + #define BENCHMARK_MODULES 0x00000000 +#endif + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#ifndef BENCHMARK_MODULES +#define BENCHMARK_MODULES 0x00000000 +#endif + +#define BENCHMARK_MOD_01 0x00000001 +#define BENCHMARK_MOD_02 0x00000002 +#define BENCHMARK_MOD_03 0x00000004 +#define BENCHMARK_MOD_04 0x00000008 +#define BENCHMARK_MOD_05 0x00000010 +#define BENCHMARK_MOD_06 0x00000020 +#define BENCHMARK_MOD_07 0x00000040 +#define BENCHMARK_MOD_08 0x00000080 +#define BENCHMARK_MOD_09 0x00000100 +#define BENCHMARK_MOD_10 0x00000200 +#define BENCHMARK_MOD_11 0x00000400 +#define BENCHMARK_MOD_12 0x00000800 +#define BENCHMARK_MOD_13 0x00001000 +#define BENCHMARK_MOD_14 0x00002000 +#define BENCHMARK_MOD_15 0x00004000 +#define BENCHMARK_MOD_16 0x00008000 +#define BENCHMARK_MOD_17 0x00010000 +#define BENCHMARK_MOD_18 0x00020000 +#define BENCHMARK_MOD_19 0x00040000 +#define BENCHMARK_MOD_20 0x00080000 +#define BENCHMARK_MOD_21 0x00100000 +#define BENCHMARK_MOD_22 0x00200000 +#define BENCHMARK_MOD_23 0x00400000 +#define BENCHMARK_MOD_24 0x00800000 +#define BENCHMARK_MOD_25 0x01000000 +#define BENCHMARK_MOD_26 0x02000000 +#define BENCHMARK_MOD_27 0x04000000 +#define BENCHMARK_MOD_28 0x08000000 +#define BENCHMARK_MOD_29 0x10000000 +#define BENCHMARK_MOD_30 0x20000000 +#define BENCHMARK_MOD_31 0x40000000 +#define BENCHMARK_MOD_32 0x80000000 + + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_01) + #define BENCHMARK_MOD_01_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_01_RESET(x) BENCHMARK_RESET(x) + #define BENCHMARK_MOD_01_TOGGLE(x) BENCHMARK_TOGGLE(x) +#else + #define BENCHMARK_MOD_01_SET(x) + #define BENCHMARK_MOD_01_RESET(x) + #define BENCHMARK_MOD_01_TOGGLE(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_02) + #define BENCHMARK_MOD_02_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_02_RESET(x) BENCHMARK_RESET(x) + #define BENCHMARK_MOD_02_TOGGLE(x) BENCHMARK_TOGGLE(x) +#else + #define BENCHMARK_MOD_02_SET(x) + #define BENCHMARK_MOD_02_RESET(x) + #define BENCHMARK_MOD_02_TOGGLE(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_03) + #define BENCHMARK_MOD_03_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_03_RESET(x) BENCHMARK_RESET(x) + #define BENCHMARK_MOD_03_TOGGLE(x) BENCHMARK_TOGGLE(x) +#else + #define BENCHMARK_MOD_03_SET(x) + #define BENCHMARK_MOD_03_RESET(x) + #define BENCHMARK_MOD_03_TOGGLE(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_04) + #define BENCHMARK_MOD_04_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_04_RESET(x) BENCHMARK_RESET(x) + #define BENCHMARK_MOD_04_TOGGLE(x) BENCHMARK_TOGGLE(x) +#else + #define BENCHMARK_MOD_04_SET(x) + #define BENCHMARK_MOD_04_RESET(x) + #define BENCHMARK_MOD_04_TOGGLE(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_05) + #define BENCHMARK_MOD_05_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_05_RESET(x) BENCHMARK_RESET(x) + #define BENCHMARK_MOD_05_TOGGLE(x) BENCHMARK_TOGGLE(x) +#else + #define BENCHMARK_MOD_05_SET(x) + #define BENCHMARK_MOD_05_RESET(x) + #define BENCHMARK_MOD_05_TOGGLE(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_06) + #define BENCHMARK_MOD_06_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_06_RESET(x) BENCHMARK_RESET(x) + #define BENCHMARK_MOD_06_TOGGLE(x) BENCHMARK_TOGGLE(x) +#else + #define BENCHMARK_MOD_06_SET(x) + #define BENCHMARK_MOD_06_RESET(x) + #define BENCHMARK_MOD_06_TOGGLE(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_07) + #define BENCHMARK_MOD_07_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_07_RESET(x) BENCHMARK_RESET(x) + #define BENCHMARK_MOD_07_TOGGLE(x) BENCHMARK_TOGGLE(x) +#else + #define BENCHMARK_MOD_07_SET(x) + #define BENCHMARK_MOD_07_RESET(x) + #define BENCHMARK_MOD_07_TOGGLE(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_08) + #define BENCHMARK_MOD_08_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_08_RESET(x) BENCHMARK_RESET(x) + #define BENCHMARK_MOD_08_TOGGLE(x) BENCHMARK_TOGGLE(x) +#else + #define BENCHMARK_MOD_08_SET(x) + #define BENCHMARK_MOD_08_RESET(x) + #define BENCHMARK_MOD_08_TOGGLE(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_09) + #define BENCHMARK_MOD_09_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_09_RESET(x) BENCHMARK_RESET(x) + #define BENCHMARK_MOD_09_TOGGLE(x) BENCHMARK_TOGGLE(x) +#else + #define BENCHMARK_MOD_09_SET(x) + #define BENCHMARK_MOD_09_RESET(x) + #define BENCHMARK_MOD_09_TOGGLE(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_10) + #define BENCHMARK_MOD_10_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_10_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_10_SET(x) + #define BENCHMARK_MOD_10_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_11) + #define BENCHMARK_MOD_11_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_11_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_11_SET(x) + #define BENCHMARK_MOD_11_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_12) + #define BENCHMARK_MOD_12_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_12_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_12_SET(x) + #define BENCHMARK_MOD_12_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_13) + #define BENCHMARK_MOD_13_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_13_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_13_SET(x) + #define BENCHMARK_MOD_13_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_14) + #define BENCHMARK_MOD_14_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_14_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_14_SET(x) + #define BENCHMARK_MOD_14_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_15) + #define BENCHMARK_MOD_15_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_15_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_15_SET(x) + #define BENCHMARK_MOD_15_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_16) + #define BENCHMARK_MOD_16_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_16_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_16_SET(x) + #define BENCHMARK_MOD_16_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_17) + #define BENCHMARK_MOD_17_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_17_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_17_SET(x) + #define BENCHMARK_MOD_17_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_18) + #define BENCHMARK_MOD_18_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_18_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_18_SET(x) + #define BENCHMARK_MOD_18_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_19) + #define BENCHMARK_MOD_19_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_19_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_19_SET(x) + #define BENCHMARK_MOD_19_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_20) + #define BENCHMARK_MOD_20_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_20_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_20_SET(x) + #define BENCHMARK_MOD_20_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_21) + #define BENCHMARK_MOD_21_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_21_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_21_SET(x) + #define BENCHMARK_MOD_21_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_22) + #define BENCHMARK_MOD_22_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_22_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_22_SET(x) + #define BENCHMARK_MOD_22_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_23) + #define BENCHMARK_MOD_23_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_23_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_23_SET(x) + #define BENCHMARK_MOD_23_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_24) + #define BENCHMARK_MOD_24_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_24_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_24_SET(x) + #define BENCHMARK_MOD_24_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_25) + #define BENCHMARK_MOD_25_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_25_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_25_SET(x) + #define BENCHMARK_MOD_25_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_26) + #define BENCHMARK_MOD_26_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_26_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_26_SET(x) + #define BENCHMARK_MOD_26_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_27) + #define BENCHMARK_MOD_27_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_27_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_27_SET(x) + #define BENCHMARK_MOD_27_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_28) + #define BENCHMARK_MOD_28_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_28_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_28_SET(x) + #define BENCHMARK_MOD_28_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_29) + #define BENCHMARK_MOD_29_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_29_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_29_SET(x) + #define BENCHMARK_MOD_29_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_30) + #define BENCHMARK_MOD_30_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_30_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_30_SET(x) + #define BENCHMARK_MOD_30_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_31) + #define BENCHMARK_MOD_31_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_31_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_31_SET(x) + #define BENCHMARK_MOD_31_RESET(x) +#endif + +#if (BENCHMARK_MODULES & BENCHMARK_MOD_32) + #define BENCHMARK_MOD_32_SET(x) BENCHMARK_SET(x) + #define BENCHMARK_MOD_32_RESET(x) BENCHMARK_RESET(x) +#else + #define BENCHMARK_MOD_32_SET(x) + #define BENCHMARK_MOD_32_RESET(x) +#endif + + +//--------------------------------------------------------------------------- +// modul global types +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +#endif // _BENCHMARK_H_ diff --git a/drivers/staging/epl/Debug.h b/drivers/staging/epl/Debug.h new file mode 100644 index 0000000..f804e2f --- /dev/null +++ b/drivers/staging/epl/Debug.h @@ -0,0 +1,750 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: Debug interface + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: Debug.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + ... + + ------------------------------------------------------------------------- + + Revision History: + +****************************************************************************/ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "global.h" + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// global const defines +//--------------------------------------------------------------------------- + +// These definitions are important for level-debug traces. +// A macro DEBUG_GLB_LVL() defines the current debug-level using following bis. +// If the corresponding bit is set then trace message will be printed out +// (only if NDEBUG is not defined). The upper debug-levels are reserved for +// the debug-levels ALWAYS, ERROR and ASSERT. +#define DEBUG_LVL_01 0x00000001 +#define DEBUG_LVL_02 0x00000002 +#define DEBUG_LVL_03 0x00000004 +#define DEBUG_LVL_04 0x00000008 +#define DEBUG_LVL_05 0x00000010 +#define DEBUG_LVL_06 0x00000020 +#define DEBUG_LVL_07 0x00000040 +#define DEBUG_LVL_08 0x00000080 +#define DEBUG_LVL_09 0x00000100 +#define DEBUG_LVL_10 0x00000200 +#define DEBUG_LVL_11 0x00000400 +#define DEBUG_LVL_12 0x00000800 +#define DEBUG_LVL_13 0x00001000 +#define DEBUG_LVL_14 0x00002000 +#define DEBUG_LVL_15 0x00004000 +#define DEBUG_LVL_16 0x00008000 +#define DEBUG_LVL_17 0x00010000 +#define DEBUG_LVL_18 0x00020000 +#define DEBUG_LVL_19 0x00040000 +#define DEBUG_LVL_20 0x00080000 +#define DEBUG_LVL_21 0x00100000 +#define DEBUG_LVL_22 0x00200000 +#define DEBUG_LVL_23 0x00400000 +#define DEBUG_LVL_24 0x00800000 +#define DEBUG_LVL_25 0x01000000 +#define DEBUG_LVL_26 0x02000000 +#define DEBUG_LVL_27 0x04000000 +#define DEBUG_LVL_28 0x08000000 +#define DEBUG_LVL_29 0x10000000 +#define DEBUG_LVL_ASSERT 0x20000000 +#define DEBUG_LVL_ERROR 0x40000000 +#define DEBUG_LVL_ALWAYS 0x80000000 + + +//--------------------------------------------------------------------------- +// global types +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// global vars +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// global function prototypes +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// global macros +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// this macro defines a version string +#define MAKE_VERSION_STRING(product,appname,verstr,author) \ + "§prd§:" product ",§app§:" appname ",§ver§:" verstr ",§dat§:" __DATE__ ",§aut§:" author + + +//--------------------------------------------------------------------------- +// this macro defines a build info string (e.g. for using in printf()) +#define DEBUG_MAKE_BUILD_INFO(prefix,product,prodid,descr,verstr,author) "\n" \ + prefix "***************************************************\n" \ + prefix "Project: " product ", " prodid "\n" \ + prefix "Descript.: " descr "\n" \ + prefix "Author: " author "\n" \ + prefix "Date: " __DATE__ "\n" \ + prefix "Version: " verstr "\n" \ + prefix "***************************************************\n\n" + + +//--------------------------------------------------------------------------- +// The default debug-level is: ERROR and ALWAYS. +// You can define an other debug-level in project settings. +#ifndef DEF_DEBUG_LVL + #define DEF_DEBUG_LVL (DEBUG_LVL_ALWAYS | DEBUG_LVL_ERROR) +#endif +#ifndef DEBUG_GLB_LVL + #define DEBUG_GLB_LVL() (DEF_DEBUG_LVL) +#endif + + +//--------------------------------------------------------------------------- +#if (DEV_SYSTEM == _DEV_WIN32_) && defined (TRACE_MSG) + + // For WIN32 the macro DEBUG_TRACE0 can be defined as function call TraceLvl() + // or as macro TRACE(). + // + // Here the parameter 'lvl' can be used with more than one + // debug-level (using OR). + // + // Example: DEBUG_TRACE1(DEBUG_LVL_30 | DEBUG_LVL_02, "Hello %d", bCount); + + #define DEBUG_TRACE0(lvl,str) TraceLvl((lvl),str) + #define DEBUG_TRACE1(lvl,str,p1) TraceLvl((lvl),str,p1) + #define DEBUG_TRACE2(lvl,str,p1,p2) TraceLvl((lvl),str,p1,p2) + #define DEBUG_TRACE3(lvl,str,p1,p2,p3) TraceLvl((lvl),str,p1,p2,p3) + #define DEBUG_TRACE4(lvl,str,p1,p2,p3,p4) TraceLvl((lvl),str,p1,p2,p3,p4) + #define DEBUG_GLB_LVL() dwDebugLevel_g + +#else + + // At microcontrollers we do reduce the memory usage by deleting DEBUG_TRACE-lines + // (compiler does delete the lines). + // + // Here the parameter 'lvl' can only be used with one debug-level. + // + // Example: DEBUG_TRACE1(DEBUG_LVL_ERROR, "error code %d", dwRet); + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_ALWAYS) + #define DEBUG_LVL_ALWAYS_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_ALWAYS_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_ALWAYS_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_ALWAYS_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_ALWAYS_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_ALWAYS_TRACE0(str) + #define DEBUG_LVL_ALWAYS_TRACE1(str,p1) + #define DEBUG_LVL_ALWAYS_TRACE2(str,p1,p2) + #define DEBUG_LVL_ALWAYS_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_ALWAYS_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_ERROR) + #define DEBUG_LVL_ERROR_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_ERROR_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_ERROR_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_ERROR_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_ERROR_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_ERROR_TRACE0(str) + #define DEBUG_LVL_ERROR_TRACE1(str,p1) + #define DEBUG_LVL_ERROR_TRACE2(str,p1,p2) + #define DEBUG_LVL_ERROR_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_ERROR_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_ASSERT) + #define DEBUG_LVL_ASSERT_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_ASSERT_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_ASSERT_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_ASSERT_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_ASSERT_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_ASSERT_TRACE0(str) + #define DEBUG_LVL_ASSERT_TRACE1(str,p1) + #define DEBUG_LVL_ASSERT_TRACE2(str,p1,p2) + #define DEBUG_LVL_ASSERT_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_ASSERT_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_29) + #define DEBUG_LVL_29_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_29_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_29_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_29_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_29_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_29_TRACE0(str) + #define DEBUG_LVL_29_TRACE1(str,p1) + #define DEBUG_LVL_29_TRACE2(str,p1,p2) + #define DEBUG_LVL_29_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_29_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_28) + #define DEBUG_LVL_28_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_28_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_28_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_28_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_28_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_28_TRACE0(str) + #define DEBUG_LVL_28_TRACE1(str,p1) + #define DEBUG_LVL_28_TRACE2(str,p1,p2) + #define DEBUG_LVL_28_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_28_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_27) + #define DEBUG_LVL_27_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_27_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_27_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_27_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_27_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_27_TRACE0(str) + #define DEBUG_LVL_27_TRACE1(str,p1) + #define DEBUG_LVL_27_TRACE2(str,p1,p2) + #define DEBUG_LVL_27_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_27_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_26) + #define DEBUG_LVL_26_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_26_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_26_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_26_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_26_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_26_TRACE0(str) + #define DEBUG_LVL_26_TRACE1(str,p1) + #define DEBUG_LVL_26_TRACE2(str,p1,p2) + #define DEBUG_LVL_26_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_26_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_25) + #define DEBUG_LVL_25_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_25_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_25_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_25_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_25_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_25_TRACE0(str) + #define DEBUG_LVL_25_TRACE1(str,p1) + #define DEBUG_LVL_25_TRACE2(str,p1,p2) + #define DEBUG_LVL_25_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_25_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_24) + #define DEBUG_LVL_24_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_24_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_24_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_24_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_24_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_24_TRACE0(str) + #define DEBUG_LVL_24_TRACE1(str,p1) + #define DEBUG_LVL_24_TRACE2(str,p1,p2) + #define DEBUG_LVL_24_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_24_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_23) + #define DEBUG_LVL_23_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_23_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_23_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_23_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_23_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_23_TRACE0(str) + #define DEBUG_LVL_23_TRACE1(str,p1) + #define DEBUG_LVL_23_TRACE2(str,p1,p2) + #define DEBUG_LVL_23_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_23_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_22) + #define DEBUG_LVL_22_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_22_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_22_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_22_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_22_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_22_TRACE0(str) + #define DEBUG_LVL_22_TRACE1(str,p1) + #define DEBUG_LVL_22_TRACE2(str,p1,p2) + #define DEBUG_LVL_22_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_22_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_21) + #define DEBUG_LVL_21_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_21_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_21_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_21_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_21_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_21_TRACE0(str) + #define DEBUG_LVL_21_TRACE1(str,p1) + #define DEBUG_LVL_21_TRACE2(str,p1,p2) + #define DEBUG_LVL_21_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_21_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_20) + #define DEBUG_LVL_20_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_20_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_20_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_20_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_20_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_20_TRACE0(str) + #define DEBUG_LVL_20_TRACE1(str,p1) + #define DEBUG_LVL_20_TRACE2(str,p1,p2) + #define DEBUG_LVL_20_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_20_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_19) + #define DEBUG_LVL_19_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_19_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_19_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_19_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_19_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_19_TRACE0(str) + #define DEBUG_LVL_19_TRACE1(str,p1) + #define DEBUG_LVL_19_TRACE2(str,p1,p2) + #define DEBUG_LVL_19_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_19_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_18) + #define DEBUG_LVL_18_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_18_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_18_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_18_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_18_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_18_TRACE0(str) + #define DEBUG_LVL_18_TRACE1(str,p1) + #define DEBUG_LVL_18_TRACE2(str,p1,p2) + #define DEBUG_LVL_18_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_18_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_17) + #define DEBUG_LVL_17_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_17_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_17_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_17_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_17_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_17_TRACE0(str) + #define DEBUG_LVL_17_TRACE1(str,p1) + #define DEBUG_LVL_17_TRACE2(str,p1,p2) + #define DEBUG_LVL_17_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_17_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_16) + #define DEBUG_LVL_16_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_16_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_16_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_16_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_16_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_16_TRACE0(str) + #define DEBUG_LVL_16_TRACE1(str,p1) + #define DEBUG_LVL_16_TRACE2(str,p1,p2) + #define DEBUG_LVL_16_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_16_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_15) + #define DEBUG_LVL_15_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_15_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_15_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_15_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_15_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_15_TRACE0(str) + #define DEBUG_LVL_15_TRACE1(str,p1) + #define DEBUG_LVL_15_TRACE2(str,p1,p2) + #define DEBUG_LVL_15_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_15_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_14) + #define DEBUG_LVL_14_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_14_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_14_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_14_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_14_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_14_TRACE0(str) + #define DEBUG_LVL_14_TRACE1(str,p1) + #define DEBUG_LVL_14_TRACE2(str,p1,p2) + #define DEBUG_LVL_14_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_14_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_13) + #define DEBUG_LVL_13_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_13_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_13_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_13_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_13_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_13_TRACE0(str) + #define DEBUG_LVL_13_TRACE1(str,p1) + #define DEBUG_LVL_13_TRACE2(str,p1,p2) + #define DEBUG_LVL_13_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_13_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_12) + #define DEBUG_LVL_12_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_12_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_12_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_12_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_12_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_12_TRACE0(str) + #define DEBUG_LVL_12_TRACE1(str,p1) + #define DEBUG_LVL_12_TRACE2(str,p1,p2) + #define DEBUG_LVL_12_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_12_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_11) + #define DEBUG_LVL_11_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_11_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_11_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_11_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_11_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_11_TRACE0(str) + #define DEBUG_LVL_11_TRACE1(str,p1) + #define DEBUG_LVL_11_TRACE2(str,p1,p2) + #define DEBUG_LVL_11_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_11_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_10) + #define DEBUG_LVL_10_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_10_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_10_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_10_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_10_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_10_TRACE0(str) + #define DEBUG_LVL_10_TRACE1(str,p1) + #define DEBUG_LVL_10_TRACE2(str,p1,p2) + #define DEBUG_LVL_10_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_10_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_09) + #define DEBUG_LVL_09_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_09_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_09_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_09_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_09_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_09_TRACE0(str) + #define DEBUG_LVL_09_TRACE1(str,p1) + #define DEBUG_LVL_09_TRACE2(str,p1,p2) + #define DEBUG_LVL_09_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_09_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_08) + #define DEBUG_LVL_08_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_08_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_08_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_08_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_08_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_08_TRACE0(str) + #define DEBUG_LVL_08_TRACE1(str,p1) + #define DEBUG_LVL_08_TRACE2(str,p1,p2) + #define DEBUG_LVL_08_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_08_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_07) + #define DEBUG_LVL_07_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_07_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_07_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_07_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_07_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_07_TRACE0(str) + #define DEBUG_LVL_07_TRACE1(str,p1) + #define DEBUG_LVL_07_TRACE2(str,p1,p2) + #define DEBUG_LVL_07_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_07_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_06) + #define DEBUG_LVL_06_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_06_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_06_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_06_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_06_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_06_TRACE0(str) + #define DEBUG_LVL_06_TRACE1(str,p1) + #define DEBUG_LVL_06_TRACE2(str,p1,p2) + #define DEBUG_LVL_06_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_06_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_05) + #define DEBUG_LVL_05_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_05_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_05_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_05_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_05_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_05_TRACE0(str) + #define DEBUG_LVL_05_TRACE1(str,p1) + #define DEBUG_LVL_05_TRACE2(str,p1,p2) + #define DEBUG_LVL_05_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_05_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_04) + #define DEBUG_LVL_04_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_04_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_04_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_04_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_04_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_04_TRACE0(str) + #define DEBUG_LVL_04_TRACE1(str,p1) + #define DEBUG_LVL_04_TRACE2(str,p1,p2) + #define DEBUG_LVL_04_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_04_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_03) + #define DEBUG_LVL_03_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_03_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_03_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_03_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_03_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_03_TRACE0(str) + #define DEBUG_LVL_03_TRACE1(str,p1) + #define DEBUG_LVL_03_TRACE2(str,p1,p2) + #define DEBUG_LVL_03_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_03_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_02) + #define DEBUG_LVL_02_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_02_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_02_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_02_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_02_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_02_TRACE0(str) + #define DEBUG_LVL_02_TRACE1(str,p1) + #define DEBUG_LVL_02_TRACE2(str,p1,p2) + #define DEBUG_LVL_02_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_02_TRACE4(str,p1,p2,p3,p4) + #endif + + #if (DEBUG_GLB_LVL() & DEBUG_LVL_01) + #define DEBUG_LVL_01_TRACE0(str) TRACE0(str) + #define DEBUG_LVL_01_TRACE1(str,p1) TRACE1(str,p1) + #define DEBUG_LVL_01_TRACE2(str,p1,p2) TRACE2(str,p1,p2) + #define DEBUG_LVL_01_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_01_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4) + #else + #define DEBUG_LVL_01_TRACE0(str) + #define DEBUG_LVL_01_TRACE1(str,p1) + #define DEBUG_LVL_01_TRACE2(str,p1,p2) + #define DEBUG_LVL_01_TRACE3(str,p1,p2,p3) + #define DEBUG_LVL_01_TRACE4(str,p1,p2,p3,p4) + #endif + + #define DEBUG_TRACE0(lvl,str) lvl##_TRACE0(str) + #define DEBUG_TRACE1(lvl,str,p1) lvl##_TRACE1(str,p1) + #define DEBUG_TRACE2(lvl,str,p1,p2) lvl##_TRACE2(str,p1,p2) + #define DEBUG_TRACE3(lvl,str,p1,p2,p3) lvl##_TRACE3(str,p1,p2,p3) + #define DEBUG_TRACE4(lvl,str,p1,p2,p3,p4) lvl##_TRACE4(str,p1,p2,p3,p4) + +#endif + + +//--------------------------------------------------------------------------- +// The macro DEBUG_DUMP_DATA() can be used with the same debug-levels to dump +// out data bytes. Function DumpData() has to be included. +// NOTE: DUMP_DATA has to be defined in project settings. +#if (!defined (NDEBUG) && defined (DUMP_DATA)) || (DEV_SYSTEM == _DEV_WIN32_) + + #ifdef __cplusplus + extern "C" + { + #endif + + void DumpData (char* szStr_p, BYTE MEM* pbData_p, WORD wSize_p); + + #ifdef __cplusplus + } // von extern "C" + #endif + + #define DEBUG_DUMP_DATA(lvl,str,ptr,siz) if ((DEBUG_GLB_LVL() & (lvl))==(lvl)) \ + DumpData (str, (BYTE MEM*) (ptr), (WORD) (siz)); + +#else + + #define DEBUG_DUMP_DATA(lvl,str,ptr,siz) + +#endif + + +//--------------------------------------------------------------------------- +// The macro DEBUG_ASSERT() can be used to print out an error string if the +// parametered expresion does not result TRUE. +// NOTE: If DEBUG_KEEP_ASSERT is defined, then DEBUG_ASSERT-line will not be +// deleted from compiler (in release version too). +#if !defined (NDEBUG) || defined (DEBUG_KEEP_ASSERT) + + #if (DEV_SYSTEM == _DEV_WIN32_) + + // For WIN32 process will be killed after closing message box. + + #define DEBUG_ASSERT0(expr,str) if (!(expr ) && ((DEBUG_GLB_LVL() & DEBUG_LVL_ASSERT)!=0)) { \ + MessageBox (NULL, \ + "Assertion failed: line " __LINE__ " file " __FILE__ \ + "\n -> " str "\n"); \ + ExitProcess (-1); } + + #define DEBUG_ASSERT1(expr,str,p1) if (!(expr ) && ((DEBUG_GLB_LVL() & DEBUG_LVL_ASSERT)!=0)) { \ + MessageBox (NULL, \ + "Assertion failed: line " __LINE__ " file " __FILE__ \ + "\n -> " str "\n"); \ + ExitProcess (-1); } + + #else + + // For microcontrollers process will be stopped using endless loop. + + #define DEBUG_ASSERT0(expr,str) if (!(expr )) { \ + DEBUG_LVL_ASSERT_TRACE3 ( \ + "Assertion failed: line %d file '%s'\n" \ + " -> '%s'\n", __LINE__, __FILE__, str); \ + while (1); } + + #define DEBUG_ASSERT1(expr,str,p1) if (!(expr )) { \ + DEBUG_LVL_ASSERT_TRACE4 ( \ + "Assertion failed: line %d file '%s'\n" \ + " -> '%s'\n" \ + " -> 0x%08lX\n", __LINE__, __FILE__, str, (DWORD) p1); \ + while (1); } + + #endif + +#else + + #define DEBUG_ASSERT0(expr,str) + #define DEBUG_ASSERT1(expr,str,p1) + +#endif + + +//--------------------------------------------------------------------------- +// The macro DEBUG_ONLY() implements code, if NDEBUG is not defined. +#if !defined (DEBUG_ONLY) + #if !defined (NDEBUG) + + #define DEBUG_ONLY(expr) expr + + #else + + #define DEBUG_ONLY(expr) + + #endif +#endif + + +#endif // _DEBUG_H_ diff --git a/drivers/staging/epl/Edrv8139.c b/drivers/staging/epl/Edrv8139.c new file mode 100644 index 0000000..3fa0564 --- /dev/null +++ b/drivers/staging/epl/Edrv8139.c @@ -0,0 +1,1317 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: Ethernet driver for Realtek RTL8139 chips + except the RTL8139C+, because it has a different + Tx descriptor handling. + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: Edrv8139.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.10 $ $Date: 2008/11/21 09:00:38 $ + + $State: Exp $ + + Build Environment: + Dev C++ and GNU-Compiler for m68k + + ------------------------------------------------------------------------- + + Revision History: + + 2008/02/05 d.k.: start of implementation + +****************************************************************************/ + +#include "global.h" +#include "EplInc.h" +#include "edrv.h" + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/major.h> +#include <linux/version.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/atomic.h> +#include <asm/irq.h> +#include <linux/sched.h> +#include <linux/delay.h> + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +// Buffer handling: +// All buffers are created statically (i.e. at compile time resp. at +// initialisation via kmalloc() ) and not dynamically on request (i.e. via +// EdrvAllocTxMsgBuffer(). +// EdrvAllocTxMsgBuffer() searches for an unused buffer which is large enough. +// EdrvInit() may allocate some buffers with sizes less than maximum frame +// size (i.e. 1514 bytes), e.g. for SoC, SoA, StatusResponse, IdentResponse, +// NMT requests / commands. The less the size of the buffer the less the +// number of the buffer. + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#ifndef EDRV_MAX_TX_BUFFERS +#define EDRV_MAX_TX_BUFFERS 20 +#endif + +#define EDRV_MAX_FRAME_SIZE 0x600 + +#define EDRV_RX_BUFFER_SIZE 0x8610 // 32 kB + 16 Byte + 1,5 kB (WRAP is enabled) +#define EDRV_RX_BUFFER_LENGTH (EDRV_RX_BUFFER_SIZE & 0xF800) // buffer size cut down to 2 kB alignment + +#define EDRV_TX_BUFFER_SIZE (EDRV_MAX_TX_BUFFERS * EDRV_MAX_FRAME_SIZE) // n * (MTU + 14 + 4) + +#define DRV_NAME "epl" + + +#define EDRV_REGW_INT_MASK 0x3C // interrupt mask register +#define EDRV_REGW_INT_STATUS 0x3E // interrupt status register +#define EDRV_REGW_INT_ROK 0x0001 // Receive OK interrupt +#define EDRV_REGW_INT_RER 0x0002 // Receive error interrupt +#define EDRV_REGW_INT_TOK 0x0004 // Transmit OK interrupt +#define EDRV_REGW_INT_TER 0x0008 // Transmit error interrupt +#define EDRV_REGW_INT_RXOVW 0x0010 // Rx buffer overflow interrupt +#define EDRV_REGW_INT_PUN 0x0020 // Packet underrun/ link change interrupt +#define EDRV_REGW_INT_FOVW 0x0040 // Rx FIFO overflow interrupt +#define EDRV_REGW_INT_LENCHG 0x2000 // Cable length change interrupt +#define EDRV_REGW_INT_TIMEOUT 0x4000 // Time out interrupt +#define EDRV_REGW_INT_SERR 0x8000 // System error interrupt +#define EDRV_REGW_INT_MASK_DEF (EDRV_REGW_INT_ROK \ + | EDRV_REGW_INT_RER \ + | EDRV_REGW_INT_TOK \ + | EDRV_REGW_INT_TER \ + | EDRV_REGW_INT_RXOVW \ + | EDRV_REGW_INT_FOVW \ + | EDRV_REGW_INT_PUN \ + | EDRV_REGW_INT_TIMEOUT \ + | EDRV_REGW_INT_SERR) // default interrupt mask + +#define EDRV_REGB_COMMAND 0x37 // command register +#define EDRV_REGB_COMMAND_RST 0x10 +#define EDRV_REGB_COMMAND_RE 0x08 +#define EDRV_REGB_COMMAND_TE 0x04 +#define EDRV_REGB_COMMAND_BUFE 0x01 + +#define EDRV_REGB_CMD9346 0x50 // 93C46 command register +#define EDRV_REGB_CMD9346_LOCK 0x00 // lock configuration registers +#define EDRV_REGB_CMD9346_UNLOCK 0xC0 // unlock configuration registers + +#define EDRV_REGDW_RCR 0x44 // Rx configuration register +#define EDRV_REGDW_RCR_NO_FTH 0x0000E000 // no receive FIFO threshold +#define EDRV_REGDW_RCR_RBLEN32K 0x00001000 // 32 kB receive buffer +#define EDRV_REGDW_RCR_MXDMAUNL 0x00000700 // unlimited maximum DMA burst size +#define EDRV_REGDW_RCR_NOWRAP 0x00000080 // do not wrap frame at end of buffer +#define EDRV_REGDW_RCR_AER 0x00000020 // accept error frames (CRC, alignment, collided) +#define EDRV_REGDW_RCR_AR 0x00000010 // accept runt +#define EDRV_REGDW_RCR_AB 0x00000008 // accept broadcast frames +#define EDRV_REGDW_RCR_AM 0x00000004 // accept multicast frames +#define EDRV_REGDW_RCR_APM 0x00000002 // accept physical match frames +#define EDRV_REGDW_RCR_AAP 0x00000001 // accept all frames +#define EDRV_REGDW_RCR_DEF (EDRV_REGDW_RCR_NO_FTH \ + | EDRV_REGDW_RCR_RBLEN32K \ + | EDRV_REGDW_RCR_MXDMAUNL \ + | EDRV_REGDW_RCR_NOWRAP \ + | EDRV_REGDW_RCR_AB \ + | EDRV_REGDW_RCR_AM \ + | EDRV_REGDW_RCR_APM) // default value + +#define EDRV_REGDW_TCR 0x40 // Tx configuration register +#define EDRV_REGDW_TCR_VER_MASK 0x7CC00000 // mask for hardware version +#define EDRV_REGDW_TCR_VER_C 0x74000000 // RTL8139C +#define EDRV_REGDW_TCR_VER_D 0x74400000 // RTL8139D +#define EDRV_REGDW_TCR_IFG96 0x03000000 // default interframe gap (960 ns) +#define EDRV_REGDW_TCR_CRC 0x00010000 // disable appending of CRC by the controller +#define EDRV_REGDW_TCR_MXDMAUNL 0x00000700 // maximum DMA burst size of 2048 b +#define EDRV_REGDW_TCR_TXRETRY 0x00000000 // 16 retries +#define EDRV_REGDW_TCR_DEF (EDRV_REGDW_TCR_IFG96 \ + | EDRV_REGDW_TCR_MXDMAUNL \ + | EDRV_REGDW_TCR_TXRETRY) + +#define EDRV_REGW_MULINT 0x5C // multiple interrupt select register + +#define EDRV_REGDW_MPC 0x4C // missed packet counter register + +#define EDRV_REGDW_TSAD0 0x20 // Transmit start address of descriptor 0 +#define EDRV_REGDW_TSAD1 0x24 // Transmit start address of descriptor 1 +#define EDRV_REGDW_TSAD2 0x28 // Transmit start address of descriptor 2 +#define EDRV_REGDW_TSAD3 0x2C // Transmit start address of descriptor 3 +#define EDRV_REGDW_TSD0 0x10 // Transmit status of descriptor 0 +#define EDRV_REGDW_TSD_CRS 0x80000000 // Carrier sense lost +#define EDRV_REGDW_TSD_TABT 0x40000000 // Transmit Abort +#define EDRV_REGDW_TSD_OWC 0x20000000 // Out of window collision +#define EDRV_REGDW_TSD_TXTH_DEF 0x00020000 // Transmit FIFO threshold of 64 bytes +#define EDRV_REGDW_TSD_TOK 0x00008000 // Transmit OK +#define EDRV_REGDW_TSD_TUN 0x00004000 // Transmit FIFO underrun +#define EDRV_REGDW_TSD_OWN 0x00002000 // Owner + +#define EDRV_REGDW_RBSTART 0x30 // Receive buffer start address + +#define EDRV_REGW_CAPR 0x38 // Current address of packet read + +#define EDRV_REGDW_IDR0 0x00 // ID register 0 +#define EDRV_REGDW_IDR4 0x04 // ID register 4 + +#define EDRV_REGDW_MAR0 0x08 // Multicast address register 0 +#define EDRV_REGDW_MAR4 0x0C // Multicast address register 4 + + +// defines for the status word in the receive buffer +#define EDRV_RXSTAT_MAR 0x8000 // Multicast address received +#define EDRV_RXSTAT_PAM 0x4000 // Physical address matched +#define EDRV_RXSTAT_BAR 0x2000 // Broadcast address received +#define EDRV_RXSTAT_ISE 0x0020 // Invalid symbol error +#define EDRV_RXSTAT_RUNT 0x0010 // Runt packet received +#define EDRV_RXSTAT_LONG 0x0008 // Long packet +#define EDRV_RXSTAT_CRC 0x0004 // CRC error +#define EDRV_RXSTAT_FAE 0x0002 // Frame alignment error +#define EDRV_RXSTAT_ROK 0x0001 // Receive OK + + +#define EDRV_REGDW_WRITE(dwReg, dwVal) writel(dwVal, EdrvInstance_l.m_pIoAddr + dwReg) +#define EDRV_REGW_WRITE(dwReg, wVal) writew(wVal, EdrvInstance_l.m_pIoAddr + dwReg) +#define EDRV_REGB_WRITE(dwReg, bVal) writeb(bVal, EdrvInstance_l.m_pIoAddr + dwReg) +#define EDRV_REGDW_READ(dwReg) readl(EdrvInstance_l.m_pIoAddr + dwReg) +#define EDRV_REGW_READ(dwReg) readw(EdrvInstance_l.m_pIoAddr + dwReg) +#define EDRV_REGB_READ(dwReg) readb(EdrvInstance_l.m_pIoAddr + dwReg) + + +// TracePoint support for realtime-debugging +#ifdef _DBG_TRACE_POINTS_ + void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); + void PUBLIC TgtDbgPostTraceValue (DWORD dwTraceValue_p); + #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) + #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) +#else + #define TGT_DBG_SIGNAL_TRACE_POINT(p) + #define TGT_DBG_POST_TRACE_VALUE(v) +#endif + +#define EDRV_COUNT_SEND TGT_DBG_SIGNAL_TRACE_POINT(2) +#define EDRV_COUNT_TIMEOUT TGT_DBG_SIGNAL_TRACE_POINT(3) +#define EDRV_COUNT_PCI_ERR TGT_DBG_SIGNAL_TRACE_POINT(4) +#define EDRV_COUNT_TX TGT_DBG_SIGNAL_TRACE_POINT(5) +#define EDRV_COUNT_RX TGT_DBG_SIGNAL_TRACE_POINT(6) +#define EDRV_COUNT_LATECOLLISION TGT_DBG_SIGNAL_TRACE_POINT(10) +#define EDRV_COUNT_TX_COL_RL TGT_DBG_SIGNAL_TRACE_POINT(11) +#define EDRV_COUNT_TX_FUN TGT_DBG_SIGNAL_TRACE_POINT(12) +#define EDRV_COUNT_TX_ERR TGT_DBG_SIGNAL_TRACE_POINT(13) +#define EDRV_COUNT_RX_CRC TGT_DBG_SIGNAL_TRACE_POINT(14) +#define EDRV_COUNT_RX_ERR TGT_DBG_SIGNAL_TRACE_POINT(15) +#define EDRV_COUNT_RX_FOVW TGT_DBG_SIGNAL_TRACE_POINT(16) +#define EDRV_COUNT_RX_PUN TGT_DBG_SIGNAL_TRACE_POINT(17) +#define EDRV_COUNT_RX_FAE TGT_DBG_SIGNAL_TRACE_POINT(18) +#define EDRV_COUNT_RX_OVW TGT_DBG_SIGNAL_TRACE_POINT(19) + +#define EDRV_TRACE_CAPR(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x06000000) +#define EDRV_TRACE_RX_CRC(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x0E000000) +#define EDRV_TRACE_RX_ERR(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x0F000000) +#define EDRV_TRACE_RX_PUN(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x11000000) +#define EDRV_TRACE(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF0000) | 0x0000FEC0) + + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- +/* +typedef struct +{ + BOOL m_fUsed; + unsigned int m_uiSize; + MCD_bufDescFec *m_pBufDescr; + +} tEdrvTxBufferIntern; +*/ + +// Private structure +typedef struct +{ + struct pci_dev* m_pPciDev; // pointer to PCI device structure + void* m_pIoAddr; // pointer to register space of Ethernet controller + BYTE* m_pbRxBuf; // pointer to Rx buffer + dma_addr_t m_pRxBufDma; + BYTE* m_pbTxBuf; // pointer to Tx buffer + dma_addr_t m_pTxBufDma; + BOOL m_afTxBufUsed[EDRV_MAX_TX_BUFFERS]; + unsigned int m_uiCurTxDesc; + + tEdrvInitParam m_InitParam; + tEdrvTxBuffer* m_pLastTransmittedTxBuffer; + +} tEdrvInstance; + + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static int EdrvInitOne(struct pci_dev *pPciDev, + const struct pci_device_id *pId); + +static void EdrvRemoveOne(struct pci_dev *pPciDev); + + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- +// buffers and buffer descriptors and pointers + +static struct pci_device_id aEdrvPciTbl[] = { + {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} +}; +MODULE_DEVICE_TABLE (pci, aEdrvPciTbl); + + +static tEdrvInstance EdrvInstance_l; + + +static struct pci_driver EdrvDriver = { + .name = DRV_NAME, + .id_table = aEdrvPciTbl, + .probe = EdrvInitOne, + .remove = EdrvRemoveOne, +}; + + + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <edrv> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static BYTE EdrvCalcHash (BYTE * pbMAC_p); + + + +//--------------------------------------------------------------------------- +// +// Function: EdrvInit +// +// Description: function for init of the Ethernet controller +// +// Parameters: pEdrvInitParam_p = pointer to struct including the init-parameters +// +// Returns: Errorcode = kEplSuccessful +// = kEplNoResource +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel EdrvInit(tEdrvInitParam * pEdrvInitParam_p) +{ +tEplKernel Ret; +int iResult; + + Ret = kEplSuccessful; + + // clear instance structure + EPL_MEMSET(&EdrvInstance_l, 0, sizeof (EdrvInstance_l)); + + // save the init data + EdrvInstance_l.m_InitParam = *pEdrvInitParam_p; + + + // register PCI driver + iResult = pci_register_driver (&EdrvDriver); + if (iResult != 0) + { + printk("%s pci_register_driver failed with %d\n", __FUNCTION__, iResult); + Ret = kEplNoResource; + goto Exit; + } + + if (EdrvInstance_l.m_pPciDev == NULL) + { + printk("%s m_pPciDev=NULL\n", __FUNCTION__); + Ret = kEplNoResource; + goto Exit; + } + + // read MAC address from controller + printk("%s local MAC = ", __FUNCTION__); + for (iResult = 0; iResult < 6; iResult++) + { + pEdrvInitParam_p->m_abMyMacAddr[iResult] = EDRV_REGB_READ((EDRV_REGDW_IDR0 + iResult)); + printk("%02X ", (unsigned int)pEdrvInitParam_p->m_abMyMacAddr[iResult]); + } + printk("\n"); + +Exit: + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvShutdown +// +// Description: Shutdown the Ethernet controller +// +// Parameters: void +// +// Returns: Errorcode = kEplSuccessful +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel EdrvShutdown(void) +{ + + // unregister PCI driver + printk("%s calling pci_unregister_driver()\n", __FUNCTION__); + pci_unregister_driver (&EdrvDriver); + + return kEplSuccessful; +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvDefineRxMacAddrEntry +// +// Description: Set a multicast entry into the Ethernet controller +// +// Parameters: pbMacAddr_p = pointer to multicast entry to set +// +// Returns: Errorcode = kEplSuccessful +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel EdrvDefineRxMacAddrEntry (BYTE * pbMacAddr_p) +{ +tEplKernel Ret = kEplSuccessful; +DWORD dwData; +BYTE bHash; + + bHash = EdrvCalcHash (pbMacAddr_p); +/* + dwData = ether_crc(6, pbMacAddr_p); + + printk("EdrvDefineRxMacAddrEntry('%02X:%02X:%02X:%02X:%02X:%02X') hash = %u / %u ether_crc = 0x%08lX\n", + (WORD) pbMacAddr_p[0], (WORD) pbMacAddr_p[1], (WORD) pbMacAddr_p[2], + (WORD) pbMacAddr_p[3], (WORD) pbMacAddr_p[4], (WORD) pbMacAddr_p[5], + (WORD) bHash, (WORD) (dwData >> 26), dwData); +*/ + if (bHash > 31) + { + dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR4); + dwData |= 1 << (bHash - 32); + EDRV_REGDW_WRITE(EDRV_REGDW_MAR4, dwData); + } + else + { + dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR0); + dwData |= 1 << bHash; + EDRV_REGDW_WRITE(EDRV_REGDW_MAR0, dwData); + } + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvUndefineRxMacAddrEntry +// +// Description: Reset a multicast entry in the Ethernet controller +// +// Parameters: pbMacAddr_p = pointer to multicast entry to reset +// +// Returns: Errorcode = kEplSuccessful +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel EdrvUndefineRxMacAddrEntry (BYTE * pbMacAddr_p) +{ +tEplKernel Ret = kEplSuccessful; +DWORD dwData; +BYTE bHash; + + bHash = EdrvCalcHash (pbMacAddr_p); + + if (bHash > 31) + { + dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR4); + dwData &= ~(1 << (bHash - 32)); + EDRV_REGDW_WRITE(EDRV_REGDW_MAR4, dwData); + } + else + { + dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR0); + dwData &= ~(1 << bHash); + EDRV_REGDW_WRITE(EDRV_REGDW_MAR0, dwData); + } + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EdrvAllocTxMsgBuffer +// +// Description: Register a Tx-Buffer +// +// Parameters: pBuffer_p = pointer to Buffer structure +// +// Returns: Errorcode = kEplSuccessful +// = kEplEdrvNoFreeBufEntry +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel EdrvAllocTxMsgBuffer (tEdrvTxBuffer * pBuffer_p) +{ +tEplKernel Ret = kEplSuccessful; +DWORD i; + + if (pBuffer_p->m_uiMaxBufferLen > EDRV_MAX_FRAME_SIZE) + { + Ret = kEplEdrvNoFreeBufEntry; + goto Exit; + } + + // search a free Tx buffer with appropriate size + for (i = 0; i < EDRV_MAX_TX_BUFFERS; i++) + { + if (EdrvInstance_l.m_afTxBufUsed[i] == FALSE) + { + // free channel found + EdrvInstance_l.m_afTxBufUsed[i] = TRUE; + pBuffer_p->m_uiBufferNumber = i; + pBuffer_p->m_pbBuffer = EdrvInstance_l.m_pbTxBuf + (i * EDRV_MAX_FRAME_SIZE); + pBuffer_p->m_uiMaxBufferLen = EDRV_MAX_FRAME_SIZE; + break; + } + } + if (i >= EDRV_MAX_TX_BUFFERS) + { + Ret = kEplEdrvNoFreeBufEntry; + goto Exit; + } + +Exit: + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvReleaseTxMsgBuffer +// +// Description: Register a Tx-Buffer +// +// Parameters: pBuffer_p = pointer to Buffer structure +// +// Returns: Errorcode = kEplSuccessful +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel EdrvReleaseTxMsgBuffer (tEdrvTxBuffer * pBuffer_p) +{ +unsigned int uiBufferNumber; + + uiBufferNumber = pBuffer_p->m_uiBufferNumber; + + if (uiBufferNumber < EDRV_MAX_TX_BUFFERS) + { + EdrvInstance_l.m_afTxBufUsed[uiBufferNumber] = FALSE; + } + + return kEplSuccessful; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvSendTxMsg +// +// Description: immediately starts the transmission of the buffer +// +// Parameters: pBuffer_p = buffer descriptor to transmit +// +// Returns: Errorcode = kEplSuccessful +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel EdrvSendTxMsg (tEdrvTxBuffer * pBuffer_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiBufferNumber; +DWORD dwTemp; + + uiBufferNumber = pBuffer_p->m_uiBufferNumber; + + if ((uiBufferNumber >= EDRV_MAX_TX_BUFFERS) + || (EdrvInstance_l.m_afTxBufUsed[uiBufferNumber] == FALSE)) + { + Ret = kEplEdrvBufNotExisting; + goto Exit; + } + + if (EdrvInstance_l.m_pLastTransmittedTxBuffer != NULL) + { // transmission is already active + Ret = kEplInvalidOperation; + dwTemp = EDRV_REGDW_READ((EDRV_REGDW_TSD0 + (EdrvInstance_l.m_uiCurTxDesc * sizeof (DWORD)))); + printk("%s InvOp TSD%u = 0x%08lX", __FUNCTION__, EdrvInstance_l.m_uiCurTxDesc, dwTemp); + printk(" Cmd = 0x%02X\n", (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND)); + goto Exit; + } + + // save pointer to buffer structure for TxHandler + EdrvInstance_l.m_pLastTransmittedTxBuffer = pBuffer_p; + + EDRV_COUNT_SEND; + + // pad with zeros if necessary, because controller does not do it + if (pBuffer_p->m_uiTxMsgLen < MIN_ETH_SIZE) + { + EPL_MEMSET(pBuffer_p->m_pbBuffer + pBuffer_p->m_uiTxMsgLen, 0, MIN_ETH_SIZE - pBuffer_p->m_uiTxMsgLen); + pBuffer_p->m_uiTxMsgLen = MIN_ETH_SIZE; + } + + // set DMA address of buffer + EDRV_REGDW_WRITE((EDRV_REGDW_TSAD0 + (EdrvInstance_l.m_uiCurTxDesc * sizeof (DWORD))), (EdrvInstance_l.m_pTxBufDma + (uiBufferNumber * EDRV_MAX_FRAME_SIZE))); + dwTemp = EDRV_REGDW_READ((EDRV_REGDW_TSAD0 + (EdrvInstance_l.m_uiCurTxDesc * sizeof (DWORD)))); +// printk("%s TSAD%u = 0x%08lX", __FUNCTION__, EdrvInstance_l.m_uiCurTxDesc, dwTemp); + + // start transmission + EDRV_REGDW_WRITE((EDRV_REGDW_TSD0 + (EdrvInstance_l.m_uiCurTxDesc * sizeof (DWORD))), (EDRV_REGDW_TSD_TXTH_DEF | pBuffer_p->m_uiTxMsgLen)); + dwTemp = EDRV_REGDW_READ((EDRV_REGDW_TSD0 + (EdrvInstance_l.m_uiCurTxDesc * sizeof (DWORD)))); +// printk(" TSD%u = 0x%08lX / 0x%08lX\n", EdrvInstance_l.m_uiCurTxDesc, dwTemp, (DWORD)(EDRV_REGDW_TSD_TXTH_DEF | pBuffer_p->m_uiTxMsgLen)); + +Exit: + return Ret; +} + +#if 0 +//--------------------------------------------------------------------------- +// +// Function: EdrvTxMsgReady +// +// Description: starts copying the buffer to the ethernet controller's FIFO +// +// Parameters: pbBuffer_p - bufferdescriptor to transmit +// +// Returns: Errorcode - kEplSuccessful +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel EdrvTxMsgReady (tEdrvTxBuffer * pBuffer_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiBufferNumber; + + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvTxMsgStart +// +// Description: starts transmission of the ethernet controller's FIFO +// +// Parameters: pbBuffer_p - bufferdescriptor to transmit +// +// Returns: Errorcode - kEplSuccessful +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel EdrvTxMsgStart (tEdrvTxBuffer * pBuffer_p) +{ +tEplKernel Ret = kEplSuccessful; + + + + return Ret; +} +#endif + + + +//--------------------------------------------------------------------------- +// +// Function: EdrvReinitRx +// +// Description: reinitialize the Rx process, because of error +// +// Parameters: void +// +// Returns: void +// +// State: +// +//--------------------------------------------------------------------------- +static void EdrvReinitRx(void) +{ +BYTE bCmd; + + // simply switch off and on the receiver + // this will reset the CAPR register + bCmd = EDRV_REGB_READ(EDRV_REGB_COMMAND); + EDRV_REGB_WRITE(EDRV_REGB_COMMAND, (bCmd & ~EDRV_REGB_COMMAND_RE)); + EDRV_REGB_WRITE(EDRV_REGB_COMMAND, bCmd); + + // set receive configuration register + EDRV_REGDW_WRITE(EDRV_REGDW_RCR, EDRV_REGDW_RCR_DEF); +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvInterruptHandler +// +// Description: interrupt handler +// +// Parameters: void +// +// Returns: void +// +// State: +// +//--------------------------------------------------------------------------- +#if 0 +void EdrvInterruptHandler (void) +{ +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) +static int TgtEthIsr (int nIrqNum_p, void* ppDevInstData_p) +#else +static int TgtEthIsr (int nIrqNum_p, void* ppDevInstData_p, struct pt_regs* ptRegs_p) +#endif +{ +// EdrvInterruptHandler(); +tEdrvRxBuffer RxBuffer; +tEdrvTxBuffer* pTxBuffer; +WORD wStatus; +DWORD dwTxStatus; +DWORD dwRxStatus; +WORD wCurRx; +BYTE* pbRxBuf; +unsigned int uiLength; +int iHandled = IRQ_HANDLED; + +// printk("¤"); + + // read the interrupt status + wStatus = EDRV_REGW_READ(EDRV_REGW_INT_STATUS); + + // acknowledge the interrupts + EDRV_REGW_WRITE(EDRV_REGW_INT_STATUS, wStatus); + + if (wStatus == 0) + { + iHandled = IRQ_NONE; + goto Exit; + } + + // process tasks + if ((wStatus & (EDRV_REGW_INT_TER | EDRV_REGW_INT_TOK)) != 0) + { // transmit interrupt + + if (EdrvInstance_l.m_pbTxBuf == NULL) + { + printk("%s Tx buffers currently not allocated\n", __FUNCTION__); + goto Exit; + } + + // read transmit status + dwTxStatus = EDRV_REGDW_READ((EDRV_REGDW_TSD0 + (EdrvInstance_l.m_uiCurTxDesc * sizeof (DWORD)))); + if ((dwTxStatus & (EDRV_REGDW_TSD_TOK | EDRV_REGDW_TSD_TABT | EDRV_REGDW_TSD_TUN)) != 0) + { // transmit finished + EdrvInstance_l.m_uiCurTxDesc = (EdrvInstance_l.m_uiCurTxDesc + 1) & 0x03; + pTxBuffer = EdrvInstance_l.m_pLastTransmittedTxBuffer; + EdrvInstance_l.m_pLastTransmittedTxBuffer = NULL; + + if ((dwTxStatus & EDRV_REGDW_TSD_TOK) != 0) + { + EDRV_COUNT_TX; + } + else if ((dwTxStatus & EDRV_REGDW_TSD_TUN) != 0) + { + EDRV_COUNT_TX_FUN; + } + else + { // assume EDRV_REGDW_TSD_TABT + EDRV_COUNT_TX_COL_RL; + } + +// printk("T"); + if (pTxBuffer != NULL) + { + // call Tx handler of Data link layer + EdrvInstance_l.m_InitParam.m_pfnTxHandler(pTxBuffer); + } + } + else + { + EDRV_COUNT_TX_ERR; + } + } + + if ((wStatus & (EDRV_REGW_INT_RER | EDRV_REGW_INT_FOVW | EDRV_REGW_INT_RXOVW | EDRV_REGW_INT_PUN)) != 0) + { // receive error interrupt + + if ((wStatus & EDRV_REGW_INT_FOVW) != 0) + { + EDRV_COUNT_RX_FOVW; + } + else if ((wStatus & EDRV_REGW_INT_RXOVW) != 0) + { + EDRV_COUNT_RX_OVW; + } + else if ((wStatus & EDRV_REGW_INT_PUN) != 0) + { // Packet underrun + EDRV_TRACE_RX_PUN(wStatus); + EDRV_COUNT_RX_PUN; + } + else /*if ((wStatus & EDRV_REGW_INT_RER) != 0)*/ + { + EDRV_TRACE_RX_ERR(wStatus); + EDRV_COUNT_RX_ERR; + } + + // reinitialize Rx process + EdrvReinitRx(); + } + + if ((wStatus & EDRV_REGW_INT_ROK) != 0) + { // receive interrupt + + if (EdrvInstance_l.m_pbRxBuf == NULL) + { + printk("%s Rx buffers currently not allocated\n", __FUNCTION__); + goto Exit; + } + + // read current offset in receive buffer + wCurRx = (EDRV_REGW_READ(EDRV_REGW_CAPR) + 0x10) % EDRV_RX_BUFFER_LENGTH; + + while ((EDRV_REGB_READ(EDRV_REGB_COMMAND) & EDRV_REGB_COMMAND_BUFE) == 0) + { // frame available + + // calculate pointer to current frame in receive buffer + pbRxBuf = EdrvInstance_l.m_pbRxBuf + wCurRx; + + // read receive status DWORD + dwRxStatus = le32_to_cpu(*((DWORD*)pbRxBuf)); + + // calculate length of received frame + uiLength = dwRxStatus >> 16; + + if (uiLength == 0xFFF0) + { // frame is unfinished (maybe early Rx interrupt is active) + break; + } + + if ((dwRxStatus & EDRV_RXSTAT_ROK) == 0) + { // error occured while receiving this frame + // ignore it + if ((dwRxStatus & EDRV_RXSTAT_FAE) != 0) + { + EDRV_COUNT_RX_FAE; + } + else if ((dwRxStatus & EDRV_RXSTAT_CRC) != 0) + { + EDRV_TRACE_RX_CRC(dwRxStatus); + EDRV_COUNT_RX_CRC; + } + else + { + EDRV_TRACE_RX_ERR(dwRxStatus); + EDRV_COUNT_RX_ERR; + } + + // reinitialize Rx process + EdrvReinitRx(); + + break; + } + else + { // frame is OK + RxBuffer.m_BufferInFrame = kEdrvBufferLastInFrame; + RxBuffer.m_uiRxMsgLen = uiLength - ETH_CRC_SIZE; + RxBuffer.m_pbBuffer = pbRxBuf + sizeof (dwRxStatus); + +// printk("R"); + EDRV_COUNT_RX; + + // call Rx handler of Data link layer + EdrvInstance_l.m_InitParam.m_pfnRxHandler(&RxBuffer); + } + + // calulate new offset (DWORD aligned) + wCurRx = (WORD) ((wCurRx + uiLength + sizeof (dwRxStatus) + 3) & ~0x3); + EDRV_TRACE_CAPR(wCurRx - 0x10); + EDRV_REGW_WRITE(EDRV_REGW_CAPR, wCurRx - 0x10); + + // reread current offset in receive buffer + wCurRx = (EDRV_REGW_READ(EDRV_REGW_CAPR) + 0x10) % EDRV_RX_BUFFER_LENGTH; + + } + } + + if ((wStatus & EDRV_REGW_INT_SERR) != 0) + { // PCI error + EDRV_COUNT_PCI_ERR; + } + + if ((wStatus & EDRV_REGW_INT_TIMEOUT) != 0) + { // Timeout + EDRV_COUNT_TIMEOUT; + } + +Exit: + return iHandled; +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvInitOne +// +// Description: initializes one PCI device +// +// Parameters: pPciDev = pointer to corresponding PCI device structure +// pId = PCI device ID +// +// Returns: (int) = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static int EdrvInitOne(struct pci_dev *pPciDev, + const struct pci_device_id *pId) +{ +int iResult = 0; +DWORD dwTemp; + + if (EdrvInstance_l.m_pPciDev != NULL) + { // Edrv is already connected to a PCI device + printk("%s device %s discarded\n", __FUNCTION__, pci_name(pPciDev)); + iResult = -ENODEV; + goto Exit; + } + + if (pPciDev->revision >= 0x20) + { + printk("%s device %s is an enhanced 8139C+ version, which is not supported\n", __FUNCTION__, pci_name(pPciDev)); + iResult = -ENODEV; + goto Exit; + } + + EdrvInstance_l.m_pPciDev = pPciDev; + + // enable device + printk("%s enable device\n", __FUNCTION__); + iResult = pci_enable_device(pPciDev); + if (iResult != 0) + { + goto Exit; + } + + if ((pci_resource_flags(pPciDev, 1) & IORESOURCE_MEM) == 0) + { + iResult = -ENODEV; + goto Exit; + } + + printk("%s request regions\n", __FUNCTION__); + iResult = pci_request_regions(pPciDev, DRV_NAME); + if (iResult != 0) + { + goto Exit; + } + + printk("%s ioremap\n", __FUNCTION__); + EdrvInstance_l.m_pIoAddr = ioremap (pci_resource_start(pPciDev, 1), pci_resource_len(pPciDev, 1)); + if (EdrvInstance_l.m_pIoAddr == NULL) + { // remap of controller's register space failed + iResult = -EIO; + goto Exit; + } + + // enable PCI busmaster + printk("%s enable busmaster\n", __FUNCTION__); + pci_set_master (pPciDev); + + // reset controller + printk("%s reset controller\n", __FUNCTION__); + EDRV_REGB_WRITE(EDRV_REGB_COMMAND, EDRV_REGB_COMMAND_RST); + + // wait until reset has finished + for (iResult = 500; iResult > 0; iResult--) + { + if ((EDRV_REGB_READ(EDRV_REGB_COMMAND) & EDRV_REGB_COMMAND_RST) == 0) + { + break; + } + + schedule_timeout(10); + } + + // check hardware version, i.e. chip ID + dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TCR); + if (((dwTemp & EDRV_REGDW_TCR_VER_MASK) != EDRV_REGDW_TCR_VER_C) + && ((dwTemp & EDRV_REGDW_TCR_VER_MASK) != EDRV_REGDW_TCR_VER_D)) + { // unsupported chip + printk("%s Unsupported chip! TCR = 0x%08lX\n", __FUNCTION__, dwTemp); + iResult = -ENODEV; + goto Exit; + } + + // disable interrupts + printk("%s disable interrupts\n", __FUNCTION__); + EDRV_REGW_WRITE(EDRV_REGW_INT_MASK, 0); + // acknowledge all pending interrupts + EDRV_REGW_WRITE(EDRV_REGW_INT_STATUS, EDRV_REGW_READ(EDRV_REGW_INT_STATUS)); + + // install interrupt handler + printk("%s install interrupt handler\n", __FUNCTION__); + iResult = request_irq(pPciDev->irq, TgtEthIsr, IRQF_SHARED, DRV_NAME /*pPciDev->dev.name*/, pPciDev); + if (iResult != 0) + { + goto Exit; + } + +/* + // unlock configuration registers + printk("%s unlock configuration registers\n", __FUNCTION__); + EDRV_REGB_WRITE(EDRV_REGB_CMD9346, EDRV_REGB_CMD9346_UNLOCK); + + // check if user specified a MAC address + printk("%s check specified MAC address\n", __FUNCTION__); + for (iResult = 0; iResult < 6; iResult++) + { + if (EdrvInstance_l.m_InitParam.m_abMyMacAddr[iResult] != 0) + { + printk("%s set local MAC address\n", __FUNCTION__); + // write this MAC address to controller + EDRV_REGDW_WRITE(EDRV_REGDW_IDR0, + le32_to_cpu(*((DWORD*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[0]))); + dwTemp = EDRV_REGDW_READ(EDRV_REGDW_IDR0); + + EDRV_REGDW_WRITE(EDRV_REGDW_IDR4, + le32_to_cpu(*((DWORD*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[4]))); + dwTemp = EDRV_REGDW_READ(EDRV_REGDW_IDR4); + break; + } + } + iResult = 0; + + // lock configuration registers + EDRV_REGB_WRITE(EDRV_REGB_CMD9346, EDRV_REGB_CMD9346_LOCK); +*/ + + // allocate buffers + printk("%s allocate buffers\n", __FUNCTION__); + EdrvInstance_l.m_pbTxBuf = pci_alloc_consistent(pPciDev, EDRV_TX_BUFFER_SIZE, + &EdrvInstance_l.m_pTxBufDma); + if (EdrvInstance_l.m_pbTxBuf == NULL) + { + iResult = -ENOMEM; + goto Exit; + } + + EdrvInstance_l.m_pbRxBuf = pci_alloc_consistent(pPciDev, EDRV_RX_BUFFER_SIZE, + &EdrvInstance_l.m_pRxBufDma); + if (EdrvInstance_l.m_pbRxBuf == NULL) + { + iResult = -ENOMEM; + goto Exit; + } + + // reset pointers for Tx buffers + printk("%s reset pointers fo Tx buffers\n", __FUNCTION__); + EDRV_REGDW_WRITE(EDRV_REGDW_TSAD0, 0); + dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD0); + EDRV_REGDW_WRITE(EDRV_REGDW_TSAD1, 0); + dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD1); + EDRV_REGDW_WRITE(EDRV_REGDW_TSAD2, 0); + dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD2); + EDRV_REGDW_WRITE(EDRV_REGDW_TSAD3, 0); + dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD3); + + printk(" Command = 0x%02X\n", (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND)); + + // set pointer for receive buffer in controller + printk("%s set pointer to Rx buffer\n", __FUNCTION__); + EDRV_REGDW_WRITE(EDRV_REGDW_RBSTART, EdrvInstance_l.m_pRxBufDma); + + // enable transmitter and receiver + printk("%s enable Tx and Rx", __FUNCTION__); + EDRV_REGB_WRITE(EDRV_REGB_COMMAND, (EDRV_REGB_COMMAND_RE | EDRV_REGB_COMMAND_TE)); + printk(" Command = 0x%02X\n", (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND)); + + // clear missed packet counter to enable Rx/Tx process + EDRV_REGDW_WRITE(EDRV_REGDW_MPC, 0); + + // set transmit configuration register + printk("%s set Tx conf register", __FUNCTION__); + EDRV_REGDW_WRITE(EDRV_REGDW_TCR, EDRV_REGDW_TCR_DEF); + printk(" = 0x%08X\n", EDRV_REGDW_READ(EDRV_REGDW_TCR)); + + // set receive configuration register + printk("%s set Rx conf register", __FUNCTION__); + EDRV_REGDW_WRITE(EDRV_REGDW_RCR, EDRV_REGDW_RCR_DEF); + printk(" = 0x%08X\n", EDRV_REGDW_READ(EDRV_REGDW_RCR)); + + // reset multicast MAC address filter + EDRV_REGDW_WRITE(EDRV_REGDW_MAR0, 0); + dwTemp = EDRV_REGDW_READ(EDRV_REGDW_MAR0); + EDRV_REGDW_WRITE(EDRV_REGDW_MAR4, 0); + dwTemp = EDRV_REGDW_READ(EDRV_REGDW_MAR4); + +/* + // enable transmitter and receiver + printk("%s enable Tx and Rx", __FUNCTION__); + EDRV_REGB_WRITE(EDRV_REGB_COMMAND, (EDRV_REGB_COMMAND_RE | EDRV_REGB_COMMAND_TE)); + printk(" Command = 0x%02X\n", (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND)); +*/ + // disable early interrupts + EDRV_REGW_WRITE(EDRV_REGW_MULINT, 0); + + // enable interrupts + printk("%s enable interrupts\n", __FUNCTION__); + EDRV_REGW_WRITE(EDRV_REGW_INT_MASK, EDRV_REGW_INT_MASK_DEF); + + +Exit: + printk("%s finished with %d\n", __FUNCTION__, iResult); + return iResult; +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvRemoveOne +// +// Description: shuts down one PCI device +// +// Parameters: pPciDev = pointer to corresponding PCI device structure +// +// Returns: (void) +// +// State: +// +//--------------------------------------------------------------------------- + +static void EdrvRemoveOne(struct pci_dev *pPciDev) +{ + + if (EdrvInstance_l.m_pPciDev != pPciDev) + { // trying to remove unknown device + BUG_ON(EdrvInstance_l.m_pPciDev != pPciDev); + goto Exit; + } + + // disable transmitter and receiver + EDRV_REGB_WRITE(EDRV_REGB_COMMAND, 0); + + // disable interrupts + EDRV_REGW_WRITE(EDRV_REGW_INT_MASK, 0); + + // remove interrupt handler + free_irq(pPciDev->irq, pPciDev); + + + // free buffers + if (EdrvInstance_l.m_pbTxBuf != NULL) + { + pci_free_consistent(pPciDev, EDRV_TX_BUFFER_SIZE, + EdrvInstance_l.m_pbTxBuf, EdrvInstance_l.m_pTxBufDma); + EdrvInstance_l.m_pbTxBuf = NULL; + } + + if (EdrvInstance_l.m_pbRxBuf != NULL) + { + pci_free_consistent(pPciDev, EDRV_RX_BUFFER_SIZE, + EdrvInstance_l.m_pbRxBuf, EdrvInstance_l.m_pRxBufDma); + EdrvInstance_l.m_pbRxBuf = NULL; + } + + // unmap controller's register space + if (EdrvInstance_l.m_pIoAddr != NULL) + { + iounmap(EdrvInstance_l.m_pIoAddr); + } + + // disable the PCI device + pci_disable_device(pPciDev); + + // release memory regions + pci_release_regions(pPciDev); + + EdrvInstance_l.m_pPciDev = NULL; + +Exit:; +} + + +//--------------------------------------------------------------------------- +// +// Function: EdrvCalcHash +// +// Description: function calculates the entry for the hash-table from MAC +// address +// +// Parameters: pbMAC_p - pointer to MAC address +// +// Returns: hash value +// +// State: +// +//--------------------------------------------------------------------------- +#define HASH_BITS 6 // used bits in hash +#define CRC32_POLY 0x04C11DB6 // +//#define CRC32_POLY 0xEDB88320 // +// G(x) = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 + +static BYTE EdrvCalcHash (BYTE * pbMAC_p) +{ +DWORD dwByteCounter; +DWORD dwBitCounter; +DWORD dwData; +DWORD dwCrc; +DWORD dwCarry; +BYTE * pbData; +BYTE bHash; + + pbData = pbMAC_p; + + // calculate crc32 value of mac address + dwCrc = 0xFFFFFFFF; + + for (dwByteCounter = 0; dwByteCounter < 6; dwByteCounter++) + { + dwData = *pbData; + pbData++; + for (dwBitCounter = 0; dwBitCounter < 8; dwBitCounter++, dwData >>= 1) + { + dwCarry = (((dwCrc >> 31) ^ dwData) & 1); + dwCrc = dwCrc << 1; + if (dwCarry != 0) + { + dwCrc = (dwCrc ^ CRC32_POLY) | dwCarry; + } + } + } + +// printk("MyCRC = 0x%08lX\n", dwCrc); + // only upper 6 bits (HASH_BITS) are used + // which point to specific bit in the hash registers + bHash = (BYTE)((dwCrc >> (32 - HASH_BITS)) & 0x3f); + + return bHash; +} + diff --git a/drivers/staging/epl/EdrvFec.h b/drivers/staging/epl/EdrvFec.h new file mode 100644 index 0000000..2dd737e --- /dev/null +++ b/drivers/staging/epl/EdrvFec.h @@ -0,0 +1,126 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: interface for ethernetdriver + "fast ethernet controller" (FEC) + freescale coldfire MCF528x and compatible FEC + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EdrvFec.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + Dev C++ and GNU-Compiler for m68k + + ------------------------------------------------------------------------- + + Revision History: + + 2005/08/01 m.b.: start of implementation + +****************************************************************************/ + +#ifndef _EDRVFEC_H_ +#define _EDRVFEC_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- +// do this in config header +#define TARGET_HARDWARE TGTHW_SPLC_CF54 + + +// base addresses +#if ((TARGET_HARDWARE & TGT_CPU_MASK_) == TGT_CPU_5282) + + +#elif ((TARGET_HARDWARE & TGT_CPU_MASK_) == TGT_CPU_5485) + + +#else + + #error 'ERROR: Target was never implemented!' + +#endif + + + +//--------------------------------------------------------------------------- +// types +//--------------------------------------------------------------------------- + + +// Rx and Tx buffer descriptor format +typedef struct +{ + WORD m_wStatus; // control / status --- used by edrv, do not change in application + WORD m_wLength; // transfer length + BYTE * m_pbData; // buffer address +} tBufferDescr; + +#if ((TARGET_HARDWARE & TGT_CPU_MASK_) == TGT_CPU_5282) + +#elif ((TARGET_HARDWARE & TGT_CPU_MASK_) == TGT_CPU_5485) + +#endif + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + + +#endif // #ifndef _EDRV_FEC_H_ + + diff --git a/drivers/staging/epl/EdrvFec5282.h b/drivers/staging/epl/EdrvFec5282.h new file mode 100644 index 0000000..8213d0a --- /dev/null +++ b/drivers/staging/epl/EdrvFec5282.h @@ -0,0 +1,347 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: interface for ethernetdriver + "fast ethernet controller" (FEC) + freescale coldfire MCF528x and compatible FEC + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EdrvFec5282.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + Dev C++ and GNU-Compiler for m68k + + ------------------------------------------------------------------------- + + Revision History: + + 2005/08/01 m.b.: start of implementation + +****************************************************************************/ + +#ifndef _EDRVFEC_H_ +#define _EDRVFEC_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- +// base addresses +#define FEC0_ADDR 0x0000 +#define FEC1_ADDR 0x0000 //tbd + +// control / status registers +#define FEC_EIR 0x1004 // interrupt event register +#define FEC_EIMR 0x1008 // interrupt mask register +#define FEC_RDAR 0x1010 // receive descriptor active register +#define FEC_TDAR 0x1014 // transmit descriptor active register +#define FEC_ECR 0x1024 // ethernet control register +#define FEC_MMFR 0x1040 // MII data register +#define FEC_MSCR 0x1044 // MII speed register +#define FEC_MIBC 0x1064 // MIB control/status register +#define FEC_RCR 0x1084 // receive control register +#define FEC_TCR 0x10C4 // transmit control register +#define FEC_PALR 0x10E4 // physical address low register +#define FEC_PAUR 0x10E8 // physical address high + type register +#define FEC_OPD 0x10EC // opcode + pause register +#define FEC_IAUR 0x1118 // upper 32 bit of individual hash table +#define FEC_IALR 0x111C // lower 32 bit of individual hash table +#define FEC_GAUR 0x1120 // upper 32 bit of group hash table +#define FEC_GALR 0x1124 // lower 32 bit of group hash table +#define FEC_TFWR 0x1144 // transmit FIFO watermark +#define FEC_FRBR 0x114C // FIFO receive bound register +#define FEC_FRSR 0x1150 // FIFO receive FIFO start register +#define FEC_ERDSR 0x1180 // pointer to receive descriptor ring +#define FEC_ETDSR 0x1184 // pointer to transmit descriptor ring +#define FEC_EMRBR 0x1188 // maximum receive buffer size + +// mib block counters memory map +#define FEC_RMON_T_DROP 0x1200 // count of frames not counted correctly +#define FEC_RMON_T_PACKETS 0x1204 // RMON tx packet count +#define FEC_RMON_T_BC_PKT 0x1208 // RMON tx broadcast packets +#define FEC_RMON_T_MC_PKT 0x120C // RMON tx multicast packets +#define FEC_RMON_T_CRC_ALIGN 0x1210 // RMON tx packets w CRC/align error +#define FEC_RMON_T_UNDERSIZE 0x1214 // RMON tx packets < 64 bytes, good CRC +#define FEC_RMON_T_OVERSIZE 0x1218 // RMON tx packets > MAX_FL bytes, good CRC +#define FEC_RMON_T_FRAG 0x121C // RMON tx packets < 64 bytes, bad CRC +#define FEC_RMON_T_JAB 0x1220 // RMON tx packets > MAX_FL bytes, bad CRC +#define FEC_RMON_T_COL 0x1224 // RMON tx collision count +#define FEC_RMON_T_P64 0x1228 // RMON tx 64 byte packets +#define FEC_RMON_T_P65TO127 0x122C // RMON tx 65 to 127 byte packets +#define FEC_RMON_T_P128TO255 0x1230 // RMON tx 128 to 255 byte packets +#define FEC_RMON_T_P256TO511 0x1234 // RMON tx 256 to 511 byte packets +#define FEC_RMON_T_P512TO1023 0x1238 // RMON tx 512 to 1023 byte packets +#define FEC_RMON_T_P1024TO2047 0x123C // RMON tx 1024 to 2047 byte packets +#define FEC_RMON_T_P_GTE2048 0x1240 // RMON tx w > 2048 bytes +#define FEC_RMON_T_OCTETS 0x1244 // RMON tx octets +#define FEC_IEEE_T_DROP 0x1248 // count of frames not counted correctly +#define FEC_IEEE_T_FRAME_OK 0x124C // frames transmitted OK +#define FEC_IEEE_T_1COL 0x1250 // frames transmitted with single collision +#define FEC_IEEE_T_MCOL 0x1254 // frames transmitted with multiple collisions +#define FEC_IEEE_T_DEF 0x1258 // frames transmitted after deferral delay +#define FEC_IEEE_T_LCOL 0x125C // frames transmitted with late collisions +#define FEC_IEEE_T_EXCOL 0x1260 // frames transmitted with excessive collisions +#define FEC_IEEE_T_MACERR 0x1264 // frames transmitted with tx-FIFO underrun +#define FEC_IEEE_T_CSERR 0x1268 // frames transmitted with carrier sense error +#define FEC_IEEE_T_SQE 0x126C // frames transmitted with SQE error +#define FEC_IEEE_T_FDXFC 0x1270 // flow control pause frames transmitted +#define FEC_IEEE_T_OCTETS_OK 0x1274 // octet count for frames transmitted w/o error +#define FEC_RMON_R_PACKETS 0x1284 // RMON rx packet count +#define FEC_RMON_R_BC_PKT 0x1288 // RMON rx broadcast packets +#define FEC_RMON_R_MC_PKT 0x128C // RMON rx multicast packets +#define FEC_RMON_R_CRC_ALIGN 0x1290 // RMON rx packets w CRC/align error +#define FEC_RMON_R_UNDERSIZE 0x1294 // RMON rx packets < 64 bytes, good CRC +#define FEC_RMON_R_OVERSIZE 0x1298 // RMON rx packets > MAX_FL bytes, good CRC +#define FEC_RMON_R_FRAG 0x129C // RMON rx packets < 64 bytes, bad CRC +#define FEC_RMON_R_JAB 0x12A0 // RMON rx packets > MAX_FL bytes, bad CRC +#define FEC_RMON_R_RESVD_0 0x12A4 // +#define FEC_RMON_R_P64 0x12A8 // RMON rx 64 byte packets +#define FEC_RMON_R_P65T0127 0x12AC // RMON rx 65 to 127 byte packets +#define FEC_RMON_R_P128TO255 0x12B0 // RMON rx 128 to 255 byte packets +#define FEC_RMON_R_P256TO511 0x12B4 // RMON rx 256 to 511 byte packets +#define FEC_RMON_R_P512TO1023 0x12B8 // RMON rx 512 to 1023 byte packets +#define FEC_RMON_R_P1024TO2047 0x12BC // RMON rx 1024 to 2047 byte packets +#define FEC_RMON_R_GTE2048 0x12C0 // RMON rx w > 2048 bytes +#define FEC_RMON_R_OCTETS 0x12C4 // RMON rx octets +#define FEC_IEEE_R_DROP 0x12C8 // count of frames not counted correctly +#define FEC_IEEE_R_FRAME_OK 0x12CC // frames received OK +#define FEC_IEEE_R_CRC 0x12D0 // frames received with CRC error +#define FEC_IEEE_R_ALIGN 0x12D4 // frames received with alignment error +#define FEC_IEEE_R_MACERR 0x12D8 // receive FIFO overflow count +#define FEC_IEEE_R_FDXFC 0x12DC // flow control pause frames received +#define FEC_IEEE_R_OCTETS_OK 0x12E0 // octet count for frames rcvd w/o error + +// register bit definitions and macros +#define FEC_EIR_UN (0x00080000) +#define FEC_EIR_RL (0x00100000) +#define FEC_EIR_LC (0x00200000) +#define FEC_EIR_EBERR (0x00400000) +#define FEC_EIR_MII (0x00800000) +#define FEC_EIR_RXB (0x01000000) +#define FEC_EIR_RXF (0x02000000) +#define FEC_EIR_TXB (0x04000000) +#define FEC_EIR_TXF (0x08000000) +#define FEC_EIR_GRA (0x10000000) +#define FEC_EIR_BABT (0x20000000) +#define FEC_EIR_BABR (0x40000000) +#define FEC_EIR_HBERR (0x80000000) + +#define FEC_EIMR_UN (0x00080000) +#define FEC_EIMR_RL (0x00100000) +#define FEC_EIMR_LC (0x00200000) +#define FEC_EIMR_EBERR (0x00400000) +#define FEC_EIMR_MII (0x00800000) +#define FEC_EIMR_RXB (0x01000000) +#define FEC_EIMR_RXF (0x02000000) +#define FEC_EIMR_TXB (0x04000000) +#define FEC_EIMR_TXF (0x08000000) +#define FEC_EIMR_GRA (0x10000000) +#define FEC_EIMR_BABT (0x20000000) +#define FEC_EIMR_BABR (0x40000000) +#define FEC_EIMR_HBERR (0x80000000) + +#define FEC_RDAR_R_DES_ACTIVE (0x01000000) + +#define FEC_TDAR_X_DES_ACTIVE (0x01000000) + +#define FEC_ECR_RESET (0x00000001) +#define FEC_ECR_ETHER_EN (0x00000002) + +#define FEC_MMFR_DATA(x) (((x) & 0xFFFF)) +#define FEC_MMFR_TA (0x00020000) +#define FEC_MMFR_RA(x) (((x) & 0x1F) << 18) +#define FEC_MMFR_PA(x) (((x) & 0x1F) << 23) +#define FEC_MMFR_OP_WR (0x10000000) +#define FEC_MMFR_OP_RD (0x20000000) +#define FEC_MMFR_ST (0x40000000) + +#define FEC_MSCR_MII_SPEED(x) (((x) & 0x1F) << 1) +#define FEC_MSCR_DIS_PREAMBLE (0x00000008) + +#define FEC_MIBC_MIB_IDLE (0x40000000) +#define FEC_MIBC_MIB_DISABLE (0x80000000) + +#define FEC_RCR_LOOP (0x00000001) +#define FEC_RCR_DRT (0x00000002) +#define FEC_RCR_MII_MODE (0x00000004) +#define FEC_RCR_PROM (0x00000008) +#define FEC_RCR_BC_REJ (0x00000010) +#define FEC_RCR_FCE (0x00000020) +#define FEC_RCR_MAX_FL(x) (((x) & 0x07FF) << 16) + +#define FEC_TCR_GTS (0x00000001) +#define FEC_TCR_HBC (0x00000002) +#define FEC_TCR_FDEN (0x00000004) +#define FEC_TCR_TFC_PAUSE (0x00000008) +#define FEC_TCR_RFC_PAUSE (0x00000010) + +#define FEC_PALR_BYTE3(x) (((x) & 0xFF) << 0) +#define FEC_PALR_BYTE2(x) (((x) & 0xFF) << 8) +#define FEC_PALR_BYTE1(x) (((x) & 0xFF) << 16) +#define FEC_PALR_BYTE0(x) (((x) & 0xFF) << 24) + +//#define FEC_PAUR_TYPE(x) (((x) & 0xFFFF) << 0) +#define FEC_PAUR_BYTE5(x) (((x) & 0xFF) << 16) +#define FEC_PAUR_BYTE4(x) (((x) & 0xFF) << 24) + +#define FEC_OPD_PAUSE_DUR(x) (((x) & 0xFFFF)) +//#define FEC_OPD_OPCODE(x) (((x) & 0xFFFF) << 16) + +//m.b. +#define FEC_IAUR_BYTE7(x) (((x) & 0xFF) << 0) +#define FEC_IAUR_BYTE6(x) (((x) & 0xFF) << 8) +#define FEC_IAUR_BYTE5(x) (((x) & 0xFF) << 16) +#define FEC_IAUR_BYTE4(x) (((x) & 0xFF) << 24) + +#define FEC_IALR_BYTE3(x) (((x) & 0xFF) << 0) +#define FEC_IALR_BYTE2(x) (((x) & 0xFF) << 8) +#define FEC_IALR_BYTE1(x) (((x) & 0xFF) << 16) +#define FEC_IALR_BYTE0(x) (((x) & 0xFF) << 24) + +#define FEC_GAUR_BYTE7(x) (((x) & 0xFF) << 0) +#define FEC_GAUR_BYTE6(x) (((x) & 0xFF) << 8) +#define FEC_GAUR_BYTE5(x) (((x) & 0xFF) << 16) +#define FEC_GAUR_BYTE4(x) (((x) & 0xFF) << 24) + +#define FEC_GALR_BYTE3(x) (((x) & 0xFF) << 0) +#define FEC_GALR_BYTE2(x) (((x) & 0xFF) << 8) +#define FEC_GALR_BYTE1(x) (((x) & 0xFF) << 16) +#define FEC_GALR_BYTE0(x) (((x) & 0xFF) << 24) +// ^^^^ + +#define FEC_TFWR_X_WMRK_64 (0x00000001) +#define FEC_TFWR_X_WMRK_128 (0x00000002) +#define FEC_TFWR_X_WMRK_192 (0x00000003) + +//m.b. +#define FEC_FRBR_R_BOUND(x) (((x) & 0xFF) << 2) + +//m.b. +#define FEC_FRSR_R_FSTART(x) (((x) & 0xFF) << 2) + +//m.b. +#define FEC_ERDSR_R_DES_START(x) (((x) & 0x3FFFFFFF) << 2) + +//m.b. +#define FEC_ETSDR_X_DES_START(x) (((x) & 0x3FFFFFFF) << 2) + +#define FEC_EMRBR_R_BUF_SIZE(x) (((x) & 0x7F) << 4) + +#define FEC_RxBD_TR 0x0001 +#define FEC_RxBD_OV 0x0002 +#define FEC_RxBD_CR 0x0004 +#define FEC_RxBD_NO 0x0010 +#define FEC_RxBD_LG 0x0020 +#define FEC_RxBD_MC 0x0040 +#define FEC_RxBD_BC 0x0080 +#define FEC_RxBD_M 0x0100 +#define FEC_RxBD_L 0x0800 +#define FEC_RxBD_R02 0x1000 +#define FEC_RxBD_W 0x2000 +#define FEC_RxBD_R01 0x4000 +#define FEC_RxBD_INUSE 0x4000 +#define FEC_RxBD_E 0x8000 + +//m.b. +//#define FEC_TxBD_CSL 0x0001 +//#define FEC_TxBD_UN 0x0002 +//#define FEC_TxBD_RL 0x0040 +//#define FEC_TxBD_LC 0x0080 +//#define FEC_TxBD_HB 0x0100 +//#define FEC_TxBD_DEF 0x0200 +#define FEC_TxBD_ABC 0x0200 +// ^^^^ +#define FEC_TxBD_TC 0x0400 +#define FEC_TxBD_L 0x0800 +#define FEC_TxBD_TO2 0x1000 +#define FEC_TxBD_W 0x2000 +#define FEC_TxBD_TO1 0x4000 +#define FEC_TxBD_INUSE 0x4000 +#define FEC_TxBD_R 0x8000 + +//--------------------------------------------------------------------------- +// types +//--------------------------------------------------------------------------- + +// Rx and Tx buffer descriptor format +typedef struct +{ + WORD m_wStatus; // control / status --- used by edrv, do not change in application + WORD m_wLength; // transfer length + BYTE * m_pbData; // buffer address +} tBufferDescr; + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if (NO_OF_INSTANCES > 1) + #define ECI_WRITE_DW_REG(off,val) (*(DWORD *)(void *)(&__IPSBAR[off]) = val) + #define ECI_READ_DW_REG(off) (*(DWORD *)(void *)(&__IPSBAR[off])) +#else + #if (EDRV_USED_ETH_CTRL == 0) + #define ECI_WRITE_DW_REG(off,val) (*(DWORD *)(void *)(&__IPSBAR[FEC0_ADDR+off]) = val) + #define ECI_READ_DW_REG(off) (*(DWORD *)(void *)(&__IPSBAR[FEC0_ADDR+off])) + #else + #define ECI_WRITE_DW_REG(off,val) (*(DWORD *)(void *)(&__IPSBAR[FEC1_ADDR+off]) = val) + #define ECI_READ_DW_REG(off) (*(DWORD *)(void *)(&__IPSBAR[FEC1_ADDR+off])) + #endif +#endif + + + + +#endif // #ifndef _EDRV_FEC_H_ + + diff --git a/drivers/staging/epl/EdrvSim.h b/drivers/staging/epl/EdrvSim.h new file mode 100644 index 0000000..eb3ef83 --- /dev/null +++ b/drivers/staging/epl/EdrvSim.h @@ -0,0 +1,94 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: interface for ethernet driver simulation + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EdrvSim.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + Dev C++ and GNU-Compiler for m68k + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/15 d.k.: start of implementation + +****************************************************************************/ + +#ifndef _EDRVSIM_H_ +#define _EDRVSIM_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// types +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +void EdrvRxInterruptHandler (BYTE bBufferInFrame_p, BYTE * pbEthernetData_p, WORD wDataLen_p); + + + +#endif // #ifndef _EDRVSIM_H_ + + diff --git a/drivers/staging/epl/Epl.h b/drivers/staging/epl/Epl.h new file mode 100644 index 0000000..986995e --- /dev/null +++ b/drivers/staging/epl/Epl.h @@ -0,0 +1,304 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for EPL API layer + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: Epl.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/11/17 16:40:39 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/05/22 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_API_H_ +#define _EPL_API_H_ + +#include "EplInc.h" +#include "EplSdo.h" +#include "EplObd.h" +#include "EplLed.h" +#include "EplEvent.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +typedef struct +{ + unsigned int m_uiNodeId; + tEplNmtState m_NmtState; + tEplNmtNodeEvent m_NodeEvent; + WORD m_wErrorCode; // EPL error code if m_NodeEvent == kEplNmtNodeEventError + BOOL m_fMandatory; + +} tEplApiEventNode; + + +typedef struct +{ + tEplNmtState m_NmtState; // local NMT state + tEplNmtBootEvent m_BootEvent; + WORD m_wErrorCode; // EPL error code if m_BootEvent == kEplNmtBootEventError + +} tEplApiEventBoot; + + +typedef struct +{ + tEplLedType m_LedType; // type of the LED (e.g. Status or Error) + BOOL m_fOn; // state of the LED (e.g. on or off) + +} tEplApiEventLed; + + +typedef enum +{ + kEplApiEventNmtStateChange = 0x10, // m_NmtStateChange +// kEplApiEventRequestNmt = 0x11, // m_bNmtCmd + kEplApiEventCriticalError = 0x12, // m_InternalError, Stack halted + kEplApiEventWarning = 0x13, // m_InternalError, Stack running + kEplApiEventNode = 0x20, // m_Node + kEplApiEventBoot = 0x21, // m_Boot + kEplApiEventSdo = 0x62, // m_Sdo + kEplApiEventObdAccess = 0x69, // m_ObdCbParam + kEplApiEventLed = 0x70, // m_Led + +} tEplApiEventType; + + +typedef union +{ + tEplEventNmtStateChange m_NmtStateChange; + tEplEventError m_InternalError; + tEplSdoComFinished m_Sdo; + tEplObdCbParam m_ObdCbParam; + tEplApiEventNode m_Node; + tEplApiEventBoot m_Boot; + tEplApiEventLed m_Led; + +} tEplApiEventArg; + + +typedef tEplKernel (PUBLIC ROM* tEplApiCbEvent) ( + tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg* pEventArg_p, // IN: event argument (union) + void GENERIC* pUserArg_p); + + +typedef struct +{ + unsigned int m_uiSizeOfStruct; + BOOL m_fAsyncOnly; // do not need to register PRes + unsigned int m_uiNodeId; // local node ID + BYTE m_abMacAddress[6]; // local MAC address + + // 0x1F82: NMT_FeatureFlags_U32 + DWORD m_dwFeatureFlags; + // Cycle Length (0x1006: NMT_CycleLen_U32) in [us] + DWORD m_dwCycleLen; // required for error detection + // 0x1F98: NMT_CycleTiming_REC + // 0x1F98.1: IsochrTxMaxPayload_U16 + unsigned int m_uiIsochrTxMaxPayload; // const + // 0x1F98.2: IsochrRxMaxPayload_U16 + unsigned int m_uiIsochrRxMaxPayload; // const + // 0x1F98.3: PResMaxLatency_U32 + DWORD m_dwPresMaxLatency; // const in [ns], only required for IdentRes + // 0x1F98.4: PReqActPayloadLimit_U16 + unsigned int m_uiPreqActPayloadLimit; // required for initialisation (+28 bytes) + // 0x1F98.5: PResActPayloadLimit_U16 + unsigned int m_uiPresActPayloadLimit; // required for initialisation of Pres frame (+28 bytes) + // 0x1F98.6: ASndMaxLatency_U32 + DWORD m_dwAsndMaxLatency; // const in [ns], only required for IdentRes + // 0x1F98.7: MultiplCycleCnt_U8 + unsigned int m_uiMultiplCycleCnt; // required for error detection + // 0x1F98.8: AsyncMTU_U16 + unsigned int m_uiAsyncMtu; // required to set up max frame size + // 0x1F98.9: Prescaler_U16 + unsigned int m_uiPrescaler; // required for sync + // $$$ Multiplexed Slot + + // 0x1C14: DLL_LossOfFrameTolerance_U32 in [ns] + DWORD m_dwLossOfFrameTolerance; + + // 0x1F8A: NMT_MNCycleTiming_REC + // 0x1F8A.1: WaitSoCPReq_U32 in [ns] + DWORD m_dwWaitSocPreq; + + // 0x1F8A.2: AsyncSlotTimeout_U32 in [ns] + DWORD m_dwAsyncSlotTimeout; + + DWORD m_dwDeviceType; // NMT_DeviceType_U32 + DWORD m_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32 + DWORD m_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32 + DWORD m_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32 + DWORD m_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32 + QWORD m_qwVendorSpecificExt1; + DWORD m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 + DWORD m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 + DWORD m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device + DWORD m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device + DWORD m_dwIpAddress; + DWORD m_dwSubnetMask; + DWORD m_dwDefaultGateway; + BYTE m_sHostname[32]; + BYTE m_abVendorSpecificExt2[48]; + + char* m_pszDevName; // NMT_ManufactDevName_VS (0x1008/0 local OD) + char* m_pszHwVersion; // NMT_ManufactHwVers_VS (0x1009/0 local OD) + char* m_pszSwVersion; // NMT_ManufactSwVers_VS (0x100A/0 local OD) + + tEplApiCbEvent m_pfnCbEvent; + void* m_pEventUserArg; + tEplSyncCb m_pfnCbSync; + +} tEplApiInitParam; + + +typedef struct +{ + void* m_pImage; + unsigned int m_uiSize; + +} tEplApiProcessImage; + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiInitialize(tEplApiInitParam* pInitParam_p); + +tEplKernel PUBLIC EplApiShutdown(void); + +tEplKernel PUBLIC EplApiReadObject( + tEplSdoComConHdl* pSdoComConHdl_p, + unsigned int uiNodeId_p, + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void* pDstData_le_p, + unsigned int* puiSize_p, + tEplSdoType SdoType_p, + void* pUserArg_p); + +tEplKernel PUBLIC EplApiWriteObject( + tEplSdoComConHdl* pSdoComConHdl_p, + unsigned int uiNodeId_p, + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void* pSrcData_le_p, + unsigned int uiSize_p, + tEplSdoType SdoType_p, + void* pUserArg_p); + +tEplKernel PUBLIC EplApiFreeSdoChannel( + tEplSdoComConHdl SdoComConHdl_p); + +tEplKernel PUBLIC EplApiReadLocalObject( + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void* pDstData_p, + unsigned int* puiSize_p); + +tEplKernel PUBLIC EplApiWriteLocalObject( + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void* pSrcData_p, + unsigned int uiSize_p); + +tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM* pParam_p); + +tEplKernel PUBLIC EplApiLinkObject( unsigned int uiObjIndex_p, + void* pVar_p, + unsigned int* puiVarEntries_p, + tEplObdSize* pEntrySize_p, + unsigned int uiFirstSubindex_p); + +tEplKernel PUBLIC EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p); + +tEplKernel PUBLIC EplApiProcess(void); + + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +tEplKernel PUBLIC EplApiMnTriggerStateChange(unsigned int uiNodeId_p, + tEplNmtNodeCommand NodeCommand_p); +#endif + +tEplKernel PUBLIC EplApiGetIdentResponse( + unsigned int uiNodeId_p, + tEplIdentResponse** ppIdentResponse_p); + + +// functions for process image will be implemented in separate file +tEplKernel PUBLIC EplApiProcessImageSetup(void); +tEplKernel PUBLIC EplApiProcessImageExchangeIn(tEplApiProcessImage* pPI_p); +tEplKernel PUBLIC EplApiProcessImageExchangeOut(tEplApiProcessImage* pPI_p); + + +#endif // #ifndef _EPL_API_H_ + + diff --git a/drivers/staging/epl/EplAmi.h b/drivers/staging/epl/EplAmi.h new file mode 100644 index 0000000..17cb62a --- /dev/null +++ b/drivers/staging/epl/EplAmi.h @@ -0,0 +1,380 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: Definitions for Abstract Memory Interface + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplAmi.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.2 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC + + ------------------------------------------------------------------------- + + Revision History: + + 06.03.2000 -rs + Implementation + + 16.09.2002 -as + To save code space the functions AmiSetByte and AmiGetByte + are replaced by macros. For targets which assign BYTE by + an 16Bit type, the definition of macros must changed to + functions. + + 23.02.2005 r.d.: + Functions included for extended data types such as UNSIGNED24, + UNSIGNED40, ... + + 13.06.2006 d.k.: + Extended the interface for EPL with the different functions + for little endian and big endian + +****************************************************************************/ + +#ifndef _EPLAMI_H_ +#define _EPLAMI_H_ + + +#if ((DEV_SYSTEM & _DEV_64BIT_SUPPORT_) == 0) +// #ifdef USE_VAR64 + #error 'ERROR: development system does not support 64 bit operations!' +// #endif +#endif + + +//--------------------------------------------------------------------------- +// types +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// Prototypen +//--------------------------------------------------------------------------- + +#ifdef __cplusplus + extern "C" { +#endif + +#if (TARGET_SYSTEM == _WIN32_) + #if defined(INLINE_FUNCTION_DEF) + #undef INLINE_FUNCTION + #define INLINE_FUNCTION INLINE_FUNCTION_DEF + #define INLINE_ENABLED TRUE + #define EPL_AMI_INLINED + #include "../EplStack/amix86.c" + #endif + +#elif (TARGET_SYSTEM == _LINUX_) + #if defined(__m68k__) // it is an big endian machine + #if defined(INLINE_FUNCTION_DEF) + #undef INLINE_FUNCTION + #define INLINE_FUNCTION INLINE_FUNCTION_DEF + #define INLINE_ENABLED TRUE + #define EPL_AMI_INLINED + #include "../EplStack/amibe.c" + #endif + #endif +#endif + +//--------------------------------------------------------------------------- +// +// write functions +// +// To save code space the function AmiSetByte is replaced by +// an macro. +// void PUBLIC AmiSetByte (void FAR* pAddr_p, BYTE bByteVal_p); + +#define AmiSetByteToBe(pAddr_p, bByteVal_p) {*(BYTE FAR*)(pAddr_p) = (bByteVal_p);} +#define AmiSetByteToLe(pAddr_p, bByteVal_p) {*(BYTE FAR*)(pAddr_p) = (bByteVal_p);} + +#if !defined(INLINE_ENABLED) +void PUBLIC AmiSetWordToBe (void FAR* pAddr_p, WORD wWordVal_p); +void PUBLIC AmiSetDwordToBe (void FAR* pAddr_p, DWORD dwDwordVal_p); +void PUBLIC AmiSetWordToLe (void FAR* pAddr_p, WORD wWordVal_p); +void PUBLIC AmiSetDwordToLe (void FAR* pAddr_p, DWORD dwDwordVal_p); +#endif + + +//--------------------------------------------------------------------------- +// +// read functions +// +// To save code space the function AmiGetByte is replaced by +// an macro. +// BYTE PUBLIC AmiGetByte (void FAR* pAddr_p); + +#define AmiGetByteFromBe(pAddr_p) (*(BYTE FAR*)(pAddr_p)) +#define AmiGetByteFromLe(pAddr_p) (*(BYTE FAR*)(pAddr_p)) + +#if !defined(INLINE_ENABLED) + +WORD PUBLIC AmiGetWordFromBe (void FAR* pAddr_p); +DWORD PUBLIC AmiGetDwordFromBe (void FAR* pAddr_p); +WORD PUBLIC AmiGetWordFromLe (void FAR* pAddr_p); +DWORD PUBLIC AmiGetDwordFromLe (void FAR* pAddr_p); + +//--------------------------------------------------------------------------- +// +// Function: AmiSetDword24() +// +// Description: sets a 24 bit value to a buffer +// +// Parameters: pAddr_p = pointer to destination buffer +// dwDwordVal_p = value to set +// +// Return: void +// +//--------------------------------------------------------------------------- + +void PUBLIC AmiSetDword24ToBe (void FAR* pAddr_p, DWORD dwDwordVal_p); +void PUBLIC AmiSetDword24ToLe (void FAR* pAddr_p, DWORD dwDwordVal_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetDword24() +// +// Description: reads a 24 bit value from a buffer +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: DWORD = read value +// +//--------------------------------------------------------------------------- + +DWORD PUBLIC AmiGetDword24FromBe (void FAR* pAddr_p); +DWORD PUBLIC AmiGetDword24FromLe (void FAR* pAddr_p); + + +//#ifdef USE_VAR64 + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword40() +// +// Description: sets a 40 bit value to a buffer +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +//--------------------------------------------------------------------------- + +void PUBLIC AmiSetQword40ToBe (void FAR* pAddr_p, QWORD qwQwordVal_p); +void PUBLIC AmiSetQword40ToLe (void FAR* pAddr_p, QWORD qwQwordVal_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword40() +// +// Description: reads a 40 bit value from a buffer +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: QWORD +// +//--------------------------------------------------------------------------- + +QWORD PUBLIC AmiGetQword40FromBe (void FAR* pAddr_p); +QWORD PUBLIC AmiGetQword40FromLe (void FAR* pAddr_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword48() +// +// Description: sets a 48 bit value to a buffer +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +//--------------------------------------------------------------------------- + +void PUBLIC AmiSetQword48ToBe (void FAR* pAddr_p, QWORD qwQwordVal_p); +void PUBLIC AmiSetQword48ToLe (void FAR* pAddr_p, QWORD qwQwordVal_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword48() +// +// Description: reads a 48 bit value from a buffer +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: QWORD +// +//--------------------------------------------------------------------------- + +QWORD PUBLIC AmiGetQword48FromBe (void FAR* pAddr_p); +QWORD PUBLIC AmiGetQword48FromLe (void FAR* pAddr_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword56() +// +// Description: sets a 56 bit value to a buffer +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +//--------------------------------------------------------------------------- + +void PUBLIC AmiSetQword56ToBe (void FAR* pAddr_p, QWORD qwQwordVal_p); +void PUBLIC AmiSetQword56ToLe (void FAR* pAddr_p, QWORD qwQwordVal_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword56() +// +// Description: reads a 56 bit value from a buffer +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: QWORD +// +//--------------------------------------------------------------------------- + +QWORD PUBLIC AmiGetQword56FromBe (void FAR* pAddr_p); +QWORD PUBLIC AmiGetQword56FromLe (void FAR* pAddr_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword64() +// +// Description: sets a 64 bit value to a buffer +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +//--------------------------------------------------------------------------- + +void PUBLIC AmiSetQword64ToBe (void FAR* pAddr_p, QWORD qwQwordVal_p); +void PUBLIC AmiSetQword64ToLe (void FAR* pAddr_p, QWORD qwQwordVal_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword64() +// +// Description: reads a 64 bit value from a buffer +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: void +// +//--------------------------------------------------------------------------- + +QWORD PUBLIC AmiGetQword64FromBe (void FAR* pAddr_p); +QWORD PUBLIC AmiGetQword64FromLe (void FAR* pAddr_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetTimeOfDay() +// +// Description: sets a TIME_OF_DAY (CANopen) value to a buffer +// +// Parameters: pAddr_p = pointer to destination buffer +// pTimeOfDay_p = pointer to struct TIME_OF_DAY +// +// Return: void +// +//--------------------------------------------------------------------------- + +void PUBLIC AmiSetTimeOfDay (void FAR* pAddr_p, tTimeOfDay FAR* pTimeOfDay_p); + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetTimeOfDay() +// +// Description: reads a TIME_OF_DAY (CANopen) value from a buffer +// +// Parameters: pAddr_p = pointer to source buffer +// pTimeOfDay_p = pointer to struct TIME_OF_DAY +// +// Return: void +// +//--------------------------------------------------------------------------- + +void PUBLIC AmiGetTimeOfDay (void FAR* pAddr_p, tTimeOfDay FAR* pTimeOfDay_p); + +#endif + + +#undef INLINE_ENABLED // disable actual inlining of functions +#define EPL_AMI_INCLUDED + +#ifdef __cplusplus + } +#endif + + +#endif // ifndef _EPLAMI_H_ + +// Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler +// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder). diff --git a/drivers/staging/epl/EplApiGeneric.c b/drivers/staging/epl/EplApiGeneric.c new file mode 100644 index 0000000..61ed18e --- /dev/null +++ b/drivers/staging/epl/EplApiGeneric.c @@ -0,0 +1,2093 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for generic EPL API module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplApiGeneric.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.21 $ $Date: 2008/11/21 09:00:38 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/09/05 d.k.: start of the implementation, version 1.00 + +****************************************************************************/ + +#include "Epl.h" +#include "kernel/EplDllk.h" +#include "kernel/EplErrorHandlerk.h" +#include "kernel/EplEventk.h" +#include "kernel/EplNmtk.h" +#include "kernel/EplObdk.h" +#include "kernel/EplTimerk.h" +#include "kernel/EplDllkCal.h" +#include "kernel/EplPdokCal.h" +#include "user/EplDlluCal.h" +#include "user/EplLedu.h" +#include "user/EplNmtCnu.h" +#include "user/EplNmtMnu.h" +#include "user/EplSdoComu.h" +#include "user/EplIdentu.h" +#include "user/EplStatusu.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) +#include "kernel/EplPdok.h" +#endif + +#include "SharedBuff.h" + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) == 0) +#error "EPL API layer needs EPL module OBDK!" +#endif + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S EplApi */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ + tEplApiInitParam m_InitParam; + +} tEplApiInstance; + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +static tEplApiInstance EplApiInstance_g; + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +// NMT state change event callback function +static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p); + +// update DLL configuration from OD +static tEplKernel PUBLIC EplApiUpdateDllConfig(BOOL fUpdateIdentity_p); + +// update OD from init param +static tEplKernel PUBLIC EplApiUpdateObd(void); + +// process events from user event queue +static tEplKernel PUBLIC EplApiProcessEvent(tEplEvent* pEplEvent_p); + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +// callback function of SDO module +static tEplKernel PUBLIC EplApiCbSdoCon(tEplSdoComFinished* pSdoComFinished_p); +#endif + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +// callback functions of NmtMnu module +static tEplKernel PUBLIC EplApiCbNodeEvent(unsigned int uiNodeId_p, + tEplNmtNodeEvent NodeEvent_p, + tEplNmtState NmtState_p, + WORD wErrorCode_p, + BOOL fMandatory_p); + +static tEplKernel PUBLIC EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p, + tEplNmtState NmtState_p, + WORD wErrorCode_p); +#endif + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) +// callback function of Ledu module +static tEplKernel PUBLIC EplApiCbLedStateChange(tEplLedType LedType_p, + BOOL fOn_p); +#endif + +// OD initialization function (implemented in Objdict.c) +tEplKernel PUBLIC EplObdInitRam (tEplObdInitParam MEM* pInitParam_p); + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplApiInitialize() +// +// Description: add and initialize new instance of EPL stack. +// After return from this function the application must start +// the NMT state machine via +// EplApiExecNmtCommand(kEplNmtEventSwReset) +// and thereby the whole EPL stack :-) +// +// Parameters: pInitParam_p = initialisation parameters +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiInitialize(tEplApiInitParam * pInitParam_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplObdInitParam ObdInitParam; +tEplDllkInitParam DllkInitParam; +#ifndef EPL_NO_FIFO + tShbError ShbError; +#endif + + // reset instance structure + EPL_MEMSET(&EplApiInstance_g, 0, sizeof (EplApiInstance_g)); + + EPL_MEMCPY(&EplApiInstance_g.m_InitParam, pInitParam_p, min(sizeof (tEplApiInitParam), pInitParam_p->m_uiSizeOfStruct)); + + // check event callback function pointer + if (EplApiInstance_g.m_InitParam.m_pfnCbEvent == NULL) + { // application must always have an event callback function + Ret = kEplApiInvalidParam; + goto Exit; + } + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + // init OD +// FIXME +// Ret = EplObdInitRam(&ObdInitParam); +// if (Ret != kEplSuccessful) +// { +// goto Exit; +// } + + // initialize EplObd module + Ret = EplObdInit(&ObdInitParam); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + +#ifndef EPL_NO_FIFO + ShbError = ShbInit(); + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + goto Exit; + } +#endif + + // initialize EplEventk module + Ret = EplEventkInit(EplApiInstance_g.m_InitParam.m_pfnCbSync); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // initialize EplEventu module + Ret = EplEventuInit(EplApiProcessEvent); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // init EplTimerk module + Ret = EplTimerkInit(); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // initialize EplNmtk module before DLL +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) + Ret = EplNmtkInit(); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + + // initialize EplDllk module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + EPL_MEMCPY(DllkInitParam.m_be_abSrcMac, EplApiInstance_g.m_InitParam.m_abMacAddress, 6); + Ret = EplDllkAddInstance(&DllkInitParam); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // initialize EplErrorHandlerk module + Ret = EplErrorHandlerkInit(); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // initialize EplDllkCal module + Ret = EplDllkCalAddInstance(); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + + // initialize EplDlluCal module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + Ret = EplDlluCalAddInstance(); + if (Ret != kEplSuccessful) + { + goto Exit; + } + +#endif + + // initialize EplPdok module +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + Ret = EplPdokAddInstance(); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + Ret = EplPdokCalAddInstance(); + if (Ret != kEplSuccessful) + { + goto Exit; + } + +#endif + + // initialize EplNmtCnu module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) + Ret = EplNmtCnuAddInstance(EplApiInstance_g.m_InitParam.m_uiNodeId); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + + // initialize EplNmtu module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + Ret = EplNmtuInit(); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // register NMT event callback function + Ret = EplNmtuRegisterStateChangeCb(EplApiCbNmtStateChange); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // initialize EplNmtMnu module + Ret = EplNmtMnuInit(EplApiCbNodeEvent, EplApiCbBootEvent); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // initialize EplIdentu module + Ret = EplIdentuInit(); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // initialize EplStatusu module + Ret = EplStatusuInit(); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + + // initialize EplLedu module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) + Ret = EplLeduInit(EplApiCbLedStateChange); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + + // init SDO module +#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) || \ + (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)) + // init sdo command layer + Ret = EplSdoComInit(); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + + // the application must start NMT state machine + // via EplApiExecNmtCommand(kEplNmtEventSwReset) + // and thereby the whole EPL stack + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplApiShutdown() +// +// Description: deletes an instance of EPL stack +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiShutdown(void) +{ +tEplKernel Ret = kEplSuccessful; + + // $$$ d.k.: check if NMT state is NMT_GS_OFF + + // $$$ d.k.: maybe delete event queues at first, but this implies that + // no other module must not use the event queues for communication + // during shutdown. + + // delete instance for all modules + + // deinitialize EplSdoCom module +#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) || \ + (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)) + Ret = EplSdoComDelInstance(); +// PRINTF1("EplSdoComDelInstance(): 0x%X\n", Ret); +#endif + + // deinitialize EplLedu module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) + Ret = EplLeduDelInstance(); +// PRINTF1("EplLeduDelInstance(): 0x%X\n", Ret); +#endif + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // deinitialize EplNmtMnu module + Ret = EplNmtMnuDelInstance(); +// PRINTF1("EplNmtMnuDelInstance(): 0x%X\n", Ret); + + // deinitialize EplIdentu module + Ret = EplIdentuDelInstance(); +// PRINTF1("EplIdentuDelInstance(): 0x%X\n", Ret); + + // deinitialize EplStatusu module + Ret = EplStatusuDelInstance(); +// PRINTF1("EplStatusuDelInstance(): 0x%X\n", Ret); +#endif + + // deinitialize EplNmtCnu module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) + Ret = EplNmtCnuDelInstance(); +// PRINTF1("EplNmtCnuDelInstance(): 0x%X\n", Ret); +#endif + + // deinitialize EplNmtu module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + Ret = EplNmtuDelInstance(); +// PRINTF1("EplNmtuDelInstance(): 0x%X\n", Ret); +#endif + + // deinitialize EplDlluCal module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + Ret = EplDlluCalDelInstance(); +// PRINTF1("EplDlluCalDelInstance(): 0x%X\n", Ret); + +#endif + + // deinitialize EplEventu module + Ret = EplEventuDelInstance(); +// PRINTF1("EplEventuDelInstance(): 0x%X\n", Ret); + + // deinitialize EplNmtk module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) + Ret = EplNmtkDelInstance(); +// PRINTF1("EplNmtkDelInstance(): 0x%X\n", Ret); +#endif + + // deinitialize EplDllk module +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + Ret = EplDllkDelInstance(); +// PRINTF1("EplDllkDelInstance(): 0x%X\n", Ret); + + // deinitialize EplDllkCal module + Ret = EplDllkCalDelInstance(); +// PRINTF1("EplDllkCalDelInstance(): 0x%X\n", Ret); +#endif + + // deinitialize EplEventk module + Ret = EplEventkDelInstance(); +// PRINTF1("EplEventkDelInstance(): 0x%X\n", Ret); + + // deinitialize EplTimerk module + Ret = EplTimerkDelInstance(); +// PRINTF1("EplTimerkDelInstance(): 0x%X\n", Ret); + +#ifndef EPL_NO_FIFO + ShbExit(); +#endif + + return Ret; +} + + +//---------------------------------------------------------------------------- +// Function: EplApiExecNmtCommand() +// +// Description: executes a NMT command, i.e. post the NMT command/event to the +// NMTk module. NMT commands which are not appropriate in the current +// NMT state are silently ignored. Please keep in mind that the +// NMT state may change until the NMT command is actually executed. +// +// Parameters: NmtEvent_p = NMT command/event +// +// Returns: tEplKernel = error code +// +// State: +//---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p) +{ +tEplKernel Ret = kEplSuccessful; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + Ret = EplNmtuNmtEvent(NmtEvent_p); +#endif + + return Ret; +} + + +//---------------------------------------------------------------------------- +// Function: EplApiLinkObject() +// +// Description: Function maps array of application variables onto specified object in OD +// +// Parameters: uiObjIndex_p = Function maps variables for this object index +// pVar_p = Pointer to data memory area for the specified object +// puiVarEntries_p = IN: pointer to number of entries to map +// OUT: pointer to number of actually used entries +// pEntrySize_p = IN: pointer to size of one entry; +// if size is zero, the actual size will be read from OD +// OUT: pointer to entire size of all entries mapped +// uiFirstSubindex_p = This is the first subindex to be mapped. +// +// Returns: tEplKernel = error code +// +// State: +//---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiLinkObject( unsigned int uiObjIndex_p, + void* pVar_p, + unsigned int* puiVarEntries_p, + tEplObdSize* pEntrySize_p, + unsigned int uiFirstSubindex_p) +{ +BYTE bVarEntries; +BYTE bIndexEntries; +BYTE MEM* pbData; +unsigned int uiSubindex; +tEplVarParam VarParam; +tEplObdSize EntrySize; +tEplObdSize UsedSize; + +tEplKernel RetCode = kEplSuccessful; + + if ((pVar_p == NULL) + || (puiVarEntries_p == NULL) + || (*puiVarEntries_p == 0) + || (pEntrySize_p == NULL)) + { + RetCode = kEplApiInvalidParam; + goto Exit; + } + + pbData = (BYTE MEM*) pVar_p; + bVarEntries = (BYTE) *puiVarEntries_p; + UsedSize = 0; + + // init VarParam structure with default values + VarParam.m_uiIndex = uiObjIndex_p; + VarParam.m_ValidFlag = kVarValidAll; + + if (uiFirstSubindex_p != 0) + { // check if object exists by reading subindex 0x00, + // because user wants to link a variable to a subindex unequal 0x00 + // read number of entries + EntrySize = (tEplObdSize) sizeof(bIndexEntries); + RetCode = EplObdReadEntry ( + uiObjIndex_p, + 0x00, + (void GENERIC*) &bIndexEntries, + &EntrySize ); + + if ((RetCode != kEplSuccessful) || (bIndexEntries == 0x00) ) + { + // Object doesn't exist or invalid entry number + RetCode = kEplObdIndexNotExist; + goto Exit; + } + } + else + { // user wants to link a variable to subindex 0x00 + // that's OK + bIndexEntries = 0; + } + + // Correct number of entries if number read from OD is greater + // than the specified number. + // This is done, so that we do not set more entries than subindexes the + // object actually has. + if ((bIndexEntries > (bVarEntries + uiFirstSubindex_p - 1)) && + (bVarEntries != 0x00) ) + { + bIndexEntries = (BYTE) (bVarEntries + uiFirstSubindex_p - 1); + } + + // map entries + for (uiSubindex = uiFirstSubindex_p; uiSubindex <= bIndexEntries; uiSubindex++) + { + // if passed entry size is 0, then get size from OD + if (*pEntrySize_p == 0x00) + { + // read entry size + EntrySize = EplObdGetDataSize(uiObjIndex_p, uiSubindex); + + if (EntrySize == 0x00) + { + // invalid entry size (maybe object doesn't exist or entry of type DOMAIN is empty) + RetCode = kEplObdSubindexNotExist; + break; + } + } + else + { // use passed entry size + EntrySize = *pEntrySize_p; + } + + VarParam.m_uiSubindex = uiSubindex; + + // set pointer to user var + VarParam.m_Size = EntrySize; + VarParam.m_pData = pbData; + + UsedSize += EntrySize; + pbData += EntrySize; + + RetCode = EplObdDefineVar(&VarParam); + if (RetCode != kEplSuccessful) + { + break; + } + } + + // set number of mapped entries and entry size + *puiVarEntries_p = ((bIndexEntries - uiFirstSubindex_p) + 1); + *pEntrySize_p = UsedSize; + + +Exit: + + return (RetCode); + +} + + +// ---------------------------------------------------------------------------- +// +// Function: EplApiReadObject() +// +// Description: reads the specified entry from the OD of the specified node. +// If this node is a remote node, it performs a SDO transfer, which +// means this function returns kEplApiTaskDeferred and the application +// is informed via the event callback function when the task is completed. +// +// Parameters: pSdoComConHdl_p = INOUT: pointer to SDO connection handle (may be NULL in case of local OD access) +// uiNodeId_p = IN: node ID (0 = itself) +// uiIndex_p = IN: index of object in OD +// uiSubindex_p = IN: sub-index of object in OD +// pDstData_le_p = OUT: pointer to data in little endian +// puiSize_p = INOUT: pointer to size of data +// SdoType_p = IN: type of SDO transfer +// pUserArg_p = IN: user-definable argument pointer, +// which will be passed to the event callback function +// +// Return: tEplKernel = error code +// +// ---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiReadObject( + tEplSdoComConHdl* pSdoComConHdl_p, + unsigned int uiNodeId_p, + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void* pDstData_le_p, + unsigned int* puiSize_p, + tEplSdoType SdoType_p, + void* pUserArg_p) +{ +tEplKernel Ret = kEplSuccessful; + + if ((uiIndex_p == 0) || (pDstData_le_p == NULL) || (puiSize_p == NULL) || (*puiSize_p == 0)) + { + Ret = kEplApiInvalidParam; + goto Exit; + } + + if (uiNodeId_p == 0 + || uiNodeId_p == EplObdGetNodeId()) + { // local OD access can be performed + tEplObdSize ObdSize; + + ObdSize = (tEplObdSize) *puiSize_p; + Ret = EplObdReadEntryToLe(uiIndex_p, uiSubindex_p, pDstData_le_p, &ObdSize); + *puiSize_p = (unsigned int) ObdSize; + } + else + { // perform SDO transfer +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + tEplSdoComTransParamByIndex TransParamByIndex; +// tEplSdoComConHdl SdoComConHdl; + + // check if application provides space for handle + if (pSdoComConHdl_p == NULL) + { + Ret = kEplApiInvalidParam; + goto Exit; +// pSdoComConHdl_p = &SdoComConHdl; + } + + // init command layer connection + Ret = EplSdoComDefineCon(pSdoComConHdl_p, + uiNodeId_p, // target node id + SdoType_p); // SDO type + if ((Ret != kEplSuccessful) && (Ret != kEplSdoComHandleExists)) + { + goto Exit; + } + TransParamByIndex.m_pData = pDstData_le_p; + TransParamByIndex.m_SdoAccessType = kEplSdoAccessTypeRead; + TransParamByIndex.m_SdoComConHdl = *pSdoComConHdl_p; + TransParamByIndex.m_uiDataSize = *puiSize_p; + TransParamByIndex.m_uiIndex = uiIndex_p; + TransParamByIndex.m_uiSubindex = uiSubindex_p; + TransParamByIndex.m_pfnSdoFinishedCb = EplApiCbSdoCon; + TransParamByIndex.m_pUserArg = pUserArg_p; + + Ret = EplSdoComInitTransferByIndex(&TransParamByIndex); + if (Ret != kEplSuccessful) + { + goto Exit; + } + Ret = kEplApiTaskDeferred; + +#else + Ret = kEplApiInvalidParam; +#endif + } + +Exit: + return Ret; +} + + +// ---------------------------------------------------------------------------- +// +// Function: EplApiWriteObject() +// +// Description: writes the specified entry to the OD of the specified node. +// If this node is a remote node, it performs a SDO transfer, which +// means this function returns kEplApiTaskDeferred and the application +// is informed via the event callback function when the task is completed. +// +// Parameters: pSdoComConHdl_p = INOUT: pointer to SDO connection handle (may be NULL in case of local OD access) +// uiNodeId_p = IN: node ID (0 = itself) +// uiIndex_p = IN: index of object in OD +// uiSubindex_p = IN: sub-index of object in OD +// pSrcData_le_p = IN: pointer to data in little endian +// uiSize_p = IN: size of data in bytes +// SdoType_p = IN: type of SDO transfer +// pUserArg_p = IN: user-definable argument pointer, +// which will be passed to the event callback function +// +// Return: tEplKernel = error code +// +// ---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiWriteObject( + tEplSdoComConHdl* pSdoComConHdl_p, + unsigned int uiNodeId_p, + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void* pSrcData_le_p, + unsigned int uiSize_p, + tEplSdoType SdoType_p, + void* pUserArg_p) +{ +tEplKernel Ret = kEplSuccessful; + + if ((uiIndex_p == 0) || (pSrcData_le_p == NULL) || (uiSize_p == 0)) + { + Ret = kEplApiInvalidParam; + goto Exit; + } + + if (uiNodeId_p == 0 + || uiNodeId_p == EplObdGetNodeId()) + { // local OD access can be performed + + Ret = EplObdWriteEntryFromLe(uiIndex_p, uiSubindex_p, pSrcData_le_p, uiSize_p); + } + else + { // perform SDO transfer +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + tEplSdoComTransParamByIndex TransParamByIndex; +// tEplSdoComConHdl SdoComConHdl; + + // check if application provides space for handle + if (pSdoComConHdl_p == NULL) + { + Ret = kEplApiInvalidParam; + goto Exit; +// pSdoComConHdl_p = &SdoComConHdl; + } + + // d.k.: How to recycle command layer connection? + // Try to redefine it, which will return kEplSdoComHandleExists + // and the existing command layer handle. + // If the returned handle is busy, EplSdoComInitTransferByIndex() + // will return with error. + // $$$ d.k.: Collisions may occur with Configuration Manager, if both the application and + // Configuration Manager, are trying to communicate with the very same node. + // possible solution: disallow communication by application if Configuration Manager is busy + + // init command layer connection + Ret = EplSdoComDefineCon(pSdoComConHdl_p, + uiNodeId_p, // target node id + SdoType_p); // SDO type + if ((Ret != kEplSuccessful) && (Ret != kEplSdoComHandleExists)) + { + goto Exit; + } + TransParamByIndex.m_pData = pSrcData_le_p; + TransParamByIndex.m_SdoAccessType = kEplSdoAccessTypeWrite; + TransParamByIndex.m_SdoComConHdl = *pSdoComConHdl_p; + TransParamByIndex.m_uiDataSize = uiSize_p; + TransParamByIndex.m_uiIndex = uiIndex_p; + TransParamByIndex.m_uiSubindex = uiSubindex_p; + TransParamByIndex.m_pfnSdoFinishedCb = EplApiCbSdoCon; + TransParamByIndex.m_pUserArg = pUserArg_p; + + Ret = EplSdoComInitTransferByIndex(&TransParamByIndex); + if (Ret != kEplSuccessful) + { + goto Exit; + } + Ret = kEplApiTaskDeferred; + +#else + Ret = kEplApiInvalidParam; +#endif + } + +Exit: + return Ret; +} + + +// ---------------------------------------------------------------------------- +// +// Function: EplApiFreeSdoChannel() +// +// Description: frees the specified SDO channel. +// This function must be called after each call to EplApiReadObject()/EplApiWriteObject() +// which returns kEplApiTaskDeferred and the application +// is informed via the event callback function when the task is completed. +// +// Parameters: SdoComConHdl_p = IN: SDO connection handle +// +// Return: tEplKernel = error code +// +// ---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiFreeSdoChannel( + tEplSdoComConHdl SdoComConHdl_p) +{ +tEplKernel Ret = kEplSuccessful; + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + + // init command layer connection + Ret = EplSdoComUndefineCon(SdoComConHdl_p); + +#else + Ret = kEplApiInvalidParam; +#endif + + return Ret; +} + + +// ---------------------------------------------------------------------------- +// +// Function: EplApiReadLocalObject() +// +// Description: reads the specified entry from the local OD. +// +// Parameters: uiIndex_p = IN: index of object in OD +// uiSubindex_p = IN: sub-index of object in OD +// pDstData_p = OUT: pointer to data in platform byte order +// puiSize_p = INOUT: pointer to size of data +// +// Return: tEplKernel = error code +// +// ---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiReadLocalObject( + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void* pDstData_p, + unsigned int* puiSize_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplObdSize ObdSize; + + ObdSize = (tEplObdSize) *puiSize_p; + Ret = EplObdReadEntry(uiIndex_p, uiSubindex_p, pDstData_p, &ObdSize); + *puiSize_p = (unsigned int) ObdSize; + + return Ret; +} + + +// ---------------------------------------------------------------------------- +// +// Function: EplApiWriteLocalObject() +// +// Description: writes the specified entry to the local OD. +// +// Parameters: uiIndex_p = IN: index of object in OD +// uiSubindex_p = IN: sub-index of object in OD +// pSrcData_p = IN: pointer to data in platform byte order +// uiSize_p = IN: size of data in bytes +// +// Return: tEplKernel = error code +// +// ---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiWriteLocalObject( + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void* pSrcData_p, + unsigned int uiSize_p) +{ +tEplKernel Ret = kEplSuccessful; + + Ret = EplObdWriteEntry(uiIndex_p, uiSubindex_p, pSrcData_p, (tEplObdSize) uiSize_p); + + return Ret; +} + + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +// ---------------------------------------------------------------------------- +// +// Function: EplApiMnTriggerStateChange() +// +// Description: triggers the specified node command for the specified node. +// +// Parameters: uiNodeId_p = node ID for which the node command will be executed +// NodeCommand_p = node command +// +// Return: tEplKernel = error code +// +// ---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiMnTriggerStateChange(unsigned int uiNodeId_p, + tEplNmtNodeCommand NodeCommand_p) +{ +tEplKernel Ret = kEplSuccessful; + + Ret = EplNmtMnuTriggerStateChange(uiNodeId_p, NodeCommand_p); + + return Ret; +} + +#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +//--------------------------------------------------------------------------- +// +// Function: EplApiCbObdAccess +// +// Description: callback function for OD accesses +// +// Parameters: pParam_p = OBD parameter +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM* pParam_p) +{ +tEplKernel Ret = kEplSuccessful; + +#if (EPL_API_OBD_FORWARD_EVENT != FALSE) +tEplApiEventArg EventArg; + + // call user callback + // must be disabled for EplApiLinuxKernel.c, because of reentrancy problem + // for local OD access. This is not so bad as user callback function in + // application does not use OD callbacks at the moment. + EventArg.m_ObdCbParam = *pParam_p; + Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventObdAccess, + &EventArg, + EplApiInstance_g.m_InitParam.m_pEventUserArg); +#endif + + switch (pParam_p->m_uiIndex) + { + //case 0x1006: // NMT_CycleLen_U32 (valid on reset) + case 0x1C14: // DLL_LossOfFrameTolerance_U32 + //case 0x1F98: // NMT_CycleTiming_REC (valid on reset) + { + if (pParam_p->m_ObdEvent == kEplObdEvPostWrite) + { + // update DLL configuration + Ret = EplApiUpdateDllConfig(FALSE); + } + break; + } + + case 0x1020: // CFM_VerifyConfiguration_REC.ConfId_U32 != 0 + { + if ((pParam_p->m_ObdEvent == kEplObdEvPostWrite) + && (pParam_p->m_uiSubIndex == 3) + && (*((DWORD*)pParam_p->m_pArg) != 0)) + { + DWORD dwVerifyConfInvalid = 0; + // set CFM_VerifyConfiguration_REC.VerifyConfInvalid_U32 to 0 + Ret = EplObdWriteEntry(0x1020, 4, &dwVerifyConfInvalid, 4); + // ignore any error because this objekt is optional + Ret = kEplSuccessful; + } + break; + } + + case 0x1F9E: // NMT_ResetCmd_U8 + { + if (pParam_p->m_ObdEvent == kEplObdEvPreWrite) + { + BYTE bNmtCommand; + + bNmtCommand = *((BYTE *) pParam_p->m_pArg); + // check value range + switch ((tEplNmtCommand)bNmtCommand) + { + case kEplNmtCmdResetNode: + case kEplNmtCmdResetCommunication: + case kEplNmtCmdResetConfiguration: + case kEplNmtCmdSwReset: + case kEplNmtCmdInvalidService: + // valid command identifier specified + break; + + default: + pParam_p->m_dwAbortCode = EPL_SDOAC_VALUE_RANGE_EXCEEDED; + Ret = kEplObdAccessViolation; + break; + } + } + else if (pParam_p->m_ObdEvent == kEplObdEvPostWrite) + { + BYTE bNmtCommand; + + bNmtCommand = *((BYTE *) pParam_p->m_pArg); + // check value range + switch ((tEplNmtCommand)bNmtCommand) + { + case kEplNmtCmdResetNode: +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + Ret = EplNmtuNmtEvent(kEplNmtEventResetNode); +#endif + break; + + case kEplNmtCmdResetCommunication: +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + Ret = EplNmtuNmtEvent(kEplNmtEventResetCom); +#endif + break; + + case kEplNmtCmdResetConfiguration: +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + Ret = EplNmtuNmtEvent(kEplNmtEventResetConfig); +#endif + break; + + case kEplNmtCmdSwReset: +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + Ret = EplNmtuNmtEvent(kEplNmtEventSwReset); +#endif + break; + + case kEplNmtCmdInvalidService: + break; + + default: + pParam_p->m_dwAbortCode = EPL_SDOAC_VALUE_RANGE_EXCEEDED; + Ret = kEplObdAccessViolation; + break; + } + } + break; + } + + default: + break; + } + +//Exit: + return Ret; +} + + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + + +//--------------------------------------------------------------------------- +// +// Function: EplApiProcessEvent +// +// Description: processes events from event queue and forwards these to +// the application's event callback function +// +// Parameters: pEplEvent_p = pointer to event +// +// Returns: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplApiProcessEvent( + tEplEvent* pEplEvent_p) +{ +tEplKernel Ret; +tEplEventError* pEventError; +tEplApiEventType EventType; + + Ret = kEplSuccessful; + + // process event + switch(pEplEvent_p->m_EventType) + { + // error event + case kEplEventTypeError: + { + pEventError = (tEplEventError*) pEplEvent_p->m_pArg; + switch (pEventError->m_EventSource) + { + // treat the errors from the following sources as critical + case kEplEventSourceEventk: + case kEplEventSourceEventu: + case kEplEventSourceDllk: + { + EventType = kEplApiEventCriticalError; + // halt the stack by entering NMT state Off + Ret = EplNmtuNmtEvent(kEplNmtEventCriticalError); + break; + } + + // the other errors are just warnings + default: + { + EventType = kEplApiEventWarning; + break; + } + } + + // call user callback + Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(EventType, (tEplApiEventArg*) pEventError, EplApiInstance_g.m_InitParam.m_pEventUserArg); + // discard error from callback function, because this could generate an endless loop + Ret = kEplSuccessful; + break; + } + + // at present, there are no other events for this module + default: + break; + } + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplApiCbNmtStateChange +// +// Description: callback function for NMT state changes +// +// Parameters: NmtStateChange_p = NMT state change event +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p) +{ +tEplKernel Ret = kEplSuccessful; +BYTE bNmtState; +tEplApiEventArg EventArg; + + // save NMT state in OD + bNmtState = (BYTE) NmtStateChange_p.m_NewNmtState; + Ret = EplObdWriteEntry(0x1F8C, 0, &bNmtState, 1); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // do work which must be done in that state + switch (NmtStateChange_p.m_NewNmtState) + { + // EPL stack is not running + case kEplNmtGsOff: + break; + + // first init of the hardware + case kEplNmtGsInitialising: +#if 0 +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + // configure SDO via UDP (i.e. bind it to the EPL ethernet interface) + Ret = EplSdoUdpuConfig(EplApiInstance_g.m_InitParam.m_dwIpAddress, EPL_C_SDO_EPL_PORT); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif +#endif + + break; + + // init of the manufacturer-specific profile area and the + // standardised device profile area + case kEplNmtGsResetApplication: + { + // reset application part of OD + Ret = EplObdAccessOdPart( + kEplObdPartApp, + kEplObdDirLoad); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + break; + } + + // init of the communication profile area + case kEplNmtGsResetCommunication: + { + // reset communication part of OD + Ret = EplObdAccessOdPart( + kEplObdPartGen, + kEplObdDirLoad); + + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // $$$ d.k.: update OD only if OD was not loaded from non-volatile memory + Ret = EplApiUpdateObd(); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + break; + } + + // build the configuration with infos from OD + case kEplNmtGsResetConfiguration: + { + + Ret = EplApiUpdateDllConfig(TRUE); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + break; + } + + //----------------------------------------------------------- + // CN part of the state machine + + // node liste for EPL-Frames and check timeout + case kEplNmtCsNotActive: + { + // indicate completion of reset in NMT_ResetCmd_U8 + bNmtState = (BYTE) kEplNmtCmdInvalidService; + Ret = EplObdWriteEntry(0x1F9E, 0, &bNmtState, 1); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + break; + } + + // node process only async frames + case kEplNmtCsPreOperational1: + { + break; + } + + // node process isochronus and asynchronus frames + case kEplNmtCsPreOperational2: + { + break; + } + + // node should be configured und application is ready + case kEplNmtCsReadyToOperate: + { + break; + } + + // normal work state + case kEplNmtCsOperational: + { + break; + } + + // node stopped by MN + // -> only process asynchronus frames + case kEplNmtCsStopped: + { + break; + } + + // no EPL cycle + // -> normal ethernet communication + case kEplNmtCsBasicEthernet: + { + break; + } + + //----------------------------------------------------------- + // MN part of the state machine + + // node listens for EPL-Frames and check timeout + case kEplNmtMsNotActive: + { + break; + } + + // node processes only async frames + case kEplNmtMsPreOperational1: + { + break; + } + + // node processes isochronous and asynchronous frames + case kEplNmtMsPreOperational2: + { + break; + } + + // node should be configured und application is ready + case kEplNmtMsReadyToOperate: + { + break; + } + + // normal work state + case kEplNmtMsOperational: + { + break; + } + + // no EPL cycle + // -> normal ethernet communication + case kEplNmtMsBasicEthernet: + { + break; + } + + default: + { + TRACE0("EplApiCbNmtStateChange(): unhandled NMT state\n"); + } + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) + // forward event to Led module + Ret = EplLeduCbNmtStateChange(NmtStateChange_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // forward event to NmtMn module + Ret = EplNmtMnuCbNmtStateChange(NmtStateChange_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + + // call user callback + EventArg.m_NmtStateChange = NmtStateChange_p; + Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventNmtStateChange, + &EventArg, + EplApiInstance_g.m_InitParam.m_pEventUserArg); + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplApiUpdateDllConfig +// +// Description: update configuration of DLL +// +// Parameters: fUpdateIdentity_p = TRUE, if identity must be updated +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplApiUpdateDllConfig(BOOL fUpdateIdentity_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplDllConfigParam DllConfigParam; +tEplDllIdentParam DllIdentParam; +tEplObdSize ObdSize; +WORD wTemp; +BYTE bTemp; + + // configure Dll + EPL_MEMSET(&DllConfigParam, 0, sizeof (DllConfigParam)); + DllConfigParam.m_uiNodeId = EplObdGetNodeId(); + + // Cycle Length (0x1006: NMT_CycleLen_U32) in [us] + ObdSize = 4; + Ret = EplObdReadEntry(0x1006, 0, &DllConfigParam.m_dwCycleLen, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // 0x1F82: NMT_FeatureFlags_U32 + ObdSize = 4; + Ret = EplObdReadEntry(0x1F82, 0, &DllConfigParam.m_dwFeatureFlags, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // d.k. There is no dependance between FeatureFlags and async-only CN + DllConfigParam.m_fAsyncOnly = EplApiInstance_g.m_InitParam.m_fAsyncOnly; + + // 0x1C14: DLL_LossOfFrameTolerance_U32 in [ns] + ObdSize = 4; + Ret = EplObdReadEntry(0x1C14, 0, &DllConfigParam.m_dwLossOfFrameTolerance, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // 0x1F98: NMT_CycleTiming_REC + // 0x1F98.1: IsochrTxMaxPayload_U16 + ObdSize = 2; + Ret = EplObdReadEntry(0x1F98, 1, &wTemp, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + DllConfigParam.m_uiIsochrTxMaxPayload = wTemp; + + // 0x1F98.2: IsochrRxMaxPayload_U16 + ObdSize = 2; + Ret = EplObdReadEntry(0x1F98, 2, &wTemp, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + DllConfigParam.m_uiIsochrRxMaxPayload = wTemp; + + // 0x1F98.3: PResMaxLatency_U32 + ObdSize = 4; + Ret = EplObdReadEntry(0x1F98, 3, &DllConfigParam.m_dwPresMaxLatency, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // 0x1F98.4: PReqActPayloadLimit_U16 + ObdSize = 2; + Ret = EplObdReadEntry(0x1F98, 4, &wTemp, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + DllConfigParam.m_uiPreqActPayloadLimit = wTemp; + + // 0x1F98.5: PResActPayloadLimit_U16 + ObdSize = 2; + Ret = EplObdReadEntry(0x1F98, 5, &wTemp, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + DllConfigParam.m_uiPresActPayloadLimit = wTemp; + + // 0x1F98.6: ASndMaxLatency_U32 + ObdSize = 4; + Ret = EplObdReadEntry(0x1F98, 6, &DllConfigParam.m_dwAsndMaxLatency, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // 0x1F98.7: MultiplCycleCnt_U8 + ObdSize = 1; + Ret = EplObdReadEntry(0x1F98, 7, &bTemp, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + DllConfigParam.m_uiMultiplCycleCnt = bTemp; + + // 0x1F98.8: AsyncMTU_U16 + ObdSize = 2; + Ret = EplObdReadEntry(0x1F98, 8, &wTemp, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + DllConfigParam.m_uiAsyncMtu = wTemp; + + // $$$ Prescaler + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // 0x1F8A.1: WaitSoCPReq_U32 in [ns] + ObdSize = 4; + Ret = EplObdReadEntry(0x1F8A, 1, &DllConfigParam.m_dwWaitSocPreq, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // 0x1F8A.2: AsyncSlotTimeout_U32 in [ns] (optional) + ObdSize = 4; + Ret = EplObdReadEntry(0x1F8A, 2, &DllConfigParam.m_dwAsyncSlotTimeout, &ObdSize); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ +#endif + + DllConfigParam.m_uiSizeOfStruct = sizeof (DllConfigParam); + Ret = EplDllkConfig(&DllConfigParam); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + if (fUpdateIdentity_p != FALSE) + { + // configure Identity + EPL_MEMSET(&DllIdentParam, 0, sizeof (DllIdentParam)); + ObdSize = 4; + Ret = EplObdReadEntry(0x1000, 0, &DllIdentParam.m_dwDeviceType, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + ObdSize = 4; + Ret = EplObdReadEntry(0x1018, 1, &DllIdentParam.m_dwVendorId, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + ObdSize = 4; + Ret = EplObdReadEntry(0x1018, 2, &DllIdentParam.m_dwProductCode, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + ObdSize = 4; + Ret = EplObdReadEntry(0x1018, 3, &DllIdentParam.m_dwRevisionNumber, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + ObdSize = 4; + Ret = EplObdReadEntry(0x1018, 4, &DllIdentParam.m_dwSerialNumber, &ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + DllIdentParam.m_dwIpAddress = EplApiInstance_g.m_InitParam.m_dwIpAddress; + DllIdentParam.m_dwSubnetMask = EplApiInstance_g.m_InitParam.m_dwSubnetMask; + EPL_MEMCPY(DllIdentParam.m_sHostname, EplApiInstance_g.m_InitParam.m_sHostname, sizeof (DllIdentParam.m_sHostname)); + + ObdSize = 4; + Ret = EplObdReadEntry(0x1020, 1, &DllIdentParam.m_dwVerifyConfigurationDate, &ObdSize); + // ignore any error, because this object is optional + + ObdSize = 4; + Ret = EplObdReadEntry(0x1020, 2, &DllIdentParam.m_dwVerifyConfigurationTime, &ObdSize); + // ignore any error, because this object is optional + + // $$$ d.k.: fill rest of ident structure + + DllIdentParam.m_uiSizeOfStruct = sizeof (DllIdentParam); + Ret = EplDllkSetIdentity(&DllIdentParam); + if(Ret != kEplSuccessful) + { + goto Exit; + } + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplApiUpdateObd +// +// Description: update OD from init param +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplApiUpdateObd(void) +{ +tEplKernel Ret = kEplSuccessful; +WORD wTemp; +BYTE bTemp; + + // set node id in OD + Ret = EplObdSetNodeId(EplApiInstance_g.m_InitParam.m_uiNodeId, // node id + kEplObdNodeIdHardware); // set by hardware + if(Ret != kEplSuccessful) + { + goto Exit; + } + + if (EplApiInstance_g.m_InitParam.m_dwCycleLen != -1) + { + Ret = EplObdWriteEntry(0x1006, 0, &EplApiInstance_g.m_InitParam.m_dwCycleLen, 4); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_dwLossOfFrameTolerance != -1) + { + Ret = EplObdWriteEntry(0x1C14, 0, &EplApiInstance_g.m_InitParam.m_dwLossOfFrameTolerance, 4); + /* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + // d.k. There is no dependance between FeatureFlags and async-only CN. + if (EplApiInstance_g.m_InitParam.m_dwFeatureFlags != -1) + { + Ret = EplObdWriteEntry(0x1F82, 0, &EplApiInstance_g.m_InitParam.m_dwFeatureFlags, 4); + /* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiIsochrTxMaxPayload; + Ret = EplObdWriteEntry(0x1F98, 1, &wTemp, 2); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + + wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiIsochrRxMaxPayload; + Ret = EplObdWriteEntry(0x1F98, 2, &wTemp, 2); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + + Ret = EplObdWriteEntry(0x1F98, 3, &EplApiInstance_g.m_InitParam.m_dwPresMaxLatency, 4); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + + if (EplApiInstance_g.m_InitParam.m_uiPreqActPayloadLimit <= EPL_C_DLL_ISOCHR_MAX_PAYL) + { + wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiPreqActPayloadLimit; + Ret = EplObdWriteEntry(0x1F98, 4, &wTemp, 2); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_uiPresActPayloadLimit <= EPL_C_DLL_ISOCHR_MAX_PAYL) + { + wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiPresActPayloadLimit; + Ret = EplObdWriteEntry(0x1F98, 5, &wTemp, 2); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + Ret = EplObdWriteEntry(0x1F98, 6, &EplApiInstance_g.m_InitParam.m_dwAsndMaxLatency, 4); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + + if (EplApiInstance_g.m_InitParam.m_uiMultiplCycleCnt <= 0xFF) + { + bTemp = (BYTE) EplApiInstance_g.m_InitParam.m_uiMultiplCycleCnt; + Ret = EplObdWriteEntry(0x1F98, 7, &bTemp, 1); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_uiAsyncMtu <= EPL_C_DLL_MAX_ASYNC_MTU) + { + wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiAsyncMtu; + Ret = EplObdWriteEntry(0x1F98, 8, &wTemp, 2); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_uiPrescaler <= 1000) + { + wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiPrescaler; + Ret = EplObdWriteEntry(0x1F98, 9, &wTemp, 2); + // ignore return code + Ret = kEplSuccessful; + } + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + if (EplApiInstance_g.m_InitParam.m_dwWaitSocPreq != -1) + { + Ret = EplObdWriteEntry(0x1F8A, 1, &EplApiInstance_g.m_InitParam.m_dwWaitSocPreq, 4); + /* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if ((EplApiInstance_g.m_InitParam.m_dwAsyncSlotTimeout != 0) && (EplApiInstance_g.m_InitParam.m_dwAsyncSlotTimeout != -1)) + { + Ret = EplObdWriteEntry(0x1F8A, 2, &EplApiInstance_g.m_InitParam.m_dwAsyncSlotTimeout, 4); + /* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } +#endif + + // configure Identity + if (EplApiInstance_g.m_InitParam.m_dwDeviceType != -1) + { + Ret = EplObdWriteEntry(0x1000, 0, &EplApiInstance_g.m_InitParam.m_dwDeviceType, 4); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_dwVendorId != -1) + { + Ret = EplObdWriteEntry(0x1018, 1, &EplApiInstance_g.m_InitParam.m_dwVendorId, 4); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_dwProductCode != -1) + { + Ret = EplObdWriteEntry(0x1018, 2, &EplApiInstance_g.m_InitParam.m_dwProductCode, 4); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_dwRevisionNumber != -1) + { + Ret = EplObdWriteEntry(0x1018, 3, &EplApiInstance_g.m_InitParam.m_dwRevisionNumber, 4); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_dwSerialNumber != -1) + { + Ret = EplObdWriteEntry(0x1018, 4, &EplApiInstance_g.m_InitParam.m_dwSerialNumber, 4); +/* if(Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_pszDevName != NULL) + { + // write Device Name (0x1008) + Ret = EplObdWriteEntry ( + 0x1008, 0, (void GENERIC*) EplApiInstance_g.m_InitParam.m_pszDevName, (tEplObdSize) strlen(EplApiInstance_g.m_InitParam.m_pszDevName)); +/* if (Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_pszHwVersion != NULL) + { + // write Hardware version (0x1009) + Ret = EplObdWriteEntry ( + 0x1009, 0, (void GENERIC*) EplApiInstance_g.m_InitParam.m_pszHwVersion, (tEplObdSize) strlen(EplApiInstance_g.m_InitParam.m_pszHwVersion)); +/* if (Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + + if (EplApiInstance_g.m_InitParam.m_pszSwVersion != NULL) + { + // write Software version (0x100A) + Ret = EplObdWriteEntry ( + 0x100A, 0, (void GENERIC*) EplApiInstance_g.m_InitParam.m_pszSwVersion, (tEplObdSize) strlen(EplApiInstance_g.m_InitParam.m_pszSwVersion)); +/* if (Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplApiCbSdoCon +// +// Description: callback function for SDO transfers +// +// Parameters: pSdoComFinished_p = SDO parameter +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +static tEplKernel PUBLIC EplApiCbSdoCon(tEplSdoComFinished* pSdoComFinished_p) +{ +tEplKernel Ret; +tEplApiEventArg EventArg; + + Ret = kEplSuccessful; + + // call user callback + EventArg.m_Sdo = *pSdoComFinished_p; + Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventSdo, + &EventArg, + EplApiInstance_g.m_InitParam.m_pEventUserArg); + + return Ret; + +} +#endif + + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +//--------------------------------------------------------------------------- +// +// Function: EplApiCbNodeEvent +// +// Description: callback function for node events +// +// Parameters: uiNodeId_p = node ID of the CN +// NodeEvent_p = event from the specified CN +// NmtState_p = current NMT state of the CN +// wErrorCode_p = EPL error code if NodeEvent_p==kEplNmtNodeEventError +// fMandatory_p = flag if CN is mandatory +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplApiCbNodeEvent(unsigned int uiNodeId_p, + tEplNmtNodeEvent NodeEvent_p, + tEplNmtState NmtState_p, + WORD wErrorCode_p, + BOOL fMandatory_p) +{ +tEplKernel Ret; +tEplApiEventArg EventArg; + + Ret = kEplSuccessful; + + // call user callback + EventArg.m_Node.m_uiNodeId = uiNodeId_p; + EventArg.m_Node.m_NodeEvent = NodeEvent_p; + EventArg.m_Node.m_NmtState = NmtState_p; + EventArg.m_Node.m_wErrorCode = wErrorCode_p; + EventArg.m_Node.m_fMandatory = fMandatory_p; + + Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventNode, + &EventArg, + EplApiInstance_g.m_InitParam.m_pEventUserArg); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplApiCbBootEvent +// +// Description: callback function for boot events +// +// Parameters: BootEvent_p = event from the boot-up process +// NmtState_p = current local NMT state +// wErrorCode_p = EPL error code if BootEvent_p==kEplNmtBootEventError +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p, + tEplNmtState NmtState_p, + WORD wErrorCode_p) +{ +tEplKernel Ret; +tEplApiEventArg EventArg; + + Ret = kEplSuccessful; + + // call user callback + EventArg.m_Boot.m_BootEvent = BootEvent_p; + EventArg.m_Boot.m_NmtState = NmtState_p; + EventArg.m_Boot.m_wErrorCode = wErrorCode_p; + + Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventBoot, + &EventArg, + EplApiInstance_g.m_InitParam.m_pEventUserArg); + + return Ret; + +} + +#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) + +//--------------------------------------------------------------------------- +// +// Function: EplApiCbLedStateChange +// +// Description: callback function for LED change events. +// +// Parameters: LedType_p = type of LED +// fOn_p = state of LED +// +// Returns: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplApiCbLedStateChange(tEplLedType LedType_p, + BOOL fOn_p) +{ +tEplKernel Ret; +tEplApiEventArg EventArg; + + Ret = kEplSuccessful; + + // call user callback + EventArg.m_Led.m_LedType = LedType_p; + EventArg.m_Led.m_fOn = fOn_p; + + Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventLed, + &EventArg, + EplApiInstance_g.m_InitParam.m_pEventUserArg); + + return Ret; + +} + +#endif + + +// EOF + diff --git a/drivers/staging/epl/EplApiLinux.h b/drivers/staging/epl/EplApiLinux.h new file mode 100644 index 0000000..02714e7 --- /dev/null +++ b/drivers/staging/epl/EplApiLinux.h @@ -0,0 +1,153 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for EPL API layer for Linux (kernel and user space) + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplApiLinux.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/08/25 12:17:41 $ + + $State: Exp $ + + Build Environment: + KEIL uVision 2 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/10/11 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_API_LINUX_H_ +#define _EPL_API_LINUX_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#define EPLLIN_DEV_NAME "epl" // used for "/dev" and "/proc" entry + + +//--------------------------------------------------------------------------- +// Commands for <ioctl> +//--------------------------------------------------------------------------- + +#define EPLLIN_CMD_INITIALIZE 0 // ulArg_p ~ tEplApiInitParam* +#define EPLLIN_CMD_PI_IN 1 // ulArg_p ~ tEplApiProcessImage* +#define EPLLIN_CMD_PI_OUT 2 // ulArg_p ~ tEplApiProcessImage* +#define EPLLIN_CMD_WRITE_OBJECT 3 // ulArg_p ~ tEplLinSdoObject* +#define EPLLIN_CMD_READ_OBJECT 4 // ulArg_p ~ tEplLinSdoObject* +#define EPLLIN_CMD_WRITE_LOCAL_OBJECT 5 // ulArg_p ~ tEplLinLocalObject* +#define EPLLIN_CMD_READ_LOCAL_OBJECT 6 // ulArg_p ~ tEplLinLocalObject* +#define EPLLIN_CMD_FREE_SDO_CHANNEL 7 // ulArg_p ~ tEplSdoComConHdl +#define EPLLIN_CMD_NMT_COMMAND 8 // ulArg_p ~ tEplNmtEvent +#define EPLLIN_CMD_GET_EVENT 9 // ulArg_p ~ tEplLinEvent* +#define EPLLIN_CMD_MN_TRIGGER_STATE_CHANGE 10 // ulArg_p ~ tEplLinNodeCmdObject* +#define EPLLIN_CMD_PI_SETUP 11 // ulArg_p ~ 0 +#define EPLLIN_CMD_SHUTDOWN 12 // ulArg_p ~ 0 + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef struct +{ + unsigned int m_uiEventArgSize; + tEplApiEventArg* m_pEventArg; + tEplApiEventType* m_pEventType; + tEplKernel m_RetCbEvent; + +} tEplLinEvent; + +typedef struct +{ + tEplSdoComConHdl m_SdoComConHdl; + BOOL m_fValidSdoComConHdl; + unsigned int m_uiNodeId; + unsigned int m_uiIndex; + unsigned int m_uiSubindex; + void* m_le_pData; + unsigned int m_uiSize; + tEplSdoType m_SdoType; + void* m_pUserArg; + +} tEplLinSdoObject; + +typedef struct +{ + unsigned int m_uiIndex; + unsigned int m_uiSubindex; + void* m_pData; + unsigned int m_uiSize; + +} tEplLinLocalObject; + +typedef struct +{ + unsigned int m_uiNodeId; + tEplNmtNodeCommand m_NodeCommand; + +} tEplLinNodeCmdObject; + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + + +#endif // #ifndef _EPL_API_LINUX_H_ + + diff --git a/drivers/staging/epl/EplApiLinuxKernel.c b/drivers/staging/epl/EplApiLinuxKernel.c new file mode 100644 index 0000000..4941760 --- /dev/null +++ b/drivers/staging/epl/EplApiLinuxKernel.c @@ -0,0 +1,1317 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: Linux kernel module as wrapper of EPL API layer, + i.e. counterpart to a Linux application + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplApiLinuxKernel.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.9 $ $Date: 2008/11/21 09:00:38 $ + + $State: Exp $ + + Build Environment: + GNU-Compiler for m68k + + ------------------------------------------------------------------------- + + Revision History: + + 2006/10/11 d.k.: Initial Version + 2008/04/10 m.u.: Changed to new char driver init + +****************************************************************************/ + + +// kernel modul and driver + +//#include <linux/version.h> +//#include <linux/config.h> + +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/cdev.h> +#include <linux/types.h> + +//#include <linux/module.h> +//#include <linux/kernel.h> +//#include <linux/init.h> +//#include <linux/errno.h> + +// scheduling +#include <linux/sched.h> + +// memory access +#include <asm/uaccess.h> +#include <linux/vmalloc.h> + +#ifdef CONFIG_DEVFS_FS +#include <linux/major.h> +#include <linux/devfs_fs_kernel.h> +#endif + +#include "Epl.h" +#include "EplApiLinux.h" +//#include "kernel/EplPdokCal.h" +#include "proc_fs.h" + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + // remove ("make invisible") obsolete symbols for kernel versions 2.6 + // and higher + #define MOD_INC_USE_COUNT + #define MOD_DEC_USE_COUNT + #define EXPORT_NO_SYMBOLS +#else + #error "This driver needs a 2.6.x kernel or higher" +#endif + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +// Metainformation +MODULE_LICENSE("Dual BSD/GPL"); +#ifdef MODULE_AUTHOR + MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com"); + MODULE_DESCRIPTION("EPL API driver"); +#endif + + +//--------------------------------------------------------------------------- +// Configuration +//--------------------------------------------------------------------------- + + +#define EPLLIN_DRV_NAME "systec_epl" // used for <register_chrdev> + + + +//--------------------------------------------------------------------------- +// Constant definitions +//--------------------------------------------------------------------------- + +// TracePoint support for realtime-debugging +#ifdef _DBG_TRACE_POINTS_ + void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); + #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) +#else + #define TGT_DBG_SIGNAL_TRACE_POINT(p) +#endif + +#define EVENT_STATE_INIT 0 +#define EVENT_STATE_IOCTL 1 // ioctl entered and ready to receive EPL event +#define EVENT_STATE_READY 2 // EPL event can be forwarded to user application +#define EVENT_STATE_TERM 3 // terminate processing + +#define EPL_STATE_NOTOPEN 0 +#define EPL_STATE_NOTINIT 1 +#define EPL_STATE_RUNNING 2 +#define EPL_STATE_SHUTDOWN 3 + + +//--------------------------------------------------------------------------- +// Global variables +//--------------------------------------------------------------------------- + +#ifdef CONFIG_DEVFS_FS + + // driver major number + static int nDrvMajorNumber_g; + +#else + + // device number (major and minor) + static dev_t nDevNum_g; + static struct cdev *pEpl_cdev_g; + +#endif + + +static volatile unsigned int uiEplState_g = EPL_STATE_NOTOPEN; + +static struct semaphore SemaphoreCbEvent_g; // semaphore for EplLinCbEvent +static wait_queue_head_t WaitQueueCbEvent_g; // wait queue EplLinCbEvent +static wait_queue_head_t WaitQueueProcess_g; // wait queue for EplApiProcess (user process) +static wait_queue_head_t WaitQueueRelease_g; // wait queue for EplLinRelease +static atomic_t AtomicEventState_g = ATOMIC_INIT(EVENT_STATE_INIT); +static tEplApiEventType EventType_g; // event type (enum) +static tEplApiEventArg* pEventArg_g; // event argument (union) +static tEplKernel RetCbEvent_g; // return code from event callback function +static wait_queue_head_t WaitQueueCbSync_g; // wait queue EplLinCbSync +static wait_queue_head_t WaitQueuePI_In_g; // wait queue for EplApiProcessImageExchangeIn (user process) +static atomic_t AtomicSyncState_g = ATOMIC_INIT(EVENT_STATE_INIT); + + +//--------------------------------------------------------------------------- +// Local types +//--------------------------------------------------------------------------- + +typedef struct +{ + void* m_pUserArg; + void* m_pData; + +} tEplLinSdoBufHeader; + + +//--------------------------------------------------------------------------- +// Local variables +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Prototypes of internal functions +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplLinCbEvent( + tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg* pEventArg_p, // IN: event argument (union) + void GENERIC* pUserArg_p); + +tEplKernel PUBLIC EplLinCbSync(void); + +static int __init EplLinInit (void); +static void __exit EplLinExit (void); + + +static int EplLinOpen (struct inode* pDeviceFile_p, struct file* pInstance_p); +static int EplLinRelease (struct inode* pDeviceFile_p, struct file* pInstance_p); +static ssize_t EplLinRead (struct file* pInstance_p, char* pDstBuff_p, size_t BuffSize_p, loff_t* pFileOffs_p); +static ssize_t EplLinWrite (struct file* pInstance_p, const char* pSrcBuff_p, size_t BuffSize_p, loff_t* pFileOffs_p); +static int EplLinIoctl (struct inode* pDeviceFile_p, struct file* pInstance_p, unsigned int uiIoctlCmd_p, unsigned long ulArg_p); + + + + +//--------------------------------------------------------------------------- +// Kernel Module specific Data Structures +//--------------------------------------------------------------------------- + +EXPORT_NO_SYMBOLS; + + + +module_init(EplLinInit); +module_exit(EplLinExit); + + + + +static struct file_operations EplLinFileOps_g = +{ + .owner = THIS_MODULE, + .open = EplLinOpen, + .release = EplLinRelease, + .read = EplLinRead, + .write = EplLinWrite, + .ioctl = EplLinIoctl, + +}; + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// Initailize Driver +//--------------------------------------------------------------------------- +// -> insmod driver +//--------------------------------------------------------------------------- + +static int __init EplLinInit (void) +{ + +tEplKernel EplRet; +int iErr; +int iRet; +#ifdef CONFIG_DEVFS_FS +int nMinorNumber; +#endif + + TRACE0("EPL: + EplLinInit...\n"); + TRACE2("EPL: Driver build: %s / %s\n", __DATE__, __TIME__); + + iRet = 0; + + // initialize global variables + atomic_set(&AtomicEventState_g, EVENT_STATE_INIT); + sema_init(&SemaphoreCbEvent_g, 1); + init_waitqueue_head(&WaitQueueCbEvent_g); + init_waitqueue_head(&WaitQueueProcess_g); + init_waitqueue_head(&WaitQueueRelease_g); + + + +#ifdef CONFIG_DEVFS_FS + + // register character device handler + TRACE2("EPL: Installing Driver '%s', Version %s...\n", EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION); + TRACE0("EPL: (using dynamic major number assignment)\n"); + nDrvMajorNumber_g = register_chrdev (0, EPLLIN_DRV_NAME, &EplLinFileOps_g); + if (nDrvMajorNumber_g != 0) + { + TRACE2("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n", EPLLIN_DRV_NAME, nDrvMajorNumber_g); + } + else + { + TRACE1("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n", EPLLIN_DRV_NAME); + iRet = -EIO; + goto Exit; + } + + + // create device node in DEVFS + nMinorNumber = 0; + TRACE1("EPL: Creating device node '/dev/%s'...\n", EPLLIN_DEV_NAME); + iErr = devfs_mk_cdev (MKDEV(nDrvMajorNumber_g, nMinorNumber), S_IFCHR | S_IRUGO | S_IWUGO, EPLLIN_DEV_NAME); + if (iErr == 0) + { + TRACE1("EPL: Device node '/dev/%s' created successful.\n", EPLLIN_DEV_NAME); + } + else + { + TRACE1("EPL: ERROR: unable to create device node '/dev/%s'\n", EPLLIN_DEV_NAME); + iRet = -EIO; + goto Exit; + } + +#else + + // register character device handler + // only one Minor required + TRACE2("EPL: Installing Driver '%s', Version %s...\n", EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION); + iRet = alloc_chrdev_region (&nDevNum_g, 0, 1, EPLLIN_DRV_NAME); + if (iRet == 0) + { + TRACE2("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n", EPLLIN_DRV_NAME, MAJOR(nDevNum_g)); + } + else + { + TRACE1("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n", EPLLIN_DRV_NAME); + iRet = -EIO; + goto Exit; + } + + // register cdev structure + pEpl_cdev_g = cdev_alloc(); + pEpl_cdev_g->ops = &EplLinFileOps_g; + pEpl_cdev_g->owner = THIS_MODULE; + iErr = cdev_add (pEpl_cdev_g, nDevNum_g, 1); + if (iErr) + { + TRACE2("EPL: ERROR %d: Driver '%s' could not be added!\n", iErr, EPLLIN_DRV_NAME); + iRet = -EIO; + goto Exit; + } + +#endif + + // create device node in PROCFS + EplRet = EplLinProcInit(); + if (EplRet != kEplSuccessful) + { + goto Exit; + } + + +Exit: + + TRACE1("EPL: - EplLinInit (iRet=%d)\n", iRet); + return (iRet); + +} + + + +//--------------------------------------------------------------------------- +// Remove Driver +//--------------------------------------------------------------------------- +// -> rmmod driver +//--------------------------------------------------------------------------- + +static void __exit EplLinExit (void) +{ + +tEplKernel EplRet; + + // delete instance for all modules +// EplRet = EplApiShutdown(); +// printk("EplApiShutdown(): 0x%X\n", EplRet); + + // deinitialize proc fs + EplRet = EplLinProcFree(); + printk("EplLinProcFree(): 0x%X\n", EplRet); + + + TRACE0("EPL: + EplLinExit...\n"); + + +#ifdef CONFIG_DEVFS_FS + + // remove device node from DEVFS + devfs_remove (EPLLIN_DEV_NAME); + TRACE1("EPL: Device node '/dev/%s' removed.\n", EPLLIN_DEV_NAME); + + // unregister character device handler + unregister_chrdev (nDrvMajorNumber_g, EPLLIN_DRV_NAME); + +#else + + // remove cdev structure + cdev_del(pEpl_cdev_g); + + // unregister character device handler + unregister_chrdev_region (nDevNum_g, 1); + +#endif + + TRACE1("EPL: Driver '%s' removed.\n", EPLLIN_DRV_NAME); + + + TRACE0("EPL: - EplLinExit\n"); + +} + + + +//--------------------------------------------------------------------------- +// Open Driver +//--------------------------------------------------------------------------- +// -> open("/dev/driver", O_RDWR)... +//--------------------------------------------------------------------------- + +static int EplLinOpen ( + struct inode* pDeviceFile_p, // information about the device to open + struct file* pInstance_p) // information about driver instance +{ + +int iRet; + + + TRACE0("EPL: + EplLinOpen...\n"); + + MOD_INC_USE_COUNT; + + if (uiEplState_g != EPL_STATE_NOTOPEN) + { // stack already initialized + iRet = -EALREADY; + } + else + { + atomic_set(&AtomicEventState_g, EVENT_STATE_INIT); + sema_init(&SemaphoreCbEvent_g, 1); + init_waitqueue_head(&WaitQueueCbEvent_g); + init_waitqueue_head(&WaitQueueProcess_g); + init_waitqueue_head(&WaitQueueRelease_g); + atomic_set(&AtomicSyncState_g, EVENT_STATE_INIT); + init_waitqueue_head(&WaitQueueCbSync_g); + init_waitqueue_head(&WaitQueuePI_In_g); + + uiEplState_g = EPL_STATE_NOTINIT; + iRet = 0; + } + + TRACE1("EPL: - EplLinOpen (iRet=%d)\n", iRet); + return (iRet); + +} + + + +//--------------------------------------------------------------------------- +// Close Driver +//--------------------------------------------------------------------------- +// -> close(device)... +//--------------------------------------------------------------------------- + +static int EplLinRelease ( + struct inode* pDeviceFile_p, // information about the device to open + struct file* pInstance_p) // information about driver instance +{ + +tEplKernel EplRet = kEplSuccessful; +int iRet; + + + TRACE0("EPL: + EplLinRelease...\n"); + + if (uiEplState_g != EPL_STATE_NOTINIT) + { + // pass control to sync kernel thread, but signal termination + atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM); + wake_up_interruptible(&WaitQueueCbSync_g); + wake_up_interruptible(&WaitQueuePI_In_g); + + // pass control to event queue kernel thread + atomic_set(&AtomicEventState_g, EVENT_STATE_TERM); + wake_up_interruptible(&WaitQueueCbEvent_g); + + if (uiEplState_g == EPL_STATE_RUNNING) + { // post NmtEventSwitchOff + EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff); + + } + + if (EplRet == kEplSuccessful) + { + TRACE0("EPL: waiting for NMT_GS_OFF\n"); + wait_event_interruptible(WaitQueueRelease_g, + (uiEplState_g == EPL_STATE_SHUTDOWN)); + } + else + { // post NmtEventSwitchOff failed + TRACE0("EPL: event post failed\n"); + } + + // $$$ d.k.: What if waiting was interrupted by signal? + + TRACE0("EPL: call EplApiShutdown()\n"); + // EPL stack can be safely shut down + // delete instance for all EPL modules + EplRet = EplApiShutdown(); + printk("EplApiShutdown(): 0x%X\n", EplRet); + } + + uiEplState_g = EPL_STATE_NOTOPEN; + iRet = 0; + + + MOD_DEC_USE_COUNT; + + + TRACE1("EPL: - EplLinRelease (iRet=%d)\n", iRet); + return (iRet); + +} + + + +//--------------------------------------------------------------------------- +// Read Data from Driver +//--------------------------------------------------------------------------- +// -> read(...) +//--------------------------------------------------------------------------- + +static ssize_t EplLinRead ( + struct file* pInstance_p, // information about driver instance + char* pDstBuff_p, // address of buffer to fill with data + size_t BuffSize_p, // length of the buffer + loff_t* pFileOffs_p) // offset in the file +{ + +int iRet; + + + TRACE0("EPL: + EplLinRead...\n"); + + + TRACE0("EPL: Sorry, this operation isn't supported.\n"); + iRet = -EINVAL; + + + TRACE1("EPL: - EplLinRead (iRet=%d)\n", iRet); + return (iRet); + +} + + + +//--------------------------------------------------------------------------- +// Write Data to Driver +//--------------------------------------------------------------------------- +// -> write(...) +//--------------------------------------------------------------------------- + +static ssize_t EplLinWrite ( + struct file* pInstance_p, // information about driver instance + const char* pSrcBuff_p, // address of buffer to get data from + size_t BuffSize_p, // length of the buffer + loff_t* pFileOffs_p) // offset in the file +{ + +int iRet; + + + TRACE0("EPL: + EplLinWrite...\n"); + + + TRACE0("EPL: Sorry, this operation isn't supported.\n"); + iRet = -EINVAL; + + + TRACE1("EPL: - EplLinWrite (iRet=%d)\n", iRet); + return (iRet); + +} + + + +//--------------------------------------------------------------------------- +// Generic Access to Driver +//--------------------------------------------------------------------------- +// -> ioctl(...) +//--------------------------------------------------------------------------- + +static int EplLinIoctl ( + struct inode* pDeviceFile_p, // information about the device to open + struct file* pInstance_p, // information about driver instance + unsigned int uiIoctlCmd_p, // Ioctl command to execute + unsigned long ulArg_p) // Ioctl command specific argument/parameter +{ + +tEplKernel EplRet; +int iErr; +int iRet; + + +// TRACE1("EPL: + EplLinIoctl (uiIoctlCmd_p=%d)...\n", uiIoctlCmd_p); + + + iRet = -EINVAL; + + switch (uiIoctlCmd_p) + { + // ---------------------------------------------------------- + case EPLLIN_CMD_INITIALIZE: + { + tEplApiInitParam EplApiInitParam; + + iErr = copy_from_user(&EplApiInitParam, (const void*)ulArg_p, sizeof (EplApiInitParam)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + EplApiInitParam.m_pfnCbEvent = EplLinCbEvent; + EplApiInitParam.m_pfnCbSync = EplLinCbSync; + + EplRet = EplApiInitialize(&EplApiInitParam); + + uiEplState_g = EPL_STATE_RUNNING; + + iRet = (int) EplRet; + break; + } + + + // ---------------------------------------------------------- + case EPLLIN_CMD_SHUTDOWN: + { // shutdown the threads + + // pass control to sync kernel thread, but signal termination + atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM); + wake_up_interruptible(&WaitQueueCbSync_g); + wake_up_interruptible(&WaitQueuePI_In_g); + + // pass control to event queue kernel thread + atomic_set(&AtomicEventState_g, EVENT_STATE_TERM); + wake_up_interruptible(&WaitQueueCbEvent_g); + + if (uiEplState_g == EPL_STATE_RUNNING) + { // post NmtEventSwitchOff + EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff); + + } + + iRet = 0; + break; + } + + + // ---------------------------------------------------------- + case EPLLIN_CMD_READ_LOCAL_OBJECT: + { + tEplLinLocalObject LocalObject; + void* pData; + + iErr = copy_from_user(&LocalObject, (const void*)ulArg_p, sizeof (LocalObject)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + if ((LocalObject.m_pData == NULL) || (LocalObject.m_uiSize == 0)) + { + iRet = (int) kEplApiInvalidParam; + goto Exit; + } + + pData = vmalloc(LocalObject.m_uiSize); + if (pData == NULL) + { // no memory available + iRet = -ENOMEM; + goto Exit; + } + + EplRet = EplApiReadLocalObject(LocalObject.m_uiIndex, LocalObject.m_uiSubindex, pData, &LocalObject.m_uiSize); + + if (EplRet == kEplSuccessful) + { + iErr = copy_to_user(LocalObject.m_pData, pData, LocalObject.m_uiSize); + + vfree(pData); + + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + // return actual size (LocalObject.m_uiSize) + iErr = put_user(LocalObject.m_uiSize, + (unsigned int*)(ulArg_p + (unsigned long)&LocalObject.m_uiSize - (unsigned long)&LocalObject)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + } + else + { + vfree(pData); + } + + iRet = (int) EplRet; + break; + } + + + // ---------------------------------------------------------- + case EPLLIN_CMD_WRITE_LOCAL_OBJECT: + { + tEplLinLocalObject LocalObject; + void* pData; + + iErr = copy_from_user(&LocalObject, (const void*)ulArg_p, sizeof (LocalObject)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + if ((LocalObject.m_pData == NULL) || (LocalObject.m_uiSize == 0)) + { + iRet = (int) kEplApiInvalidParam; + goto Exit; + } + + pData = vmalloc(LocalObject.m_uiSize); + if (pData == NULL) + { // no memory available + iRet = -ENOMEM; + goto Exit; + } + iErr = copy_from_user(pData, LocalObject.m_pData, LocalObject.m_uiSize); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + EplRet = EplApiWriteLocalObject(LocalObject.m_uiIndex, LocalObject.m_uiSubindex, pData, LocalObject.m_uiSize); + + vfree(pData); + + iRet = (int) EplRet; + break; + } + + + case EPLLIN_CMD_READ_OBJECT: + { + tEplLinSdoObject SdoObject; + void* pData; + tEplLinSdoBufHeader* pBufHeader; + tEplSdoComConHdl* pSdoComConHdl; + + iErr = copy_from_user(&SdoObject, (const void*)ulArg_p, sizeof (SdoObject)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + if ((SdoObject.m_le_pData == NULL) || (SdoObject.m_uiSize == 0)) + { + iRet = (int) kEplApiInvalidParam; + goto Exit; + } + + pBufHeader = (tEplLinSdoBufHeader*) vmalloc(sizeof (tEplLinSdoBufHeader) + SdoObject.m_uiSize); + if (pBufHeader == NULL) + { // no memory available + iRet = -ENOMEM; + goto Exit; + } + + // initiate temporary buffer + pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer + pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app + pData = pBufHeader + sizeof (tEplLinSdoBufHeader); + + if (SdoObject.m_fValidSdoComConHdl != FALSE) + { + pSdoComConHdl = &SdoObject.m_SdoComConHdl; + } + else + { + pSdoComConHdl = NULL; + } + + EplRet = EplApiReadObject(pSdoComConHdl, SdoObject.m_uiNodeId, SdoObject.m_uiIndex, + SdoObject.m_uiSubindex, pData, &SdoObject.m_uiSize, + SdoObject.m_SdoType, pBufHeader); + + // return actual SDO handle (SdoObject.m_SdoComConHdl) + iErr = put_user(SdoObject.m_SdoComConHdl, + (unsigned int*)(ulArg_p + (unsigned long)&SdoObject.m_SdoComConHdl - (unsigned long)&SdoObject)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + if (EplRet == kEplSuccessful) + { + iErr = copy_to_user(SdoObject.m_le_pData, pData, SdoObject.m_uiSize); + + vfree(pBufHeader); + + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + // return actual size (SdoObject.m_uiSize) + iErr = put_user(SdoObject.m_uiSize, + (unsigned int*)(ulArg_p + (unsigned long)&SdoObject.m_uiSize - (unsigned long)&SdoObject)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + } + else if (EplRet != kEplApiTaskDeferred) + { // error ocurred + vfree(pBufHeader); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + } + + iRet = (int) EplRet; + break; + } + + + case EPLLIN_CMD_WRITE_OBJECT: + { + tEplLinSdoObject SdoObject; + void* pData; + tEplLinSdoBufHeader* pBufHeader; + tEplSdoComConHdl* pSdoComConHdl; + + iErr = copy_from_user(&SdoObject, (const void*)ulArg_p, sizeof (SdoObject)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + if ((SdoObject.m_le_pData == NULL) || (SdoObject.m_uiSize == 0)) + { + iRet = (int) kEplApiInvalidParam; + goto Exit; + } + + pBufHeader = (tEplLinSdoBufHeader*) vmalloc(sizeof (tEplLinSdoBufHeader) + SdoObject.m_uiSize); + if (pBufHeader == NULL) + { // no memory available + iRet = -ENOMEM; + goto Exit; + } + + // initiate temporary buffer + pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer + pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app + pData = pBufHeader + sizeof (tEplLinSdoBufHeader); + + iErr = copy_from_user(pData, SdoObject.m_le_pData, SdoObject.m_uiSize); + + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + if (SdoObject.m_fValidSdoComConHdl != FALSE) + { + pSdoComConHdl = &SdoObject.m_SdoComConHdl; + } + else + { + pSdoComConHdl = NULL; + } + + EplRet = EplApiWriteObject(pSdoComConHdl, SdoObject.m_uiNodeId, SdoObject.m_uiIndex, + SdoObject.m_uiSubindex, pData, SdoObject.m_uiSize, + SdoObject.m_SdoType, pBufHeader); + + // return actual SDO handle (SdoObject.m_SdoComConHdl) + iErr = put_user(SdoObject.m_SdoComConHdl, + (unsigned int*)(ulArg_p + (unsigned long)&SdoObject.m_SdoComConHdl - (unsigned long)&SdoObject)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + if (EplRet != kEplApiTaskDeferred) + { // succeeded or error ocurred, but task not deferred + vfree(pBufHeader); + } + + iRet = (int) EplRet; + break; + } + + + // ---------------------------------------------------------- + case EPLLIN_CMD_FREE_SDO_CHANNEL: + { + // forward SDO handle to EPL stack + EplRet = EplApiFreeSdoChannel((tEplSdoComConHdl)ulArg_p); + + iRet = (int) EplRet; + break; + } + + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // ---------------------------------------------------------- + case EPLLIN_CMD_MN_TRIGGER_STATE_CHANGE: + { + tEplLinNodeCmdObject NodeCmdObject; + + iErr = copy_from_user(&NodeCmdObject, (const void*)ulArg_p, sizeof (NodeCmdObject)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + EplRet = EplApiMnTriggerStateChange(NodeCmdObject.m_uiNodeId, + NodeCmdObject.m_NodeCommand); + iRet = (int) EplRet; + break; + } +#endif + + + // ---------------------------------------------------------- + case EPLLIN_CMD_GET_EVENT: + { + tEplLinEvent Event; + + // save event structure + iErr = copy_from_user(&Event, (const void*)ulArg_p, sizeof (Event)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + // save return code from application's event callback function + RetCbEvent_g = Event.m_RetCbEvent; + + if (RetCbEvent_g == kEplShutdown) + { + // pass control to event queue kernel thread, but signal termination + atomic_set(&AtomicEventState_g, EVENT_STATE_TERM); + wake_up_interruptible(&WaitQueueCbEvent_g); + // exit with error -> EplApiProcess() will leave the infinite loop + iRet = 1; + goto Exit; + } + + // pass control to event queue kernel thread + atomic_set(&AtomicEventState_g, EVENT_STATE_IOCTL); + wake_up_interruptible(&WaitQueueCbEvent_g); + + // fall asleep itself in own wait queue + iErr = wait_event_interruptible(WaitQueueProcess_g, + (atomic_read(&AtomicEventState_g) == EVENT_STATE_READY) + || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)); + if (iErr != 0) + { // waiting was interrupted by signal + // pass control to event queue kernel thread, but signal termination + atomic_set(&AtomicEventState_g, EVENT_STATE_TERM); + wake_up_interruptible(&WaitQueueCbEvent_g); + // exit with this error -> EplApiProcess() will leave the infinite loop + iRet = iErr; + goto Exit; + } + else if (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM) + { // termination in progress + // pass control to event queue kernel thread, but signal termination + wake_up_interruptible(&WaitQueueCbEvent_g); + // exit with this error -> EplApiProcess() will leave the infinite loop + iRet = 1; + goto Exit; + } + + // copy event to user space + iErr = copy_to_user(Event.m_pEventType, &EventType_g, sizeof (EventType_g)); + if (iErr != 0) + { // not all data could be copied + iRet = -EIO; + goto Exit; + } + + // $$$ d.k. perform SDO event processing + if (EventType_g == kEplApiEventSdo) + { + void* pData; + tEplLinSdoBufHeader* pBufHeader; + + pBufHeader = (tEplLinSdoBufHeader*) pEventArg_g->m_Sdo.m_pUserArg; + pData = pBufHeader + sizeof (tEplLinSdoBufHeader); + + if (pEventArg_g->m_Sdo.m_SdoAccessType == kEplSdoAccessTypeRead) + { + // copy read data to user space + iErr = copy_to_user(pBufHeader->m_pData, pData, pEventArg_g->m_Sdo.m_uiTransferredByte); + if (iErr != 0) + { // not all data could be copied + iRet = -EIO; + goto Exit; + } + } + pEventArg_g->m_Sdo.m_pUserArg = pBufHeader->m_pUserArg; + vfree(pBufHeader); + } + + iErr = copy_to_user(Event.m_pEventArg, pEventArg_g, min(sizeof (tEplApiEventArg), Event.m_uiEventArgSize)); + if (iErr != 0) + { // not all data could be copied + iRet = -EIO; + goto Exit; + } + + // return to EplApiProcess(), which will call the application's event callback function + iRet = 0; + + break; + } + + + // ---------------------------------------------------------- + case EPLLIN_CMD_PI_SETUP: + { + EplRet = EplApiProcessImageSetup(); + iRet = (int) EplRet; + + break; + } + + + // ---------------------------------------------------------- + case EPLLIN_CMD_PI_IN: + { + tEplApiProcessImage ProcessImageIn; + + // save process image structure + iErr = copy_from_user(&ProcessImageIn, (const void*)ulArg_p, sizeof (ProcessImageIn)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + // pass control to event queue kernel thread + atomic_set(&AtomicSyncState_g, EVENT_STATE_IOCTL); + + // fall asleep itself in own wait queue + iErr = wait_event_interruptible(WaitQueuePI_In_g, + (atomic_read(&AtomicSyncState_g) == EVENT_STATE_READY) + || (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM)); + if (iErr != 0) + { // waiting was interrupted by signal + // pass control to sync kernel thread, but signal termination + atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM); + wake_up_interruptible(&WaitQueueCbSync_g); + // exit with this error -> application will leave the infinite loop + iRet = iErr; + goto Exit; + } + else if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM) + { // termination in progress + // pass control to sync kernel thread, but signal termination + wake_up_interruptible(&WaitQueueCbSync_g); + // exit with this error -> application will leave the infinite loop + iRet = 1; + goto Exit; + } + + // exchange process image + EplRet = EplApiProcessImageExchangeIn(&ProcessImageIn); + + // return to EplApiProcessImageExchangeIn() + iRet = (int) EplRet; + + break; + } + + + // ---------------------------------------------------------- + case EPLLIN_CMD_PI_OUT: + { + tEplApiProcessImage ProcessImageOut; + + // save process image structure + iErr = copy_from_user(&ProcessImageOut, (const void*)ulArg_p, sizeof (ProcessImageOut)); + if (iErr != 0) + { + iRet = -EIO; + goto Exit; + } + + if (atomic_read(&AtomicSyncState_g) != EVENT_STATE_READY) + { + iRet = (int) kEplInvalidOperation; + goto Exit; + } + + // exchange process image + EplRet = EplApiProcessImageExchangeOut(&ProcessImageOut); + + // pass control to sync kernel thread + atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM); + wake_up_interruptible(&WaitQueueCbSync_g); + + // return to EplApiProcessImageExchangeout() + iRet = (int) EplRet; + + break; + } + + + // ---------------------------------------------------------- + case EPLLIN_CMD_NMT_COMMAND: + { + // forward NMT command to EPL stack + EplRet = EplApiExecNmtCommand((tEplNmtEvent)ulArg_p); + + iRet = (int) EplRet; + + break; + } + + + + // ---------------------------------------------------------- + default: + { + break; + } + } + + +Exit: + +// TRACE1("EPL: - EplLinIoctl (iRet=%d)\n", iRet); + return (iRet); + +} + + + + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + + +tEplKernel PUBLIC EplLinCbEvent( + tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg* pEventArg_p, // IN: event argument (union) + void GENERIC* pUserArg_p) +{ +tEplKernel EplRet = kEplSuccessful; +int iErr; + + // block any further call to this function, i.e. enter critical section + iErr = down_interruptible(&SemaphoreCbEvent_g); + if (iErr != 0) + { // waiting was interrupted by signal + EplRet = kEplShutdown; + goto Exit; + } + + // wait for EplApiProcess() to call ioctl + // normally it should be waiting already for us to pass a new event + iErr = wait_event_interruptible(WaitQueueCbEvent_g, + (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL) + || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)); + if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)) + { // waiting was interrupted by signal + EplRet = kEplShutdown; + goto LeaveCriticalSection; + } + + // save event information for ioctl + EventType_g = EventType_p; + pEventArg_g = pEventArg_p; + + // pass control to application's event callback function, i.e. EplApiProcess() + atomic_set(&AtomicEventState_g, EVENT_STATE_READY); + wake_up_interruptible(&WaitQueueProcess_g); + + // now, the application's event callback function processes the event + + // wait for completion of application's event callback function, i.e. EplApiProcess() calls ioctl again + iErr = wait_event_interruptible(WaitQueueCbEvent_g, + (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL) + || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)); + if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)) + { // waiting was interrupted by signal + EplRet = kEplShutdown; + goto LeaveCriticalSection; + } + + // read return code from application's event callback function + EplRet = RetCbEvent_g; + + +LeaveCriticalSection: + up(&SemaphoreCbEvent_g); + +Exit: + // check if NMT_GS_OFF is reached + if (EventType_p == kEplApiEventNmtStateChange) + { + if (pEventArg_p->m_NmtStateChange.m_NewNmtState == kEplNmtGsOff) + { // NMT state machine was shut down + TRACE0("EPL: EplLinCbEvent(NMT_GS_OFF)\n"); + uiEplState_g = EPL_STATE_SHUTDOWN; + atomic_set(&AtomicEventState_g, EVENT_STATE_TERM); + wake_up(&WaitQueueRelease_g); + } + else + { // NMT state machine is running + uiEplState_g = EPL_STATE_RUNNING; + } + } + + + return EplRet; +} + + +tEplKernel PUBLIC EplLinCbSync(void) +{ +tEplKernel EplRet = kEplSuccessful; +int iErr; + + // check if user process waits for sync + if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL) + { + // pass control to application, i.e. EplApiProcessImageExchangeIn() + atomic_set(&AtomicSyncState_g, EVENT_STATE_READY); + wake_up_interruptible(&WaitQueuePI_In_g); + + // now, the application processes the sync event + + // wait for call of EplApiProcessImageExchangeOut() + iErr = wait_event_interruptible(WaitQueueCbSync_g, + (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL) + || (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM)); + if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL)) + { // waiting was interrupted by signal or application called wrong function + EplRet = kEplShutdown; + } + } + else + { // application is currently not waiting for sync + // continue without interruption + // TPDO are set valid by caller (i.e. EplEventkProcess()) + } + + TGT_DBG_SIGNAL_TRACE_POINT(1); + + return EplRet; +} + + + +// EOF + diff --git a/drivers/staging/epl/EplApiProcessImage.c b/drivers/staging/epl/EplApiProcessImage.c new file mode 100644 index 0000000..b433369 --- /dev/null +++ b/drivers/staging/epl/EplApiProcessImage.c @@ -0,0 +1,374 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for EPL API module (process image) + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplApiProcessImage.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.7 $ $Date: 2008/11/13 17:13:09 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/10/10 d.k.: start of the implementation, version 1.00 + +****************************************************************************/ + +#include "Epl.h" +//#include "kernel/EplPdokCal.h" + +#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) +#include <asm/uaccess.h> +#endif + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S EplApi */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +#if ((EPL_API_PROCESS_IMAGE_SIZE_IN > 0) || (EPL_API_PROCESS_IMAGE_SIZE_OUT > 0)) + typedef struct + { + #if EPL_API_PROCESS_IMAGE_SIZE_IN > 0 + BYTE m_abProcessImageInput[EPL_API_PROCESS_IMAGE_SIZE_IN]; + #endif + #if EPL_API_PROCESS_IMAGE_SIZE_OUT > 0 + BYTE m_abProcessImageOutput[EPL_API_PROCESS_IMAGE_SIZE_OUT]; + #endif + + } tEplApiProcessImageInstance; + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +static tEplApiProcessImageInstance EplApiProcessImageInstance_g; +#endif + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + + +//--------------------------------------------------------------------------- +// +// Function: EplApiProcessImageSetup() +// +// Description: sets up static process image +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiProcessImageSetup(void) +{ +tEplKernel Ret = kEplSuccessful; +#if ((EPL_API_PROCESS_IMAGE_SIZE_IN > 0) || (EPL_API_PROCESS_IMAGE_SIZE_OUT > 0)) +unsigned int uiVarEntries; +tEplObdSize ObdSize; +#endif + +#if EPL_API_PROCESS_IMAGE_SIZE_IN > 0 + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN; + ObdSize = 1; + Ret = EplApiLinkObject( + 0x2000, + EplApiProcessImageInstance_g.m_abProcessImageInput, + &uiVarEntries, + &ObdSize, + 1); + + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN; + ObdSize = 1; + Ret = EplApiLinkObject( + 0x2001, + EplApiProcessImageInstance_g.m_abProcessImageInput, + &uiVarEntries, + &ObdSize, + 1); + + ObdSize = 2; + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN / ObdSize; + Ret = EplApiLinkObject( + 0x2010, + EplApiProcessImageInstance_g.m_abProcessImageInput, + &uiVarEntries, + &ObdSize, + 1); + + ObdSize = 2; + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN / ObdSize; + Ret = EplApiLinkObject( + 0x2011, + EplApiProcessImageInstance_g.m_abProcessImageInput, + &uiVarEntries, + &ObdSize, + 1); + + ObdSize = 4; + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN / ObdSize; + Ret = EplApiLinkObject( + 0x2020, + EplApiProcessImageInstance_g.m_abProcessImageInput, + &uiVarEntries, + &ObdSize, + 1); + + ObdSize = 4; + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN / ObdSize; + Ret = EplApiLinkObject( + 0x2021, + EplApiProcessImageInstance_g.m_abProcessImageInput, + &uiVarEntries, + &ObdSize, + 1); +#endif + +#if EPL_API_PROCESS_IMAGE_SIZE_OUT > 0 + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT; + ObdSize = 1; + Ret = EplApiLinkObject( + 0x2030, + EplApiProcessImageInstance_g.m_abProcessImageOutput, + &uiVarEntries, + &ObdSize, + 1); + + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT; + ObdSize = 1; + Ret = EplApiLinkObject( + 0x2031, + EplApiProcessImageInstance_g.m_abProcessImageOutput, + &uiVarEntries, + &ObdSize, + 1); + + ObdSize = 2; + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT / ObdSize; + Ret = EplApiLinkObject( + 0x2040, + EplApiProcessImageInstance_g.m_abProcessImageOutput, + &uiVarEntries, + &ObdSize, + 1); + + ObdSize = 2; + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT / ObdSize; + Ret = EplApiLinkObject( + 0x2041, + EplApiProcessImageInstance_g.m_abProcessImageOutput, + &uiVarEntries, + &ObdSize, + 1); + + ObdSize = 4; + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT / ObdSize; + Ret = EplApiLinkObject( + 0x2050, + EplApiProcessImageInstance_g.m_abProcessImageOutput, + &uiVarEntries, + &ObdSize, + 1); + + ObdSize = 4; + uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT / ObdSize; + Ret = EplApiLinkObject( + 0x2051, + EplApiProcessImageInstance_g.m_abProcessImageOutput, + &uiVarEntries, + &ObdSize, + 1); +#endif + + return Ret; +} + +//---------------------------------------------------------------------------- +// Function: EplApiProcessImageExchangeIn() +// +// Description: replaces passed input process image with the one of EPL stack +// +// Parameters: pPI_p = input process image +// +// Returns: tEplKernel = error code +// +// State: +//---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiProcessImageExchangeIn(tEplApiProcessImage* pPI_p) +{ +tEplKernel Ret = kEplSuccessful; + +#if EPL_API_PROCESS_IMAGE_SIZE_IN > 0 + #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + copy_to_user(pPI_p->m_pImage, + EplApiProcessImageInstance_g.m_abProcessImageInput, + min(pPI_p->m_uiSize, sizeof (EplApiProcessImageInstance_g.m_abProcessImageInput))); + #else + EPL_MEMCPY(pPI_p->m_pImage, + EplApiProcessImageInstance_g.m_abProcessImageInput, + min(pPI_p->m_uiSize, sizeof (EplApiProcessImageInstance_g.m_abProcessImageInput))); + #endif +#endif + + return Ret; +} + + +//---------------------------------------------------------------------------- +// Function: EplApiProcessImageExchangeOut() +// +// Description: copies passed output process image to EPL stack. +// +// Parameters: pPI_p = output process image +// +// Returns: tEplKernel = error code +// +// State: +//---------------------------------------------------------------------------- + +tEplKernel PUBLIC EplApiProcessImageExchangeOut(tEplApiProcessImage* pPI_p) +{ +tEplKernel Ret = kEplSuccessful; + +#if EPL_API_PROCESS_IMAGE_SIZE_OUT > 0 + #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + copy_from_user(EplApiProcessImageInstance_g.m_abProcessImageOutput, + pPI_p->m_pImage, + min(pPI_p->m_uiSize, sizeof (EplApiProcessImageInstance_g.m_abProcessImageOutput))); + #else + EPL_MEMCPY(EplApiProcessImageInstance_g.m_abProcessImageOutput, + pPI_p->m_pImage, + min(pPI_p->m_uiSize, sizeof (EplApiProcessImageInstance_g.m_abProcessImageOutput))); + #endif +#endif + + return Ret; +} + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + + + +// EOF + diff --git a/drivers/staging/epl/EplCfg.h b/drivers/staging/epl/EplCfg.h new file mode 100644 index 0000000..0684583 --- /dev/null +++ b/drivers/staging/epl/EplCfg.h @@ -0,0 +1,207 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: configuration file + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplCfg.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + ... + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/06 k.t.: Start of Implementation + +****************************************************************************/ + +#ifndef _EPLCFG_H_ +#define _EPLCFG_H_ + + + + +// ========================================================================= +// generic defines which for whole EPL Stack +// ========================================================================= +#define EPL_USE_DELETEINST_FUNC TRUE + +// needed to support datatypes over 32 bit by global.h +#define USE_VAR64 + +// EPL_MAX_INSTANCES specifies count of instances of all EPL modules. +// If it is greater than 1 the first parameter of all +// functions is the instance number. +#define EPL_MAX_INSTANCES 1 + +// This defines the target hardware. Here is encoded wich CPU and wich external +// peripherals are connected. For possible values refere to target.h. If +// necessary value is not available EPL stack has to +// be adapted and tested. +#define TARGET_HARDWARE TGTHW_PC_WRAPP + +// use no FIFOs, make direct calls +//#define EPL_NO_FIFO + +// use no IPC between user- and kernelspace modules, make direct calls +#define EPL_NO_USER_KERNEL + +#ifndef BENCHMARK_MODULES +#define BENCHMARK_MODULES 0 //0xEE800042L +#endif + +// Default defug level: +// Only debug traces of these modules will be compiled which flags are set in define DEF_DEBUG_LVL. +#ifndef DEF_DEBUG_LVL +#define DEF_DEBUG_LVL 0xEC000000L +#endif +// EPL_DBGLVL_OBD = 0x00000004L +// * EPL_DBGLVL_ASSERT = 0x20000000L +// * EPL_DBGLVL_ERROR = 0x40000000L +// * EPL_DBGLVL_ALWAYS = 0x80000000L + + +// EPL_MODULE_INTEGRATION defines all modules which are included in +// EPL application. Please add or delete modules for your application. +#define EPL_MODULE_INTEGRATION EPL_MODULE_OBDK \ + | EPL_MODULE_PDOK \ + | EPL_MODULE_NMT_MN \ + | EPL_MODULE_SDOS \ + | EPL_MODULE_SDOC \ + | EPL_MODULE_SDO_ASND \ + | EPL_MODULE_SDO_UDP \ + | EPL_MODULE_NMT_CN \ + | EPL_MODULE_NMTU \ + | EPL_MODULE_NMTK \ + | EPL_MODULE_DLLK \ + | EPL_MODULE_DLLU \ + | EPL_MODULE_VETH +// | EPL_MODULE_OBDU + +// ========================================================================= +// EPL ethernet driver (Edrv) specific defines +// ========================================================================= + +// switch this define to TRUE if Edrv supports fast tx frames +#define EDRV_FAST_TXFRAMES FALSE +//#define EDRV_FAST_TXFRAMES TRUE + +// switch this define to TRUE if Edrv supports early receive interrupts +#define EDRV_EARLY_RX_INT FALSE +//#define EDRV_EARLY_RX_INT TRUE + +// enables setting of several port pins for benchmarking purposes +#define EDRV_BENCHMARK FALSE +//#define EDRV_BENCHMARK TRUE // MCF_GPIO_PODR_PCIBR + +// Call Tx handler (i.e. EplDllCbFrameTransmitted()) already if DMA has finished, +// otherwise call the Tx handler if frame was actually transmitted over ethernet. +#define EDRV_DMA_TX_HANDLER FALSE +//#define EDRV_DMA_TX_HANDLER TRUE + +// number of used ethernet controller +//#define EDRV_USED_ETH_CTRL 1 + + +// ========================================================================= +// Data Link Layer (DLL) specific defines +// ========================================================================= + +// switch this define to TRUE if Edrv supports fast tx frames +// and DLL shall pass PRes as ready to Edrv after SoC +#define EPL_DLL_PRES_READY_AFTER_SOC FALSE +//#define EPL_DLL_PRES_READY_AFTER_SOC TRUE + +// switch this define to TRUE if Edrv supports fast tx frames +// and DLL shall pass PRes as ready to Edrv after SoA +#define EPL_DLL_PRES_READY_AFTER_SOA FALSE +//#define EPL_DLL_PRES_READY_AFTER_SOA TRUE + + +// ========================================================================= +// OBD specific defines +// ========================================================================= + +// switch this define to TRUE if Epl should compare object range +// automaticly +#define EPL_OBD_CHECK_OBJECT_RANGE FALSE +//#define EPL_OBD_CHECK_OBJECT_RANGE TRUE + +// set this define to TRUE if there are strings or domains in OD, which +// may be changed in object size and/or object data pointer by its object +// callback function (called event kObdEvWrStringDomain) +//#define EPL_OBD_USE_STRING_DOMAIN_IN_RAM FALSE +#define EPL_OBD_USE_STRING_DOMAIN_IN_RAM TRUE + +#define EPL_OBD_USE_VARIABLE_SUBINDEX_TAB TRUE + + +// ========================================================================= +// Timer module specific defines +// ========================================================================= + +// if TRUE it uses the Timer module implementation of EPL user also in EPL kernel +#define EPL_TIMER_USE_USER TRUE + +// if TRUE the high resolution timer module will be used +#define EPL_TIMER_USE_HIGHRES TRUE +//#define EPL_TIMER_USE_HIGHRES FALSE + + +#endif //_EPLCFG_H_ + + + diff --git a/drivers/staging/epl/EplDef.h b/drivers/staging/epl/EplDef.h new file mode 100644 index 0000000..ff704d6 --- /dev/null +++ b/drivers/staging/epl/EplDef.h @@ -0,0 +1,362 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for EPL default constants + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDef.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.15 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/05/22 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_DEF_H_ +#define _EPL_DEF_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#define EPL_C_ADR_BROADCAST 0xFF // EPL broadcast address +#define EPL_C_ADR_DIAG_DEF_NODE_ID 0xFD // EPL default address of dignostic device +#define EPL_C_ADR_DUMMY_NODE_ID 0xFC // EPL dummy node address +#define EPL_C_ADR_INVALID 0x00 // invalid EPL address +#define EPL_C_ADR_MN_DEF_NODE_ID 0xF0 // EPL default address of MN +#define EPL_C_ADR_RT1_DEF_NODE_ID 0xFE // EPL default address of router type 1 +#define EPL_C_DLL_ASND_PRIO_NMTRQST 7 // increased ASnd request priority to be used by NMT Requests +#define EPL_C_DLL_ASND_PRIO_STD 0 // standard ASnd request priority +#define EPL_C_DLL_ETHERTYPE_EPL 0x88AB +#define EPL_C_DLL_ISOCHR_MAX_PAYL 1490 // Byte: maximum size of PReq and PRes payload data, requires C_IP_MAX_MTU +#define EPL_C_DLL_MAX_ASYNC_MTU 1500 // Byte: maximum asynchronous payload in bytes +#define EPL_C_DLL_MAX_PAYL_OFFSET 1499 // Byte: maximum offset of Ethernet frame payload, requires C_IP_MAX_MTU +#define EPL_C_DLL_MAX_RS 7 +#define EPL_C_DLL_MIN_ASYNC_MTU 282 // Byte: minimum asynchronous payload in bytes. +#define EPL_C_DLL_MIN_PAYL_OFFSET 45 // Byte: minimum offset of Ethernet frame payload +#define EPL_C_DLL_MULTICAST_ASND 0x01111E000004LL // EPL ASnd multicast MAC address, canonical form +#define EPL_C_DLL_MULTICAST_PRES 0x01111E000002LL // EPL PRes multicast MAC address, canonical form +#define EPL_C_DLL_MULTICAST_SOA 0x01111E000003LL // EPL SoA multicast MAC address, canonical form +#define EPL_C_DLL_MULTICAST_SOC 0x01111E000001LL // EPL Soc multicast MAC address, canonical form +#define EPL_C_DLL_PREOP1_START_CYCLES 10 // number of unassigning SoA frames at start of NMT_MS_PRE_OPERATIONAL_1 +#define EPL_C_DLL_T_BITTIME 10 // ns: Transmission time per bit on 100 Mbit/s network +#define EPL_C_DLL_T_EPL_PDO_HEADER 10 // Byte: size of PReq and PRes EPL PDO message header +#define EPL_C_DLL_T_ETH2_WRAPPER 18 // Byte: size of Ethernet type II wrapper consisting of header and checksum +#define EPL_C_DLL_T_IFG 640 // ns: Ethernet Interframe Gap +#define EPL_C_DLL_T_MIN_FRAME 5120 // ns: Size of minimum Ethernet frame (without preamble) +#define EPL_C_DLL_T_PREAMBLE 960 // ns: Size of Ethernet frame preamble + +#define EPL_C_DLL_MINSIZE_SOC 36 // minimum size of SoC without padding and CRC +#define EPL_C_DLL_MINSIZE_PREQ 60 // minimum size of PRec without CRC +#define EPL_C_DLL_MINSIZE_PRES 60 // minimum size of PRes without CRC +#define EPL_C_DLL_MINSIZE_SOA 24 // minimum size of SoA without padding and CRC +#define EPL_C_DLL_MINSIZE_IDENTRES 176 // minimum size of IdentResponse without CRC +#define EPL_C_DLL_MINSIZE_STATUSRES 72 // minimum size of StatusResponse without CRC +#define EPL_C_DLL_MINSIZE_NMTCMD 20 // minimum size of NmtCommand without CommandData, padding and CRC +#define EPL_C_DLL_MINSIZE_NMTCMDEXT 52 // minimum size of NmtCommand without padding and CRC +#define EPL_C_DLL_MINSIZE_NMTREQ 20 // minimum size of NmtRequest without CommandData, padding and CRC +#define EPL_C_DLL_MINSIZE_NMTREQEXT 52 // minimum size of NmtRequest without padding and CRC + +#define EPL_C_ERR_MONITOR_DELAY 10 // Error monitoring start delay (not used in DS 1.0.0) +#define EPL_C_IP_ADR_INVALID 0x00000000L // invalid IP address (0.0.0.0) used to indicate no change +#define EPL_C_IP_INVALID_MTU 0 // Byte: invalid MTU size used to indicate no change +#define EPL_C_IP_MAX_MTU 1518 // Byte: maximum size in bytes of the IP stack which must be processed. +#define EPL_C_IP_MIN_MTU 300 // Byte: minimum size in bytes of the IP stack which must be processed. +#define EPL_C_NMT_STATE_TOLERANCE 5 // Cycles: maximum reaction time to NMT state commands +#define EPL_C_NMT_STATREQ_CYCLE 5 // sec: StatusRequest cycle time to be applied to AsyncOnly CNs +#define EPL_C_SDO_EPL_PORT 3819 + +#define EPL_C_DLL_MAX_ASND_SERVICE_IDS 5 // see tEplDllAsndServiceId in EplDll.h + + + +// Default configuration +// ====================== + +#ifndef EPL_D_PDO_Granularity_U8 +#define EPL_D_PDO_Granularity_U8 8 // minimum size of objects to be mapped in bits UNSIGNED8 O O 1 1 +#endif + +#ifndef EPL_NMT_MAX_NODE_ID +#define EPL_NMT_MAX_NODE_ID 254 // maximum node-ID +#endif + +#ifndef EPL_D_NMT_MaxCNNumber_U8 +#define EPL_D_NMT_MaxCNNumber_U8 239 // maximum number of supported regular CNs in the Node ID range 1 .. 239 UNSIGNED8 O O 239 239 +#endif + +// defines for EPL API layer static process image +#ifndef EPL_API_PROCESS_IMAGE_SIZE_IN +#define EPL_API_PROCESS_IMAGE_SIZE_IN 0 +#endif + +#ifndef EPL_API_PROCESS_IMAGE_SIZE_OUT +#define EPL_API_PROCESS_IMAGE_SIZE_OUT 0 +#endif + +// configure whether OD access events shall be forwarded +// to user callback function. +// Because of reentrancy for local OD accesses, this has to be disabled +// when application resides in other address space as the stack (e.g. if +// EplApiLinuxUser.c and EplApiLinuxKernel.c are used) +#ifndef EPL_API_OBD_FORWARD_EVENT +#define EPL_API_OBD_FORWARD_EVENT TRUE +#endif + +#ifndef EPL_OBD_MAX_STRING_SIZE +#define EPL_OBD_MAX_STRING_SIZE 32 // is used for objects 0x1008/0x1009/0x100A +#endif + +#ifndef EPL_OBD_USE_STORE_RESTORE +#define EPL_OBD_USE_STORE_RESTORE FALSE +#endif + +#ifndef EPL_OBD_CHECK_OBJECT_RANGE +#define EPL_OBD_CHECK_OBJECT_RANGE TRUE +#endif + +#ifndef EPL_OBD_USE_STRING_DOMAIN_IN_RAM +#define EPL_OBD_USE_STRING_DOMAIN_IN_RAM TRUE +#endif + +#ifndef EPL_OBD_USE_VARIABLE_SUBINDEX_TAB +#define EPL_OBD_USE_VARIABLE_SUBINDEX_TAB TRUE +#endif + +#ifndef EPL_OBD_USE_KERNEL +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) +#define EPL_OBD_USE_KERNEL TRUE +#else +#define EPL_OBD_USE_KERNEL FALSE +#endif +#endif + +#ifndef EPL_OBD_INCLUDE_A000_TO_DEVICE_PART +#define EPL_OBD_INCLUDE_A000_TO_DEVICE_PART FALSE +#endif + +#ifndef EPL_VETH_NAME +#define EPL_VETH_NAME "epl" // name of net device in Linux +#endif + +/* +#define EPL_D_CFG_ConfigManager_BOOL // Ability of a MN node to perform Configuration Manager functions BOOLEAN O - N - +#define EPL_D_CFM_VerifyConf_BOOL // Support of objects CFM_VerifyConfiguration_REC, CFM_ExpConfDateList_AU32, CFM_ExpConfTimeList_AU32 BOOLEAN O O N N +#define EPL_D_CFM_VerifyConfId_BOOL // Support of objects CFM_VerifyConfiguration_REC.ConfId_U32 and CFM_ExpConfIdList_AU32 BOOLEAN O O N N +#define EPL_D_DLL_CNFeatureIsochr_BOOL // CN’s ability to perform isochronous functions BOOLEAN - O - Y +#define EPL_D_DLL_CNFeatureMultiplex_BOOL // node’s ability to perform control of multiplexed isochronous communication BOOLEAN - O - N +#define EPL_D_DLL_FeatureCN_BOOL // node’s ability to perform CN functions BOOLEAN O O Y Y +#define EPL_D_DLL_FeatureMN_BOOL // node’s ability to perform MN functions BOOLEAN M O - N +#define EPL_D_DLL_MNFeatureMultiplex_BOOL // MN’s ability to perform control of multiplexed isochronous communication BOOLEAN O - Y - +#define EPL_D_DLL_MNFeaturePResTx_BOOL // MN’s ability to transmit PRes BOOLEAN O - Y - +#define EPL_D_NMT_ASndRxMaxPayload_U16 // size of ASnd frame receive buffer UNSIGNED16 M M - - +#define EPL_D_NMT_ASndTxMaxPayload_U16 // size of ASnd frame transmit buffer UNSIGNED16 M M - - +#define EPL_D_NMT_CNASnd2SoC_U32 // minimum delay between end of reception of ASnd and start of reception of SoC UNSIGNED32 - M - - +#define EPL_D_NMT_CNASndMaxLatency_U32 // delay between end of SoA reception and start of ASnd transmission UNSIGNED32 - M - - +#define EPL_D_NMT_CNPResMaxLatency_U32 // delay between end of PReq reception and start of PRes transmission UNSIGNED32 - M - - +#define EPL_D_NMT_CNSoC2PReq_U32 // CN SoC handling maximum time, a subsequent PReq won’t be handled before SoC handling was finished UNSIGNED32 - M - - +#define EPL_D_NMT_DeviceType_U32 // Device Type ID UNSIGNED32 M M - - +#define EPL_D_NMT_EPLVers_U8 EPL // Version implemented by the device UNSIGNED8 M M - - +#define EPL_D_NMT_ExtStateCmd_BOOL // abitilty to support Extended NMT State Commands BOOLEAN O O Y Y +#define EPL_D_NMT_InfoSvc_BOOL // ability to support NMT Info Services BOOLEAN O - Y - +#define EPL_D_NMT_InterfaceAddr_Xh_OSTR // Physical Address of Interface No. Xh OCTET_STRING M M - - +#define EPL_D_NMT_InterfaceDescr_Xh_VSTR // Description text of Interface No. Xh VISIBLE_STRINGM M - - +#define EPL_D_NMT_InterfaceMtu_Xh_U32 // MTU of Interface No. Xh UNSIGNED32 M M - - +#define EPL_D_NMT_InterfaceType_Xh_U8 // Type of Interface No. Xh UNSIGNED8 M M - - +#define EPL_D_NMT_IsochrRxMaxPayload_U16 // size of isochronous frame receive buffer UNSIGNED16 M M - - +#define EPL_D_NMT_IsochrTxMaxPayload_U16 // size of isochronous frame transmit buffer UNSIGNED16 M M - - +#define EPL_D_NMT_ManufactDevName_VS // Manufacturer Device Name VISIBLE_STRING O O - - +#define EPL_D_NMT_ManufactHwVers_VS // Manufacturer HW version VISIBLE_STRING O O - - +#define EPL_D_NMT_ManufactSwVers_VS // Manufacturer SW version VISIBLE_STRING O O - - +#define EPL_D_NMT_MaxCNNodeID_U8 // maximum Node ID available for regular CNs the entry provides an upper limit to the NodeID available for cross traffic PDO reception from a regular CN UNSIGNED8 O O 239 239 +#define EPL_D_NMT_MaxCNNumber_U8 // maximum number of supported regular CNs in the Node ID range 1 .. 239 UNSIGNED8 O O 239 239 +#define EPL_D_NMT_MaxHeartbeats_U8 // number of guard channels UNSIGNED8 O O 254 254 +#define EPL_D_NMT_MNASnd2SoC_U32 // minimum delay between end of reception of ASnd and start of transmission of SoC UNSIGNED32 M - - - +#define EPL_D_NMT_MNMultiplCycMax_U8 // maximum number of EPL cycles per multiplexed cycle UNSIGNED8 O - 0 - +#define EPL_D_NMT_MNPRes2PReq_U32 // delay between end of PRes reception and start of PReq transmission UNSIGNED32 M - - - +#define EPL_D_NMT_MNPRes2PRes_U32 // delay between end of reception of PRes from CNn and start of transmission of PRes by MN UNSIGNED32 M - - - +#define EPL_D_NMT_MNPResRx2SoA_U32 // delay between end of reception of PRes from CNn and start of transmission of SoA by MN UNSIGNED32 M - - - +#define EPL_D_NMT_MNPResTx2SoA_U32 // delay between end of PRes transmission by MN and start of transmission of SoA by MN UNSIGNED32 M - - - +#define EPL_D_NMT_MNSoA2ASndTx_U32 // delay between end of transmission of SoA and start of transmission of ASnd by MN UNSIGNED32 M - - - +#define EPL_D_NMT_MNSoC2PReq_U32 // MN minimum delay between end of SoC transmission and start of PReq transmission UNSIGNED32 M - - - +#define EPL_D_NMT_NMTSvcViaUDPIP_BOOL // Ability of a node to perform NMT services via UDP/IP BOOLEAN O - Y - +#define EPL_D_NMT_NodeIDByHW_BOOL // Ability of a node to support NodeID setup by HW BOOLEAN O O Y Y +#define EPL_D_NMT_NodeIDBySW_BOOL // Ability of a node to support NodeID setup by SW BOOLEAN O O N N +#define EPL_D_NMT_ProductCode_U32 // Identity Object Product Code UNSIGNED32 M M - - +#define EPL_D_NMT_RevisionNo_U32 // Identity Object Revision Number UNSIGNED32 M M - - +#define EPL_D_NMT_SerialNo_U32 // Identity Object Serial Number UNSIGNED32 M M - - +#define EPL_D_NMT_SimpleBoot_BOOL // Ability of a MN node to perform Simple Boot Process, if not set Indivual Boot Process shall be proviced BOOLEAN M - - - +#define EPL_D_NMT_VendorID_U32 // Identity Object Vendor ID UNSIGNED32 M M - - +#define EPL_D_NWL_Forward_BOOL // Ability of node to forward datagrams BOOLEAN O O N N +#define EPL_D_NWL_IPSupport_BOOL // Ability of the node cummunicate via IP BOOLEAN - - Y Y +#define EPL_D_PDO_DynamicMapping_BOOL // Ability of a node to perform dynamic PDO mapping BOOLEAN O O Y Y +#define EPL_D_PDO_MaxDescrMem_U32 // maximum cumulative memory consumption of TPDO and RPDO describing objects in byte UNSIGNED32 O O MAX_U32 MAX_U32 +#define EPL_D_PDO_RPDOChannels_U8 // number of supported RPDO channels UNSIGNED8 O O 256 256 +#define EPL_D_PDO_RPDOMaxMem_U32 // Maximum memory available for RPDO data per EPL cycle in byte UNSIGNED32 O O MAX_U32 MAX_U32 +#define EPL_D_PDO_RPDOObjects_U8 // Number of supported mapped objects per RPDO channel UNSIGNED8 O O 254 254 +#define EPL_D_PDO_TPDOChannels_U8 // number of supported TPDO channels UNSIGNED8 O - 256 - +#define EPL_D_PDO_TPDOMaxMem_U32 // Maximum memory available for TPDO data per EPL cycle in byte UNSIGNED32 O O MAX_U32 MAX_U32 +#define EPL_D_PDO_TPDOObjects_U8 // Number of supported mapped objects per TPDO channel UNSIGNED8 O O 254 254 +#define EPL_D_SDO_ViaASnd_BOOL // Ability of a CN to perform SDO transfer by EPL ASnd BOOLEAN - M - - +#define EPL_D_SDO_ViaPDO_BOOL // Ability of a node to perform SDO transfer by PDO BOOLEAN O O N N +#define EPL_D_SDO_ViaUDPIP_BOOL // Ability of a CN to perform SDO transfer by UDP/IP BOOLEAN - M - - +#define EPL_D_SYN_OptimizedSync_BOOL // Ability of node to perform optimized synchronisation BOOLEAN O O N N +*/ + +// Emergency error codes +// ====================== +#define EPL_E_NO_ERROR 0x0000 +// 0xFxxx manufacturer specific error codes +#define EPL_E_NMT_NO_IDENT_RES 0xF001 +#define EPL_E_NMT_NO_STATUS_RES 0xF002 + +// 0x816x HW errors +#define EPL_E_DLL_BAD_PHYS_MODE 0x8161 +#define EPL_E_DLL_COLLISION 0x8162 +#define EPL_E_DLL_COLLISION_TH 0x8163 +#define EPL_E_DLL_CRC_TH 0x8164 +#define EPL_E_DLL_LOSS_OF_LINK 0x8165 +#define EPL_E_DLL_MAC_BUFFER 0x8166 +// 0x82xx Protocol errors +#define EPL_E_DLL_ADDRESS_CONFLICT 0x8201 +#define EPL_E_DLL_MULTIPLE_MN 0x8202 +// 0x821x Frame size errors +#define EPL_E_PDO_SHORT_RX 0x8210 +#define EPL_E_PDO_MAP_VERS 0x8211 +#define EPL_E_NMT_ASND_MTU_DIF 0x8212 +#define EPL_E_NMT_ASND_MTU_LIM 0x8213 +#define EPL_E_NMT_ASND_TX_LIM 0x8214 +// 0x823x Timing errors +#define EPL_E_NMT_CYCLE_LEN 0x8231 +#define EPL_E_DLL_CYCLE_EXCEED 0x8232 +#define EPL_E_DLL_CYCLE_EXCEED_TH 0x8233 +#define EPL_E_NMT_IDLE_LIM 0x8234 +#define EPL_E_DLL_JITTER_TH 0x8235 +#define EPL_E_DLL_LATE_PRES_TH 0x8236 +#define EPL_E_NMT_PREQ_CN 0x8237 +#define EPL_E_NMT_PREQ_LIM 0x8238 +#define EPL_E_NMT_PRES_CN 0x8239 +#define EPL_E_NMT_PRES_RX_LIM 0x823A +#define EPL_E_NMT_PRES_TX_LIM 0x823B +// 0x824x Frame errors +#define EPL_E_DLL_INVALID_FORMAT 0x8241 +#define EPL_E_DLL_LOSS_PREQ_TH 0x8242 +#define EPL_E_DLL_LOSS_PRES_TH 0x8243 +#define EPL_E_DLL_LOSS_SOA_TH 0x8244 +#define EPL_E_DLL_LOSS_SOC_TH 0x8245 +// 0x84xx BootUp Errors +#define EPL_E_NMT_BA1 0x8410 // other MN in MsNotActive active +#define EPL_E_NMT_BA1_NO_MN_SUPPORT 0x8411 // MN is not supported +#define EPL_E_NMT_BPO1 0x8420 // mandatory CN was not found or failed in BootStep1 +#define EPL_E_NMT_BPO1_GET_IDENT 0x8421 // IdentRes was not received +#define EPL_E_NMT_BPO1_DEVICE_TYPE 0x8422 // wrong device type +#define EPL_E_NMT_BPO1_VENDOR_ID 0x8423 // wrong vendor ID +#define EPL_E_NMT_BPO1_PRODUCT_CODE 0x8424 // wrong product code +#define EPL_E_NMT_BPO1_REVISION_NO 0x8425 // wrong revision number +#define EPL_E_NMT_BPO1_SERIAL_NO 0x8426 // wrong serial number +#define EPL_E_NMT_BPO1_CF_VERIFY 0x8428 // verification of configuration failed +#define EPL_E_NMT_BPO2 0x8430 // mandatory CN failed in BootStep2 +#define EPL_E_NMT_BRO 0x8440 // CheckCommunication failed for mandatory CN +#define EPL_E_NMT_WRONG_STATE 0x8480 // mandatory CN has wrong NMT state + +// Defines for object 0x1F80 NMT_StartUp_U32 +// ========================================== +#define EPL_NMTST_STARTALLNODES 0x00000002L // Bit 1 +#define EPL_NMTST_NO_AUTOSTART 0x00000004L // Bit 2 +#define EPL_NMTST_NO_STARTNODE 0x00000008L // Bit 3 +#define EPL_NMTST_RESETALL_MAND_CN 0x00000010L // Bit 4 +#define EPL_NMTST_STOPALL_MAND_CN 0x00000040L // Bit 6 +#define EPL_NMTST_NO_AUTOPREOP2 0x00000080L // Bit 7 +#define EPL_NMTST_NO_AUTOREADYTOOP 0x00000100L // Bit 8 +#define EPL_NMTST_EXT_CNIDENTCHECK 0x00000200L // Bit 9 +#define EPL_NMTST_SWVERSIONCHECK 0x00000400L // Bit 10 +#define EPL_NMTST_CONFCHECK 0x00000800L // Bit 11 +#define EPL_NMTST_NO_RETURN_PREOP1 0x00001000L // Bit 12 +#define EPL_NMTST_BASICETHERNET 0x00002000L // Bit 13 + +// Defines for object 0x1F81 NMT_NodeAssignment_AU32 +// ================================================== +#define EPL_NODEASSIGN_NODE_EXISTS 0x00000001L // Bit 0 +#define EPL_NODEASSIGN_NODE_IS_CN 0x00000002L // Bit 1 +#define EPL_NODEASSIGN_START_CN 0x00000004L // Bit 2 +#define EPL_NODEASSIGN_MANDATORY_CN 0x00000008L // Bit 3 +#define EPL_NODEASSIGN_KEEPALIVE 0x00000010L //currently not used in EPL V2 standard +#define EPL_NODEASSIGN_SWVERSIONCHECK 0x00000020L // Bit 5 +#define EPL_NODEASSIGN_SWUPDATE 0x00000040L // Bit 6 +#define EPL_NODEASSIGN_ASYNCONLY_NODE 0x00000100L // Bit 8 +#define EPL_NODEASSIGN_MULTIPLEXED_CN 0x00000200L // Bit 9 +#define EPL_NODEASSIGN_RT1 0x00000400L // Bit 10 +#define EPL_NODEASSIGN_RT2 0x00000800L // Bit 11 +#define EPL_NODEASSIGN_MN_PRES 0x00001000L // Bit 12 +#define EPL_NODEASSIGN_VALID 0x80000000L // Bit 31 + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPL_DEF_H_ diff --git a/drivers/staging/epl/EplDll.h b/drivers/staging/epl/EplDll.h new file mode 100644 index 0000000..941ccef --- /dev/null +++ b/drivers/staging/epl/EplDll.h @@ -0,0 +1,220 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for DLL module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDll.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/08 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_DLL_H_ +#define _EPL_DLL_H_ + +#include "EplInc.h" +#include "EplFrame.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +#ifndef EPL_DLL_MAX_ASND_SERVICE_ID +#define EPL_DLL_MAX_ASND_SERVICE_ID (EPL_C_DLL_MAX_ASND_SERVICE_IDS + 1) // last is kEplDllAsndSdo == 5 +#endif + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef enum +{ + kEplDllAsndNotDefined = 0x00, + kEplDllAsndIdentResponse = 0x01, + kEplDllAsndStatusResponse = 0x02, + kEplDllAsndNmtRequest = 0x03, + kEplDllAsndNmtCommand = 0x04, + kEplDllAsndSdo = 0x05 + +} tEplDllAsndServiceId; + +typedef enum +{ + kEplDllAsndFilterNone = 0x00, + kEplDllAsndFilterLocal = 0x01, // receive only ASnd frames with local or broadcast node ID + kEplDllAsndFilterAny = 0x02, // receive any ASnd frame +} tEplDllAsndFilter; + +typedef enum +{ + kEplDllReqServiceNo = 0x00, + kEplDllReqServiceIdent = 0x01, + kEplDllReqServiceStatus = 0x02, + kEplDllReqServiceNmtRequest = 0x03, + kEplDllReqServiceUnspecified= 0xFF, + +} tEplDllReqServiceId; + +typedef enum +{ + kEplDllAsyncReqPrioNmt = 0x07, // PRIO_NMT_REQUEST + kEplDllAsyncReqPrio6 = 0x06, + kEplDllAsyncReqPrio5 = 0x05, + kEplDllAsyncReqPrio4 = 0x04, + kEplDllAsyncReqPrioGeneric = 0x03, // PRIO_GENERIC_REQUEST + kEplDllAsyncReqPrio2 = 0x02, // till WSP 0.1.3: PRIO_ABOVE_GENERIC + kEplDllAsyncReqPrio1 = 0x01, // till WSP 0.1.3: PRIO_BELOW_GENERIC + kEplDllAsyncReqPrio0 = 0x00, // till WSP 0.1.3: PRIO_GENERIC_REQUEST + +} tEplDllAsyncReqPriority; + +typedef struct +{ + unsigned int m_uiFrameSize; + tEplFrame * m_pFrame; + tEplNetTime m_NetTime; + +} tEplFrameInfo; + +typedef struct +{ + unsigned int m_uiSizeOfStruct; + BOOL m_fAsyncOnly; // do not need to register PRes-Frame + unsigned int m_uiNodeId; // local node ID + + // 0x1F82: NMT_FeatureFlags_U32 + DWORD m_dwFeatureFlags; + // Cycle Length (0x1006: NMT_CycleLen_U32) in [us] + DWORD m_dwCycleLen; // required for error detection + // 0x1F98: NMT_CycleTiming_REC + // 0x1F98.1: IsochrTxMaxPayload_U16 + unsigned int m_uiIsochrTxMaxPayload; // const + // 0x1F98.2: IsochrRxMaxPayload_U16 + unsigned int m_uiIsochrRxMaxPayload; // const + // 0x1F98.3: PResMaxLatency_U32 + DWORD m_dwPresMaxLatency; // const in [ns], only required for IdentRes + // 0x1F98.4: PReqActPayloadLimit_U16 + unsigned int m_uiPreqActPayloadLimit; // required for initialisation (+24 bytes) + // 0x1F98.5: PResActPayloadLimit_U16 + unsigned int m_uiPresActPayloadLimit; // required for initialisation of Pres frame (+24 bytes) + // 0x1F98.6: ASndMaxLatency_U32 + DWORD m_dwAsndMaxLatency; // const in [ns], only required for IdentRes + // 0x1F98.7: MultiplCycleCnt_U8 + unsigned int m_uiMultiplCycleCnt; // required for error detection + // 0x1F98.8: AsyncMTU_U16 + unsigned int m_uiAsyncMtu; // required to set up max frame size + // $$$ 0x1F98.9: Prescaler_U16 + // $$$ Multiplexed Slot + + // 0x1C14: DLL_LossOfFrameTolerance_U32 in [ns] + DWORD m_dwLossOfFrameTolerance; + + // 0x1F8A: NMT_MNCycleTiming_REC + // 0x1F8A.1: WaitSoCPReq_U32 in [ns] + DWORD m_dwWaitSocPreq; + + // 0x1F8A.2: AsyncSlotTimeout_U32 in [ns] + DWORD m_dwAsyncSlotTimeout; + +} tEplDllConfigParam; + +typedef struct +{ + unsigned int m_uiSizeOfStruct; + DWORD m_dwDeviceType; // NMT_DeviceType_U32 + DWORD m_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32 + DWORD m_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32 + DWORD m_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32 + DWORD m_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32 + QWORD m_qwVendorSpecificExt1; + DWORD m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 + DWORD m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 + DWORD m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device + DWORD m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device + DWORD m_dwIpAddress; + DWORD m_dwSubnetMask; + DWORD m_dwDefaultGateway; + BYTE m_sHostname[32]; + BYTE m_abVendorSpecificExt2[48]; + +} tEplDllIdentParam; + +typedef struct +{ + unsigned int m_uiNodeId; + WORD m_wPreqPayloadLimit; // object 0x1F8B: NMT_MNPReqPayloadLimitList_AU16 + WORD m_wPresPayloadLimit; // object 0x1F8D: NMT_PResPayloadLimitList_AU16 + DWORD m_dwPresTimeout; // object 0x1F92: NMT_MNCNPResTimeout_AU32 + +} tEplDllNodeInfo; + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + + +#endif // #ifndef _EPL_DLL_H_ + + diff --git a/drivers/staging/epl/EplDllCal.h b/drivers/staging/epl/EplDllCal.h new file mode 100644 index 0000000..d8bf731 --- /dev/null +++ b/drivers/staging/epl/EplDllCal.h @@ -0,0 +1,131 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for DLL Communication Abstraction Layer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDllCal.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/20 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_DLLCAL_H_ +#define _EPL_DLLCAL_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +/*#ifndef EPL_DLLCAL_BUFFER_ID_RX +#define EPL_DLLCAL_BUFFER_ID_RX "EplSblDllCalRx" +#endif + +#ifndef EPL_DLLCAL_BUFFER_SIZE_RX +#define EPL_DLLCAL_BUFFER_SIZE_RX 32767 +#endif +*/ +#ifndef EPL_DLLCAL_BUFFER_ID_TX_NMT +#define EPL_DLLCAL_BUFFER_ID_TX_NMT "EplSblDllCalTxNmt" +#endif + +#ifndef EPL_DLLCAL_BUFFER_SIZE_TX_NMT +#define EPL_DLLCAL_BUFFER_SIZE_TX_NMT 32767 +#endif + +#ifndef EPL_DLLCAL_BUFFER_ID_TX_GEN +#define EPL_DLLCAL_BUFFER_ID_TX_GEN "EplSblDllCalTxGen" +#endif + +#ifndef EPL_DLLCAL_BUFFER_SIZE_TX_GEN +#define EPL_DLLCAL_BUFFER_SIZE_TX_GEN 32767 +#endif + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef struct +{ + tEplDllAsndServiceId m_ServiceId; + tEplDllAsndFilter m_Filter; + +} tEplDllCalAsndServiceIdFilter; + +typedef struct +{ + tEplDllReqServiceId m_Service; + unsigned int m_uiNodeId; + BYTE m_bSoaFlag1; + +} tEplDllCalIssueRequest; + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + + +#endif // #ifndef _EPL_DLLKCAL_H_ + + diff --git a/drivers/staging/epl/EplDllk.c b/drivers/staging/epl/EplDllk.c new file mode 100644 index 0000000..dee0d3d --- /dev/null +++ b/drivers/staging/epl/EplDllk.c @@ -0,0 +1,3783 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for kernel DLL module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDllk.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.21 $ $Date: 2008/11/13 17:13:09 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/12 d.k.: start of the implementation, version 1.00 + +****************************************************************************/ + +#include "kernel/EplDllk.h" +#include "kernel/EplDllkCal.h" +#include "kernel/EplEventk.h" +#include "kernel/EplNmtk.h" +#include "edrv.h" +#include "Benchmark.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) +#include "kernel/EplPdok.h" +#endif + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0) +#include "kernel/VirtualEthernet.h" +#endif + +//#if EPL_TIMER_USE_HIGHRES != FALSE +#include "kernel/EplTimerHighResk.h" +//#endif + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) == 0) +#error "EPL module DLLK needs EPL module NMTK!" +#endif + +#if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) && (EPL_DLL_PRES_READY_AFTER_SOC != FALSE) +#error "EPL module DLLK: select only one of EPL_DLL_PRES_READY_AFTER_SOA and EPL_DLL_PRES_READY_AFTER_SOC." +#endif + +#if ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)) \ + && (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0) +#error "EPL module DLLK: currently, EPL_DLL_PRES_READY_AFTER_* is not supported if EPL_MODULE_NMT_MN is enabled." +#endif + +#if (EDRV_FAST_TXFRAMES == FALSE) && \ + ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)) +#error "EPL module DLLK: EPL_DLL_PRES_READY_AFTER_* is enabled, but not EDRV_FAST_TXFRAMES." +#endif + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// TracePoint support for realtime-debugging +#ifdef _DBG_TRACE_POINTS_ + void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); + void PUBLIC TgtDbgPostTraceValue (DWORD dwTraceValue_p); + #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) + #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) +#else + #define TGT_DBG_SIGNAL_TRACE_POINT(p) + #define TGT_DBG_POST_TRACE_VALUE(v) +#endif +#define EPL_DLLK_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \ + TGT_DBG_POST_TRACE_VALUE((kEplEventSinkDllk << 28) | (Event_p << 24) \ + | (uiNodeId_p << 16) | wErrorCode_p) + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S EplDllk */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// defines for indexes of tEplDllInstance.m_pTxFrameInfo +#define EPL_DLLK_TXFRAME_IDENTRES 0 // IdentResponse on CN / MN +#define EPL_DLLK_TXFRAME_STATUSRES 1 // StatusResponse on CN / MN +#define EPL_DLLK_TXFRAME_NMTREQ 2 // NMT Request from FIFO on CN / MN +#define EPL_DLLK_TXFRAME_NONEPL 3 // non-EPL frame from FIFO on CN / MN +#define EPL_DLLK_TXFRAME_PRES 4 // PRes on CN / MN +#define EPL_DLLK_TXFRAME_SOC 5 // SoC on MN +#define EPL_DLLK_TXFRAME_SOA 6 // SoA on MN +#define EPL_DLLK_TXFRAME_PREQ 7 // PReq on MN +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +#define EPL_DLLK_TXFRAME_COUNT (7 + EPL_D_NMT_MaxCNNumber_U8 + 2) // on MN: 7 + MaxPReq of regular CNs + 1 Diag + 1 Router +#else +#define EPL_DLLK_TXFRAME_COUNT 5 // on CN: 5 +#endif + +#define EPL_DLLK_BUFLEN_EMPTY 0 // buffer is empty +#define EPL_DLLK_BUFLEN_FILLING 1 // just the buffer is being filled +#define EPL_DLLK_BUFLEN_MIN 60 // minimum ethernet frame length + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef enum +{ + kEplDllGsInit = 0x00, // MN/CN: initialisation (< PreOp2) + kEplDllCsWaitPreq = 0x01, // CN: wait for PReq frame + kEplDllCsWaitSoc = 0x02, // CN: wait for SoC frame + kEplDllCsWaitSoa = 0x03, // CN: wait for SoA frame + kEplDllMsNonCyclic = 0x04, // MN: reduced EPL cycle (PreOp1) + kEplDllMsWaitSocTrig = 0x05, // MN: wait for SoC trigger (cycle timer) + kEplDllMsWaitPreqTrig = 0x06, // MN: wait for (first) PReq trigger (WaitSoCPReq_U32) + kEplDllMsWaitPres = 0x07, // MN: wait for PRes frame from CN + kEplDllMsWaitSoaTrig = 0x08, // MN: wait for SoA trigger (PRes transmitted) + kEplDllMsWaitAsndTrig = 0x09, // MN: wait for ASnd trigger (SoA transmitted) + kEplDllMsWaitAsnd = 0x0A, // MN: wait for ASnd frame if SoA contained invitation + +} tEplDllState; + +typedef struct +{ + BYTE m_be_abSrcMac[6]; + tEdrvTxBuffer* m_pTxBuffer; // Buffers for Tx-Frames + unsigned int m_uiMaxTxFrames; + BYTE m_bFlag1; // Flag 1 with EN, EC for PRes, StatusRes + BYTE m_bMnFlag1; // Flag 1 with EA, ER from PReq, SoA of MN + BYTE m_bFlag2; // Flag 2 with PR and RS for PRes, StatusRes, IdentRes + tEplDllConfigParam m_DllConfigParam; + tEplDllIdentParam m_DllIdentParam; + tEplDllState m_DllState; + tEplDllkCbAsync m_pfnCbAsync; + tEplDllAsndFilter m_aAsndFilter[EPL_DLL_MAX_ASND_SERVICE_ID]; + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + tEplDllkNodeInfo* m_pFirstNodeInfo; + tEplDllkNodeInfo* m_pCurNodeInfo; + tEplDllkNodeInfo m_aNodeInfo[EPL_NMT_MAX_NODE_ID]; + tEplDllReqServiceId m_LastReqServiceId; + unsigned int m_uiLastTargetNodeId; +#endif + +#if EPL_TIMER_USE_HIGHRES != FALSE + tEplTimerHdl m_TimerHdlCycle; // used for EPL cycle monitoring on CN and generation on MN +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + tEplTimerHdl m_TimerHdlResponse; // used for CN response monitoring +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +#endif + + unsigned int m_uiCycleCount; // cycle counter (needed for multiplexed cycle support) + unsigned long long m_ullFrameTimeout; // frame timeout (cycle length + loss of frame tolerance) + +} tEplDllkInstance; + + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +// if no dynamic memory allocation shall be used +// define structures statically +static tEplDllkInstance EplDllkInstance_g; + +static tEdrvTxBuffer aEplDllkTxBuffer_l[EPL_DLLK_TXFRAME_COUNT]; + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +// change DLL state on event +static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p, tEplNmtState NmtState_p); + +// called from EdrvInterruptHandler() +static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p); + +// called from EdrvInterruptHandler() +static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p); + +// check frame and set missing information +static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p, unsigned int uiFrameSize_p); + +// called by high resolution timer module to monitor EPL cycle as CN +#if EPL_TIMER_USE_HIGHRES != FALSE +static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg* pEventArg_p); +#endif + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +// MN: returns internal node info structure +static tEplDllkNodeInfo* EplDllkGetNodeInfo(unsigned int uiNodeId_p); + +// transmit SoA +static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p, + tEplDllState* pDllStateProposed_p, + BOOL fEnableInvitation_p); + +static tEplKernel EplDllkMnSendSoc(void); + +static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p, + tEplDllState* pDllStateProposed_p); + +static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId ReqServiceId_p, unsigned int uiNodeId_p); + +static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg* pEventArg_p); + +static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg* pEventArg_p); + +#endif + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplDllkAddInstance() +// +// Description: add and initialize new instance of EPL stack +// +// Parameters: pInitParam_p = initialisation parameters like MAC address +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiIndex; +tEdrvInitParam EdrvInitParam; + + // reset instance structure + EPL_MEMSET(&EplDllkInstance_g, 0, sizeof (EplDllkInstance_g)); + +#if EPL_TIMER_USE_HIGHRES != FALSE + Ret = EplTimerHighReskInit(); + if (Ret != kEplSuccessful) + { // error occured while initializing high resolution timer module + goto Exit; + } +#endif + + // if dynamic memory allocation available + // allocate instance structure + // allocate TPDO and RPDO table with default size + + // initialize and link pointers in instance structure to frame tables + EplDllkInstance_g.m_pTxBuffer = aEplDllkTxBuffer_l; + EplDllkInstance_g.m_uiMaxTxFrames = sizeof (aEplDllkTxBuffer_l) / sizeof (tEdrvTxBuffer); + + // initialize state + EplDllkInstance_g.m_DllState = kEplDllGsInit; + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // set up node info structure + for (uiIndex = 0; uiIndex < tabentries (EplDllkInstance_g.m_aNodeInfo); uiIndex++) + { + EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1; + EplDllkInstance_g.m_aNodeInfo[uiIndex].m_wPresPayloadLimit = 0xFFFF; + } +#endif + + // initialize Edrv + EPL_MEMCPY(EdrvInitParam.m_abMyMacAddr, pInitParam_p->m_be_abSrcMac, 6); + EdrvInitParam.m_pfnRxHandler = EplDllkCbFrameReceived; + EdrvInitParam.m_pfnTxHandler = EplDllkCbFrameTransmitted; + Ret = EdrvInit(&EdrvInitParam); + if (Ret != kEplSuccessful) + { // error occured while initializing ethernet driver + goto Exit; + } + + // copy local MAC address from Ethernet driver back to local instance structure + // because Ethernet driver may have read it from controller EEPROM + EPL_MEMCPY(EplDllkInstance_g.m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr, 6); + EPL_MEMCPY(pInitParam_p->m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr, 6); + + // initialize TxBuffer array + for (uiIndex = 0; uiIndex < EplDllkInstance_g.m_uiMaxTxFrames; uiIndex++) + { + EplDllkInstance_g.m_pTxBuffer[uiIndex].m_pbBuffer = NULL; + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0) + Ret = VEthAddInstance(pInitParam_p); +#endif + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkDelInstance() +// +// Description: deletes an instance of EPL stack +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkDelInstance(void) +{ +tEplKernel Ret = kEplSuccessful; + + // reset state + EplDllkInstance_g.m_DllState = kEplDllGsInit; + +#if EPL_TIMER_USE_HIGHRES != FALSE + Ret = EplTimerHighReskDelInstance(); +#endif + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0) + Ret = VEthDelInstance(); +#endif + + Ret = EdrvShutdown(); + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCreateTxFrame +// +// Description: creates the buffer for a Tx frame and registers it to the +// ethernet driver +// +// Parameters: puiHandle_p = OUT: handle to frame buffer +// ppFrame_p = OUT: pointer to pointer of EPL frame +// puiFrameSize_p = IN/OUT: pointer to size of frame +// returned size is always equal or larger than +// requested size, if that is not possible +// an error will be returned +// MsgType_p = EPL message type +// ServiceId_p = Service ID in case of ASnd frame, otherwise +// kEplDllAsndNotDefined +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCreateTxFrame (unsigned int * puiHandle_p, + tEplFrame ** ppFrame_p, + unsigned int * puiFrameSize_p, + tEplMsgType MsgType_p, + tEplDllAsndServiceId ServiceId_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplFrame *pTxFrame; +unsigned int uiHandle = EplDllkInstance_g.m_uiMaxTxFrames; +tEdrvTxBuffer *pTxBuffer = NULL; + + if (MsgType_p == kEplMsgTypeAsnd) + { + // search for fixed Tx buffers + if (ServiceId_p == kEplDllAsndIdentResponse) + { + uiHandle = EPL_DLLK_TXFRAME_IDENTRES; + } + else if (ServiceId_p == kEplDllAsndStatusResponse) + { + uiHandle = EPL_DLLK_TXFRAME_STATUSRES; + } + else if ((ServiceId_p == kEplDllAsndNmtRequest) || (ServiceId_p == kEplDllAsndNmtCommand)) + { + uiHandle = EPL_DLLK_TXFRAME_NMTREQ; + } + + if (uiHandle >= EplDllkInstance_g.m_uiMaxTxFrames) + { // look for free entry + uiHandle = EPL_DLLK_TXFRAME_PREQ; + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle]; + for (; uiHandle < EplDllkInstance_g.m_uiMaxTxFrames; uiHandle++, pTxBuffer++) + { + if (pTxBuffer->m_pbBuffer == NULL) + { // free entry found + break; + } + } + } + } + else if (MsgType_p == kEplMsgTypeNonEpl) + { + uiHandle = EPL_DLLK_TXFRAME_NONEPL; + } + else if (MsgType_p == kEplMsgTypePres) + { + uiHandle = EPL_DLLK_TXFRAME_PRES; + } + else if (MsgType_p == kEplMsgTypeSoc) + { + uiHandle = EPL_DLLK_TXFRAME_SOC; + } + else if (MsgType_p == kEplMsgTypeSoa) + { + uiHandle = EPL_DLLK_TXFRAME_SOA; + } + else + { // look for free entry + uiHandle = EPL_DLLK_TXFRAME_PREQ; + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle]; + for (; uiHandle < EplDllkInstance_g.m_uiMaxTxFrames; uiHandle++, pTxBuffer++) + { + if (pTxBuffer->m_pbBuffer == NULL) + { // free entry found + break; + } + } + if (pTxBuffer->m_pbBuffer != NULL) + { + Ret = kEplEdrvNoFreeBufEntry; + goto Exit; + } + } + + // test if requested entry is free + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle]; + if (pTxBuffer->m_pbBuffer != NULL) + { // entry is not free + Ret = kEplEdrvNoFreeBufEntry; + goto Exit; + } + + // setup Tx buffer + pTxBuffer->m_EplMsgType = MsgType_p; + pTxBuffer->m_uiMaxBufferLen = *puiFrameSize_p; + + Ret = EdrvAllocTxMsgBuffer(pTxBuffer); + if (Ret != kEplSuccessful) + { // error occured while registering Tx frame + goto Exit; + } + + // because buffer size may be larger than requested + // memorize real length of frame + pTxBuffer->m_uiTxMsgLen = *puiFrameSize_p; + + // fill whole frame with 0 + EPL_MEMSET(pTxBuffer->m_pbBuffer, 0, pTxBuffer->m_uiMaxBufferLen); + + pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + + if (MsgType_p != kEplMsgTypeNonEpl) + { // fill out Frame only if it is an EPL frame + // ethertype + AmiSetWordToBe(&pTxFrame->m_be_wEtherType, EPL_C_DLL_ETHERTYPE_EPL); + // source node ID + AmiSetByteToLe(&pTxFrame->m_le_bSrcNodeId, (BYTE) EplDllkInstance_g.m_DllConfigParam.m_uiNodeId); + // source MAC address + EPL_MEMCPY(&pTxFrame->m_be_abSrcMac[0], &EplDllkInstance_g.m_be_abSrcMac[0], 6); + switch (MsgType_p) + { + case kEplMsgTypeAsnd: + // destination MAC address + AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0], EPL_C_DLL_MULTICAST_ASND); + // destination node ID + switch (ServiceId_p) + { + case kEplDllAsndIdentResponse: + case kEplDllAsndStatusResponse: + { // IdentResponses and StatusResponses are Broadcast + AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId, (BYTE) EPL_C_ADR_BROADCAST); + break; + } + + default: + break; + } + // ASnd Service ID + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_le_bServiceId, ServiceId_p); + break; + + case kEplMsgTypeSoc: + // destination MAC address + AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0], EPL_C_DLL_MULTICAST_SOC); + // destination node ID + AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId, (BYTE) EPL_C_ADR_BROADCAST); + // reset Flags + //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag1, (BYTE) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag2, (BYTE) 0); + break; + + case kEplMsgTypeSoa: + // destination MAC address + AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0], EPL_C_DLL_MULTICAST_SOA); + // destination node ID + AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId, (BYTE) EPL_C_ADR_BROADCAST); + // reset Flags + //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag1, (BYTE) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag2, (BYTE) 0); + // EPL profile version + AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bEplVersion, (BYTE) EPL_SPEC_VERSION); + break; + + case kEplMsgTypePres: + // destination MAC address + AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0], EPL_C_DLL_MULTICAST_PRES); + // destination node ID + AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId, (BYTE) EPL_C_ADR_BROADCAST); + // reset Flags + //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, (BYTE) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, (BYTE) 0); + // PDO size + //AmiSetWordToLe(&pTxFrame->m_Data.m_Pres.m_le_wSize, 0); + break; + + case kEplMsgTypePreq: + // reset Flags + //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, (BYTE) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag2, (BYTE) 0); + // PDO size + //AmiSetWordToLe(&pTxFrame->m_Data.m_Preq.m_le_wSize, 0); + break; + + default: + break; + } + // EPL message type + AmiSetByteToLe(&pTxFrame->m_le_bMessageType, (BYTE) MsgType_p); + } + + *ppFrame_p = pTxFrame; + *puiFrameSize_p = pTxBuffer->m_uiMaxBufferLen; + *puiHandle_p = uiHandle; + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkDeleteTxFrame +// +// Description: deletes the buffer for a Tx frame and frees it in the +// ethernet driver +// +// Parameters: uiHandle_p = IN: handle to frame buffer +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkDeleteTxFrame (unsigned int uiHandle_p) +{ +tEplKernel Ret = kEplSuccessful; +tEdrvTxBuffer *pTxBuffer = NULL; + + if (uiHandle_p >= EplDllkInstance_g.m_uiMaxTxFrames) + { // handle is not valid + Ret = kEplDllIllegalHdl; + goto Exit; + } + + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle_p]; + + // mark buffer as free so that frame will not be send in future anymore + // $$$ d.k. What's up with running transmissions? + pTxBuffer->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY; + pTxBuffer->m_pbBuffer = NULL; + + // delete Tx buffer + Ret = EdrvReleaseTxMsgBuffer(pTxBuffer); + if (Ret != kEplSuccessful) + { // error occured while releasing Tx frame + goto Exit; + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkProcess +// +// Description: process the passed event +// +// Parameters: pEvent_p = event to be processed +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkProcess(tEplEvent * pEvent_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplFrame *pTxFrame; +tEdrvTxBuffer *pTxBuffer; +unsigned int uiHandle; +unsigned int uiFrameSize; +BYTE abMulticastMac[6]; +tEplDllAsyncReqPriority AsyncReqPriority; +unsigned int uiFrameCount; +tEplNmtState NmtState; +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) +tEplFrameInfo FrameInfo; +#endif + + + switch (pEvent_p->m_EventType) + { + case kEplEventTypeDllkCreate: + { + // $$$ reset ethernet driver + + NmtState = *((tEplNmtState*)pEvent_p->m_pArg); + + // initialize flags for PRes and StatusRes + EplDllkInstance_g.m_bFlag1 = EPL_FRAME_FLAG1_EC; + EplDllkInstance_g.m_bMnFlag1 = 0; + EplDllkInstance_g.m_bFlag2 = 0; + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // initialize linked node list + EplDllkInstance_g.m_pFirstNodeInfo = NULL; +#endif + + // register TxFrames in Edrv + + // IdentResponse + uiFrameSize = EPL_C_DLL_MINSIZE_IDENTRES; + Ret = EplDllkCreateTxFrame(&uiHandle, &pTxFrame, &uiFrameSize, kEplMsgTypeAsnd, kEplDllAsndIdentResponse); + if (Ret != kEplSuccessful) + { // error occured while registering Tx frame + goto Exit; + } + + // EPL profile version + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_bEplProfileVersion, + (BYTE) EPL_SPEC_VERSION); + // FeatureFlags + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwFeatureFlags, + EplDllkInstance_g.m_DllConfigParam.m_dwFeatureFlags); + // MTU + AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_wMtu, + (WORD) EplDllkInstance_g.m_DllConfigParam.m_uiAsyncMtu); + // PollInSize + AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_wPollInSize, + (WORD)EplDllkInstance_g.m_DllConfigParam.m_uiPreqActPayloadLimit); + // PollOutSize + AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_wPollOutSize, + (WORD)EplDllkInstance_g.m_DllConfigParam.m_uiPresActPayloadLimit); + // ResponseTime / PresMaxLatency + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwResponseTime, + EplDllkInstance_g.m_DllConfigParam.m_dwPresMaxLatency); + // DeviceType + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwDeviceType, + EplDllkInstance_g.m_DllIdentParam.m_dwDeviceType); + // VendorId + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwVendorId, + EplDllkInstance_g.m_DllIdentParam.m_dwVendorId); + // ProductCode + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwProductCode, + EplDllkInstance_g.m_DllIdentParam.m_dwProductCode); + // RevisionNumber + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwRevisionNumber, + EplDllkInstance_g.m_DllIdentParam.m_dwRevisionNumber); + // SerialNumber + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwSerialNumber, + EplDllkInstance_g.m_DllIdentParam.m_dwSerialNumber); + // VendorSpecificExt1 + AmiSetQword64ToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_qwVendorSpecificExt1, + EplDllkInstance_g.m_DllIdentParam.m_qwVendorSpecificExt1); + // VerifyConfigurationDate + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwVerifyConfigurationDate, + EplDllkInstance_g.m_DllIdentParam.m_dwVerifyConfigurationDate); + // VerifyConfigurationTime + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwVerifyConfigurationTime, + EplDllkInstance_g.m_DllIdentParam.m_dwVerifyConfigurationTime); + // ApplicationSwDate + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwApplicationSwDate, + EplDllkInstance_g.m_DllIdentParam.m_dwApplicationSwDate); + // ApplicationSwTime + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwApplicationSwTime, + EplDllkInstance_g.m_DllIdentParam.m_dwApplicationSwTime); + // IPAddress + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwIpAddress, + EplDllkInstance_g.m_DllIdentParam.m_dwIpAddress); + // SubnetMask + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwSubnetMask, + EplDllkInstance_g.m_DllIdentParam.m_dwSubnetMask); + // DefaultGateway + AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_dwDefaultGateway, + EplDllkInstance_g.m_DllIdentParam.m_dwDefaultGateway); + // HostName + EPL_MEMCPY(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_sHostname[0], + &EplDllkInstance_g.m_DllIdentParam.m_sHostname[0], + sizeof (EplDllkInstance_g.m_DllIdentParam.m_sHostname)); + // VendorSpecificExt2 + EPL_MEMCPY(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_abVendorSpecificExt2[0], + &EplDllkInstance_g.m_DllIdentParam.m_abVendorSpecificExt2[0], + sizeof (EplDllkInstance_g.m_DllIdentParam.m_abVendorSpecificExt2)); + + // StatusResponse + uiFrameSize = EPL_C_DLL_MINSIZE_STATUSRES; + Ret = EplDllkCreateTxFrame(&uiHandle, &pTxFrame, &uiFrameSize, kEplMsgTypeAsnd, kEplDllAsndStatusResponse); + if (Ret != kEplSuccessful) + { // error occured while registering Tx frame + goto Exit; + } + + // PRes $$$ maybe move this to PDO module + if ((EplDllkInstance_g.m_DllConfigParam.m_fAsyncOnly == FALSE) + && (EplDllkInstance_g.m_DllConfigParam.m_uiPresActPayloadLimit >= 36)) + { // it is not configured as async-only CN, + // so take part in isochronous phase and register PRes frame + uiFrameSize = EplDllkInstance_g.m_DllConfigParam.m_uiPresActPayloadLimit + 24; + Ret = EplDllkCreateTxFrame(&uiHandle, &pTxFrame, &uiFrameSize, kEplMsgTypePres, kEplDllAsndNotDefined); + if (Ret != kEplSuccessful) + { // error occured while registering Tx frame + goto Exit; + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + // initially encode TPDO -> inform PDO module + FrameInfo.m_pFrame = pTxFrame; + FrameInfo.m_uiFrameSize = uiFrameSize; + Ret = EplPdokCbPdoTransmitted(&FrameInfo); +#endif + // reset cycle counter + EplDllkInstance_g.m_uiCycleCount = 0; + } + else + { // it is an async-only CN + // fool EplDllkChangeState() to think that PRes was not expected + EplDllkInstance_g.m_uiCycleCount = 1; + } + + // NMT request + uiFrameSize = EPL_C_IP_MAX_MTU; + Ret = EplDllkCreateTxFrame(&uiHandle, &pTxFrame, &uiFrameSize, kEplMsgTypeAsnd, kEplDllAsndNmtRequest); + if (Ret != kEplSuccessful) + { // error occured while registering Tx frame + goto Exit; + } + // mark Tx buffer as empty + EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY; + + // non-EPL frame + uiFrameSize = EPL_C_IP_MAX_MTU; + Ret = EplDllkCreateTxFrame(&uiHandle, &pTxFrame, &uiFrameSize, kEplMsgTypeNonEpl, kEplDllAsndNotDefined); + if (Ret != kEplSuccessful) + { // error occured while registering Tx frame + goto Exit; + } + // mark Tx buffer as empty + EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY; + + // register multicast MACs in ethernet driver + AmiSetQword48ToBe(&abMulticastMac[0], EPL_C_DLL_MULTICAST_SOC); + Ret = EdrvDefineRxMacAddrEntry(abMulticastMac); + AmiSetQword48ToBe(&abMulticastMac[0], EPL_C_DLL_MULTICAST_SOA); + Ret = EdrvDefineRxMacAddrEntry(abMulticastMac); + AmiSetQword48ToBe(&abMulticastMac[0], EPL_C_DLL_MULTICAST_PRES); + Ret = EdrvDefineRxMacAddrEntry(abMulticastMac); + AmiSetQword48ToBe(&abMulticastMac[0], EPL_C_DLL_MULTICAST_ASND); + Ret = EdrvDefineRxMacAddrEntry(abMulticastMac); + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + if (NmtState >= kEplNmtMsNotActive) + { // local node is MN + unsigned int uiIndex; + + // SoC + uiFrameSize = EPL_C_DLL_MINSIZE_SOC; + Ret = EplDllkCreateTxFrame(&uiHandle, &pTxFrame, &uiFrameSize, kEplMsgTypeSoc, kEplDllAsndNotDefined); + if (Ret != kEplSuccessful) + { // error occured while registering Tx frame + goto Exit; + } + + // SoA + uiFrameSize = EPL_C_DLL_MINSIZE_SOA; + Ret = EplDllkCreateTxFrame(&uiHandle, &pTxFrame, &uiFrameSize, kEplMsgTypeSoa, kEplDllAsndNotDefined); + if (Ret != kEplSuccessful) + { // error occured while registering Tx frame + goto Exit; + } + + for (uiIndex = 0; uiIndex < tabentries (EplDllkInstance_g.m_aNodeInfo); uiIndex++) + { +// EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1; + EplDllkInstance_g.m_aNodeInfo[uiIndex].m_wPresPayloadLimit = (WORD) EplDllkInstance_g.m_DllConfigParam.m_uiIsochrRxMaxPayload; + } + + // calculate cycle length + EplDllkInstance_g.m_ullFrameTimeout = 1000LL + * ((unsigned long long) EplDllkInstance_g.m_DllConfigParam.m_dwCycleLen); + } +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + Ret = EplDllkCalAsyncClearBuffer(); + + break; + } + + case kEplEventTypeDllkDestroy: + { + // destroy all data structures + + NmtState = *((tEplNmtState*)pEvent_p->m_pArg); + + // delete Tx frames + Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_IDENTRES); + if (Ret != kEplSuccessful) + { // error occured while deregistering Tx frame + goto Exit; + } + + Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_STATUSRES); + if (Ret != kEplSuccessful) + { // error occured while deregistering Tx frame + goto Exit; + } + + Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_PRES); + if (Ret != kEplSuccessful) + { // error occured while deregistering Tx frame + goto Exit; + } + + Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NMTREQ); + if (Ret != kEplSuccessful) + { // error occured while deregistering Tx frame + goto Exit; + } + + Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NONEPL); + if (Ret != kEplSuccessful) + { // error occured while deregistering Tx frame + goto Exit; + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + if (NmtState >= kEplNmtMsNotActive) + { // local node was MN + unsigned int uiIndex; + + Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOC); + if (Ret != kEplSuccessful) + { // error occured while deregistering Tx frame + goto Exit; + } + + Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOA); + if (Ret != kEplSuccessful) + { // error occured while deregistering Tx frame + goto Exit; + } + + for (uiIndex = 0; uiIndex < tabentries (EplDllkInstance_g.m_aNodeInfo); uiIndex++) + { + if (EplDllkInstance_g.m_aNodeInfo[uiIndex].m_pPreqTxBuffer != NULL) + { + uiHandle = EplDllkInstance_g.m_aNodeInfo[uiIndex].m_pPreqTxBuffer - EplDllkInstance_g.m_pTxBuffer; + EplDllkInstance_g.m_aNodeInfo[uiIndex].m_pPreqTxBuffer = NULL; + Ret = EplDllkDeleteTxFrame(uiHandle); + if (Ret != kEplSuccessful) + { // error occured while deregistering Tx frame + goto Exit; + } + + } + EplDllkInstance_g.m_aNodeInfo[uiIndex].m_wPresPayloadLimit = 0xFFFF; + } + } +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + // deregister multicast MACs in ethernet driver + AmiSetQword48ToBe(&abMulticastMac[0], EPL_C_DLL_MULTICAST_SOC); + Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac); + AmiSetQword48ToBe(&abMulticastMac[0], EPL_C_DLL_MULTICAST_SOA); + Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac); + AmiSetQword48ToBe(&abMulticastMac[0], EPL_C_DLL_MULTICAST_PRES); + Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac); + AmiSetQword48ToBe(&abMulticastMac[0], EPL_C_DLL_MULTICAST_ASND); + Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac); + + // delete timer +#if EPL_TIMER_USE_HIGHRES != FALSE + Ret = EplTimerHighReskDeleteTimer(&EplDllkInstance_g.m_TimerHdlCycle); +#endif + + break; + } + + case kEplEventTypeDllkFillTx: + { + // fill TxBuffer of specified priority with new frame if empty + + pTxFrame = NULL; + AsyncReqPriority = *((tEplDllAsyncReqPriority *) pEvent_p->m_pArg); + switch (AsyncReqPriority) + { + case kEplDllAsyncReqPrioNmt: // NMT request priority + { + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ]; + if (pTxBuffer->m_pbBuffer != NULL) + { // NmtRequest does exist + // check if frame is empty and not being filled + if (pTxBuffer->m_uiTxMsgLen == EPL_DLLK_BUFLEN_EMPTY) + { + // mark Tx buffer as filling is in process + pTxBuffer->m_uiTxMsgLen = EPL_DLLK_BUFLEN_FILLING; + // set max buffer size as input parameter + uiFrameSize = pTxBuffer->m_uiMaxBufferLen; + // copy frame from shared loop buffer to Tx buffer + Ret = EplDllkCalAsyncGetTxFrame( + pTxBuffer->m_pbBuffer, &uiFrameSize, AsyncReqPriority); + if (Ret == kEplSuccessful) + { + pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + Ret = EplDllkCheckFrame(pTxFrame, uiFrameSize); + + // set buffer valid + pTxBuffer->m_uiTxMsgLen = uiFrameSize; + } + else if (Ret == kEplDllAsyncTxBufferEmpty) + { // empty Tx buffer is not a real problem + // so just ignore it + Ret = kEplSuccessful; + // mark Tx buffer as empty + pTxBuffer->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY; + } + } + } + break; + } + + default: // generic priority + { + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL]; + if (pTxBuffer->m_pbBuffer != NULL) + { // non-EPL frame does exist + // check if frame is empty and not being filled + if (pTxBuffer->m_uiTxMsgLen == EPL_DLLK_BUFLEN_EMPTY) + { + // mark Tx buffer as filling is in process + pTxBuffer->m_uiTxMsgLen = EPL_DLLK_BUFLEN_FILLING; + // set max buffer size as input parameter + uiFrameSize = pTxBuffer->m_uiMaxBufferLen; + // copy frame from shared loop buffer to Tx buffer + Ret = EplDllkCalAsyncGetTxFrame( + pTxBuffer->m_pbBuffer, &uiFrameSize, AsyncReqPriority); + if (Ret == kEplSuccessful) + { + pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + Ret = EplDllkCheckFrame(pTxFrame, uiFrameSize); + + // set buffer valid + pTxBuffer->m_uiTxMsgLen = uiFrameSize; + } + else if (Ret == kEplDllAsyncTxBufferEmpty) + { // empty Tx buffer is not a real problem + // so just ignore it + Ret = kEplSuccessful; + // mark Tx buffer as empty + pTxBuffer->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY; + } + } + } + break; + } + } + + NmtState = EplNmtkGetNmtState(); + + if ((NmtState == kEplNmtCsBasicEthernet) || (NmtState == kEplNmtMsBasicEthernet)) + { // send frame immediately + if (pTxFrame != NULL) + { // frame is present + // padding is done by Edrv or ethernet controller + Ret = EdrvSendTxMsg(pTxBuffer); + } + else + { // no frame moved to TxBuffer + // check if TxBuffers contain unsent frames + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) + { // NMT request Tx buffer contains a frame + Ret = EdrvSendTxMsg( + &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ]); + } + else if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) + { // non-EPL Tx buffer contains a frame + Ret = EdrvSendTxMsg( + &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL]); + } + if (Ret == kEplInvalidOperation) + { // ignore error if caused by already active transmission + Ret = kEplSuccessful; + } + } + // reset PRes flag 2 + EplDllkInstance_g.m_bFlag2 = 0; + } + else + { + // update Flag 2 (PR, RS) + Ret = EplDllkCalAsyncGetTxCount(&AsyncReqPriority, &uiFrameCount); + if (AsyncReqPriority == kEplDllAsyncReqPrioNmt) + { // non-empty FIFO with hightest priority is for NMT requests + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) + { // NMT request Tx buffer contains a frame + // add one more frame + uiFrameCount++; + } + } + else + { // non-empty FIFO with highest priority is for generic frames + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) + { // NMT request Tx buffer contains a frame + // use NMT request FIFO, because of higher priority + uiFrameCount = 1; + AsyncReqPriority = kEplDllAsyncReqPrioNmt; + } + else if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) + { // non-EPL Tx buffer contains a frame + // use NMT request FIFO, because of higher priority + // add one more frame + uiFrameCount++; + } + } + + if (uiFrameCount > 7) + { // limit frame request to send counter to 7 + uiFrameCount = 7; + } + if (uiFrameCount > 0) + { + EplDllkInstance_g.m_bFlag2 = + (BYTE) (((AsyncReqPriority << EPL_FRAME_FLAG2_PR_SHIFT) & EPL_FRAME_FLAG2_PR) + | (uiFrameCount & EPL_FRAME_FLAG2_RS)); + } + else + { + EplDllkInstance_g.m_bFlag2 = 0; + } + } + + break; + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + case kEplEventTypeDllkStartReducedCycle: + { + // start the reduced cycle by programming the cycle timer + // it is issued by NMT MN module, when PreOp1 is entered + + // clear the asynchronous queues + Ret = EplDllkCalAsyncClearQueues(); + + // reset cycle counter (everytime a SoA is triggerd in PreOp1 the counter is incremented + // and when it reaches EPL_C_DLL_PREOP1_START_CYCLES the SoA may contain invitations) + EplDllkInstance_g.m_uiCycleCount = 0; + + // remove any CN from isochronous phase + while (EplDllkInstance_g.m_pFirstNodeInfo != NULL) + { + EplDllkDeleteNode(EplDllkInstance_g.m_pFirstNodeInfo->m_uiNodeId); + } + + // change state to NonCyclic, + // hence EplDllkChangeState() will not ignore the next call + EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic; + +#if EPL_TIMER_USE_HIGHRES != FALSE + if (EplDllkInstance_g.m_DllConfigParam.m_dwAsyncSlotTimeout != 0) + { + Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, + EplDllkInstance_g.m_DllConfigParam.m_dwAsyncSlotTimeout, + EplDllkCbMnTimerCycle, + 0L, + FALSE); + } +#endif + + break; + } +#endif + +#if EPL_DLL_PRES_READY_AFTER_SOA != FALSE + case kEplEventTypeDllkPresReady: + { + // post PRes to transmit FIFO + + NmtState = EplNmtkGetNmtState(); + + if (NmtState != kEplNmtCsBasicEthernet) + { + // Does PRes exist? + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES].m_pbBuffer != NULL) + { // PRes does exist + pTxFrame = (tEplFrame *) EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES].m_pbBuffer; + // update frame (NMT state, RD, RS, PR, MS, EN flags) + if (NmtState < kEplNmtCsPreOperational2) + { // NMT state is not PreOp2, ReadyToOp or Op + // fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater + NmtState = kEplNmtCsPreOperational2; + } + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bNmtStatus, (BYTE) NmtState); + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, EplDllkInstance_g.m_bFlag2); + if (NmtState != kEplNmtCsOperational) + { // mark PDO as invalid in NMT state Op + // $$$ reset only RD flag; set other flags appropriately + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, 0); + } + // $$$ make function that updates Pres, StatusRes + // mark PRes frame as ready for transmission + Ret = EdrvTxMsgReady(&EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]); + } + } + + break; + } +#endif + default: + { + ASSERTMSG(FALSE, "EplDllkProcess(): unhandled event type!\n"); + } + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkConfig +// +// Description: configure parameters of DLL +// +// Parameters: pDllConfigParam_p = configuration parameters +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkConfig(tEplDllConfigParam * pDllConfigParam_p) +{ +tEplKernel Ret = kEplSuccessful; + +// d.k. check of NMT state disabled, because CycleLen is programmed at run time by MN without reset of CN +/*tEplNmtState NmtState; + + NmtState = EplNmtkGetNmtState(); + + if (NmtState > kEplNmtGsResetConfiguration) + { // only allowed in state DLL_GS_INIT + Ret = kEplInvalidOperation; + goto Exit; + } +*/ + EPL_MEMCPY (&EplDllkInstance_g.m_DllConfigParam, pDllConfigParam_p, + (pDllConfigParam_p->m_uiSizeOfStruct < sizeof (tEplDllConfigParam) ? + pDllConfigParam_p->m_uiSizeOfStruct : sizeof (tEplDllConfigParam))); + + if ((EplDllkInstance_g.m_DllConfigParam.m_dwCycleLen != 0) + && (EplDllkInstance_g.m_DllConfigParam.m_dwLossOfFrameTolerance != 0)) + { // monitor EPL cycle, calculate frame timeout + EplDllkInstance_g.m_ullFrameTimeout = (1000LL + * ((unsigned long long) EplDllkInstance_g.m_DllConfigParam.m_dwCycleLen)) + + ((unsigned long long) EplDllkInstance_g.m_DllConfigParam.m_dwLossOfFrameTolerance); + } + else + { + EplDllkInstance_g.m_ullFrameTimeout = 0LL; + } + + if (EplDllkInstance_g.m_DllConfigParam.m_fAsyncOnly != FALSE) + { // it is configured as async-only CN + // disable multiplexed cycle, that m_uiCycleCount will not be incremented spuriously on SoC + EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt = 0; + } + +//Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkSetIdentity +// +// Description: configure identity of local node for IdentResponse +// +// Parameters: pDllIdentParam_p = identity +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkSetIdentity(tEplDllIdentParam * pDllIdentParam_p) +{ +tEplKernel Ret = kEplSuccessful; + + EPL_MEMCPY (&EplDllkInstance_g.m_DllIdentParam, pDllIdentParam_p, + (pDllIdentParam_p->m_uiSizeOfStruct < sizeof (tEplDllIdentParam) ? + pDllIdentParam_p->m_uiSizeOfStruct : sizeof (tEplDllIdentParam))); + + // $$$ if IdentResponse frame exists update it + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkRegAsyncHandler +// +// Description: registers handler for non-EPL frames +// +// Parameters: pfnDllkCbAsync_p = pointer to callback function +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p) +{ +tEplKernel Ret = kEplSuccessful; + + if (EplDllkInstance_g.m_pfnCbAsync == NULL) + { // no handler registered yet + EplDllkInstance_g.m_pfnCbAsync = pfnDllkCbAsync_p; + } + else + { // handler already registered + Ret = kEplDllCbAsyncRegistered; + } + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkDeregAsyncHandler +// +// Description: deregisters handler for non-EPL frames +// +// Parameters: pfnDllkCbAsync_p = pointer to callback function +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p) +{ +tEplKernel Ret = kEplSuccessful; + + if (EplDllkInstance_g.m_pfnCbAsync == pfnDllkCbAsync_p) + { // same handler is registered + // deregister it + EplDllkInstance_g.m_pfnCbAsync = NULL; + } + else + { // wrong handler or no handler registered + Ret = kEplDllCbAsyncRegistered; + } + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkSetAsndServiceIdFilter() +// +// Description: sets the specified node ID filter for the specified +// AsndServiceId. It registers C_DLL_MULTICAST_ASND in ethernet +// driver if any AsndServiceId is open. +// +// Parameters: ServiceId_p = ASnd Service ID +// Filter_p = node ID filter +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p, tEplDllAsndFilter Filter_p) +{ +tEplKernel Ret = kEplSuccessful; + + if (ServiceId_p < tabentries (EplDllkInstance_g.m_aAsndFilter)) + { + EplDllkInstance_g.m_aAsndFilter[ServiceId_p] = Filter_p; + } + + return Ret; +} + + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +//--------------------------------------------------------------------------- +// +// Function: EplDllkSetFlag1OfNode() +// +// Description: sets Flag1 (for PReq and SoA) of the specified node ID. +// +// Parameters: uiNodeId_p = node ID +// bSoaFlag1_p = flag1 +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, BYTE bSoaFlag1_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplDllkNodeInfo* pNodeInfo; + + pNodeInfo = EplDllkGetNodeInfo(uiNodeId_p); + if (pNodeInfo == NULL) + { // no node info structure available + Ret = kEplDllNoNodeInfo; + goto Exit; + } + + // store flag1 in internal node info structure + pNodeInfo->m_bSoaFlag1 = bSoaFlag1_p; + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkGetFirstNodeInfo() +// +// Description: returns first info structure of first node in isochronous phase. +// It is only useful for ErrorHandlerk module. +// +// Parameters: ppNodeInfo_p = pointer to pointer of internal node info structure +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkGetFirstNodeInfo(tEplDllkNodeInfo** ppNodeInfo_p) +{ +tEplKernel Ret = kEplSuccessful; + + *ppNodeInfo_p = EplDllkInstance_g.m_pFirstNodeInfo; + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkAddNode() +// +// Description: adds the specified node to the isochronous phase. +// +// Parameters: pNodeInfo_p = pointer of node info structure +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplDllkNodeInfo* pIntNodeInfo; +tEplDllkNodeInfo** ppIntNodeInfo; +unsigned int uiHandle; +tEplFrame* pFrame; +unsigned int uiFrameSize; + + pIntNodeInfo = EplDllkGetNodeInfo(pNodeInfo_p->m_uiNodeId); + if (pIntNodeInfo == NULL) + { // no node info structure available + Ret = kEplDllNoNodeInfo; + goto Exit; + } + + EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkAddNode, + pNodeInfo_p->m_uiNodeId, + 0); + + // copy node configuration + pIntNodeInfo->m_dwPresTimeout = pNodeInfo_p->m_dwPresTimeout; + pIntNodeInfo->m_wPresPayloadLimit = pNodeInfo_p->m_wPresPayloadLimit; + + // $$$ d.k.: actually add node only if MN. On CN it is sufficient to update the node configuration + if (pNodeInfo_p->m_uiNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) + { // we shall send PRes ourself + // insert our node at the end of the list + ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo; + while ((*ppIntNodeInfo != NULL) && ((*ppIntNodeInfo)->m_pNextNodeInfo != NULL)) + { + ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo; + } + if (*ppIntNodeInfo != NULL) + { + if ((*ppIntNodeInfo)->m_uiNodeId == pNodeInfo_p->m_uiNodeId) + { // node was already added to list + // $$$ d.k. maybe this should be an error + goto Exit; + } + else + { // add our node at the end of the list + ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo; + } + } + // set "PReq"-TxBuffer to PRes-TxBuffer + pIntNodeInfo->m_pPreqTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]; + } + else + { // normal CN shall be added to isochronous phase + // insert node into list in ascending order + ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo; + while ((*ppIntNodeInfo != NULL) + && ((*ppIntNodeInfo)->m_uiNodeId < pNodeInfo_p->m_uiNodeId) + && ((*ppIntNodeInfo)->m_uiNodeId != EplDllkInstance_g.m_DllConfigParam.m_uiNodeId)) + { + ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo; + } + if ((*ppIntNodeInfo != NULL) && ((*ppIntNodeInfo)->m_uiNodeId == pNodeInfo_p->m_uiNodeId)) + { // node was already added to list + // $$$ d.k. maybe this should be an error + goto Exit; + } + } + + // initialize elements of internal node info structure + pIntNodeInfo->m_bSoaFlag1 = 0; + pIntNodeInfo->m_fSoftDelete = FALSE; + pIntNodeInfo->m_NmtState = kEplNmtCsNotActive; + if (pIntNodeInfo->m_pPreqTxBuffer == NULL) + { // create TxBuffer entry + uiFrameSize = pNodeInfo_p->m_wPreqPayloadLimit + 24; + Ret = EplDllkCreateTxFrame(&uiHandle, &pFrame, &uiFrameSize, kEplMsgTypePreq, kEplDllAsndNotDefined); + if (Ret != kEplSuccessful) + { + goto Exit; + } + pIntNodeInfo->m_pPreqTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle]; + AmiSetByteToLe(&pFrame->m_le_bDstNodeId, (BYTE) pNodeInfo_p->m_uiNodeId); + + // set up destination MAC address + EPL_MEMCPY(pFrame->m_be_abDstMac, pIntNodeInfo->m_be_abMacAddr, 6); + + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + { + tEplFrameInfo FrameInfo; + + // initially encode TPDO -> inform PDO module + FrameInfo.m_pFrame = pFrame; + FrameInfo.m_uiFrameSize = uiFrameSize; + Ret = EplPdokCbPdoTransmitted(&FrameInfo); + } + #endif + } + pIntNodeInfo->m_ulDllErrorEvents = 0L; + // add node to list + pIntNodeInfo->m_pNextNodeInfo = *ppIntNodeInfo; + *ppIntNodeInfo = pIntNodeInfo; + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkDeleteNode() +// +// Description: removes the specified node from the isochronous phase. +// +// Parameters: uiNodeId_p = node ID +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkDeleteNode(unsigned int uiNodeId_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplDllkNodeInfo* pIntNodeInfo; +tEplDllkNodeInfo** ppIntNodeInfo; +unsigned int uiHandle; + + pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p); + if (pIntNodeInfo == NULL) + { // no node info structure available + Ret = kEplDllNoNodeInfo; + goto Exit; + } + + EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkDelNode, + uiNodeId_p, + 0); + + // search node in whole list + ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo; + while ((*ppIntNodeInfo != NULL) && ((*ppIntNodeInfo)->m_uiNodeId != uiNodeId_p)) + { + ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo; + } + if ((*ppIntNodeInfo == NULL) || ((*ppIntNodeInfo)->m_uiNodeId != uiNodeId_p)) + { // node was not found in list + // $$$ d.k. maybe this should be an error + goto Exit; + } + + // remove node from list + *ppIntNodeInfo = pIntNodeInfo->m_pNextNodeInfo; + + if ((pIntNodeInfo->m_pPreqTxBuffer != NULL) + && (pIntNodeInfo->m_pPreqTxBuffer != &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES])) + { // delete TxBuffer entry + uiHandle = pIntNodeInfo->m_pPreqTxBuffer - EplDllkInstance_g.m_pTxBuffer; + pIntNodeInfo->m_pPreqTxBuffer = NULL; + Ret = EplDllkDeleteTxFrame(uiHandle); +/* if (Ret != kEplSuccessful) + { + goto Exit; + }*/ + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkSoftDeleteNode() +// +// Description: removes the specified node not immediately from the isochronous phase. +// Instead the will be removed after error (late/loss PRes) without +// charging the error. +// +// Parameters: uiNodeId_p = node ID +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkSoftDeleteNode(unsigned int uiNodeId_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplDllkNodeInfo* pIntNodeInfo; + + pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p); + if (pIntNodeInfo == NULL) + { // no node info structure available + Ret = kEplDllNoNodeInfo; + goto Exit; + } + + EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkSoftDelNode, + uiNodeId_p, + 0); + + pIntNodeInfo->m_fSoftDelete = TRUE; + +Exit: + return Ret; +} + + +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkChangeState +// +// Description: change DLL state on event and diagnose some communication errors +// +// Parameters: NmtEvent_p = DLL event (wrapped in NMT event) +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p, tEplNmtState NmtState_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; +tEplErrorHandlerkEvent DllEvent; + + DllEvent.m_ulDllErrorEvents = 0; + DllEvent.m_uiNodeId = 0; + DllEvent.m_NmtState = NmtState_p; + + switch (NmtState_p) + { + case kEplNmtGsOff: + case kEplNmtGsInitialising: + case kEplNmtGsResetApplication: + case kEplNmtGsResetCommunication: + case kEplNmtGsResetConfiguration: + case kEplNmtCsBasicEthernet: + // enter DLL_GS_INIT + EplDllkInstance_g.m_DllState = kEplDllGsInit; + break; + + case kEplNmtCsNotActive: + case kEplNmtCsPreOperational1: + // reduced EPL cycle is active + if (NmtEvent_p == kEplNmtEventDllCeSoc) + { // SoC received + // enter DLL_CS_WAIT_PREQ + EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq; + } + else + { + // enter DLL_GS_INIT + EplDllkInstance_g.m_DllState = kEplDllGsInit; + } + break; + + case kEplNmtCsPreOperational2: + case kEplNmtCsReadyToOperate: + case kEplNmtCsOperational: + // full EPL cycle is active + + switch (EplDllkInstance_g.m_DllState) + { + case kEplDllCsWaitPreq: + switch (NmtEvent_p) + { + // DLL_CT2 + case kEplNmtEventDllCePreq: + // enter DLL_CS_WAIT_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_RECVD_PREQ; + EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa; + break; + + // DLL_CT8 + case kEplNmtEventDllCeFrameTimeout: + if (NmtState_p == kEplNmtCsPreOperational2) + { // ignore frame timeout in PreOp2, + // because the previously configured cycle len + // may be wrong. + // 2008/10/15 d.k. If it would not be ignored, + // we would go cyclically to PreOp1 and on next + // SoC back to PreOp2. + break; + } + + // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA | EPL_DLL_ERR_CN_LOSS_SOC; + + // enter DLL_CS_WAIT_SOC + EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc; + break; + + case kEplNmtEventDllCeSoa: + // check if multiplexed and PReq should have been received in this cycle + // and if >= NMT_CS_READY_TO_OPERATE + if ((EplDllkInstance_g.m_uiCycleCount == 0) + && (NmtState_p >= kEplNmtCsReadyToOperate)) + { // report DLL_CEV_LOSS_OF_PREQ + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_PREQ; + } + + // enter DLL_CS_WAIT_SOC + EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc; + break; + + // DLL_CT7 + case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCeAsnd: + // report DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA; + + case kEplNmtEventDllCePres: + default: + // remain in this state + break; + } + break; + + case kEplDllCsWaitSoc: + switch (NmtEvent_p) + { + // DLL_CT1 + case kEplNmtEventDllCeSoc: + // start of cycle and isochronous phase + // enter DLL_CS_WAIT_PREQ + EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq; + break; + + // DLL_CT4 +// case kEplNmtEventDllCePres: + case kEplNmtEventDllCeFrameTimeout: + if (NmtState_p == kEplNmtCsPreOperational2) + { // ignore frame timeout in PreOp2, + // because the previously configured cycle len + // may be wrong. + // 2008/10/15 d.k. If it would not be ignored, + // we would go cyclically to PreOp1 and on next + // SoC back to PreOp2. + break; + } + + // fall through + + case kEplNmtEventDllCePreq: + case kEplNmtEventDllCeSoa: + // report DLL_CEV_LOSS_SOC + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOC; + + case kEplNmtEventDllCeAsnd: + default: + // remain in this state + break; + } + break; + + case kEplDllCsWaitSoa: + switch (NmtEvent_p) + { + case kEplNmtEventDllCeFrameTimeout: + // DLL_CT3 + if (NmtState_p == kEplNmtCsPreOperational2) + { // ignore frame timeout in PreOp2, + // because the previously configured cycle len + // may be wrong. + // 2008/10/15 d.k. If it would not be ignored, + // we would go cyclically to PreOp1 and on next + // SoC back to PreOp2. + break; + } + + // fall through + + case kEplNmtEventDllCePreq: + // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA | EPL_DLL_ERR_CN_LOSS_SOC; + + case kEplNmtEventDllCeSoa: + // enter DLL_CS_WAIT_SOC + EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc; + break; + + // DLL_CT9 + case kEplNmtEventDllCeSoc: + // report DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA; + + // enter DLL_CS_WAIT_PREQ + EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq; + break; + + // DLL_CT10 + case kEplNmtEventDllCeAsnd: + // report DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA; + + case kEplNmtEventDllCePres: + default: + // remain in this state + break; + } + break; + + case kEplDllGsInit: + // enter DLL_CS_WAIT_PREQ + EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq; + break; + + default: + break; + } + break; + + case kEplNmtCsStopped: + // full EPL cycle is active, but without PReq/PRes + + switch (EplDllkInstance_g.m_DllState) + { + case kEplDllCsWaitPreq: + switch (NmtEvent_p) + { + // DLL_CT2 + case kEplNmtEventDllCePreq: + // enter DLL_CS_WAIT_SOA + EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa; + break; + + // DLL_CT8 + case kEplNmtEventDllCeFrameTimeout: + // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA | EPL_DLL_ERR_CN_LOSS_SOC; + + case kEplNmtEventDllCeSoa: + // NMT_CS_STOPPED active + // it is Ok if no PReq was received + + // enter DLL_CS_WAIT_SOC + EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc; + break; + + // DLL_CT7 + case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCeAsnd: + // report DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA; + + case kEplNmtEventDllCePres: + default: + // remain in this state + break; + } + break; + + case kEplDllCsWaitSoc: + switch (NmtEvent_p) + { + // DLL_CT1 + case kEplNmtEventDllCeSoc: + // start of cycle and isochronous phase + // enter DLL_CS_WAIT_SOA + EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa; + break; + + // DLL_CT4 +// case kEplNmtEventDllCePres: + case kEplNmtEventDllCePreq: + case kEplNmtEventDllCeSoa: + case kEplNmtEventDllCeFrameTimeout: + // report DLL_CEV_LOSS_SOC + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOC; + + case kEplNmtEventDllCeAsnd: + default: + // remain in this state + break; + } + break; + + case kEplDllCsWaitSoa: + switch (NmtEvent_p) + { + // DLL_CT3 + case kEplNmtEventDllCeFrameTimeout: + // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA | EPL_DLL_ERR_CN_LOSS_SOC; + + case kEplNmtEventDllCeSoa: + // enter DLL_CS_WAIT_SOC + EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc; + break; + + // DLL_CT9 + case kEplNmtEventDllCeSoc: + // report DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA; + // remain in DLL_CS_WAIT_SOA + break; + + // DLL_CT10 + case kEplNmtEventDllCeAsnd: + // report DLL_CEV_LOSS_SOA + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_CN_LOSS_SOA; + + case kEplNmtEventDllCePreq: + // NMT_CS_STOPPED active and we do not expect any PReq + // so just ignore it + case kEplNmtEventDllCePres: + default: + // remain in this state + break; + } + break; + + case kEplDllGsInit: + default: + // enter DLL_CS_WAIT_PREQ + EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa; + break; + } + break; + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + case kEplNmtMsNotActive: + case kEplNmtMsBasicEthernet: + break; + + case kEplNmtMsPreOperational1: + // reduced EPL cycle is active + if (EplDllkInstance_g.m_DllState != kEplDllMsNonCyclic) + { // stop cycle timer +#if EPL_TIMER_USE_HIGHRES != FALSE + Ret = EplTimerHighReskDeleteTimer(&EplDllkInstance_g.m_TimerHdlCycle); +#endif + EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic; + + // stop further processing, + // because it will be restarted by NMT MN module + break; + } + + switch (NmtEvent_p) + { + case kEplNmtEventDllMeSocTrig: + case kEplNmtEventDllCeAsnd: + { // because of reduced EPL cycle SoA shall be triggered, not SoC + tEplDllState DummyDllState; + + Ret = EplDllkAsyncFrameNotReceived(EplDllkInstance_g.m_LastReqServiceId, + EplDllkInstance_g.m_uiLastTargetNodeId); + + // go ahead and send SoA + Ret = EplDllkMnSendSoa(NmtState_p, + &DummyDllState, + (EplDllkInstance_g.m_uiCycleCount >= EPL_C_DLL_PREOP1_START_CYCLES)); + // increment cycle counter to detect if EPL_C_DLL_PREOP1_START_CYCLES empty cycles are elapsed + EplDllkInstance_g.m_uiCycleCount++; + + // reprogram timer +#if EPL_TIMER_USE_HIGHRES != FALSE + if (EplDllkInstance_g.m_DllConfigParam.m_dwAsyncSlotTimeout != 0) + { + Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, + EplDllkInstance_g.m_DllConfigParam.m_dwAsyncSlotTimeout, + EplDllkCbMnTimerCycle, + 0L, + FALSE); + } +#endif + break; + } + + default: + break; + } + break; + + case kEplNmtMsPreOperational2: + case kEplNmtMsReadyToOperate: + case kEplNmtMsOperational: + // full EPL cycle is active + switch (NmtEvent_p) + { + case kEplNmtEventDllMeSocTrig: + { + // update cycle counter + if (EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt > 0) + { // multiplexed cycle active + EplDllkInstance_g.m_uiCycleCount = (EplDllkInstance_g.m_uiCycleCount + 1) % EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt; + // $$$ check multiplexed cycle restart + // -> toggle MC flag + // -> change node linked list + } + else + { // non-multiplexed cycle active + // start with first node in isochronous phase + EplDllkInstance_g.m_pCurNodeInfo = NULL; + } + + switch (EplDllkInstance_g.m_DllState) + { + case kEplDllMsNonCyclic: + { // start continuous cycle timer +#if EPL_TIMER_USE_HIGHRES != FALSE + Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, + EplDllkInstance_g.m_ullFrameTimeout, + EplDllkCbMnTimerCycle, + 0L, + TRUE); +#endif + // continue with sending SoC + } + + case kEplDllMsWaitAsnd: + case kEplDllMsWaitSocTrig: + { // if m_LastReqServiceId is still valid, + // SoA was not correctly answered + // and user part has to be informed + Ret = EplDllkAsyncFrameNotReceived(EplDllkInstance_g.m_LastReqServiceId, + EplDllkInstance_g.m_uiLastTargetNodeId); + + // send SoC + Ret = EplDllkMnSendSoc(); + + // new DLL state + EplDllkInstance_g.m_DllState = kEplDllMsWaitPreqTrig; + + // start WaitSoCPReq Timer +#if EPL_TIMER_USE_HIGHRES != FALSE + Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlResponse, + EplDllkInstance_g.m_DllConfigParam.m_dwWaitSocPreq, + EplDllkCbMnTimerResponse, + 0L, + FALSE); +#endif + break; + } + + default: + { // wrong DLL state / cycle time exceeded + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_MN_CYCTIMEEXCEED; + EplDllkInstance_g.m_DllState = kEplDllMsWaitSocTrig; + break; + } + } + + break; + } + + case kEplNmtEventDllMePresTimeout: + { + + switch (EplDllkInstance_g.m_DllState) + { + case kEplDllMsWaitPres: + { // PRes not received + + if (EplDllkInstance_g.m_pCurNodeInfo->m_fSoftDelete == FALSE) + { // normal isochronous CN + DllEvent.m_ulDllErrorEvents |= EPL_DLL_ERR_MN_CN_LOSS_PRES; + DllEvent.m_uiNodeId = EplDllkInstance_g.m_pCurNodeInfo->m_uiNodeId; + } + else + { // CN shall be deleted softly + Event.m_EventSink = kEplEventSinkDllkCal; + Event.m_EventType = kEplEventTypeDllkSoftDelNode; + // $$$ d.k. set Event.m_NetTime to current time + Event.m_uiSize = sizeof (unsigned int); + Event.m_pArg = &EplDllkInstance_g.m_pCurNodeInfo->m_uiNodeId; + Ret = EplEventkPost(&Event); + } + + // continue with sending next PReq + } + + case kEplDllMsWaitPreqTrig: + { + // send next PReq + Ret = EplDllkMnSendPreq(NmtState_p, &EplDllkInstance_g.m_DllState); + + break; + } + + default: + { // wrong DLL state + break; + } + } + + break; + } + + case kEplNmtEventDllCePres: + { + + switch (EplDllkInstance_g.m_DllState) + { + case kEplDllMsWaitPres: + { // PRes received + // send next PReq + Ret = EplDllkMnSendPreq(NmtState_p, &EplDllkInstance_g.m_DllState); + + break; + } + + default: + { // wrong DLL state + break; + } + } + + break; + } + + case kEplNmtEventDllMeSoaTrig: + { + + switch (EplDllkInstance_g.m_DllState) + { + case kEplDllMsWaitSoaTrig: + { // MN PRes sent + // send SoA + Ret = EplDllkMnSendSoa(NmtState_p, &EplDllkInstance_g.m_DllState, TRUE); + + break; + } + + default: + { // wrong DLL state + break; + } + } + + break; + } + + case kEplNmtEventDllCeAsnd: + { // ASnd has been received, but it may be not the requested one +/* + // report if SoA was correctly answered + Ret = EplDllkAsyncFrameNotReceived(EplDllkInstance_g.m_LastReqServiceId, + EplDllkInstance_g.m_uiLastTargetNodeId); +*/ + if (EplDllkInstance_g.m_DllState == kEplDllMsWaitAsnd) + { + EplDllkInstance_g.m_DllState = kEplDllMsWaitSocTrig; + } + break; + } + + default: + break; + } + break; +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + default: + break; + } + + if (DllEvent.m_ulDllErrorEvents != 0) + { // error event set -> post it to error handler + Event.m_EventSink = kEplEventSinkErrk; + Event.m_EventType = kEplEventTypeDllError; + // $$$ d.k. set Event.m_NetTime to current time + Event.m_uiSize = sizeof (DllEvent); + Event.m_pArg = &DllEvent; + Ret = EplEventkPost(&Event); + } + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCbFrameReceived() +// +// Description: called from EdrvInterruptHandler() +// +// Parameters: pRxBuffer_p = receive buffer structure +// +// Returns: (none) +// +// +// State: +// +//--------------------------------------------------------------------------- + +static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplNmtState NmtState; +tEplNmtEvent NmtEvent = kEplNmtEventNoEvent; +tEplEvent Event; +tEplFrame *pFrame; +tEplFrame *pTxFrame; +tEdrvTxBuffer *pTxBuffer = NULL; +tEplFrameInfo FrameInfo; +tEplMsgType MsgType; +tEplDllReqServiceId ReqServiceId; +unsigned int uiAsndServiceId; +unsigned int uiNodeId; +BYTE bFlag1; + + BENCHMARK_MOD_02_SET(3); + NmtState = EplNmtkGetNmtState(); + + if (NmtState <= kEplNmtGsResetConfiguration) + { + goto Exit; + } + + pFrame = (tEplFrame *) pRxBuffer_p->m_pbBuffer; + +#if EDRV_EARLY_RX_INT != FALSE + switch (pRxBuffer_p->m_BufferInFrame) + { + case kEdrvBufferFirstInFrame: + { + MsgType = (tEplMsgType)AmiGetByteFromLe(&pFrame->m_le_bMessageType); + if (MsgType == kEplMsgTypePreq) + { + if (EplDllkInstance_g.m_DllState == kEplDllCsWaitPreq) + { // PReq expected and actually received + // d.k.: The condition above is sufficent, because EPL cycle is active + // and no non-EPL frame shall be received in isochronous phase. + // start transmission PRes + // $$$ What if Tx buffer is invalid? + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]; +#if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE) + Ret = EdrvTxMsgStart(pTxBuffer); +#else + pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + // update frame (NMT state, RD, RS, PR, MS, EN flags) + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bNmtStatus, (BYTE) NmtState); + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, EplDllkInstance_g.m_bFlag2); + if (NmtState != kEplNmtCsOperational) + { // mark PDO as invalid in NMT state Op + // $$$ reset only RD flag; set other flags appropriately + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, 0); + } + // $$$ make function that updates Pres, StatusRes + // send PRes frame + Ret = EdrvSendTxMsg(pTxBuffer); +#endif + } + } + goto Exit; + } + + case kEdrvBufferMiddleInFrame: + { + goto Exit; + } + + case kEdrvBufferLastInFrame: + { + break; + } + } +#endif + + FrameInfo.m_pFrame = pFrame; + FrameInfo.m_uiFrameSize = pRxBuffer_p->m_uiRxMsgLen; + FrameInfo.m_NetTime.m_dwNanoSec = pRxBuffer_p->m_NetTime.m_dwNanoSec; + FrameInfo.m_NetTime.m_dwSec = pRxBuffer_p->m_NetTime.m_dwSec; + + if (AmiGetWordFromBe(&pFrame->m_be_wEtherType) != EPL_C_DLL_ETHERTYPE_EPL) + { // non-EPL frame + //TRACE2("EplDllkCbFrameReceived: pfnCbAsync=0x%p SrcMAC=0x%llx\n", EplDllkInstance_g.m_pfnCbAsync, AmiGetQword48FromBe(pFrame->m_be_abSrcMac)); + if (EplDllkInstance_g.m_pfnCbAsync != NULL) + { // handler for async frames is registered + EplDllkInstance_g.m_pfnCbAsync(&FrameInfo); + } + + goto Exit; + } + + MsgType = (tEplMsgType)AmiGetByteFromLe(&pFrame->m_le_bMessageType); + switch (MsgType) + { + case kEplMsgTypePreq: + { + // PReq frame + // d.k.: (we assume that this PReq frame is intended for us and don't check DstNodeId) + if (AmiGetByteFromLe(&pFrame->m_le_bDstNodeId) != EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) + { // this PReq is not intended for us + goto Exit; + } + NmtEvent = kEplNmtEventDllCePreq; + + if (NmtState >= kEplNmtMsNotActive) + { // MN is active -> wrong msg type + break; + } + +#if EDRV_EARLY_RX_INT == FALSE + if (NmtState >= kEplNmtCsPreOperational2) + { // respond to and process PReq frames only in PreOp2, ReadyToOp and Op + // Does PRes exist? + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]; + if (pTxBuffer->m_pbBuffer != NULL) + { // PRes does exist +#if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE) + EdrvTxMsgStart(pTxBuffer); +#else + pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + // update frame (NMT state, RD, RS, PR, MS, EN flags) + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bNmtStatus, (BYTE) NmtState); + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, EplDllkInstance_g.m_bFlag2); + bFlag1 = AmiGetByteFromLe(&pFrame->m_Data.m_Preq.m_le_bFlag1); + // save EA flag + EplDllkInstance_g.m_bMnFlag1 = + (EplDllkInstance_g.m_bMnFlag1 & ~EPL_FRAME_FLAG1_EA) + | (bFlag1 & EPL_FRAME_FLAG1_EA); + // preserve MS flag + bFlag1 &= EPL_FRAME_FLAG1_MS; + // add EN flag from Error signaling module + bFlag1 |= EplDllkInstance_g.m_bFlag1 & EPL_FRAME_FLAG1_EN; + if (NmtState != kEplNmtCsOperational) + { // mark PDO as invalid in NMT state Op + // reset only RD flag + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, bFlag1); + } + else + { // leave RD flag untouched + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, + (AmiGetByteFromLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1) & EPL_FRAME_FLAG1_RD) + | bFlag1); + } + // $$$ update EPL_DLL_PRES_READY_AFTER_* code + // send PRes frame + Ret = EdrvSendTxMsg(pTxBuffer); + if (Ret != kEplSuccessful) + { + goto Exit; + } +#endif + } +#endif + // inform PDO module +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + if (NmtState >= kEplNmtCsReadyToOperate) + { // inform PDO module only in ReadyToOp and Op + if (NmtState != kEplNmtCsOperational) + { + // reset RD flag and all other flags, but that does not matter, because they were processed above + AmiSetByteToLe(&pFrame->m_Data.m_Preq.m_le_bFlag1, 0); + } + + // compares real frame size and PDO size + if ((unsigned int) (AmiGetWordFromLe(&pFrame->m_Data.m_Preq.m_le_wSize) + 24) + > FrameInfo.m_uiFrameSize) + { // format error + tEplErrorHandlerkEvent DllEvent; + + DllEvent.m_ulDllErrorEvents = EPL_DLL_ERR_INVALID_FORMAT; + DllEvent.m_uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId); + DllEvent.m_NmtState = NmtState; + Event.m_EventSink = kEplEventSinkErrk; + Event.m_EventType = kEplEventTypeDllError; + Event.m_NetTime = FrameInfo.m_NetTime; + Event.m_uiSize = sizeof (DllEvent); + Event.m_pArg = &DllEvent; + Ret = EplEventkPost(&Event); + break; + } + + // forward PReq frame as RPDO to PDO module + Ret = EplPdokCbPdoReceived(&FrameInfo); + + } +#if (EPL_DLL_PRES_READY_AFTER_SOC != FALSE) + if (pTxBuffer->m_pbBuffer != NULL) + { // PRes does exist + // inform PDO module about PRes after PReq + FrameInfo.m_pFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + FrameInfo.m_uiFrameSize = pTxBuffer->m_uiMaxBufferLen; + Ret = EplPdokCbPdoTransmitted(&FrameInfo); + } +#endif +#endif + +#if EDRV_EARLY_RX_INT == FALSE + // $$$ inform emergency protocol handling (error signaling module) about flags + } +#endif + + // reset cycle counter + EplDllkInstance_g.m_uiCycleCount = 0; + + break; + } + + case kEplMsgTypePres: + { +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + tEplDllkNodeInfo* pIntNodeInfo; + tEplHeartbeatEvent HeartbeatEvent; +#endif + + // PRes frame + NmtEvent = kEplNmtEventDllCePres; + + uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId); + + if ((NmtState >= kEplNmtCsPreOperational2) + && (NmtState <= kEplNmtCsOperational)) + { // process PRes frames only in PreOp2, ReadyToOp and Op of CN + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId); + if (pIntNodeInfo == NULL) + { // no node info structure available + Ret = kEplDllNoNodeInfo; + goto Exit; + } + } + else if (EplDllkInstance_g.m_DllState == kEplDllMsWaitPres) + { // or process PRes frames in MsWaitPres + + pIntNodeInfo = EplDllkInstance_g.m_pCurNodeInfo; + if ((pIntNodeInfo == NULL) || (pIntNodeInfo->m_uiNodeId != uiNodeId)) + { // ignore PRes, because it is from wrong CN + // $$$ maybe post event to NmtMn module + goto Exit; + } + + // forward Flag2 to asynchronous scheduler + bFlag1 = AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.m_Payload.m_StatusResponse.m_le_bFlag2); + Ret = EplDllkCalAsyncSetPendingRequests(uiNodeId, + ((tEplDllAsyncReqPriority) ((bFlag1 & EPL_FRAME_FLAG2_PR) >> EPL_FRAME_FLAG2_PR_SHIFT)), + (bFlag1 & EPL_FRAME_FLAG2_RS)); + +#endif + } + else + { // ignore PRes, because it was received in wrong NMT state + // but execute EplDllkChangeState() and post event to NMT module + break; + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + { // check NMT state of CN + HeartbeatEvent.m_wErrorCode = EPL_E_NO_ERROR; + HeartbeatEvent.m_NmtState = + (tEplNmtState) (AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bNmtStatus) | EPL_NMT_TYPE_CS); + if (pIntNodeInfo->m_NmtState != HeartbeatEvent.m_NmtState) + { // NMT state of CN has changed -> post event to NmtMnu module + if (pIntNodeInfo->m_fSoftDelete == FALSE) + { // normal isochronous CN + HeartbeatEvent.m_uiNodeId = uiNodeId; + Event.m_EventSink = kEplEventSinkNmtMnu; + Event.m_EventType = kEplEventTypeHeartbeat; + Event.m_uiSize = sizeof (HeartbeatEvent); + Event.m_pArg = &HeartbeatEvent; + } + else + { // CN shall be deleted softly + Event.m_EventSink = kEplEventSinkDllkCal; + Event.m_EventType = kEplEventTypeDllkSoftDelNode; + Event.m_uiSize = sizeof (unsigned int); + Event.m_pArg = &pIntNodeInfo->m_uiNodeId; + } + Event.m_NetTime = FrameInfo.m_NetTime; + Ret = EplEventkPost(&Event); + + // save current NMT state of CN in internal node structure + pIntNodeInfo->m_NmtState = HeartbeatEvent.m_NmtState; + } + } +#endif + + // inform PDO module +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + if ((NmtState != kEplNmtCsPreOperational2) + && (NmtState != kEplNmtMsPreOperational2)) + { // inform PDO module only in ReadyToOp and Op + // compare real frame size and PDO size? + if (((unsigned int) (AmiGetWordFromLe(&pFrame->m_Data.m_Pres.m_le_wSize) + 24) + > FrameInfo.m_uiFrameSize) +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + || (AmiGetWordFromLe(&pFrame->m_Data.m_Pres.m_le_wSize) > pIntNodeInfo->m_wPresPayloadLimit) +#endif + ) + { // format error + tEplErrorHandlerkEvent DllEvent; + + DllEvent.m_ulDllErrorEvents = EPL_DLL_ERR_INVALID_FORMAT; + DllEvent.m_uiNodeId = uiNodeId; + DllEvent.m_NmtState = NmtState; + Event.m_EventSink = kEplEventSinkErrk; + Event.m_EventType = kEplEventTypeDllError; + Event.m_NetTime = FrameInfo.m_NetTime; + Event.m_uiSize = sizeof (DllEvent); + Event.m_pArg = &DllEvent; + Ret = EplEventkPost(&Event); + break; + } + if ((NmtState != kEplNmtCsOperational) + && (NmtState != kEplNmtMsOperational)) + { + // reset RD flag and all other flags, but that does not matter, because they were processed above + AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bFlag1, 0); + } + Ret = EplPdokCbPdoReceived(&FrameInfo); + } +#endif + + break; + } + + case kEplMsgTypeSoc: + { + // SoC frame + NmtEvent = kEplNmtEventDllCeSoc; + + if (NmtState >= kEplNmtMsNotActive) + { // MN is active -> wrong msg type + break; + } + +#if EPL_DLL_PRES_READY_AFTER_SOC != FALSE + // post PRes to transmit FIFO of the ethernet controller, but don't start + // transmission over bus + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]; + // Does PRes exist? + if (pTxBuffer->m_pbBuffer != NULL) + { // PRes does exist + pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + // update frame (NMT state, RD, RS, PR, MS, EN flags) + if (NmtState < kEplNmtCsPreOperational2) + { // NMT state is not PreOp2, ReadyToOp or Op + // fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater + NmtState = kEplNmtCsPreOperational2; + } + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bNmtStatus, (BYTE) NmtState); + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, EplDllkInstance_g.m_bFlag2); + if (NmtState != kEplNmtCsOperational) + { // mark PDO as invalid in NMT state Op + // $$$ reset only RD flag; set other flags appropriately + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, 0); + } + // $$$ make function that updates Pres, StatusRes + // mark PRes frame as ready for transmission + Ret = EdrvTxMsgReady(pTxBuffer); + } +#endif + + if (NmtState >= kEplNmtCsPreOperational2) + { // SoC frames only in PreOp2, ReadyToOp and Op + // trigger synchronous task + Event.m_EventSink = kEplEventSinkSync; + Event.m_EventType = kEplEventTypeSync; + Event.m_uiSize = 0; + Ret = EplEventkPost(&Event); + + // update cycle counter + if (EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt > 0) + { // multiplexed cycle active + EplDllkInstance_g.m_uiCycleCount = (EplDllkInstance_g.m_uiCycleCount + 1) % EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt; + } + } + + // reprogram timer +#if EPL_TIMER_USE_HIGHRES != FALSE + if (EplDllkInstance_g.m_ullFrameTimeout != 0) + { + Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, EplDllkInstance_g.m_ullFrameTimeout, EplDllkCbCnTimer, 0L, FALSE); + } +#endif + + break; + } + + case kEplMsgTypeSoa: + { + // SoA frame + NmtEvent = kEplNmtEventDllCeSoa; + + if (NmtState >= kEplNmtMsNotActive) + { // MN is active -> wrong msg type + break; + } + + pTxFrame = NULL; + + if ((NmtState & EPL_NMT_SUPERSTATE_MASK) != EPL_NMT_CS_EPLMODE) + { // do not respond, if NMT state is < PreOp1 (i.e. not EPL_MODE) + break; + } + + // check TargetNodeId + uiNodeId = AmiGetByteFromLe(&pFrame->m_Data.m_Soa.m_le_bReqServiceTarget); + if (uiNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) + { // local node is the target of the current request + + // check ServiceId + ReqServiceId = (tEplDllReqServiceId) AmiGetByteFromLe(&pFrame->m_Data.m_Soa.m_le_bReqServiceId); + if (ReqServiceId == kEplDllReqServiceStatus) + { // StatusRequest + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) + { // StatusRes does exist + + pTxFrame = (tEplFrame *) EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer; + // update StatusRes frame (NMT state, EN, EC, RS, PR flags) + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_StatusResponse.m_le_bNmtStatus, (BYTE) NmtState); + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_StatusResponse.m_le_bFlag1, EplDllkInstance_g.m_bFlag1); + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_StatusResponse.m_le_bFlag2, EplDllkInstance_g.m_bFlag2); + // send StatusRes + Ret = EdrvSendTxMsg(&EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES]); + if (Ret != kEplSuccessful) + { + goto Exit; + } + TGT_DBG_SIGNAL_TRACE_POINT(8); + + // update error signaling + bFlag1 = AmiGetByteFromLe(&pFrame->m_Data.m_Soa.m_le_bFlag1); + if (((bFlag1 ^ EplDllkInstance_g.m_bMnFlag1) & EPL_FRAME_FLAG1_ER) != 0) + { // exception reset flag was changed by MN + // assume same state for EC in next cycle (clear all other bits) + if ((bFlag1 & EPL_FRAME_FLAG1_ER) != 0) + { + // set EC and reset rest + EplDllkInstance_g.m_bFlag1 = EPL_FRAME_FLAG1_EC; + } + else + { + // reset complete flag 1 (including EC and EN) + EplDllkInstance_g.m_bFlag1 = 0; + } + } + // save flag 1 from MN for Status request response cycle + EplDllkInstance_g.m_bMnFlag1 = bFlag1; + } + } + else if (ReqServiceId == kEplDllReqServiceIdent) + { // IdentRequest + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer != NULL) + { // IdentRes does exist + pTxFrame = (tEplFrame *) EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer; + // update IdentRes frame (NMT state, RS, PR flags) + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_bNmtStatus, (BYTE) NmtState); + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_bFlag2, EplDllkInstance_g.m_bFlag2); + // send IdentRes + Ret = EdrvSendTxMsg(&EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES]); + if (Ret != kEplSuccessful) + { + goto Exit; + } + TGT_DBG_SIGNAL_TRACE_POINT(7); + } + } + else if (ReqServiceId == kEplDllReqServiceNmtRequest) + { // NmtRequest + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_pbBuffer != NULL) + { // NmtRequest does exist + // check if frame is not empty and not being filled + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_FILLING) + { + /*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN) + { // pad frame + EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN; + }*/ + // memorize transmission + pTxFrame = (tEplFrame*)1; + // send NmtRequest + Ret = EdrvSendTxMsg(&EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ]); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + } + } + + } + else if (ReqServiceId == kEplDllReqServiceUnspecified) + { // unspecified invite + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_pbBuffer != NULL) + { // non-EPL frame does exist + // check if frame is not empty and not being filled + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_FILLING) + { + /*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN) + { // pad frame + EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN; + }*/ + // memorize transmission + pTxFrame = (tEplFrame*)1; + // send non-EPL frame + Ret = EdrvSendTxMsg(&EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL]); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + } + } + + } + else if (ReqServiceId == kEplDllReqServiceNo) + { // no async service requested -> do nothing + } + } + +#if EPL_DLL_PRES_READY_AFTER_SOA != FALSE + if (pTxFrame == NULL) + { // signal process function readiness of PRes frame + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkPresReady; + Event.m_uiSize = 0; + Event.m_pArg = NULL; + Ret = EplEventkPost(&Event); + } +#endif + + // inform PDO module +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) +// Ret = EplPdokCbSoa(&FrameInfo); +#endif + + // $$$ put SrcNodeId, NMT state and NetTime as HeartbeatEvent into eventqueue + + // $$$ inform emergency protocol handling about flags + break; + } + + case kEplMsgTypeAsnd: + { + // ASnd frame + NmtEvent = kEplNmtEventDllCeAsnd; + + // ASnd service registered? + uiAsndServiceId = (unsigned int) AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId); + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + if ((EplDllkInstance_g.m_DllState >= kEplDllMsNonCyclic) + && ((((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndStatusResponse) + || (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse))) + { // StatusRes or IdentRes received + uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId); + if ((EplDllkInstance_g.m_LastReqServiceId == ((tEplDllReqServiceId) uiAsndServiceId)) + && (uiNodeId == EplDllkInstance_g.m_uiLastTargetNodeId)) + { // mark request as responded + EplDllkInstance_g.m_LastReqServiceId = kEplDllReqServiceNo; + } + if (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse) + { // memorize MAC address of CN for PReq + tEplDllkNodeInfo* pIntNodeInfo; + + pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId); + if (pIntNodeInfo == NULL) + { // no node info structure available + Ret = kEplDllNoNodeInfo; + } + else + { + EPL_MEMCPY(pIntNodeInfo->m_be_abMacAddr, pFrame->m_be_abSrcMac, 6); + } + } + + // forward Flag2 to asynchronous scheduler + bFlag1 = AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.m_Payload.m_StatusResponse.m_le_bFlag2); + Ret = EplDllkCalAsyncSetPendingRequests(uiNodeId, + ((tEplDllAsyncReqPriority) ((bFlag1 & EPL_FRAME_FLAG2_PR) >> EPL_FRAME_FLAG2_PR_SHIFT)), + (bFlag1 & EPL_FRAME_FLAG2_RS)); + } +#endif + + if (uiAsndServiceId < EPL_DLL_MAX_ASND_SERVICE_ID) + { // ASnd service ID is valid + if (EplDllkInstance_g.m_aAsndFilter[uiAsndServiceId] == kEplDllAsndFilterAny) + { // ASnd service ID is registered + // forward frame via async receive FIFO to userspace + Ret = EplDllkCalAsyncFrameReceived(&FrameInfo); + } + else if (EplDllkInstance_g.m_aAsndFilter[uiAsndServiceId] == kEplDllAsndFilterLocal) + { // ASnd service ID is registered, but only local node ID or broadcasts + // shall be forwarded + uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId); + if ((uiNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) + || (uiNodeId == EPL_C_ADR_BROADCAST)) + { // ASnd frame is intended for us + // forward frame via async receive FIFO to userspace + Ret = EplDllkCalAsyncFrameReceived(&FrameInfo); + } + } + } + break; + } + + default: + { + break; + } + } + + if (NmtEvent != kEplNmtEventNoEvent) + { // event for DLL and NMT state machine generated + Ret = EplDllkChangeState(NmtEvent, NmtState); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + if ((NmtEvent != kEplNmtEventDllCeAsnd) + && ((NmtState <= kEplNmtCsPreOperational1) || (NmtEvent != kEplNmtEventDllCePres))) + { // NMT state machine is not interested in ASnd frames and PRes frames when not CsNotActive or CsPreOp1 + // inform NMT module + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_uiSize = sizeof (NmtEvent); + Event.m_pArg = &NmtEvent; + Ret = EplEventkPost(&Event); + } + } + +Exit: + if (Ret != kEplSuccessful) + { + DWORD dwArg; + + BENCHMARK_MOD_02_TOGGLE(9); + + dwArg = EplDllkInstance_g.m_DllState | (NmtEvent << 8); + + // Error event for API layer + Ret = EplEventkPostError(kEplEventSourceDllk, + Ret, + sizeof(dwArg), + &dwArg); + } + BENCHMARK_MOD_02_RESET(3); + return; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCbFrameTransmitted() +// +// Description: called from EdrvInterruptHandler(). +// It signals +// +// Parameters: pRxBuffer_p = receive buffer structure +// +// Returns: (none) +// +// +// State: +// +//--------------------------------------------------------------------------- + +static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; +tEplDllAsyncReqPriority Priority; +tEplNmtState NmtState; + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \ + && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE) +tEplFrameInfo FrameInfo; +#endif + + NmtState = EplNmtkGetNmtState(); + + if (NmtState <= kEplNmtGsResetConfiguration) + { + goto Exit; + } + + if ((pTxBuffer_p - EplDllkInstance_g.m_pTxBuffer) == EPL_DLLK_TXFRAME_NMTREQ) + { // frame from NMT request FIFO sent + // mark Tx-buffer as empty + pTxBuffer_p->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY; + + // post event to DLL + Priority = kEplDllAsyncReqPrioNmt; + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkFillTx; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = &Priority; + Event.m_uiSize = sizeof(Priority); + Ret = EplEventkPost(&Event); + } + else if ((pTxBuffer_p - EplDllkInstance_g.m_pTxBuffer) == EPL_DLLK_TXFRAME_NONEPL) + { // frame from generic priority FIFO sent + // mark Tx-buffer as empty + pTxBuffer_p->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY; + + // post event to DLL + Priority = kEplDllAsyncReqPrioGeneric; + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkFillTx; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = &Priority; + Event.m_uiSize = sizeof(Priority); + Ret = EplEventkPost(&Event); + } +#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \ + && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)) \ + || (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + else if ((pTxBuffer_p->m_EplMsgType == kEplMsgTypePreq) + || (pTxBuffer_p->m_EplMsgType == kEplMsgTypePres)) + { // PRes resp. PReq frame sent + + #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \ + && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)) + { + // inform PDO module + FrameInfo.m_pFrame = (tEplFrame *) pTxBuffer_p->m_pbBuffer; + FrameInfo.m_uiFrameSize = pTxBuffer_p->m_uiMaxBufferLen; + Ret = EplPdokCbPdoTransmitted(&FrameInfo); + } + #endif + + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + { + // if own Pres on MN, trigger SoA + if ((NmtState >= kEplNmtMsPreOperational2) + && (pTxBuffer_p == &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES])) + { + Ret = EplDllkChangeState(kEplNmtEventDllMeSoaTrig, NmtState); + } + } + #endif + + #if EPL_DLL_PRES_READY_AFTER_SOA != FALSE + goto Exit; + #endif + } +#endif +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + else if (pTxBuffer_p->m_EplMsgType == kEplMsgTypeSoa) + { // SoA frame sent + tEplNmtEvent NmtEvent = kEplNmtEventDllMeSoaSent; + + // check if we are invited + if (EplDllkInstance_g.m_uiLastTargetNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) + { + tEplFrame *pTxFrame; + + if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceStatus) + { // StatusRequest + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) + { // StatusRes does exist + + pTxFrame = (tEplFrame *) EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer; + // update StatusRes frame (NMT state, EN, EC, RS, PR flags) + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_StatusResponse.m_le_bNmtStatus, (BYTE) NmtState); + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_StatusResponse.m_le_bFlag1, EplDllkInstance_g.m_bFlag1); + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_StatusResponse.m_le_bFlag2, EplDllkInstance_g.m_bFlag2); + // send StatusRes + Ret = EdrvSendTxMsg(&EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES]); + if (Ret != kEplSuccessful) + { + goto Exit; + } + TGT_DBG_SIGNAL_TRACE_POINT(8); + + } + } + else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceIdent) + { // IdentRequest + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer != NULL) + { // IdentRes does exist + pTxFrame = (tEplFrame *) EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer; + // update IdentRes frame (NMT state, RS, PR flags) + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_bNmtStatus, (BYTE) NmtState); + AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse.m_le_bFlag2, EplDllkInstance_g.m_bFlag2); + // send IdentRes + Ret = EdrvSendTxMsg(&EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES]); + if (Ret != kEplSuccessful) + { + goto Exit; + } + TGT_DBG_SIGNAL_TRACE_POINT(7); + } + } + else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceNmtRequest) + { // NmtRequest + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_pbBuffer != NULL) + { // NmtRequest does exist + // check if frame is not empty and not being filled + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_FILLING) + { + // check if this frame is a NMT command, + // then forward this frame back to NmtMnu module, + // because it needs the time, when this frame is + // actually sent, to start the timer for monitoring + // the NMT state change. + + pTxFrame = (tEplFrame *) EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_pbBuffer; + if ((AmiGetByteFromLe(&pTxFrame->m_le_bMessageType) + == (BYTE) kEplMsgTypeAsnd) + && (AmiGetByteFromLe(&pTxFrame->m_Data.m_Asnd.m_le_bServiceId) + == (BYTE) kEplDllAsndNmtCommand)) + { // post event directly to NmtMnu module + Event.m_EventSink = kEplEventSinkNmtMnu; + Event.m_EventType = kEplEventTypeNmtMnuNmtCmdSent; + Event.m_uiSize = EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen; + Event.m_pArg = pTxFrame; + Ret = EplEventkPost(&Event); + + } + + // send NmtRequest + Ret = EdrvSendTxMsg(&EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ]); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + } + } + + } + else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceUnspecified) + { // unspecified invite + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_pbBuffer != NULL) + { // non-EPL frame does exist + // check if frame is not empty and not being filled + if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_FILLING) + { + // send non-EPL frame + Ret = EdrvSendTxMsg(&EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL]); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + } + } + } + // ASnd frame was sent, remove the request + EplDllkInstance_g.m_LastReqServiceId = kEplDllReqServiceNo; + } + + // forward event to ErrorHandler and PDO module + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_uiSize = sizeof (NmtEvent); + Event.m_pArg = &NmtEvent; + Ret = EplEventkPost(&Event); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } +#endif + +#if EPL_DLL_PRES_READY_AFTER_SOA != FALSE + else + { // d.k.: Why that else? on CN it is entered on IdentRes and StatusRes + goto Exit; + } + + // signal process function readiness of PRes frame + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkPresReady; + Event.m_uiSize = 0; + Event.m_pArg = NULL; + Ret = EplEventkPost(&Event); + +#endif + +Exit: + if (Ret != kEplSuccessful) + { + DWORD dwArg; + + BENCHMARK_MOD_02_TOGGLE(9); + + dwArg = EplDllkInstance_g.m_DllState | (pTxBuffer_p->m_EplMsgType << 16); + + // Error event for API layer + Ret = EplEventkPostError(kEplEventSourceDllk, + Ret, + sizeof(dwArg), + &dwArg); + } + + return; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCheckFrame() +// +// Description: check frame and set missing information +// +// Parameters: pFrame_p = ethernet frame +// uiFrameSize_p = size of frame +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p, unsigned int uiFrameSize_p) +{ +tEplMsgType MsgType; +WORD wEtherType; + + // check frame + if (pFrame_p != NULL) + { + // check SrcMAC + if (AmiGetQword48FromBe(pFrame_p->m_be_abSrcMac) == 0) + { + // source MAC address + EPL_MEMCPY(&pFrame_p->m_be_abSrcMac[0], &EplDllkInstance_g.m_be_abSrcMac[0], 6); + } + + // check ethertype + wEtherType = AmiGetWordFromBe(&pFrame_p->m_be_wEtherType); + if (wEtherType == 0) + { + // assume EPL frame + wEtherType = EPL_C_DLL_ETHERTYPE_EPL; + AmiSetWordToBe(&pFrame_p->m_be_wEtherType, wEtherType); + } + + if (wEtherType == EPL_C_DLL_ETHERTYPE_EPL) + { + // source node ID + AmiSetByteToLe(&pFrame_p->m_le_bSrcNodeId, (BYTE) EplDllkInstance_g.m_DllConfigParam.m_uiNodeId); + + // check message type + MsgType = AmiGetByteFromLe(&pFrame_p->m_le_bMessageType); + if (MsgType == 0) + { + MsgType = kEplMsgTypeAsnd; + AmiSetByteToLe(&pFrame_p->m_le_bMessageType, (BYTE) MsgType); + } + + if (MsgType == kEplMsgTypeAsnd) + { + // destination MAC address + AmiSetQword48ToBe(&pFrame_p->m_be_abDstMac[0], EPL_C_DLL_MULTICAST_ASND); + } + + } + } + + return kEplSuccessful; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCbCnTimer() +// +// Description: called by timer module. It monitors the EPL cycle when it is a CN. +// +// Parameters: pEventArg_p = timer event argument +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +#if EPL_TIMER_USE_HIGHRES != FALSE +static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg* pEventArg_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplNmtState NmtState; + +#if EPL_TIMER_USE_HIGHRES != FALSE + if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlCycle) + { // zombie callback + // just exit + goto Exit; + } +#endif + + NmtState = EplNmtkGetNmtState(); + + if (NmtState <= kEplNmtGsResetConfiguration) + { + goto Exit; + } + + Ret = EplDllkChangeState(kEplNmtEventDllCeFrameTimeout, NmtState); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // 2008/10/15 d.k. reprogramming of timer not necessary, + // because it will be programmed, when SoC is received. +/* + // reprogram timer +#if EPL_TIMER_USE_HIGHRES != FALSE + if ((NmtState > kEplNmtCsPreOperational1) + && (EplDllkInstance_g.m_ullFrameTimeout != 0)) + { + Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, EplDllkInstance_g.m_ullFrameTimeout, EplDllkCbCnTimer, 0L, FALSE); + } +#endif +*/ + +Exit: + if (Ret != kEplSuccessful) + { + DWORD dwArg; + + BENCHMARK_MOD_02_TOGGLE(9); + + dwArg = EplDllkInstance_g.m_DllState | (kEplNmtEventDllCeFrameTimeout << 8); + + // Error event for API layer + Ret = EplEventkPostError(kEplEventSourceDllk, + Ret, + sizeof(dwArg), + &dwArg); + } + + return Ret; +} +#endif + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCbMnTimerCycle() +// +// Description: called by timer module. It triggers the SoC when it is a MN. +// +// Parameters: pEventArg_p = timer event argument +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg* pEventArg_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplNmtState NmtState; + +#if EPL_TIMER_USE_HIGHRES != FALSE + if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlCycle) + { // zombie callback + // just exit + goto Exit; + } +#endif + + NmtState = EplNmtkGetNmtState(); + + if (NmtState <= kEplNmtGsResetConfiguration) + { + goto Exit; + } + + Ret = EplDllkChangeState(kEplNmtEventDllMeSocTrig, NmtState); + +Exit: + if (Ret != kEplSuccessful) + { + DWORD dwArg; + + BENCHMARK_MOD_02_TOGGLE(9); + + dwArg = EplDllkInstance_g.m_DllState | (kEplNmtEventDllMeSocTrig << 8); + + // Error event for API layer + Ret = EplEventkPostError(kEplEventSourceDllk, + Ret, + sizeof(dwArg), + &dwArg); + } + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCbMnTimerResponse() +// +// Description: called by timer module. It monitors the PRes timeout. +// +// Parameters: pEventArg_p = timer event argument +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg* pEventArg_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplNmtState NmtState; + +#if EPL_TIMER_USE_HIGHRES != FALSE + if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlResponse) + { // zombie callback + // just exit + goto Exit; + } +#endif + + NmtState = EplNmtkGetNmtState(); + + if (NmtState <= kEplNmtGsResetConfiguration) + { + goto Exit; + } + + Ret = EplDllkChangeState(kEplNmtEventDllMePresTimeout, NmtState); + +Exit: + if (Ret != kEplSuccessful) + { + DWORD dwArg; + + BENCHMARK_MOD_02_TOGGLE(9); + + dwArg = EplDllkInstance_g.m_DllState | (kEplNmtEventDllMePresTimeout << 8); + + // Error event for API layer + Ret = EplEventkPostError(kEplEventSourceDllk, + Ret, + sizeof(dwArg), + &dwArg); + } + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkGetNodeInfo() +// +// Description: returns node info structure of the specified node. +// +// Parameters: uiNodeId_p = node ID +// +// Returns: tEplDllkNodeInfo* = pointer to internal node info structure +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplDllkNodeInfo* EplDllkGetNodeInfo(unsigned int uiNodeId_p) +{ + // $$$ d.k.: use hash algorithm to retrieve the appropriate node info structure + // if size of array is less than 254. + uiNodeId_p--; // node ID starts at 1 but array at 0 + if (uiNodeId_p >= tabentries (EplDllkInstance_g.m_aNodeInfo)) + { + return NULL; + } + else + { + return &EplDllkInstance_g.m_aNodeInfo[uiNodeId_p]; + } +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkMnSendSoa() +// +// Description: it updates and transmits the SoA. +// +// Parameters: NmtState_p = current NMT state +// pDllStateProposed_p = proposed DLL state +// fEnableInvitation_p = enable invitation for asynchronous phase +// it will be disabled for EPL_C_DLL_PREOP1_START_CYCLES SoAs +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p, + tEplDllState* pDllStateProposed_p, + BOOL fEnableInvitation_p) +{ +tEplKernel Ret = kEplSuccessful; +tEdrvTxBuffer *pTxBuffer = NULL; +tEplFrame *pTxFrame; +tEplDllkNodeInfo* pNodeInfo; + + *pDllStateProposed_p = kEplDllMsNonCyclic; + + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_SOA]; + if (pTxBuffer->m_pbBuffer != NULL) + { // SoA does exist + pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + + if (fEnableInvitation_p != FALSE) + { // fetch target of asynchronous phase + if (EplDllkInstance_g.m_bFlag2 == 0) + { // own queues are empty + EplDllkInstance_g.m_LastReqServiceId = kEplDllReqServiceNo; + } + else if (((tEplDllAsyncReqPriority) (EplDllkInstance_g.m_bFlag2 >> EPL_FRAME_FLAG2_PR_SHIFT)) == kEplDllAsyncReqPrioNmt) + { // frames in own NMT request queue available + EplDllkInstance_g.m_LastReqServiceId = kEplDllReqServiceNmtRequest; + } + else + { + EplDllkInstance_g.m_LastReqServiceId = kEplDllReqServiceUnspecified; + } + Ret = EplDllkCalAsyncGetSoaRequest(&EplDllkInstance_g.m_LastReqServiceId, &EplDllkInstance_g.m_uiLastTargetNodeId); + if (Ret != kEplSuccessful) + { + goto Exit; + } + if (EplDllkInstance_g.m_LastReqServiceId != kEplDllReqServiceNo) + { // asynchronous phase will be assigned to one node + if (EplDllkInstance_g.m_uiLastTargetNodeId == EPL_C_ADR_INVALID) + { // exchange invalid node ID with local node ID + EplDllkInstance_g.m_uiLastTargetNodeId = EplDllkInstance_g.m_DllConfigParam.m_uiNodeId; + // d.k. DLL state WaitAsndTrig is not helpful; + // so just step over to WaitSocTrig, + // because own ASnd is sent automatically in CbFrameTransmitted() after SoA. + //*pDllStateProposed_p = kEplDllMsWaitAsndTrig; + *pDllStateProposed_p = kEplDllMsWaitSocTrig; + } + else + { // assignment to CN + *pDllStateProposed_p = kEplDllMsWaitAsnd; + } + + pNodeInfo = EplDllkGetNodeInfo(EplDllkInstance_g.m_uiLastTargetNodeId); + if (pNodeInfo == NULL) + { // no node info structure available + Ret = kEplDllNoNodeInfo; + goto Exit; + } + + // update frame (EA, ER flags) + AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag1, + pNodeInfo->m_bSoaFlag1 & (EPL_FRAME_FLAG1_EA | EPL_FRAME_FLAG1_ER)); + } + else + { // no assignment of asynchronous phase + *pDllStateProposed_p = kEplDllMsWaitSocTrig; + EplDllkInstance_g.m_uiLastTargetNodeId = EPL_C_ADR_INVALID; + } + + // update frame (target) + AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bReqServiceId, (BYTE) EplDllkInstance_g.m_LastReqServiceId); + AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bReqServiceTarget, (BYTE) EplDllkInstance_g.m_uiLastTargetNodeId); + + } + else + { // invite nobody + // update frame (target) + AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bReqServiceId, (BYTE) 0); + AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bReqServiceTarget, (BYTE) 0); + } + + // update frame (NMT state) + AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bNmtStatus, (BYTE) NmtState_p); + + // send SoA frame + Ret = EdrvSendTxMsg(pTxBuffer); + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkMnSendSoc() +// +// Description: it updates and transmits the SoA. +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplDllkMnSendSoc(void) +{ +tEplKernel Ret = kEplSuccessful; +tEdrvTxBuffer* pTxBuffer = NULL; +tEplFrame* pTxFrame; +tEplEvent Event; + + pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_SOC]; + if (pTxBuffer->m_pbBuffer != NULL) + { // SoC does exist + pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + + // $$$ update NetTime + + // send SoC frame + Ret = EdrvSendTxMsg(pTxBuffer); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // trigger synchronous task + Event.m_EventSink = kEplEventSinkSync; + Event.m_EventType = kEplEventTypeSync; + Event.m_uiSize = 0; + Ret = EplEventkPost(&Event); + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkMnSendPreq() +// +// Description: it updates and transmits the PReq for the next isochronous CN +// or own PRes if enabled. +// +// Parameters: NmtState_p = current NMT state +// pDllStateProposed_p = proposed DLL state +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p, + tEplDllState* pDllStateProposed_p) +{ +tEplKernel Ret = kEplSuccessful; +tEdrvTxBuffer *pTxBuffer = NULL; +tEplFrame *pTxFrame; +BYTE bFlag1 = 0; + + + if (EplDllkInstance_g.m_pCurNodeInfo == NULL) + { // start with first isochronous CN + EplDllkInstance_g.m_pCurNodeInfo = EplDllkInstance_g.m_pFirstNodeInfo; + } + else + { // iterate to next isochronous CN + EplDllkInstance_g.m_pCurNodeInfo = EplDllkInstance_g.m_pCurNodeInfo->m_pNextNodeInfo; + } + + if (EplDllkInstance_g.m_pCurNodeInfo == NULL) + { // last isochronous CN reached + Ret = EplDllkMnSendSoa(NmtState_p, pDllStateProposed_p, TRUE); + goto Exit; + } + else + { + pTxBuffer = EplDllkInstance_g.m_pCurNodeInfo->m_pPreqTxBuffer; + bFlag1 = EplDllkInstance_g.m_pCurNodeInfo->m_bSoaFlag1 & EPL_FRAME_FLAG1_EA; + *pDllStateProposed_p = kEplDllMsWaitPres; + + // start PRes Timer + // $$$ d.k.: maybe move this call to CbFrameTransmitted(), because the time should run from there +#if EPL_TIMER_USE_HIGHRES != FALSE + Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlResponse, + EplDllkInstance_g.m_pCurNodeInfo->m_dwPresTimeout, + EplDllkCbMnTimerResponse, + 0L, + FALSE); +#endif + } + + if (pTxBuffer == NULL) + { // PReq does not exist + Ret = kEplDllTxBufNotReady; + goto Exit; + } + + pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer; + + if (pTxFrame != NULL) + { // PReq does exist + if (NmtState_p == kEplNmtMsOperational) + { // leave RD flag untouched + bFlag1 |= AmiGetByteFromLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1) & EPL_FRAME_FLAG1_RD; + } + + if (pTxBuffer == &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]) + { // PRes of MN will be sent + // update NMT state + AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bNmtStatus, (BYTE) NmtState_p); + *pDllStateProposed_p = kEplDllMsWaitSoaTrig; + } + + // $$$ d.k. set EPL_FRAME_FLAG1_MS if necessary + // update frame (Flag1) + AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, bFlag1); + + // calculate frame size from payload size + pTxBuffer->m_uiTxMsgLen = AmiGetWordFromLe(&pTxFrame->m_Data.m_Preq.m_le_wSize) + 24; + + // send PReq frame + Ret = EdrvSendTxMsg(pTxBuffer); + } + else + { + Ret = kEplDllTxFrameInvalid; + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkAsyncFrameNotReceived() +// +// Description: passes empty ASnd frame to receive FIFO. +// It will be called only for frames with registered AsndServiceIds +// (only kEplDllAsndFilterAny). +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId ReqServiceId_p, unsigned int uiNodeId_p) +{ +tEplKernel Ret = kEplSuccessful; +BYTE abBuffer[18]; +tEplFrame* pFrame = (tEplFrame*) abBuffer; +tEplFrameInfo FrameInfo; + + // check if previous SoA invitation was not answered + switch (ReqServiceId_p) + { + case kEplDllReqServiceIdent: + case kEplDllReqServiceStatus: + // ASnd service registered? + if (EplDllkInstance_g.m_aAsndFilter[ReqServiceId_p] == kEplDllAsndFilterAny) + { // ASnd service ID is registered + AmiSetByteToLe(&pFrame->m_le_bSrcNodeId, (BYTE) uiNodeId_p); + // EPL MsgType ASnd + AmiSetByteToLe(&pFrame->m_le_bMessageType, (BYTE) kEplMsgTypeAsnd); + // ASnd Service ID + AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId, (BYTE) ReqServiceId_p); + // create frame info structure + FrameInfo.m_pFrame = pFrame; + FrameInfo.m_uiFrameSize = 18; // empty non existing ASnd frame + // forward frame via async receive FIFO to userspace + Ret = EplDllkCalAsyncFrameReceived(&FrameInfo); + } + break; + default: + // no invitation issued or it was successfully answered or it is uninteresting + break; + } + + return Ret; +} + + +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) +// EOF + diff --git a/drivers/staging/epl/EplDllkCal.c b/drivers/staging/epl/EplDllkCal.c new file mode 100644 index 0000000..de67e5b --- /dev/null +++ b/drivers/staging/epl/EplDllkCal.c @@ -0,0 +1,1193 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for kernel DLL Communication Abstraction Layer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDllkCal.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.7 $ $Date: 2008/11/13 17:13:09 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/15 d.k.: start of the implementation, version 1.00 + +****************************************************************************/ + +#include "kernel/EplDllkCal.h" +#include "kernel/EplDllk.h" +#include "kernel/EplEventk.h" + +#include "EplDllCal.h" +#ifndef EPL_NO_FIFO +#include "SharedBuff.h" +#endif + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S EplDllkCal */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#define EPL_DLLKCAL_MAX_QUEUES 5 // CnGenReq, CnNmtReq, {MnGenReq, MnNmtReq}, MnIdentReq, MnStatusReq + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ +#ifndef EPL_NO_FIFO +// tShbInstance m_ShbInstanceRx; // FIFO for Rx ASnd frames + tShbInstance m_ShbInstanceTxNmt; // FIFO for Tx frames with NMT request priority + tShbInstance m_ShbInstanceTxGen; // FIFO for Tx frames with generic priority +#else + unsigned int m_uiFrameSizeNmt; + BYTE m_abFrameNmt[1500]; + unsigned int m_uiFrameSizeGen; + BYTE m_abFrameGen[1500]; +#endif + + tEplDllkCalStatistics m_Statistics; + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // IdentRequest queue with CN node IDs + unsigned int m_auiQueueIdentReq[EPL_D_NMT_MaxCNNumber_U8 + 1]; // 1 entry is reserved to distinguish between full and empty + unsigned int m_uiWriteIdentReq; + unsigned int m_uiReadIdentReq; + + // StatusRequest queue with CN node IDs + unsigned int m_auiQueueStatusReq[EPL_D_NMT_MaxCNNumber_U8 + 1]; // 1 entry is reserved to distinguish between full and empty + unsigned int m_uiWriteStatusReq; + unsigned int m_uiReadStatusReq; + + unsigned int m_auiQueueCnRequests[254 * 2]; + // first 254 entries represent the generic requests of the corresponding node + // second 254 entries represent the NMT requests of the corresponding node + unsigned int m_uiNextQueueCnRequest; + unsigned int m_uiNextRequestQueue; +#endif + +} tEplDllkCalInstance; + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +// if no dynamic memory allocation shall be used +// define structures statically +static tEplDllkCalInstance EplDllkCalInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalAddInstance() +// +// Description: add and initialize new instance of DLL CAL module +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalAddInstance() +{ +tEplKernel Ret = kEplSuccessful; +#ifndef EPL_NO_FIFO +tShbError ShbError; +unsigned int fShbNewCreated; + +/* ShbError = ShbCirAllocBuffer (EPL_DLLCAL_BUFFER_SIZE_RX, EPL_DLLCAL_BUFFER_ID_RX, + &EplDllkCalInstance_g.m_ShbInstanceRx, &fShbNewCreated); + // returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg + + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + } +*/ + ShbError = ShbCirAllocBuffer (EPL_DLLCAL_BUFFER_SIZE_TX_NMT, EPL_DLLCAL_BUFFER_ID_TX_NMT, + &EplDllkCalInstance_g.m_ShbInstanceTxNmt, &fShbNewCreated); + // returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg + + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + } + +/* ShbError = ShbCirSetSignalHandlerNewData (EplDllkCalInstance_g.m_ShbInstanceTxNmt, EplDllkCalTxNmtSignalHandler, kShbPriorityNormal); + // returns kShbOk, kShbAlreadySignaling or kShbInvalidArg + + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + } +*/ + ShbError = ShbCirAllocBuffer (EPL_DLLCAL_BUFFER_SIZE_TX_GEN, EPL_DLLCAL_BUFFER_ID_TX_GEN, + &EplDllkCalInstance_g.m_ShbInstanceTxGen, &fShbNewCreated); + // returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg + + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + } + +/* ShbError = ShbCirSetSignalHandlerNewData (EplDllkCalInstance_g.m_ShbInstanceTxGen, EplDllkCalTxGenSignalHandler, kShbPriorityNormal); + // returns kShbOk, kShbAlreadySignaling or kShbInvalidArg + + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + } +*/ +#else + EplDllkCalInstance_g.m_uiFrameSizeNmt = 0; + EplDllkCalInstance_g.m_uiFrameSizeGen = 0; +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalDelInstance() +// +// Description: deletes instance of DLL CAL module +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalDelInstance() +{ +tEplKernel Ret = kEplSuccessful; +#ifndef EPL_NO_FIFO +tShbError ShbError; + +/* ShbError = ShbCirReleaseBuffer (EplDllkCalInstance_g.m_ShbInstanceRx); + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + } + EplDllkCalInstance_g.m_ShbInstanceRx = NULL; +*/ + ShbError = ShbCirReleaseBuffer (EplDllkCalInstance_g.m_ShbInstanceTxNmt); + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + } + EplDllkCalInstance_g.m_ShbInstanceTxNmt = NULL; + + ShbError = ShbCirReleaseBuffer (EplDllkCalInstance_g.m_ShbInstanceTxGen); + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + } + EplDllkCalInstance_g.m_ShbInstanceTxGen = NULL; + +#else + EplDllkCalInstance_g.m_uiFrameSizeNmt = 0; + EplDllkCalInstance_g.m_uiFrameSizeGen = 0; +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalProcess +// +// Description: process the passed configuration +// +// Parameters: pEvent_p = event containing configuration options +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalProcess(tEplEvent * pEvent_p) +{ +tEplKernel Ret = kEplSuccessful; + + switch (pEvent_p->m_EventType) + { + case kEplEventTypeDllkServFilter: + { + tEplDllCalAsndServiceIdFilter* pServFilter; + + pServFilter = (tEplDllCalAsndServiceIdFilter*) pEvent_p->m_pArg; + Ret = EplDllkSetAsndServiceIdFilter(pServFilter->m_ServiceId, pServFilter->m_Filter); + break; + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + case kEplEventTypeDllkIssueReq: + { + tEplDllCalIssueRequest* pIssueReq; + + pIssueReq = (tEplDllCalIssueRequest*) pEvent_p->m_pArg; + Ret = EplDllkCalIssueRequest(pIssueReq->m_Service, pIssueReq->m_uiNodeId, pIssueReq->m_bSoaFlag1); + break; + } + + case kEplEventTypeDllkAddNode: + { + tEplDllNodeInfo* pNodeInfo; + + pNodeInfo = (tEplDllNodeInfo*) pEvent_p->m_pArg; + Ret = EplDllkAddNode(pNodeInfo); + break; + } + + case kEplEventTypeDllkDelNode: + { + unsigned int* puiNodeId; + + puiNodeId = (unsigned int*) pEvent_p->m_pArg; + Ret = EplDllkDeleteNode(*puiNodeId); + break; + } + + case kEplEventTypeDllkSoftDelNode: + { + unsigned int* puiNodeId; + + puiNodeId = (unsigned int*) pEvent_p->m_pArg; + Ret = EplDllkSoftDeleteNode(*puiNodeId); + break; + } +#endif + + case kEplEventTypeDllkIdentity: + { + tEplDllIdentParam* pIdentParam; + + pIdentParam = (tEplDllIdentParam*) pEvent_p->m_pArg; + if (pIdentParam->m_uiSizeOfStruct > pEvent_p->m_uiSize) + { + pIdentParam->m_uiSizeOfStruct = pEvent_p->m_uiSize; + } + Ret = EplDllkSetIdentity(pIdentParam); + break; + } + + case kEplEventTypeDllkConfig: + { + tEplDllConfigParam* pConfigParam; + + pConfigParam = (tEplDllConfigParam*) pEvent_p->m_pArg; + if (pConfigParam->m_uiSizeOfStruct > pEvent_p->m_uiSize) + { + pConfigParam->m_uiSizeOfStruct = pEvent_p->m_uiSize; + } + Ret = EplDllkConfig(pConfigParam); + break; + } + + default: + break; + } + +//Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalAsyncGetTxCount() +// +// Description: returns count of Tx frames of FIFO with highest priority +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalAsyncGetTxCount(tEplDllAsyncReqPriority * pPriority_p, unsigned int * puiCount_p) +{ +tEplKernel Ret = kEplSuccessful; +#ifndef EPL_NO_FIFO +tShbError ShbError; +unsigned long ulFrameCount; + + // get frame count of Tx FIFO with NMT request priority + ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxNmt, &ulFrameCount); + // returns kShbOk, kShbInvalidArg + + // error handling + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + goto Exit; + } + + if (ulFrameCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt) + { + EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt = ulFrameCount; + } + + if (ulFrameCount != 0) + { // NMT requests are in queue + *pPriority_p = kEplDllAsyncReqPrioNmt; + *puiCount_p = (unsigned int) ulFrameCount; + goto Exit; + } + + // get frame count of Tx FIFO with generic priority + ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxGen, &ulFrameCount); + // returns kShbOk, kShbInvalidArg + + // error handling + if (ShbError != kShbOk) + { + Ret = kEplNoResource; + goto Exit; + } + + if (ulFrameCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen) + { + EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen = ulFrameCount; + } + + *pPriority_p = kEplDllAsyncReqPrioGeneric; + *puiCount_p = (unsigned int) ulFrameCount; + +Exit: +#else + if (EplDllkCalInstance_g.m_uiFrameSizeNmt > 0) + { + *pPriority_p = kEplDllAsyncReqPrioNmt; + *puiCount_p = 1; + } + else if (EplDllkCalInstance_g.m_uiFrameSizeGen > 0) + { + *pPriority_p = kEplDllAsyncReqPrioGeneric; + *puiCount_p = 1; + } + else + { + *pPriority_p = kEplDllAsyncReqPrioGeneric; + *puiCount_p = 0; + } +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalAsyncGetTxFrame() +// +// Description: returns Tx frames from FIFO with specified priority +// +// Parameters: pFrame_p = IN: pointer to buffer +// puiFrameSize_p = IN: max size of buffer +// OUT: actual size of frame +// Priority_p = IN: priority +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalAsyncGetTxFrame(void * pFrame_p, unsigned int * puiFrameSize_p, tEplDllAsyncReqPriority Priority_p) +{ +tEplKernel Ret = kEplSuccessful; +#ifndef EPL_NO_FIFO +tShbError ShbError; +unsigned long ulFrameSize; + + switch (Priority_p) + { + case kEplDllAsyncReqPrioNmt: // NMT request priority + ShbError = ShbCirReadDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxNmt, (BYTE *) pFrame_p, *puiFrameSize_p, &ulFrameSize); + // returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData + break; + + default: // generic priority + ShbError = ShbCirReadDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxGen, (BYTE *) pFrame_p, *puiFrameSize_p, &ulFrameSize); + // returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData + break; + + } + + // error handling + if (ShbError != kShbOk) + { + if (ShbError == kShbNoReadableData) + { + Ret = kEplDllAsyncTxBufferEmpty; + } + else + { // other error + Ret = kEplNoResource; + } + goto Exit; + } + + *puiFrameSize_p = (unsigned int) ulFrameSize; + +Exit: +#else + switch (Priority_p) + { + case kEplDllAsyncReqPrioNmt: // NMT request priority + *puiFrameSize_p = min(*puiFrameSize_p, EplDllkCalInstance_g.m_uiFrameSizeNmt); + EPL_MEMCPY(pFrame_p, EplDllkCalInstance_g.m_abFrameNmt, *puiFrameSize_p); + EplDllkCalInstance_g.m_uiFrameSizeNmt = 0; + break; + + default: // generic priority + *puiFrameSize_p = min(*puiFrameSize_p, EplDllkCalInstance_g.m_uiFrameSizeGen); + EPL_MEMCPY(pFrame_p, EplDllkCalInstance_g.m_abFrameGen, *puiFrameSize_p); + EplDllkCalInstance_g.m_uiFrameSizeGen = 0; + break; + } + +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalAsyncFrameReceived() +// +// Description: passes ASnd frame to receive FIFO. +// It will be called only for frames with registered AsndServiceIds. +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalAsyncFrameReceived(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; + + Event.m_EventSink = kEplEventSinkDlluCal; + Event.m_EventType = kEplEventTypeAsndRx; + Event.m_pArg = pFrameInfo_p->m_pFrame; + Event.m_uiSize = pFrameInfo_p->m_uiFrameSize; + // pass NetTime of frame to userspace + Event.m_NetTime = pFrameInfo_p->m_NetTime; + + Ret = EplEventkPost(&Event); + if (Ret != kEplSuccessful) + { + EplDllkCalInstance_g.m_Statistics.m_ulCurRxFrameCount++; + } + else + { + EplDllkCalInstance_g.m_Statistics.m_ulMaxRxFrameCount++; + } + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalAsyncSend() +// +// Description: puts the given frame into the transmit FIFO with the specified +// priority. +// +// Parameters: pFrameInfo_p = frame info structure +// Priority_p = priority +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalAsyncSend(tEplFrameInfo * pFrameInfo_p, tEplDllAsyncReqPriority Priority_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; +#ifndef EPL_NO_FIFO +tShbError ShbError; + + switch (Priority_p) + { + case kEplDllAsyncReqPrioNmt: // NMT request priority + ShbError = ShbCirWriteDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxNmt, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize); + // returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg + break; + + default: // generic priority + ShbError = ShbCirWriteDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxGen, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize); + // returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg + break; + + } + + // error handling + switch (ShbError) + { + case kShbOk: + break; + + case kShbExceedDataSizeLimit: + Ret = kEplDllAsyncTxBufferFull; + break; + + case kShbBufferFull: + Ret = kEplDllAsyncTxBufferFull; + break; + + case kShbInvalidArg: + default: + Ret = kEplNoResource; + break; + } + +#else + + switch (Priority_p) + { + case kEplDllAsyncReqPrioNmt: // NMT request priority + if (EplDllkCalInstance_g.m_uiFrameSizeNmt == 0) + { + EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameNmt, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize); + EplDllkCalInstance_g.m_uiFrameSizeNmt = pFrameInfo_p->m_uiFrameSize; + } + else + { + Ret = kEplDllAsyncTxBufferFull; + goto Exit; + } + break; + + default: // generic priority + if (EplDllkCalInstance_g.m_uiFrameSizeGen == 0) + { + EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameGen, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize); + EplDllkCalInstance_g.m_uiFrameSizeGen = pFrameInfo_p->m_uiFrameSize; + } + else + { + Ret = kEplDllAsyncTxBufferFull; + goto Exit; + } + break; + } + +#endif + + // post event to DLL + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkFillTx; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = &Priority_p; + Event.m_uiSize = sizeof(Priority_p); + Ret = EplEventkPost(&Event); + +#ifdef EPL_NO_FIFO +Exit: +#endif + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalAsyncClearBuffer() +// +// Description: clears the transmit buffer +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalAsyncClearBuffer(void) +{ +tEplKernel Ret = kEplSuccessful; +#ifndef EPL_NO_FIFO +tShbError ShbError; + + ShbError = ShbCirResetBuffer (EplDllkCalInstance_g.m_ShbInstanceTxNmt, 1000, NULL); + ShbError = ShbCirResetBuffer (EplDllkCalInstance_g.m_ShbInstanceTxGen, 1000, NULL); + +#else + EplDllkCalInstance_g.m_uiFrameSizeNmt = 0; + EplDllkCalInstance_g.m_uiFrameSizeGen = 0; +#endif + +// EPL_MEMSET(&EplDllkCalInstance_g.m_Statistics, 0, sizeof (tEplDllkCalStatistics)); + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalAsyncClearQueues() +// +// Description: clears the transmit buffer +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +tEplKernel EplDllkCalAsyncClearQueues(void) +{ +tEplKernel Ret = kEplSuccessful; + + // clear MN asynchronous queues + EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0; + EplDllkCalInstance_g.m_uiNextRequestQueue = 0; + EplDllkCalInstance_g.m_uiReadIdentReq = 0; + EplDllkCalInstance_g.m_uiWriteIdentReq = 0; + EplDllkCalInstance_g.m_uiReadStatusReq = 0; + EplDllkCalInstance_g.m_uiWriteStatusReq = 0; + + return Ret; +} +#endif + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalGetStatistics() +// +// Description: returns statistics of the asynchronous queues. +// +// Parameters: ppStatistics = statistics structure +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalGetStatistics(tEplDllkCalStatistics ** ppStatistics) +{ +tEplKernel Ret = kEplSuccessful; +#ifndef EPL_NO_FIFO +tShbError ShbError; + + ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxNmt, &EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt); + ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxGen, &EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen); +// ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceRx, &EplDllkCalInstance_g.m_Statistics.m_ulCurRxFrameCount); + +#else + if (EplDllkCalInstance_g.m_uiFrameSizeNmt > 0) + { + EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt = 1; + } + else + { + EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt = 0; + } + if (EplDllkCalInstance_g.m_uiFrameSizeGen > 0) + { + EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen = 1; + } + else + { + EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen = 0; + } +#endif + + *ppStatistics = &EplDllkCalInstance_g.m_Statistics; + return Ret; +} + + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalIssueRequest() +// +// Description: issues a StatusRequest or a IdentRequest to the specified node. +// +// Parameters: Service_p = request service ID +// uiNodeId_p = node ID +// bSoaFlag1_p = flag1 for this node (transmit in SoA and PReq) +// If 0xFF this flag is ignored. +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalIssueRequest(tEplDllReqServiceId Service_p, unsigned int uiNodeId_p, BYTE bSoaFlag1_p) +{ +tEplKernel Ret = kEplSuccessful; + + if (bSoaFlag1_p != 0xFF) + { + Ret = EplDllkSetFlag1OfNode(uiNodeId_p, bSoaFlag1_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + + // add node to appropriate request queue + switch (Service_p) + { + case kEplDllReqServiceIdent: + { + if (((EplDllkCalInstance_g.m_uiWriteIdentReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueIdentReq)) + == EplDllkCalInstance_g.m_uiReadIdentReq) + { // queue is full + Ret = kEplDllAsyncTxBufferFull; + goto Exit; + } + EplDllkCalInstance_g.m_auiQueueIdentReq[EplDllkCalInstance_g.m_uiWriteIdentReq] = uiNodeId_p; + EplDllkCalInstance_g.m_uiWriteIdentReq = + (EplDllkCalInstance_g.m_uiWriteIdentReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueIdentReq); + break; + } + + case kEplDllReqServiceStatus: + { + if (((EplDllkCalInstance_g.m_uiWriteStatusReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueStatusReq)) + == EplDllkCalInstance_g.m_uiReadStatusReq) + { // queue is full + Ret = kEplDllAsyncTxBufferFull; + goto Exit; + } + EplDllkCalInstance_g.m_auiQueueStatusReq[EplDllkCalInstance_g.m_uiWriteStatusReq] = uiNodeId_p; + EplDllkCalInstance_g.m_uiWriteStatusReq = + (EplDllkCalInstance_g.m_uiWriteStatusReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueStatusReq); + break; + } + + default: + { + Ret = kEplDllInvalidParam; + goto Exit; + } + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalAsyncGetSoaRequest() +// +// Description: returns next request for SoA. This function is called by DLLk module. +// +// Parameters: pReqServiceId_p = pointer to request service ID +// IN: available request for MN NMT or generic request queue (Flag2.PR) +// or kEplDllReqServiceNo if queues are empty +// OUT: next request +// puiNodeId_p = OUT: pointer to node ID of next request +// = EPL_C_ADR_INVALID, if request is self addressed +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalAsyncGetSoaRequest(tEplDllReqServiceId* pReqServiceId_p, unsigned int* puiNodeId_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiCount; + +// *pReqServiceId_p = kEplDllReqServiceNo; + + for (uiCount = EPL_DLLKCAL_MAX_QUEUES; uiCount > 0; uiCount--) + { + switch (EplDllkCalInstance_g.m_uiNextRequestQueue) + { + case 0: + { // CnGenReq + for (;EplDllkCalInstance_g.m_uiNextQueueCnRequest < (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2); + EplDllkCalInstance_g.m_uiNextQueueCnRequest++) + { + if (EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest] > 0) + { // non empty queue found + // remove one request from queue + EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest]--; + *puiNodeId_p = EplDllkCalInstance_g.m_uiNextQueueCnRequest + 1; + *pReqServiceId_p = kEplDllReqServiceUnspecified; + EplDllkCalInstance_g.m_uiNextQueueCnRequest++; + if (EplDllkCalInstance_g.m_uiNextQueueCnRequest >= (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2)) + { // last node reached + // continue with CnNmtReq queue at next SoA + EplDllkCalInstance_g.m_uiNextRequestQueue = 1; + } + goto Exit; + } + } + // all CnGenReq queues are empty -> continue with CnNmtReq queue + EplDllkCalInstance_g.m_uiNextRequestQueue = 1; + break; + } + + case 1: + { // CnNmtReq + for (;EplDllkCalInstance_g.m_uiNextQueueCnRequest < tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests); + EplDllkCalInstance_g.m_uiNextQueueCnRequest++) + { + if (EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest] > 0) + { // non empty queue found + // remove one request from queue + EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest]--; + *puiNodeId_p = EplDllkCalInstance_g.m_uiNextQueueCnRequest + 1 - (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2); + *pReqServiceId_p = kEplDllReqServiceNmtRequest; + EplDllkCalInstance_g.m_uiNextQueueCnRequest++; + if (EplDllkCalInstance_g.m_uiNextQueueCnRequest > tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests)) + { // last node reached + // restart CnGenReq queue + EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0; + // continue with MnGenReq queue at next SoA + EplDllkCalInstance_g.m_uiNextRequestQueue = 2; + } + goto Exit; + } + } + // restart CnGenReq queue + EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0; + // all CnNmtReq queues are empty -> continue with MnGenReq queue + EplDllkCalInstance_g.m_uiNextRequestQueue = 2; + break; + } + + case 2: + { // MnNmtReq and MnGenReq + // next queue will be MnIdentReq queue + EplDllkCalInstance_g.m_uiNextRequestQueue = 3; + if (*pReqServiceId_p != kEplDllReqServiceNo) + { + *puiNodeId_p = EPL_C_ADR_INVALID; // DLLk must exchange this with the actual node ID + goto Exit; + } + break; + } + + case 3: + { // MnIdentReq + // next queue will be MnStatusReq queue + EplDllkCalInstance_g.m_uiNextRequestQueue = 4; + if (EplDllkCalInstance_g.m_uiReadIdentReq != EplDllkCalInstance_g.m_uiWriteIdentReq) + { // queue is not empty + *puiNodeId_p = EplDllkCalInstance_g.m_auiQueueIdentReq[EplDllkCalInstance_g.m_uiReadIdentReq]; + EplDllkCalInstance_g.m_uiReadIdentReq = + (EplDllkCalInstance_g.m_uiReadIdentReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueIdentReq); + *pReqServiceId_p = kEplDllReqServiceIdent; + goto Exit; + } + break; + } + + case 4: + { // MnStatusReq + // next queue will be CnGenReq queue + EplDllkCalInstance_g.m_uiNextRequestQueue = 0; + if (EplDllkCalInstance_g.m_uiReadStatusReq != EplDllkCalInstance_g.m_uiWriteStatusReq) + { // queue is not empty + *puiNodeId_p = EplDllkCalInstance_g.m_auiQueueStatusReq[EplDllkCalInstance_g.m_uiReadStatusReq]; + EplDllkCalInstance_g.m_uiReadStatusReq = + (EplDllkCalInstance_g.m_uiReadStatusReq + 1) % tabentries (EplDllkCalInstance_g.m_auiQueueStatusReq); + *pReqServiceId_p = kEplDllReqServiceStatus; + goto Exit; + } + break; + } + + } + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDllkCalAsyncSetPendingRequests() +// +// Description: sets the pending asynchronous frame requests of the specified node. +// This will add the node to the asynchronous request scheduler. +// +// Parameters: uiNodeId_p = node ID +// AsyncReqPrio_p = asynchronous request priority +// uiCount_p = count of asynchronous frames +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDllkCalAsyncSetPendingRequests(unsigned int uiNodeId_p, tEplDllAsyncReqPriority AsyncReqPrio_p, unsigned int uiCount_p) +{ +tEplKernel Ret = kEplSuccessful; + + // add node to appropriate request queue + switch (AsyncReqPrio_p) + { + case kEplDllAsyncReqPrioNmt: + { + uiNodeId_p--; + if (uiNodeId_p >= (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2)) + { + Ret = kEplDllInvalidParam; + goto Exit; + } + uiNodeId_p += tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2; + EplDllkCalInstance_g.m_auiQueueCnRequests[uiNodeId_p] = uiCount_p; + break; + } + + default: + { + uiNodeId_p--; + if (uiNodeId_p >= (tabentries (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2)) + { + Ret = kEplDllInvalidParam; + goto Exit; + } + EplDllkCalInstance_g.m_auiQueueCnRequests[uiNodeId_p] = uiCount_p; + break; + } + } + +Exit: + return Ret; +} +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// Callback handler for new data signaling +//--------------------------------------------------------------------------- + +#ifndef EPL_NO_FIFO +/*static void EplDllkCalTxNmtSignalHandler ( + tShbInstance pShbRxInstance_p, + unsigned long ulDataSize_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; +tEplDllAsyncReqPriority Priority; +#ifndef EPL_NO_FIFO +tShbError ShbError; +unsigned long ulBlockCount; + + + ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxNmt, &ulBlockCount); + if (ulBlockCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt) + { + EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt = ulBlockCount; + } + +#endif + + // post event to DLL + Priority = kEplDllAsyncReqPrioNmt; + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkFillTx; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = &Priority; + Event.m_uiSize = sizeof(Priority); + Ret = EplEventkPost(&Event); + +} + +static void EplDllkCalTxGenSignalHandler ( + tShbInstance pShbRxInstance_p, + unsigned long ulDataSize_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; +tEplDllAsyncReqPriority Priority; +#ifndef EPL_NO_FIFO +tShbError ShbError; +unsigned long ulBlockCount; + + + ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxGen, &ulBlockCount); + if (ulBlockCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen) + { + EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen = ulBlockCount; + } + +#endif + + // post event to DLL + Priority = kEplDllAsyncReqPrioGeneric; + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkFillTx; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = &Priority; + Event.m_uiSize = sizeof(Priority); + Ret = EplEventkPost(&Event); + +} +*/ +#endif + + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplDlluCal.c b/drivers/staging/epl/EplDlluCal.c new file mode 100644 index 0000000..595e9c7 --- /dev/null +++ b/drivers/staging/epl/EplDlluCal.c @@ -0,0 +1,534 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for DLL Communication Abstraction Layer module in EPL user part + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDlluCal.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.7 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/20 d.k.: start of the implementation, version 1.00 + +****************************************************************************/ + +#include "user/EplDlluCal.h" +#include "user/EplEventu.h" + +#include "EplDllCal.h" + +// include only if direct call between user- and kernelspace is enabled +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) +#include "kernel/EplDllkCal.h" +#endif + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S EplDlluCal */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ + tEplDlluCbAsnd m_apfnDlluCbAsnd[EPL_DLL_MAX_ASND_SERVICE_ID]; + +} tEplDlluCalInstance; + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +// if no dynamic memory allocation shall be used +// define structures statically +static tEplDlluCalInstance EplDlluCalInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static tEplKernel EplDlluCalSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p, tEplDllAsndFilter Filter_p); + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalAddInstance() +// +// Description: add and initialize new instance of DLL CAL module +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalAddInstance() +{ +tEplKernel Ret = kEplSuccessful; + + // reset instance structure + EPL_MEMSET(&EplDlluCalInstance_g, 0, sizeof (EplDlluCalInstance_g)); + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalDelInstance() +// +// Description: deletes an instance of DLL CAL module +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalDelInstance() +{ +tEplKernel Ret = kEplSuccessful; + + // reset instance structure + EPL_MEMSET(&EplDlluCalInstance_g, 0, sizeof (EplDlluCalInstance_g)); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalProcess +// +// Description: process the passed asynch frame +// +// Parameters: pEvent_p = event containing frame to be processed +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalProcess(tEplEvent * pEvent_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplMsgType MsgType; +unsigned int uiAsndServiceId; +tEplFrameInfo FrameInfo; + + if (pEvent_p->m_EventType == kEplEventTypeAsndRx) + { + FrameInfo.m_pFrame = (tEplFrame*) pEvent_p->m_pArg; + FrameInfo.m_uiFrameSize = pEvent_p->m_uiSize; + // extract NetTime + FrameInfo.m_NetTime = pEvent_p->m_NetTime; + + MsgType = (tEplMsgType)AmiGetByteFromLe(&FrameInfo.m_pFrame->m_le_bMessageType); + if (MsgType != kEplMsgTypeAsnd) + { + Ret = kEplInvalidOperation; + goto Exit; + } + + uiAsndServiceId = (unsigned int) AmiGetByteFromLe(&FrameInfo.m_pFrame->m_Data.m_Asnd.m_le_bServiceId); + if (uiAsndServiceId < EPL_DLL_MAX_ASND_SERVICE_ID) + { // ASnd service ID is valid + if (EplDlluCalInstance_g.m_apfnDlluCbAsnd[uiAsndServiceId] != NULL) + { // handler was registered + Ret = EplDlluCalInstance_g.m_apfnDlluCbAsnd[uiAsndServiceId](&FrameInfo); + } + } + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalRegAsndService() +// +// Description: registers the specified handler for the specified +// AsndServiceId with the specified node ID filter. +// +// Parameters: ServiceId_p = ASnd Service ID +// pfnDlluCbAsnd_p = callback function +// Filter_p = node ID filter +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalRegAsndService(tEplDllAsndServiceId ServiceId_p, tEplDlluCbAsnd pfnDlluCbAsnd_p, tEplDllAsndFilter Filter_p) +{ +tEplKernel Ret = kEplSuccessful; + + if (ServiceId_p < tabentries (EplDlluCalInstance_g.m_apfnDlluCbAsnd)) + { + // memorize function pointer + EplDlluCalInstance_g.m_apfnDlluCbAsnd[ServiceId_p] = pfnDlluCbAsnd_p; + + if (pfnDlluCbAsnd_p == NULL) + { // close filter + Filter_p = kEplDllAsndFilterNone; + } + + // set filter in DLL module in kernel part + Ret = EplDlluCalSetAsndServiceIdFilter(ServiceId_p, Filter_p); + + } + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalAsyncSend() +// +// Description: sends the frame with the specified priority. +// +// Parameters: pFrameInfo_p = frame +// m_uiFrameSize does not include the +// ethernet header (14 bytes) +// Priority_p = priority +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalAsyncSend(tEplFrameInfo * pFrameInfo_p, tEplDllAsyncReqPriority Priority_p) +{ +tEplKernel Ret = kEplSuccessful; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + pFrameInfo_p->m_uiFrameSize += 14; // add size of ethernet header + Ret = EplDllkCalAsyncSend(pFrameInfo_p, Priority_p); +#else + Ret = kEplSuccessful; +#endif + + return Ret; +} + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalIssueRequest() +// +// Description: issues a StatusRequest or a IdentRequest to the specified node. +// +// Parameters: Service_p = request service ID +// uiNodeId_p = node ID +// bSoaFlag1_p = flag1 for this node (transmit in SoA and PReq) +// If 0xFF this flag is ignored. +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalIssueRequest(tEplDllReqServiceId Service_p, unsigned int uiNodeId_p, BYTE bSoaFlag1_p) +{ +tEplKernel Ret = kEplSuccessful; + + // add node to appropriate request queue + switch (Service_p) + { + case kEplDllReqServiceIdent: + case kEplDllReqServiceStatus: + { + tEplEvent Event; + tEplDllCalIssueRequest IssueReq; + + Event.m_EventSink = kEplEventSinkDllkCal; + Event.m_EventType = kEplEventTypeDllkIssueReq; + IssueReq.m_Service = Service_p; + IssueReq.m_uiNodeId = uiNodeId_p; + IssueReq.m_bSoaFlag1 = bSoaFlag1_p; + Event.m_pArg = &IssueReq; + Event.m_uiSize = sizeof (IssueReq); + + Ret = EplEventuPost(&Event); + break; + } + + default: + { + Ret = kEplDllInvalidParam; + goto Exit; + } + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalAddNode() +// +// Description: adds the specified node to the isochronous phase. +// +// Parameters: pNodeInfo_p = pointer of node info structure +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalAddNode(tEplDllNodeInfo * pNodeInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; + + Event.m_EventSink = kEplEventSinkDllkCal; + Event.m_EventType = kEplEventTypeDllkAddNode; + Event.m_pArg = pNodeInfo_p; + Event.m_uiSize = sizeof (tEplDllNodeInfo); + + Ret = EplEventuPost(&Event); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalDeleteNode() +// +// Description: removes the specified node from the isochronous phase. +// +// Parameters: uiNodeId_p = node ID +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalDeleteNode(unsigned int uiNodeId_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; + + Event.m_EventSink = kEplEventSinkDllkCal; + Event.m_EventType = kEplEventTypeDllkDelNode; + Event.m_pArg = &uiNodeId_p; + Event.m_uiSize = sizeof (uiNodeId_p); + + Ret = EplEventuPost(&Event); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalSoftDeleteNode() +// +// Description: removes the specified node softly from the isochronous phase. +// +// Parameters: uiNodeId_p = node ID +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalSoftDeleteNode(unsigned int uiNodeId_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; + + Event.m_EventSink = kEplEventSinkDllkCal; + Event.m_EventType = kEplEventTypeDllkSoftDelNode; + Event.m_pArg = &uiNodeId_p; + Event.m_uiSize = sizeof (uiNodeId_p); + + Ret = EplEventuPost(&Event); + + return Ret; +} + + +#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplDlluCalSetAsndServiceIdFilter() +// +// Description: forwards call to EplDllkSetAsndServiceIdFilter() in kernel part +// +// Parameters: ServiceId_p = ASnd Service ID +// Filter_p = node ID filter +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplDlluCalSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p, tEplDllAsndFilter Filter_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; +tEplDllCalAsndServiceIdFilter ServFilter; + + Event.m_EventSink = kEplEventSinkDllkCal; + Event.m_EventType = kEplEventTypeDllkServFilter; + ServFilter.m_ServiceId = ServiceId_p; + ServFilter.m_Filter = Filter_p; + Event.m_pArg = &ServFilter; + Event.m_uiSize = sizeof (ServFilter); + + Ret = EplEventuPost(&Event); + + return Ret; +} + + +#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplErrDef.h b/drivers/staging/epl/EplErrDef.h new file mode 100644 index 0000000..5261692 --- /dev/null +++ b/drivers/staging/epl/EplErrDef.h @@ -0,0 +1,302 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: definitions for all EPL-function return codes + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplErrDef.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.9 $ $Date: 2008/06/23 14:56:33 $ + + $State: Exp $ + + Build Environment: + all + + ------------------------------------------------------------------------- + + Revision History: + + 2005/12/05 -as: start of the implementation, version 1.00 + +****************************************************************************/ + +#ifndef _EPL_ERRORDEF_H_ +#define _EPL_ERRORDEF_H_ + + +//--------------------------------------------------------------------------- +// return codes +//--------------------------------------------------------------------------- + +typedef enum +{ + // area for generic errors 0x0000 - 0x000F + kEplSuccessful = 0x0000, // no error/successful run + kEplIllegalInstance = 0x0001, // the called Instanz does not exist + kEplInvalidInstanceParam = 0x0002, // + kEplNoFreeInstance = 0x0003, // XxxAddInstance was called but no free instance is available + kEplWrongSignature = 0x0004, // wrong signature while writing to object 0x1010 or 0x1011 + kEplInvalidOperation = 0x0005, // operation not allowed in this situation + kEplInvalidNodeId = 0x0007, // invalid NodeId was specified + kEplNoResource = 0x0008, // resource could not be created (Windows, PxROS, ...) + kEplShutdown = 0x0009, // stack is shutting down + kEplReject = 0x000A, // reject the subsequent command + + // area for EDRV module 0x0010 - 0x001F +// kEplEdrvNoFrame = 0x0010, // no CAN message was received +// kEplEdrvMsgHigh = 0x0011, // CAN message with high priority was received +// kEplEdrvMsgLow = 0x0012, // CAN message with low priority was received + kEplEdrvInitError = 0x0013, // initialisation error + kEplEdrvNoFreeBufEntry = 0x0014, // no free entry in internal buffer table for Tx frames + kEplEdrvBufNotExisting = 0x0015, // specified Tx buffer does not exist +// kEplEdrvNoFreeChannel = 0x0014, // CAN controller has not a free channel +// kEplEdrvTxBuffHighOverrun = 0x0015, // buffer for high priority CAN transmit messages has overrun +// kEplEdrvTxBuffLowOverrun = 0x0016, // buffer for low priority CAN transmit messages has overrun +// kEplEdrvIllegalBdi = 0x0017, // unsupported baudrate within baudrate table +// kEplEdrvBusy = 0x0018, // remote frame can not be updated because no bus contact or CAN + // transmission is activ +// kEplEdrvInvalidDriverType = 0x0019, // (PC: Windows or Linux) invalid driver type +// kEplEdrvDriverNotFound = 0x001A, // (PC: Windows or Linux) driver (DLL) could not be found +// kEplEdrvInvalidBaseAddress = 0x001B, // (PC: Windows or Linux) driver could not found the CAN controller +// kEplEdrvInvalidParam = 0x001C, // invalid param in function call + + // area for COB module 0x0020 - 0x002F +/* kEplCobNoFreeEntry = 0x0020, // no free entry in RX- or TX-COB table + kEplCobAlreadyExist = 0x0021, // COB-ID already exists in RX- resp. TX-COB table + */ + kEplDllIllegalHdl = 0x0022, // illegal handle for a TxFrame was passed + kEplDllCbAsyncRegistered = 0x0023, // handler for non-EPL frames was already registered before +// kEplDllAsyncRxBufferFull = 0x0024, // receive buffer for asynchronous frames is full + kEplDllAsyncTxBufferEmpty = 0x0025, // transmit buffer for asynchronous frames is empty + kEplDllAsyncTxBufferFull = 0x0026, // transmit buffer for asynchronous frames is full + kEplDllNoNodeInfo = 0x0027, // MN: too less space in the internal node info structure + kEplDllInvalidParam = 0x0028, // invalid parameters passed to function + kEplDllTxBufNotReady = 0x002E, // TxBuffer (e.g. for PReq) is not ready yet + kEplDllTxFrameInvalid = 0x002F, // TxFrame (e.g. for PReq) is invalid or does not exist +/* kEplCobIllegalCanId = 0x0023, // COB-ID is not allowed (like 0x000 is reserved for NMT, ...) + kEplCobInvalidCanId = 0x0024, // COB-ID is switched off + kEplCobCdrvStateSet = 0x0025, // at least one bit of CAN driver state is set + kEplCobNoFreeEntryHighBuf = 0x0026, // no free entry in high priotity RX- or TX-COB table + kEplCobOwnId = 0x0027, // COB-ID already exists in own module which calls CobDefine() or CobCheck() +*/ + // area for OBD module 0x0030 - 0x003F + kEplObdIllegalPart = 0x0030, // unknown OD part + kEplObdIndexNotExist = 0x0031, // object index does not exist in OD + kEplObdSubindexNotExist = 0x0032, // subindex does not exist in object index + kEplObdReadViolation = 0x0033, // read access to a write-only object + kEplObdWriteViolation = 0x0034, // write access to a read-only object + kEplObdAccessViolation = 0x0035, // access not allowed + kEplObdUnknownObjectType = 0x0036, // object type not defined/known + kEplObdVarEntryNotExist = 0x0037, // object does not contain VarEntry structure + kEplObdValueTooLow = 0x0038, // value to write to an object is too low + kEplObdValueTooHigh = 0x0039, // value to write to an object is too high + kEplObdValueLengthError = 0x003A, // value to write is to long or to short +// kEplObdIllegalFloat = 0x003B, // illegal float variable +// kEplObdWrongOdBuilderKey = 0x003F, // OD was generated with demo version of tool ODBuilder + + // area for NMT module 0x0040 - 0x004F + kEplNmtUnknownCommand = 0x0040, // unknown NMT command + kEplNmtInvalidFramePointer = 0x0041, // pointer to the frame is not valid + kEplNmtInvalidEvent = 0x0042, // invalid event send to NMT-modul + kEplNmtInvalidState = 0x0043, // unknown state in NMT-State-Maschine + kEplNmtInvalidParam = 0x0044, // invalid parameters specified + + // area for SDO/UDP module 0x0050 - 0x005F + kEplSdoUdpMissCb = 0x0050, // missing callback-function pointer during inti of + // module + kEplSdoUdpNoSocket = 0x0051, // error during init of socket + kEplSdoUdpSocketError = 0x0052, // error during usage of socket + kEplSdoUdpThreadError = 0x0053, // error during start of listen thread + kEplSdoUdpNoFreeHandle = 0x0054, // no free connection handle for Udp + kEplSdoUdpSendError = 0x0055, // Error during send of frame + kEplSdoUdpInvalidHdl = 0x0056, // the connection handle is invalid + + // area for SDO Sequence layer module 0x0060 - 0x006F + kEplSdoSeqMissCb = 0x0060, // no callback-function assign + kEplSdoSeqNoFreeHandle = 0x0061, // no free handle for connection + kEplSdoSeqInvalidHdl = 0x0062, // invalid handle in SDO sequence layer + kEplSdoSeqUnsupportedProt = 0x0063, // unsupported Protocol selected + kEplSdoSeqNoFreeHistory = 0x0064, // no free entry in history + kEplSdoSeqFrameSizeError = 0x0065, // the size of the frames is not correct + kEplSdoSeqRequestAckNeeded = 0x0066, // indeicates that the history buffer is full + // and a ack request is needed + kEplSdoSeqInvalidFrame = 0x0067, // frame not valid + kEplSdoSeqConnectionBusy = 0x0068, // connection is busy -> retry later + kEplSdoSeqInvalidEvent = 0x0069, // invalid event received + + // area for SDO Command Layer Module 0x0070 - 0x007F + kEplSdoComUnsupportedProt = 0x0070, // unsupported Protocol selected + kEplSdoComNoFreeHandle = 0x0071, // no free handle for connection + kEplSdoComInvalidServiceType= 0x0072, // invalid SDO service type specified + kEplSdoComInvalidHandle = 0x0073, // handle invalid + kEplSdoComInvalidSendType = 0x0074, // the stated to of frame to send is + // not possible + kEplSdoComNotResponsible = 0x0075, // internal error: command layer handle is + // not responsible for this event from sequence layer + kEplSdoComHandleExists = 0x0076, // handle to same node already exists + kEplSdoComHandleBusy = 0x0077, // transfer via this handle is already running + kEplSdoComInvalidParam = 0x0078, // invalid parameters passed to function + + // area for EPL Event-Modul 0x0080 - 0x008F + kEplEventUnknownSink = 0x0080, // unknown sink for event + kEplEventPostError = 0x0081, // error during post of event + + + + // area for EPL Timer Modul 0x0090 - 0x009F + kEplTimerInvalidHandle = 0x0090, // invalid handle for timer + kEplTimerNoTimerCreated = 0x0091, // no timer was created caused by + // an error + + // area for EPL SDO/Asnd Module 0x00A0 - 0x0AF + kEplSdoAsndInvalidNodeId = 0x00A0, //0 node id is invalid + kEplSdoAsndNoFreeHandle = 0x00A1, // no free handle for connection + kEplSdoAsndInvalidHandle = 0x00A2, // handle for connection is invalid + + + // area for PDO module 0x00B0 - 0x00BF + kEplPdoNotExist = 0x00B0, // selected PDO does not exist + kEplPdoLengthExceeded = 0x00B1, // length of PDO mapping exceedes 64 bis + kEplPdoGranularityMismatch = 0x00B2, // configured PDO granularity is not equal to supported granularity + kEplPdoInitError = 0x00B3, // error during initialisation of PDO module + kEplPdoErrorPdoEncode = 0x00B4, // error during encoding a PDO + kEplPdoErrorPdoDecode = 0x00B5, // error during decoding a PDO + kEplPdoErrorSend = 0x00B6, // error during sending a PDO + kEplPdoErrorSyncWin = 0x00B7, // the SYNC window runs out during sending SYNC-PDOs + kEplPdoErrorMapp = 0x00B8, // invalid PDO mapping + kEplPdoVarNotFound = 0x00B9, // variable was not found in function PdoSignalVar() + kEplPdoErrorEmcyPdoLen = 0x00BA, // the length of a received PDO is unequal to the expected value + kEplPdoWriteConstObject = 0x00BB, // constant object can not be written + // (only TxType, Inhibit-, Event Time for CANopen Kit) + + // area for LSS slave module +/* kEplLsssResetNode = 0x0080, // NMT command "reset node" has to be processed after LSS configuration + // new of NodeId + kEplLsssInvalidNodeId = 0x0081, // no valid NodeId is configured -> wait until it is configured with + // LSS service before calling CcmConnectToNet() +*/ + // area for emergency consumer module 0x0090 - 0x009F +/* kEplEmccNoFreeProducerEntry = 0x0090, // no free entry to add a Emergency Producer + kEplEmccNodeIdNotExist = 0x0091, // selected NodeId was never added + kEplEmccNodeIdInvalid = 0x0092, // selected NodeId is outside of range (0x01 until 0x7F) + kEplEmccNodeIdExist = 0x0093, // selected NodeId already exist +*/ + // area for dynamic OD 0x00A0 - 0x00AF +/* kEplDynNoMemory = 0x00A0, // no memory available + kEplDynInvalidConfig = 0x00A1, // invalid configuration in segment container +*/ + // area for hertbeat consumer module 0x00B0 - 0x00BF +/* kEplHbcEntryNotExist = 0x00B0, // Heartbeat Producer node not configured + kEplHbcEntryAlreadyExist = 0x00B1, // NodeId was already defined in heartbeat consumer table (object 0x1016) +*/ + // Configuration manager module 0x00C0 - 0x00CF + kEplCfgMaConfigError = 0x00C0, // error in configuration manager + kEplCfgMaSdocTimeOutError = 0x00C1, // error in configuration manager, Sdo timeout + kEplCfgMaInvalidDcf = 0x00C2, // configration file not valid + kEplCfgMaUnsupportedDcf = 0x00C3, // unsupported Dcf format + kEplCfgMaConfigWithErrors = 0x00C4, // configuration finished with errors + kEplCfgMaNoFreeConfig = 0x00C5, // no free configuration entry + kEplCfgMaNoConfigData = 0x00C6, // no configuration data present + kEplCfgMaUnsuppDatatypeDcf = 0x00C7, // unsupported datatype found in dcf + // -> this entry was not configured + + + // area for LSS master module 0x00D0 - 0x00DF +/* kEplLssmIllegalMode = 0x00D0, // illegal LSS mode (operation / configuration) + kEplLssmIllegalState = 0x00D1, // function was called in illegal state of LSS master + kEplLssmBusy = 0x00D2, // LSS process is busy with an previous service + kEplLssmIllegalCmd = 0x00D3, // illegal command code was set for function LssmInquireIdentity() + kEplLssmTimeout = 0x00D4, // LSS slave did not answer a LSS service + kEplLssmErrorInConfirm = 0x00D5, // LSS slave replied an error code for a LSS service +*/ + // area for CCM modules 0x00E0 - 0xEF +/* kEplCcmStoreUnvalidState = 0x00E0, // memory device not available due device state + kEplCcmStoreHwError = 0x00E1, // hw error due device access +*/ + // area for SRDO module 0x0100 - 0x011F +/* kEplSrdoNotExist = 0x0100, // selected SRDO does not exist + kEplSrdoGranularityMismatch = 0x0101, // configured SRDO granularity is not equal to supported granularity + kEplSrdoCfgTimingError = 0x0102, // configuration is not ok (Timing) + kEplSrdoCfgIdError = 0x0103, // configuration is not ok (CobIds) + kEplSrdoCfgCrcError = 0x0104, // configuration is not ok (CRC) + kEplSrdoNmtError = 0x0105, // an action was tried in a wrong NMT state + kEplSrdoInvalidCfg = 0x0106, // an action was tried with an invald SRDO configuration + kEplSrdoInvalid = 0x0107, // an action was tried with an invald SRDO + kEplSrdoRxTxConflict = 0x0108, // an transmission was tried with an receive SRDO (or the other way) + kEplSrdoIllegalCanId = 0x0109, // the CanId is invalid + kEplSrdoCanIdAlreadyInUse = 0x010A, // the CanId is already in use + kEplSrdoNotInOrder = 0x010B, // the two messages of a SRDO are not in order + kEplSrdoSctTimeout = 0x010C, // timeout of SCT + kEplSrdoSrvtTimeout = 0x010D, // timeout of SRVT + kEplSrdoCanIdNotValid = 0x010E, // one of received CAN-IDs are not equal to configured one + kEplSrdoDlcNotValid = 0x010F, // one of received CAN-DLC are not equal to configured one + kEplSrdoErrorMapp = 0x0110, // wrong values in mapping found + kEplSrdoDataError = 0x0111, // data of CAN messages are not invers + kEplSrdoLengthExceeded = 0x0112, // length of SRDO mapping exceedes 64 bit per CAN-message + kEplSrdoNotHandledInApp = 0x0113, // the SRDO error was not handled in AppSrdoError() + kEplSrdoOverrun = 0x0114 // a RxSRDO was received but the pevious one was not else processed +*/ + + kEplApiTaskDeferred = 0x0140, // EPL performs task in background and informs the application (or vice-versa), when it is finished + kEplApiInvalidParam = 0x0142, // passed invalid parameters to a function (e.g. invalid node id) + + // area untill 0x07FF is reserved + // area for user application from 0x0800 to 0x7FFF + +} tEplKernel; + + +#endif +//EOF + +// Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler +// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder). + diff --git a/drivers/staging/epl/EplErrorHandlerk.c b/drivers/staging/epl/EplErrorHandlerk.c new file mode 100644 index 0000000..121f026 --- /dev/null +++ b/drivers/staging/epl/EplErrorHandlerk.c @@ -0,0 +1,800 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for error handler module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplErrorHandlerk.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.9 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/10/02 d.k.: start of the implementation + +****************************************************************************/ + +#include "kernel/EplErrorHandlerk.h" +#include "EplNmt.h" +#include "kernel/EplEventk.h" +#include "kernel/EplObdk.h" // function prototyps of the EplOBD-Modul +#include "kernel/EplDllk.h" + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) == 0) +#error "EPL ErrorHandler module needs EPL module OBDK!" +#endif + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ + DWORD m_dwCumulativeCnt; // subindex 1 + DWORD m_dwThresholdCnt; // subindex 2 + DWORD m_dwThreshold; // subindex 3 + +} tEplErrorHandlerkErrorCounter; + +typedef struct +{ + tEplErrorHandlerkErrorCounter m_CnLossSoc; // object 0x1C0B + tEplErrorHandlerkErrorCounter m_CnLossPreq; // object 0x1C0D + tEplErrorHandlerkErrorCounter m_CnCrcErr; // object 0x1C0F + unsigned long m_ulDllErrorEvents; + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + tEplErrorHandlerkErrorCounter m_MnCrcErr; // object 0x1C00 + tEplErrorHandlerkErrorCounter m_MnCycTimeExceed; // object 0x1C02 + DWORD m_adwMnCnLossPresCumCnt[254]; // object 0x1C07 + DWORD m_adwMnCnLossPresThrCnt[254]; // object 0x1C08 + DWORD m_adwMnCnLossPresThreshold[254];// object 0x1C09 + BOOL m_afMnCnLossPresEvent[254]; +#endif + +} tEplErrorHandlerkInstance; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +static tEplErrorHandlerkInstance EplErrorHandlerkInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static tEplKernel EplErrorHandlerkLinkErrorCounter( + tEplErrorHandlerkErrorCounter* pErrorCounter_p, + unsigned int uiIndex_p); + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +static tEplKernel EplErrorHandlerkLinkArray( + DWORD* pdwValue_p, + unsigned int uiValueCount_p, + unsigned int uiIndex_p); +#endif + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <Epl-Kernelspace-Error-Handler> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplErrorHandlerkInit +// +// Description: function initialize the first instance +// +// +// +// Parameters: +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplErrorHandlerkInit(void) +{ +tEplKernel Ret; + + + Ret = EplErrorHandlerkAddInstance(); + + +return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplErrorHandlerkAddInstance +// +// Description: function add one more instance +// +// +// +// Parameters: +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplErrorHandlerkAddInstance(void) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // reset only event variable, + // all other instance members are reset by OD or may keep their current value + // d.k.: this is necessary for the cumulative counters, which shall not be reset + EplErrorHandlerkInstance_g.m_ulDllErrorEvents = 0; + + // link counters to OD + // $$$ d.k. if OD resides in userspace, fetch pointer to shared memory, + // which shall have the same structure as the instance (needs to be declared globally). + // Other idea: error counter shall belong to the process image + // (reset of counters by SDO write are a little bit tricky). + + Ret = EplErrorHandlerkLinkErrorCounter( + &EplErrorHandlerkInstance_g.m_CnLossSoc, + 0x1C0B); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + Ret = EplErrorHandlerkLinkErrorCounter( + &EplErrorHandlerkInstance_g.m_CnLossPreq, + 0x1C0D); + // ignore return code, because object 0x1C0D is conditional + + Ret = EplErrorHandlerkLinkErrorCounter( + &EplErrorHandlerkInstance_g.m_CnCrcErr, + 0x1C0F); + if (Ret != kEplSuccessful) + { + goto Exit; + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + Ret = EplErrorHandlerkLinkErrorCounter( + &EplErrorHandlerkInstance_g.m_MnCrcErr, + 0x1C00); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + Ret = EplErrorHandlerkLinkErrorCounter( + &EplErrorHandlerkInstance_g.m_MnCycTimeExceed, + 0x1C02); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + Ret = EplErrorHandlerkLinkArray( + EplErrorHandlerkInstance_g.m_adwMnCnLossPresCumCnt, + tabentries(EplErrorHandlerkInstance_g.m_adwMnCnLossPresCumCnt), + 0x1C07); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + Ret = EplErrorHandlerkLinkArray( + EplErrorHandlerkInstance_g.m_adwMnCnLossPresThrCnt, + tabentries(EplErrorHandlerkInstance_g.m_adwMnCnLossPresThrCnt), + 0x1C08); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + Ret = EplErrorHandlerkLinkArray( + EplErrorHandlerkInstance_g.m_adwMnCnLossPresThreshold, + tabentries(EplErrorHandlerkInstance_g.m_adwMnCnLossPresThreshold), + 0x1C09); + if (Ret != kEplSuccessful) + { + goto Exit; + } + +#endif + +Exit: + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplErrorHandlerkDelInstance +// +// Description: function delete instance an free the bufferstructure +// +// +// +// Parameters: +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplErrorHandlerkDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + +return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplErrorHandlerkProcess +// +// Description: processes error events from DLL +// +// +// +// Parameters: pEvent_p = pointer to event-structur from buffer +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplErrorHandlerkProcess(tEplEvent* pEvent_p) +{ +tEplKernel Ret; +unsigned long ulDllErrorEvents; +tEplEvent Event; +tEplNmtEvent NmtEvent; + + Ret = kEplSuccessful; + + // check m_EventType + switch(pEvent_p->m_EventType) + { + case kEplEventTypeDllError: + { + tEplErrorHandlerkEvent* pErrHandlerEvent = (tEplErrorHandlerkEvent*)pEvent_p->m_pArg; + + ulDllErrorEvents = pErrHandlerEvent->m_ulDllErrorEvents; + + // check the several error events + if ((EplErrorHandlerkInstance_g.m_CnLossSoc.m_dwThreshold > 0) + && ((ulDllErrorEvents & EPL_DLL_ERR_CN_LOSS_SOC) != 0)) + { // loss of SoC event occured + // increment cumulative counter by 1 + EplErrorHandlerkInstance_g.m_CnLossSoc.m_dwCumulativeCnt++; + // increment threshold counter by 8 + EplErrorHandlerkInstance_g.m_CnLossSoc.m_dwThresholdCnt += 8; + if (EplErrorHandlerkInstance_g.m_CnLossSoc.m_dwThresholdCnt + >= EplErrorHandlerkInstance_g.m_CnLossSoc.m_dwThreshold) + { // threshold is reached + // $$$ d.k.: generate error history entry E_DLL_LOSS_SOC_TH + + // post event to NMT state machine + NmtEvent = kEplNmtEventNmtCycleError; + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_pArg = &NmtEvent; + Event.m_uiSize = sizeof (NmtEvent); + Ret = EplEventkPost(&Event); + } + EplErrorHandlerkInstance_g.m_ulDllErrorEvents |= + EPL_DLL_ERR_CN_LOSS_SOC; + } + + if ((EplErrorHandlerkInstance_g.m_CnLossPreq.m_dwThreshold > 0) + && ((ulDllErrorEvents & EPL_DLL_ERR_CN_LOSS_PREQ) != 0)) + { // loss of PReq event occured + // increment cumulative counter by 1 + EplErrorHandlerkInstance_g.m_CnLossPreq.m_dwCumulativeCnt++; + // increment threshold counter by 8 + EplErrorHandlerkInstance_g.m_CnLossPreq.m_dwThresholdCnt += 8; + if (EplErrorHandlerkInstance_g.m_CnLossPreq.m_dwThresholdCnt + >= EplErrorHandlerkInstance_g.m_CnLossPreq.m_dwThreshold) + { // threshold is reached + // $$$ d.k.: generate error history entry E_DLL_LOSS_PREQ_TH + + // post event to NMT state machine + NmtEvent = kEplNmtEventNmtCycleError; + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_pArg = &NmtEvent; + Event.m_uiSize = sizeof (NmtEvent); + Ret = EplEventkPost(&Event); + } + } + + if ((EplErrorHandlerkInstance_g.m_CnLossPreq.m_dwThresholdCnt > 0) + && ((ulDllErrorEvents & EPL_DLL_ERR_CN_RECVD_PREQ) != 0)) + { // PReq correctly received + // decrement threshold counter by 1 + EplErrorHandlerkInstance_g.m_CnLossPreq.m_dwThresholdCnt--; + } + + if ((EplErrorHandlerkInstance_g.m_CnCrcErr.m_dwThreshold > 0) + && ((ulDllErrorEvents & EPL_DLL_ERR_CN_CRC) != 0)) + { // CRC error event occured + // increment cumulative counter by 1 + EplErrorHandlerkInstance_g.m_CnCrcErr.m_dwCumulativeCnt++; + // increment threshold counter by 8 + EplErrorHandlerkInstance_g.m_CnCrcErr.m_dwThresholdCnt += 8; + if (EplErrorHandlerkInstance_g.m_CnCrcErr.m_dwThresholdCnt + >= EplErrorHandlerkInstance_g.m_CnCrcErr.m_dwThreshold) + { // threshold is reached + // $$$ d.k.: generate error history entry E_DLL_CRC_TH + + // post event to NMT state machine + NmtEvent = kEplNmtEventNmtCycleError; + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_pArg = &NmtEvent; + Event.m_uiSize = sizeof (NmtEvent); + Ret = EplEventkPost(&Event); + } + EplErrorHandlerkInstance_g.m_ulDllErrorEvents |= + EPL_DLL_ERR_CN_CRC; + } + + if ((ulDllErrorEvents & EPL_DLL_ERR_INVALID_FORMAT) != 0) + { // invalid format error occured (only direct reaction) + // $$$ d.k.: generate error history entry E_DLL_INVALID_FORMAT +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + if (pErrHandlerEvent->m_NmtState >= kEplNmtMsNotActive) + { // MN is active + if (pErrHandlerEvent->m_uiNodeId != 0) + { + tEplHeartbeatEvent HeartbeatEvent; + + // remove node from isochronous phase + Ret = EplDllkDeleteNode(pErrHandlerEvent->m_uiNodeId); + + // inform NmtMnu module about state change, which shall send NMT command ResetNode to this CN + HeartbeatEvent.m_uiNodeId = pErrHandlerEvent->m_uiNodeId; + HeartbeatEvent.m_NmtState = kEplNmtCsNotActive; + HeartbeatEvent.m_wErrorCode = EPL_E_DLL_INVALID_FORMAT; + Event.m_EventSink = kEplEventSinkNmtMnu; + Event.m_EventType = kEplEventTypeHeartbeat; + Event.m_uiSize = sizeof (HeartbeatEvent); + Event.m_pArg = &HeartbeatEvent; + Ret = EplEventkPost(&Event); + } + // $$$ and else should lead to InternComError + } + else +#endif + { // CN is active + // post event to NMT state machine + NmtEvent = kEplNmtEventInternComError; + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_pArg = &NmtEvent; + Event.m_uiSize = sizeof (NmtEvent); + Ret = EplEventkPost(&Event); + } + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + if ((EplErrorHandlerkInstance_g.m_MnCrcErr.m_dwThreshold > 0) + && ((ulDllErrorEvents & EPL_DLL_ERR_MN_CRC) != 0)) + { // CRC error event occured + // increment cumulative counter by 1 + EplErrorHandlerkInstance_g.m_MnCrcErr.m_dwCumulativeCnt++; + // increment threshold counter by 8 + EplErrorHandlerkInstance_g.m_MnCrcErr.m_dwThresholdCnt += 8; + if (EplErrorHandlerkInstance_g.m_MnCrcErr.m_dwThresholdCnt + >= EplErrorHandlerkInstance_g.m_MnCrcErr.m_dwThreshold) + { // threshold is reached + // $$$ d.k.: generate error history entry E_DLL_CRC_TH + + // post event to NMT state machine + NmtEvent = kEplNmtEventNmtCycleError; + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_pArg = &NmtEvent; + Event.m_uiSize = sizeof (NmtEvent); + Ret = EplEventkPost(&Event); + } + EplErrorHandlerkInstance_g.m_ulDllErrorEvents |= + EPL_DLL_ERR_MN_CRC; + } + + if ((EplErrorHandlerkInstance_g.m_MnCycTimeExceed.m_dwThreshold > 0) + && ((ulDllErrorEvents & EPL_DLL_ERR_MN_CYCTIMEEXCEED) != 0)) + { // cycle time exceeded event occured + // increment cumulative counter by 1 + EplErrorHandlerkInstance_g.m_MnCycTimeExceed.m_dwCumulativeCnt++; + // increment threshold counter by 8 + EplErrorHandlerkInstance_g.m_MnCycTimeExceed.m_dwThresholdCnt += 8; + if (EplErrorHandlerkInstance_g.m_MnCycTimeExceed.m_dwThresholdCnt + >= EplErrorHandlerkInstance_g.m_MnCycTimeExceed.m_dwThreshold) + { // threshold is reached + // $$$ d.k.: generate error history entry E_DLL_CYCLE_EXCEED_TH + + // post event to NMT state machine + NmtEvent = kEplNmtEventNmtCycleError; + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_pArg = &NmtEvent; + Event.m_uiSize = sizeof (NmtEvent); + Ret = EplEventkPost(&Event); + } + // $$$ d.k.: else generate error history entry E_DLL_CYCLE_EXCEED + EplErrorHandlerkInstance_g.m_ulDllErrorEvents |= + EPL_DLL_ERR_MN_CYCTIMEEXCEED; + } + + if ((ulDllErrorEvents & EPL_DLL_ERR_MN_CN_LOSS_PRES) != 0) + { // CN loss PRes event occured + unsigned int uiNodeId; + + uiNodeId = pErrHandlerEvent->m_uiNodeId - 1; + if ((uiNodeId < tabentries(EplErrorHandlerkInstance_g.m_adwMnCnLossPresCumCnt)) + && (EplErrorHandlerkInstance_g.m_adwMnCnLossPresThreshold[uiNodeId] > 0)) + { + // increment cumulative counter by 1 + EplErrorHandlerkInstance_g.m_adwMnCnLossPresCumCnt[uiNodeId]++; + // increment threshold counter by 8 + EplErrorHandlerkInstance_g.m_adwMnCnLossPresThrCnt[uiNodeId] += 8; + if (EplErrorHandlerkInstance_g.m_adwMnCnLossPresThrCnt[uiNodeId] + >= EplErrorHandlerkInstance_g.m_adwMnCnLossPresThreshold[uiNodeId]) + { // threshold is reached + tEplHeartbeatEvent HeartbeatEvent; + + // $$$ d.k.: generate error history entry E_DLL_LOSS_PRES_TH + + // remove node from isochronous phase + Ret = EplDllkDeleteNode(pErrHandlerEvent->m_uiNodeId); + + // inform NmtMnu module about state change, which shall send NMT command ResetNode to this CN + HeartbeatEvent.m_uiNodeId = pErrHandlerEvent->m_uiNodeId; + HeartbeatEvent.m_NmtState = kEplNmtCsNotActive; + HeartbeatEvent.m_wErrorCode = EPL_E_DLL_LOSS_PRES_TH; + Event.m_EventSink = kEplEventSinkNmtMnu; + Event.m_EventType = kEplEventTypeHeartbeat; + Event.m_uiSize = sizeof (HeartbeatEvent); + Event.m_pArg = &HeartbeatEvent; + Ret = EplEventkPost(&Event); + } + EplErrorHandlerkInstance_g.m_afMnCnLossPresEvent[uiNodeId] = TRUE; + } + } +#endif + + break; + } + + // NMT event + case kEplEventTypeNmtEvent: + { + if ((*(tEplNmtEvent*)pEvent_p->m_pArg) == kEplNmtEventDllCeSoa) + { // SoA event of CN -> decrement threshold counters + + if ((EplErrorHandlerkInstance_g.m_ulDllErrorEvents & EPL_DLL_ERR_CN_LOSS_SOC) == 0) + { // decrement loss of SoC threshold counter, because it didn't occur last cycle + if (EplErrorHandlerkInstance_g.m_CnLossSoc.m_dwThresholdCnt > 0) + { + EplErrorHandlerkInstance_g.m_CnLossSoc.m_dwThresholdCnt--; + } + } + + if ((EplErrorHandlerkInstance_g.m_ulDllErrorEvents & EPL_DLL_ERR_CN_CRC) == 0) + { // decrement CRC threshold counter, because it didn't occur last cycle + if (EplErrorHandlerkInstance_g.m_CnCrcErr.m_dwThresholdCnt > 0) + { + EplErrorHandlerkInstance_g.m_CnCrcErr.m_dwThresholdCnt--; + } + } + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + else if ((*(tEplNmtEvent*)pEvent_p->m_pArg) == kEplNmtEventDllMeSoaSent) + { // SoA event of MN -> decrement threshold counters + tEplDllkNodeInfo* pIntNodeInfo; + unsigned int uiNodeId; + + Ret = EplDllkGetFirstNodeInfo(&pIntNodeInfo); + if (Ret != kEplSuccessful) + { + break; + } + // iterate through node info structure list + while (pIntNodeInfo != NULL) + { + uiNodeId = pIntNodeInfo->m_uiNodeId - 1; + if (uiNodeId < tabentries(EplErrorHandlerkInstance_g.m_adwMnCnLossPresCumCnt)) + { + if (EplErrorHandlerkInstance_g.m_afMnCnLossPresEvent[uiNodeId] == FALSE) + { + if (EplErrorHandlerkInstance_g.m_adwMnCnLossPresThrCnt[uiNodeId] > 0) + { + EplErrorHandlerkInstance_g.m_adwMnCnLossPresThrCnt[uiNodeId]--; + } + } + else + { + EplErrorHandlerkInstance_g.m_afMnCnLossPresEvent[uiNodeId] = FALSE; + } + } + pIntNodeInfo = pIntNodeInfo->m_pNextNodeInfo; + } + + if ((EplErrorHandlerkInstance_g.m_ulDllErrorEvents & EPL_DLL_ERR_MN_CRC) == 0) + { // decrement CRC threshold counter, because it didn't occur last cycle + if (EplErrorHandlerkInstance_g.m_MnCrcErr.m_dwThresholdCnt > 0) + { + EplErrorHandlerkInstance_g.m_MnCrcErr.m_dwThresholdCnt--; + } + } + + if ((EplErrorHandlerkInstance_g.m_ulDllErrorEvents & EPL_DLL_ERR_MN_CYCTIMEEXCEED) == 0) + { // decrement cycle exceed threshold counter, because it didn't occur last cycle + if (EplErrorHandlerkInstance_g.m_MnCycTimeExceed.m_dwThresholdCnt > 0) + { + EplErrorHandlerkInstance_g.m_MnCycTimeExceed.m_dwThresholdCnt--; + } + } + } +#endif + + // reset error events + EplErrorHandlerkInstance_g.m_ulDllErrorEvents = 0L; + + break; + } + + + // unknown type + default: + { + } + + } // end of switch(pEvent_p->m_EventType) + + + return Ret; + +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplErrorHandlerkLinkErrorCounter +// +// Description: link specified error counter structure to OD entry +// +// Parameters: pErrorCounter_p = pointer to error counter structure +// uiIndex_p = OD index +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplErrorHandlerkLinkErrorCounter( + tEplErrorHandlerkErrorCounter* pErrorCounter_p, + unsigned int uiIndex_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplVarParam VarParam; + + VarParam.m_pData = &pErrorCounter_p->m_dwCumulativeCnt; + VarParam.m_Size = sizeof(DWORD); + VarParam.m_uiIndex = uiIndex_p; + VarParam.m_uiSubindex = 0x01; + VarParam.m_ValidFlag = kVarValidAll; + Ret = EplObdDefineVar(&VarParam); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + VarParam.m_pData = &pErrorCounter_p->m_dwThresholdCnt; + VarParam.m_Size = sizeof(DWORD); + VarParam.m_uiIndex = uiIndex_p; + VarParam.m_uiSubindex = 0x02; + VarParam.m_ValidFlag = kVarValidAll; + Ret = EplObdDefineVar(&VarParam); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + VarParam.m_pData = &pErrorCounter_p->m_dwThreshold; + VarParam.m_Size = sizeof(DWORD); + VarParam.m_uiIndex = uiIndex_p; + VarParam.m_uiSubindex = 0x03; + VarParam.m_ValidFlag = kVarValidAll; + Ret = EplObdDefineVar(&VarParam); + if (Ret != kEplSuccessful) + { + goto Exit; + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplErrorHandlerkLinkErrorCounter +// +// Description: link specified error counter structure to OD entry +// +// Parameters: pErrorCounter_p = pointer to error counter structure +// uiIndex_p = OD index +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +static tEplKernel EplErrorHandlerkLinkArray( + DWORD* pdwValue_p, + unsigned int uiValueCount_p, + unsigned int uiIndex_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplVarParam VarParam; +tEplObdSize EntrySize; +BYTE bIndexEntries; + + EntrySize = (tEplObdSize) sizeof(bIndexEntries); + Ret = EplObdReadEntry ( + uiIndex_p, + 0x00, + (void GENERIC*) &bIndexEntries, + &EntrySize ); + + if ((Ret != kEplSuccessful) || (bIndexEntries == 0x00)) + { + // Object doesn't exist or invalid entry number + Ret = kEplObdIndexNotExist; + goto Exit; + } + + if (bIndexEntries < uiValueCount_p) + { + uiValueCount_p = bIndexEntries; + } + + VarParam.m_Size = sizeof(DWORD); + VarParam.m_uiIndex = uiIndex_p; + VarParam.m_ValidFlag = kVarValidAll; + + for (VarParam.m_uiSubindex = 0x01; VarParam.m_uiSubindex <= uiValueCount_p; VarParam.m_uiSubindex++) + { + VarParam.m_pData = pdwValue_p; + Ret = EplObdDefineVar(&VarParam); + if (Ret != kEplSuccessful) + { + goto Exit; + } + pdwValue_p++; + } + +Exit: + return Ret; +} +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplEvent.h b/drivers/staging/epl/EplEvent.h new file mode 100644 index 0000000..5c26202 --- /dev/null +++ b/drivers/staging/epl/EplEvent.h @@ -0,0 +1,303 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for event module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplEvent.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/11/17 16:40:39 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/12 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_EVENT_H_ +#define _EPL_EVENT_H_ + +#include "EplInc.h" +#include "EplNmt.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// name and size of event queues +#define EPL_EVENT_NAME_SHB_KERNEL_TO_USER "ShbKernelToUser" +#ifndef EPL_EVENT_SIZE_SHB_KERNEL_TO_USER +#define EPL_EVENT_SIZE_SHB_KERNEL_TO_USER 32768 // 32 kByte +#endif + +#define EPL_EVENT_NAME_SHB_USER_TO_KERNEL "ShbUserToKernel" +#ifndef EPL_EVENT_SIZE_SHB_USER_TO_KERNEL +#define EPL_EVENT_SIZE_SHB_USER_TO_KERNEL 32768 // 32 kByte +#endif + + +// max size of event argument +#ifndef EPL_MAX_EVENT_ARG_SIZE +#define EPL_MAX_EVENT_ARG_SIZE 256 // because of PDO +#endif + +#define EPL_DLL_ERR_MN_CRC 0x00000001L // object 0x1C00 +#define EPL_DLL_ERR_MN_COLLISION 0x00000002L // object 0x1C01 +#define EPL_DLL_ERR_MN_CYCTIMEEXCEED 0x00000004L // object 0x1C02 +#define EPL_DLL_ERR_MN_LOSS_LINK 0x00000008L // object 0x1C03 +#define EPL_DLL_ERR_MN_CN_LATE_PRES 0x00000010L // objects 0x1C04-0x1C06 +#define EPL_DLL_ERR_MN_CN_LOSS_PRES 0x00000080L // objects 0x1C07-0x1C09 +#define EPL_DLL_ERR_CN_COLLISION 0x00000400L // object 0x1C0A +#define EPL_DLL_ERR_CN_LOSS_SOC 0x00000800L // object 0x1C0B +#define EPL_DLL_ERR_CN_LOSS_SOA 0x00001000L // object 0x1C0C +#define EPL_DLL_ERR_CN_LOSS_PREQ 0x00002000L // object 0x1C0D +#define EPL_DLL_ERR_CN_RECVD_PREQ 0x00004000L // decrement object 0x1C0D/2 +#define EPL_DLL_ERR_CN_SOC_JITTER 0x00008000L // object 0x1C0E +#define EPL_DLL_ERR_CN_CRC 0x00010000L // object 0x1C0F +#define EPL_DLL_ERR_CN_LOSS_LINK 0x00020000L // object 0x1C10 +#define EPL_DLL_ERR_MN_LOSS_STATRES 0x00040000L // objects 0x1C15-0x1C17 (should be operated by NmtMnu module) +#define EPL_DLL_ERR_BAD_PHYS_MODE 0x00080000L // no object +#define EPL_DLL_ERR_MAC_BUFFER 0x00100000L // no object (NMT_GT6) +#define EPL_DLL_ERR_INVALID_FORMAT 0x00200000L // no object (NMT_GT6) +#define EPL_DLL_ERR_ADDRESS_CONFLICT 0x00400000L // no object (remove CN from configuration) + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +// EventType determines the argument of the event +typedef enum +{ + kEplEventTypeNmtEvent = 0x01, // NMT event + // arg is pointer to tEplNmtEvent + kEplEventTypePdoRx = 0x02, // PDO frame received event (PRes/PReq) + // arg is pointer to tEplFrame + kEplEventTypePdoTx = 0x03, // PDO frame transmitted event (PRes/PReq) + // arg is pointer to tEplFrameInfo + kEplEventTypePdoSoa = 0x04, // SoA frame received event (isochronous phase completed) + // arg is pointer to nothing + kEplEventTypeSync = 0x05, // Sync event (e.g. SoC or anticipated SoC) + // arg is pointer to nothing + kEplEventTypeTimer = 0x06, // Timer event + // arg is pointer to tEplTimerEventArg + kEplEventTypeHeartbeat = 0x07, // Heartbeat event + // arg is pointer to tEplHeartbeatEvent + kEplEventTypeDllkCreate = 0x08, // DLL kernel create event + // arg is pointer to the new tEplNmtState + kEplEventTypeDllkDestroy = 0x09, // DLL kernel destroy event + // arg is pointer to the old tEplNmtState + kEplEventTypeDllkFillTx = 0x0A, // DLL kernel fill TxBuffer event + // arg is pointer to tEplDllAsyncReqPriority + kEplEventTypeDllkPresReady = 0x0B, // DLL kernel PRes ready event + // arg is pointer to nothing + kEplEventTypeError = 0x0C, // Error event for API layer + // arg is pointer to tEplEventError + kEplEventTypeNmtStateChange = 0x0D, // indicate change of NMT-State + // arg is pointer to tEplEventNmtStateChange + kEplEventTypeDllError = 0x0E, // DLL error event for Error handler + // arg is pointer to tEplErrorHandlerkEvent + kEplEventTypeAsndRx = 0x0F, // received ASnd frame for DLL user module + // arg is pointer to tEplFrame + kEplEventTypeDllkServFilter = 0x10, // configure ServiceIdFilter + // arg is pointer to tEplDllCalServiceIdFilter + kEplEventTypeDllkIdentity = 0x11, // configure Identity + // arg is pointer to tEplDllIdentParam + kEplEventTypeDllkConfig = 0x12, // configure ConfigParam + // arg is pointer to tEplDllConfigParam + kEplEventTypeDllkIssueReq = 0x13, // issue Ident/Status request + // arg is pointer to tEplDllCalIssueRequest + kEplEventTypeDllkAddNode = 0x14, // add node to isochronous phase + // arg is pointer to tEplDllNodeInfo + kEplEventTypeDllkDelNode = 0x15, // remove node from isochronous phase + // arg is pointer to unsigned int + kEplEventTypeDllkSoftDelNode= 0x16, // remove node softly from isochronous phase + // arg is pointer to unsigned int + kEplEventTypeDllkStartReducedCycle = 0x17, // start reduced EPL cycle on MN + // arg is pointer to nothing + kEplEventTypeNmtMnuNmtCmdSent = 0x18, // NMT command was actually sent + // arg is pointer to tEplFrame + +} tEplEventType; + + +// EventSink determines the consumer of the event +typedef enum +{ + kEplEventSinkSync = 0x00, // Sync event for application or kernel EPL module + kEplEventSinkNmtk = 0x01, // events for Nmtk module + kEplEventSinkDllk = 0x02, // events for Dllk module + kEplEventSinkDlluCal = 0x03, // events for DlluCal module + kEplEventSinkDllkCal = 0x04, // events for DllkCal module + kEplEventSinkPdok = 0x05, // events for Pdok module + kEplEventSinkNmtu = 0x06, // events for Nmtu module + kEplEventSinkErrk = 0x07, // events for Error handler module + kEplEventSinkErru = 0x08, // events for Error signaling module + kEplEventSinkSdoAsySeq = 0x09, // events for asyncronous SDO Sequence Layer module + kEplEventSinkNmtMnu = 0x0A, // events for NmtMnu module + kEplEventSinkLedu = 0x0B, // events for Ledu module + kEplEventSinkApi = 0x0F, // events for API module + +} tEplEventSink; + + +// EventSource determines the source of an errorevent +typedef enum +{ + // kernelspace modules + kEplEventSourceDllk = 0x01, // Dllk module + kEplEventSourceNmtk = 0x02, // Nmtk module + kEplEventSourceObdk = 0x03, // Obdk module + kEplEventSourcePdok = 0x04, // Pdok module + kEplEventSourceTimerk = 0x05, // Timerk module + kEplEventSourceEventk = 0x06, // Eventk module + kEplEventSourceSyncCb = 0x07, // sync-Cb + kEplEventSourceErrk = 0x08, // Error handler module + + // userspace modules + kEplEventSourceDllu = 0x10, // Dllu module + kEplEventSourceNmtu = 0x11, // Nmtu module + kEplEventSourceNmtCnu = 0x12, // NmtCnu module + kEplEventSourceNmtMnu = 0x13, // NmtMnu module + kEplEventSourceObdu = 0x14, // Obdu module + kEplEventSourceSdoUdp = 0x15, // Sdo/Udp module + kEplEventSourceSdoAsnd = 0x16, // Sdo/Asnd module + kEplEventSourceSdoAsySeq = 0x17, // Sdo asynchronus Sequence Layer module + kEplEventSourceSdoCom = 0x18, // Sdo command layer module + kEplEventSourceTimeru = 0x19, // Timeru module + kEplEventSourceCfgMau = 0x1A, // CfgMau module + kEplEventSourceEventu = 0x1B, // Eventu module + kEplEventSourceEplApi = 0x1C, // Api module + kEplEventSourceLedu = 0x1D, // Ledu module + +} tEplEventSource; + + +// structure of EPL event (element order must not be changed!) +typedef struct +{ + tEplEventType m_EventType /*:28*/; // event type + tEplEventSink m_EventSink /*:4*/; // event sink + tEplNetTime m_NetTime; // timestamp + unsigned int m_uiSize; // size of argument + void * m_pArg; // argument of event + +} tEplEvent; + + +// short structure of EPL event without argument and its size (element order must not be changed!) +typedef struct +{ + tEplEventType m_EventType /*:28*/; // event type + tEplEventSink m_EventSink /*:4*/; // event sink + tEplNetTime m_NetTime; // timestamp + +} tEplEventShort; + + +typedef struct +{ + unsigned int m_uiIndex; + unsigned int m_uiSubIndex; + +} tEplEventObdError; + + +// structure for kEplEventTypeError +typedef struct +{ + tEplEventSource m_EventSource; // module which posted this error event + tEplKernel m_EplError; // EPL error which occured + union + { + BYTE m_bArg; + DWORD m_dwArg; + tEplEventSource m_EventSource; // from Eventk/u module (originating error source) + tEplEventObdError m_ObdError; // from Obd module +// tEplErrHistoryEntry m_HistoryEntry; // from Nmtk/u module + + } m_Arg; + +} tEplEventError; + + +// structure for kEplEventTypeDllError +typedef struct +{ + unsigned long m_ulDllErrorEvents; // EPL_DLL_ERR_* + unsigned int m_uiNodeId; + tEplNmtState m_NmtState; + +} tEplErrorHandlerkEvent; + + +// callback function to get informed about sync event +typedef tEplKernel (PUBLIC* tEplSyncCb) (void); + +// callback function for generic events +typedef tEplKernel (PUBLIC* tEplProcessEventCb) (tEplEvent* pEplEvent_p); + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + + +#endif // #ifndef _EPL_EVENT_H_ + + diff --git a/drivers/staging/epl/EplEventk.c b/drivers/staging/epl/EplEventk.c new file mode 100644 index 0000000..ea612c7 --- /dev/null +++ b/drivers/staging/epl/EplEventk.c @@ -0,0 +1,858 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for Epl-Kernelspace-Event-Modul + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplEventk.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.9 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/20 k.t.: start of the implementation + +****************************************************************************/ + +#include "kernel/EplEventk.h" +#include "kernel/EplNmtk.h" +#include "kernel/EplDllk.h" +#include "kernel/EplDllkCal.h" +#include "kernel/EplErrorHandlerk.h" +#include "Benchmark.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) +#include "kernel/EplPdok.h" +#include "kernel/EplPdokCal.h" +#endif + +#ifdef EPL_NO_FIFO + #include "user/EplEventu.h" +#else + #include "SharedBuff.h" +#endif + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// TracePoint support for realtime-debugging +#ifdef _DBG_TRACE_POINTS_ + void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); + void PUBLIC TgtDbgPostTraceValue (DWORD dwTraceValue_p); + #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) + #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) +#else + #define TGT_DBG_SIGNAL_TRACE_POINT(p) + #define TGT_DBG_POST_TRACE_VALUE(v) +#endif + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ +#ifndef EPL_NO_FIFO + tShbInstance m_pShbKernelToUserInstance; + tShbInstance m_pShbUserToKernelInstance; +#else + +#endif + tEplSyncCb m_pfnCbSync; + unsigned int m_uiUserToKernelFullCount; + +} tEplEventkInstance; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- +static tEplEventkInstance EplEventkInstance_g; +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +// callback function for incoming events +#ifndef EPL_NO_FIFO +static void EplEventkRxSignalHandlerCb ( + tShbInstance pShbRxInstance_p, + unsigned long ulDataSize_p); +#endif + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <Epl-Kernelspace-Event> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplEventkInit +// +// Description: function initializes the first instance +// +// Parameters: pfnCbSync_p = callback-function for sync event +// +// Returns: tEpKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplEventkInit(tEplSyncCb pfnCbSync_p) +{ +tEplKernel Ret; + + Ret = EplEventkAddInstance(pfnCbSync_p); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplEventkAddInstance +// +// Description: function adds one more instance +// +// Parameters: pfnCbSync_p = callback-function for sync event +// +// Returns: tEpKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplEventkAddInstance(tEplSyncCb pfnCbSync_p) +{ +tEplKernel Ret; +#ifndef EPL_NO_FIFO +tShbError ShbError; +unsigned int fShbNewCreated; +#endif + + Ret = kEplSuccessful; + + // init instance structure + EplEventkInstance_g.m_uiUserToKernelFullCount = 0; + + // save cb-function + EplEventkInstance_g.m_pfnCbSync = pfnCbSync_p; + +#ifndef EPL_NO_FIFO + // init shared loop buffer + // kernel -> user + ShbError = ShbCirAllocBuffer (EPL_EVENT_SIZE_SHB_KERNEL_TO_USER, + EPL_EVENT_NAME_SHB_KERNEL_TO_USER, + &EplEventkInstance_g.m_pShbKernelToUserInstance, + &fShbNewCreated); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkAddInstance(): ShbCirAllocBuffer(K2U) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + goto Exit; + } + + // user -> kernel + ShbError = ShbCirAllocBuffer (EPL_EVENT_SIZE_SHB_USER_TO_KERNEL, + EPL_EVENT_NAME_SHB_USER_TO_KERNEL, + &EplEventkInstance_g.m_pShbUserToKernelInstance, + &fShbNewCreated); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkAddInstance(): ShbCirAllocBuffer(U2K) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + goto Exit; + } + + // register eventhandler + ShbError = ShbCirSetSignalHandlerNewData (EplEventkInstance_g.m_pShbUserToKernelInstance, + EplEventkRxSignalHandlerCb, + kshbPriorityHigh); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkAddInstance(): ShbCirSetSignalHandlerNewData(U2K) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + goto Exit; + } + +Exit: +#endif + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplEventkDelInstance +// +// Description: function deletes instance and frees the buffers +// +// Parameters: void +// +// Returns: tEpKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplEventkDelInstance() +{ +tEplKernel Ret; +#ifndef EPL_NO_FIFO +tShbError ShbError; +#endif + + Ret = kEplSuccessful; + +#ifndef EPL_NO_FIFO + // set eventhandler to NULL + ShbError = ShbCirSetSignalHandlerNewData (EplEventkInstance_g.m_pShbUserToKernelInstance, + NULL, + kShbPriorityNormal); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkDelInstance(): ShbCirSetSignalHandlerNewData(U2K) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + } + + // free buffer User -> Kernel + ShbError = ShbCirReleaseBuffer (EplEventkInstance_g.m_pShbUserToKernelInstance); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkDelInstance(): ShbCirReleaseBuffer(U2K) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + } + else + { + EplEventkInstance_g.m_pShbUserToKernelInstance = NULL; + } + + // free buffer Kernel -> User + ShbError = ShbCirReleaseBuffer (EplEventkInstance_g.m_pShbKernelToUserInstance); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkDelInstance(): ShbCirReleaseBuffer(K2U) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + } + else + { + EplEventkInstance_g.m_pShbKernelToUserInstance = NULL; + } +#endif + +return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplEventkProcess +// +// Description: Kernelthread that dispatches events in kernel part +// +// Parameters: pEvent_p = pointer to event-structure from buffer +// +// Returns: tEpKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplEventkProcess(tEplEvent* pEvent_p) +{ +tEplKernel Ret; +tEplEventSource EventSource; + + Ret = kEplSuccessful; + + // error handling if event queue is full + if (EplEventkInstance_g.m_uiUserToKernelFullCount > 0) + { // UserToKernel event queue has run out of space -> kEplNmtEventInternComError +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) + tEplEvent Event; + tEplNmtEvent NmtEvent; +#endif +#ifndef EPL_NO_FIFO + tShbError ShbError; +#endif + + // directly call NMTk process function, because event queue is full +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) + NmtEvent = kEplNmtEventInternComError; + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_NetTime.m_dwNanoSec = 0; + Event.m_NetTime.m_dwSec = 0; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_pArg = &NmtEvent; + Event.m_uiSize = sizeof(NmtEvent); + Ret = EplNmtkProcess(&Event); +#endif + + // NMT state machine changed to reset (i.e. NMT_GS_RESET_COMMUNICATION) + // now, it is safe to reset the counter and empty the event queue +#ifndef EPL_NO_FIFO + ShbError = ShbCirResetBuffer (EplEventkInstance_g.m_pShbUserToKernelInstance, 1000, NULL); +#endif + + EplEventkInstance_g.m_uiUserToKernelFullCount = 0; + TGT_DBG_SIGNAL_TRACE_POINT(22); + + // also discard the current event (it doesn't matter if we lose another event) + goto Exit; + } + + // check m_EventSink + switch(pEvent_p->m_EventSink) + { + case kEplEventSinkSync: + { + if (EplEventkInstance_g.m_pfnCbSync != NULL) + { + Ret = EplEventkInstance_g.m_pfnCbSync(); + if (Ret == kEplSuccessful) + { +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + // mark TPDOs as valid + Ret = EplPdokCalSetTpdosValid(TRUE); +#endif + } + else if ((Ret != kEplReject) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceSyncCb; + + // Error event for API layer + EplEventkPostError(kEplEventSourceEventk, + Ret, + sizeof(EventSource), + &EventSource); + } + } + break; + } + + // NMT-Kernel-Modul + case kEplEventSinkNmtk: + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) + Ret = EplNmtkProcess(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceNmtk; + + // Error event for API layer + EplEventkPostError(kEplEventSourceEventk, + Ret, + sizeof(EventSource), + &EventSource); + } +#endif +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + if ((pEvent_p->m_EventType == kEplEventTypeNmtEvent) + && ((*((tEplNmtEvent*)pEvent_p->m_pArg) == kEplNmtEventDllCeSoa) +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + || (*((tEplNmtEvent*)pEvent_p->m_pArg) == kEplNmtEventDllMeSoaSent) +#endif + )) + { // forward SoA event to error handler + Ret = EplErrorHandlerkProcess(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceErrk; + + // Error event for API layer + EplEventkPostError(kEplEventSourceEventk, + Ret, + sizeof(EventSource), + &EventSource); + } + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + // forward SoA event to PDO module + pEvent_p->m_EventType = kEplEventTypePdoSoa; + Ret = EplPdokProcess(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourcePdok; + + // Error event for API layer + EplEventkPostError(kEplEventSourceEventk, + Ret, + sizeof(EventSource), + &EventSource); + } +#endif + + } + break; +#endif + } + + // events for Dllk module + case kEplEventSinkDllk: + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + Ret = EplDllkProcess(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceDllk; + + // Error event for API layer + EplEventkPostError(kEplEventSourceEventk, + Ret, + sizeof(EventSource), + &EventSource); + } +#endif + break; + } + + // events for DllkCal module + case kEplEventSinkDllkCal: + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + Ret = EplDllkCalProcess(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceDllk; + + // Error event for API layer + EplEventkPostError(kEplEventSourceEventk, + Ret, + sizeof(EventSource), + &EventSource); + } +#endif + break; + } + + // + case kEplEventSinkPdok: + { + // PDO-Module +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + Ret = EplPdokProcess(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourcePdok; + + // Error event for API layer + EplEventkPostError(kEplEventSourceEventk, + Ret, + sizeof(EventSource), + &EventSource); + } +#endif + break; + } + + // events for Error handler module + case kEplEventSinkErrk: + { + // only call error handler if DLL is present +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + Ret = EplErrorHandlerkProcess(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceErrk; + + // Error event for API layer + EplEventkPostError(kEplEventSourceEventk, + Ret, + sizeof(EventSource), + &EventSource); + } + break; +#endif + } + + // unknown sink + default: + { + Ret = kEplEventUnknownSink; + } + + } // end of switch(pEvent_p->m_EventSink) + +Exit: + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplEventkPost +// +// Description: post events from kernel part +// +// Parameters: pEvent_p = pointer to event-structure from buffer +// +// Returns: tEpKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplEventkPost(tEplEvent * pEvent_p) +{ +tEplKernel Ret; +#ifndef EPL_NO_FIFO +tShbError ShbError; +tShbCirChunk ShbCirChunk; +unsigned long ulDataSize; +unsigned int fBufferCompleted; +#endif + + Ret = kEplSuccessful; + + + // the event must be posted by using the abBuffer + // it is neede because the Argument must by copied + // to the buffer too and not only the pointer + +#ifndef EPL_NO_FIFO + // 2006/08/03 d.k.: Event and argument are posted as separate chunks to the event queue. + ulDataSize = sizeof(tEplEvent) + ((pEvent_p->m_pArg != NULL) ? pEvent_p->m_uiSize : 0); +#endif + + // decide in which buffer the event have to write + switch(pEvent_p->m_EventSink) + { + // kernelspace modules + case kEplEventSinkSync: + case kEplEventSinkNmtk: + case kEplEventSinkDllk: + case kEplEventSinkDllkCal: + case kEplEventSinkPdok: + case kEplEventSinkErrk: + { +#ifndef EPL_NO_FIFO + // post message + BENCHMARK_MOD_27_SET(2); + ShbError = ShbCirAllocDataBlock (EplEventkInstance_g.m_pShbUserToKernelInstance, + &ShbCirChunk, + ulDataSize); + switch (ShbError) + { + case kShbOk: + break; + + case kShbBufferFull: + { + EplEventkInstance_g.m_uiUserToKernelFullCount++; + Ret = kEplEventPostError; + goto Exit; + } + + default: + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkPost(): ShbCirAllocDataBlock(U2K) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + } + ShbError = ShbCirWriteDataChunk (EplEventkInstance_g.m_pShbUserToKernelInstance, + &ShbCirChunk, + pEvent_p, + sizeof (tEplEvent), + &fBufferCompleted); + if (ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkPost(): ShbCirWriteDataChunk(U2K) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + if (fBufferCompleted == FALSE) + { + ShbError = ShbCirWriteDataChunk (EplEventkInstance_g.m_pShbUserToKernelInstance, + &ShbCirChunk, + pEvent_p->m_pArg, + (unsigned long) pEvent_p->m_uiSize, + &fBufferCompleted); + if ((ShbError != kShbOk) || (fBufferCompleted == FALSE)) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkPost(): ShbCirWriteDataChunk2(U2K) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + } + BENCHMARK_MOD_27_RESET(2); + +#else + Ret = EplEventkProcess(pEvent_p); +#endif + + break; + } + + // userspace modules + case kEplEventSinkNmtu: + case kEplEventSinkNmtMnu: + case kEplEventSinkSdoAsySeq: + case kEplEventSinkApi: + case kEplEventSinkDlluCal: + case kEplEventSinkErru: + { +#ifndef EPL_NO_FIFO + // post message +// BENCHMARK_MOD_27_SET(3); // 74 µs until reset + ShbError = ShbCirAllocDataBlock (EplEventkInstance_g.m_pShbKernelToUserInstance, + &ShbCirChunk, + ulDataSize); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkPost(): ShbCirAllocDataBlock(K2U) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + ShbError = ShbCirWriteDataChunk (EplEventkInstance_g.m_pShbKernelToUserInstance, + &ShbCirChunk, + pEvent_p, + sizeof (tEplEvent), + &fBufferCompleted); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkPost(): ShbCirWriteDataChunk(K2U) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + if (fBufferCompleted == FALSE) + { + ShbError = ShbCirWriteDataChunk (EplEventkInstance_g.m_pShbKernelToUserInstance, + &ShbCirChunk, + pEvent_p->m_pArg, + (unsigned long) pEvent_p->m_uiSize, + &fBufferCompleted); + if ((ShbError != kShbOk) || (fBufferCompleted == FALSE)) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventkPost(): ShbCirWriteDataChunk2(K2U) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + } +// BENCHMARK_MOD_27_RESET(3); // 82 µs until ShbCirGetReadDataSize() in EplEventu + +#else + Ret = EplEventuProcess(pEvent_p); +#endif + + break; + } + + default: + { + Ret = kEplEventUnknownSink; + } + + + }// end of switch(pEvent_p->m_EventSink) + +#ifndef EPL_NO_FIFO +Exit: +#endif + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplEventkPostError +// +// Description: post error event from kernel part to API layer +// +// Parameters: EventSource_p = source-module of the error event +// EplError_p = code of occured error +// ArgSize_p = size of the argument +// pArg_p = pointer to the argument +// +// Returns: tEpKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplEventkPostError(tEplEventSource EventSource_p, + tEplKernel EplError_p, + unsigned int uiArgSize_p, + void* pArg_p) +{ +tEplKernel Ret; +BYTE abBuffer[EPL_MAX_EVENT_ARG_SIZE]; +tEplEventError* pEventError = (tEplEventError*) abBuffer; +tEplEvent EplEvent; + + Ret = kEplSuccessful; + + // create argument + pEventError->m_EventSource = EventSource_p; + pEventError->m_EplError = EplError_p; + EPL_MEMCPY(&pEventError->m_Arg, pArg_p, uiArgSize_p); + + // create event + EplEvent.m_EventType = kEplEventTypeError; + EplEvent.m_EventSink = kEplEventSinkApi; + EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(EplEvent.m_NetTime)); + EplEvent.m_uiSize = (sizeof(EventSource_p)+ sizeof(EplError_p)+ uiArgSize_p); + EplEvent.m_pArg = &abBuffer[0]; + + // post errorevent + Ret = EplEventkPost(&EplEvent); + + return Ret; +} + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplEventkRxSignalHandlerCb() +// +// Description: Callback-function for events from user and kernel part +// +// Parameters: pShbRxInstance_p = Instance-pointer of buffer +// ulDataSize_p = size of data +// +// Returns: void +// +// State: +// +//--------------------------------------------------------------------------- + +#ifndef EPL_NO_FIFO +static void EplEventkRxSignalHandlerCb ( + tShbInstance pShbRxInstance_p, + unsigned long ulDataSize_p) +{ +tEplEvent *pEplEvent; +tShbError ShbError; +//unsigned long ulBlockCount; +//unsigned long ulDataSize; +BYTE abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE]; + // d.k.: abDataBuffer contains the complete tEplEvent structure + // and behind this the argument + + TGT_DBG_SIGNAL_TRACE_POINT(20); + + BENCHMARK_MOD_27_RESET(0); + // copy data from event queue + ShbError = ShbCirReadDataBlock (pShbRxInstance_p, + &abDataBuffer[0], + sizeof(abDataBuffer), + &ulDataSize_p); + if(ShbError != kShbOk) + { + // error goto exit + goto Exit; + } + + // resolve the pointer to the event structure + pEplEvent = (tEplEvent *) abDataBuffer; + // set Datasize + pEplEvent->m_uiSize = (ulDataSize_p - sizeof(tEplEvent)); + if(pEplEvent->m_uiSize > 0) + { + // set pointer to argument + pEplEvent->m_pArg = &abDataBuffer[sizeof(tEplEvent)]; + } + else + { + //set pointer to NULL + pEplEvent->m_pArg = NULL; + } + + BENCHMARK_MOD_27_SET(0); + // call processfunction + EplEventkProcess(pEplEvent); + +Exit: + return; +} +#endif + +// EOF + diff --git a/drivers/staging/epl/EplEventu.c b/drivers/staging/epl/EplEventu.c new file mode 100644 index 0000000..cb0215a --- /dev/null +++ b/drivers/staging/epl/EplEventu.c @@ -0,0 +1,813 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for Epl-Userspace-Event-Modul + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplEventu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/11/17 16:40:39 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/20 k.t.: start of the implementation + +****************************************************************************/ + +#include "user/EplEventu.h" +#include "user/EplNmtu.h" +#include "user/EplNmtMnu.h" +#include "user/EplSdoAsySequ.h" +#include "user/EplDlluCal.h" +#include "user/EplLedu.h" +#include "Benchmark.h" + +#ifdef EPL_NO_FIFO + #include "kernel/EplEventk.h" +#else + #include "SharedBuff.h" +#endif + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// TracePoint support for realtime-debugging +#ifdef _DBG_TRACE_POINTS_ + void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); + void PUBLIC TgtDbgPostTraceValue (DWORD dwTraceValue_p); + #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) + #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) +#else + #define TGT_DBG_SIGNAL_TRACE_POINT(p) + #define TGT_DBG_POST_TRACE_VALUE(v) +#endif + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ +#ifndef EPL_NO_FIFO + tShbInstance m_pShbKernelToUserInstance; + tShbInstance m_pShbUserToKernelInstance; +#endif + tEplProcessEventCb m_pfnApiProcessEventCb; + +}tEplEventuInstance; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//#ifndef EPL_NO_FIFO +static tEplEventuInstance EplEventuInstance_g; +//#endif + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +#ifndef EPL_NO_FIFO +// callback function for incomming events +static void EplEventuRxSignalHandlerCb ( + tShbInstance pShbRxInstance_p, + unsigned long ulDataSize_p); +#endif + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <Epl-User-Event> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplEventuInit +// +// Description: function initialize the first instance +// +// +// +// Parameters: pfnApiProcessEventCb_p = function pointer for API event callback +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplEventuInit(tEplProcessEventCb pfnApiProcessEventCb_p) +{ +tEplKernel Ret; + + + Ret = EplEventuAddInstance(pfnApiProcessEventCb_p); + + +return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplEventuAddInstance +// +// Description: function add one more instance +// +// +// +// Parameters: pfnApiProcessEventCb_p = function pointer for API event callback +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplEventuAddInstance(tEplProcessEventCb pfnApiProcessEventCb_p) +{ +tEplKernel Ret; +#ifndef EPL_NO_FIFO +tShbError ShbError; +unsigned int fShbNewCreated; +#endif + + Ret = kEplSuccessful; + + + // init instance variables + EplEventuInstance_g.m_pfnApiProcessEventCb = pfnApiProcessEventCb_p; + +#ifndef EPL_NO_FIFO + // init shared loop buffer + // kernel -> user + ShbError = ShbCirAllocBuffer (EPL_EVENT_SIZE_SHB_KERNEL_TO_USER, + EPL_EVENT_NAME_SHB_KERNEL_TO_USER, + &EplEventuInstance_g.m_pShbKernelToUserInstance, + &fShbNewCreated); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuAddInstance(): ShbCirAllocBuffer(K2U) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + goto Exit; + } + + + // user -> kernel + ShbError = ShbCirAllocBuffer (EPL_EVENT_SIZE_SHB_USER_TO_KERNEL, + EPL_EVENT_NAME_SHB_USER_TO_KERNEL, + &EplEventuInstance_g.m_pShbUserToKernelInstance, + &fShbNewCreated); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuAddInstance(): ShbCirAllocBuffer(U2K) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + goto Exit; + } + + // register eventhandler + ShbError = ShbCirSetSignalHandlerNewData (EplEventuInstance_g.m_pShbKernelToUserInstance, + EplEventuRxSignalHandlerCb, + kShbPriorityNormal); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuAddInstance(): ShbCirSetSignalHandlerNewData(K2U) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + goto Exit; + } + +Exit: +#endif + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplEventuDelInstance +// +// Description: function delete instance an free the bufferstructure +// +// +// +// Parameters: +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplEventuDelInstance() +{ +tEplKernel Ret; +#ifndef EPL_NO_FIFO +tShbError ShbError; +#endif + + Ret = kEplSuccessful; + +#ifndef EPL_NO_FIFO + // set eventhandler to NULL + ShbError = ShbCirSetSignalHandlerNewData (EplEventuInstance_g.m_pShbKernelToUserInstance, + NULL, + kShbPriorityNormal); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuDelInstance(): ShbCirSetSignalHandlerNewData(K2U) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + } + + // free buffer User -> Kernel + ShbError = ShbCirReleaseBuffer (EplEventuInstance_g.m_pShbUserToKernelInstance); + if((ShbError != kShbOk) && (ShbError != kShbMemUsedByOtherProcs)) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuDelInstance(): ShbCirReleaseBuffer(U2K) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + } + else + { + EplEventuInstance_g.m_pShbUserToKernelInstance = NULL; + } + + // free buffer Kernel -> User + ShbError = ShbCirReleaseBuffer (EplEventuInstance_g.m_pShbKernelToUserInstance); + if((ShbError != kShbOk) && (ShbError != kShbMemUsedByOtherProcs)) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuDelInstance(): ShbCirReleaseBuffer(K2U) -> 0x%X\n", ShbError); + Ret = kEplNoResource; + } + else + { + EplEventuInstance_g.m_pShbKernelToUserInstance = NULL; + } + +#endif + +return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplEventuProcess +// +// Description: Kernelthread that dispatches events in kernelspace +// +// +// +// Parameters: pEvent_p = pointer to event-structur from buffer +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplEventuProcess(tEplEvent* pEvent_p) +{ +tEplKernel Ret; +tEplEventSource EventSource; + + Ret = kEplSuccessful; + + // check m_EventSink + switch(pEvent_p->m_EventSink) + { + // NMT-User-Module + case kEplEventSinkNmtu: + { +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + Ret = EplNmtuProcessEvent(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceNmtu; + + // Error event for API layer + EplEventuPostError(kEplEventSourceEventu, + Ret, + sizeof(EventSource), + &EventSource); + } +#endif + break; + } + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // NMT-MN-User-Module + case kEplEventSinkNmtMnu: + { + Ret = EplNmtMnuProcessEvent(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceNmtMnu; + + // Error event for API layer + EplEventuPostError(kEplEventSourceEventu, + Ret, + sizeof(EventSource), + &EventSource); + } + break; + } +#endif + +#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) \ + || (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)) + // events for asynchronus SDO Sequence Layer + case kEplEventSinkSdoAsySeq: + { + Ret = EplSdoAsySeqProcessEvent(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceSdoAsySeq; + + // Error event for API layer + EplEventuPostError(kEplEventSourceEventu, + Ret, + sizeof(EventSource), + &EventSource); + } + break; + } +#endif + + // LED user part module + case kEplEventSinkLedu: + { +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) + Ret = EplLeduProcessEvent(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceLedu; + + // Error event for API layer + EplEventuPostError(kEplEventSourceEventu, + Ret, + sizeof(EventSource), + &EventSource); + } +#endif + break; + } + + // event for EPL api + case kEplEventSinkApi: + { + if (EplEventuInstance_g.m_pfnApiProcessEventCb != NULL) + { + Ret = EplEventuInstance_g.m_pfnApiProcessEventCb(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceEplApi; + + // Error event for API layer + EplEventuPostError(kEplEventSourceEventu, + Ret, + sizeof(EventSource), + &EventSource); + } + } + break; + + } + + case kEplEventSinkDlluCal: + { + Ret = EplDlluCalProcess(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceDllu; + + // Error event for API layer + EplEventuPostError(kEplEventSourceEventu, + Ret, + sizeof(EventSource), + &EventSource); + } + break; + + } + + case kEplEventSinkErru: + { + /* + Ret = EplErruProcess(pEvent_p); + if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) + { + EventSource = kEplEventSourceErru; + + // Error event for API layer + EplEventuPostError(kEplEventSourceEventu, + Ret, + sizeof(EventSource), + &EventSource); + } + */ + break; + + } + + // unknown sink + default: + { + Ret = kEplEventUnknownSink; + } + + } // end of switch(pEvent_p->m_EventSink) + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplEventuPost +// +// Description: post events from userspace +// +// +// +// Parameters: pEvent_p = pointer to event-structur from buffer +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplEventuPost(tEplEvent * pEvent_p) +{ +tEplKernel Ret; +#ifndef EPL_NO_FIFO +tShbError ShbError; +tShbCirChunk ShbCirChunk; +unsigned long ulDataSize; +unsigned int fBufferCompleted; +#endif + + Ret = kEplSuccessful; + + +#ifndef EPL_NO_FIFO + // 2006/08/03 d.k.: Event and argument are posted as separate chunks to the event queue. + ulDataSize = sizeof(tEplEvent) + ((pEvent_p->m_pArg != NULL) ? pEvent_p->m_uiSize : 0); +#endif + + // decide in which buffer the event have to write + switch(pEvent_p->m_EventSink) + { + // kernelspace modules + case kEplEventSinkSync: + case kEplEventSinkNmtk: + case kEplEventSinkDllk: + case kEplEventSinkDllkCal: + case kEplEventSinkPdok: + case kEplEventSinkErrk: + { +#ifndef EPL_NO_FIFO + // post message + ShbError = ShbCirAllocDataBlock (EplEventuInstance_g.m_pShbUserToKernelInstance, + &ShbCirChunk, + ulDataSize); + if (ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuPost(): ShbCirAllocDataBlock(U2K) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + ShbError = ShbCirWriteDataChunk (EplEventuInstance_g.m_pShbUserToKernelInstance, + &ShbCirChunk, + pEvent_p, + sizeof (tEplEvent), + &fBufferCompleted); + if (ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuPost(): ShbCirWriteDataChunk(U2K) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + if (fBufferCompleted == FALSE) + { + ShbError = ShbCirWriteDataChunk (EplEventuInstance_g.m_pShbUserToKernelInstance, + &ShbCirChunk, + pEvent_p->m_pArg, + (unsigned long) pEvent_p->m_uiSize, + &fBufferCompleted); + if ((ShbError != kShbOk) || (fBufferCompleted == FALSE)) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuPost(): ShbCirWriteDataChunk2(U2K) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + } +#else + Ret = EplEventkProcess(pEvent_p); +#endif + + break; + } + + // userspace modules + case kEplEventSinkNmtMnu: + case kEplEventSinkNmtu: + case kEplEventSinkSdoAsySeq: + case kEplEventSinkApi: + case kEplEventSinkDlluCal: + case kEplEventSinkErru: + case kEplEventSinkLedu: + { +#ifndef EPL_NO_FIFO + // post message + ShbError = ShbCirAllocDataBlock (EplEventuInstance_g.m_pShbKernelToUserInstance, + &ShbCirChunk, + ulDataSize); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuPost(): ShbCirAllocDataBlock(K2U) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + ShbError = ShbCirWriteDataChunk (EplEventuInstance_g.m_pShbKernelToUserInstance, + &ShbCirChunk, + pEvent_p, + sizeof (tEplEvent), + &fBufferCompleted); + if(ShbError != kShbOk) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuPost(): ShbCirWriteDataChunk(K2U) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + if (fBufferCompleted == FALSE) + { + ShbError = ShbCirWriteDataChunk (EplEventuInstance_g.m_pShbKernelToUserInstance, + &ShbCirChunk, + pEvent_p->m_pArg, + (unsigned long) pEvent_p->m_uiSize, + &fBufferCompleted); + if ((ShbError != kShbOk) || (fBufferCompleted == FALSE)) + { + EPL_DBGLVL_EVENTK_TRACE1("EplEventuPost(): ShbCirWriteDataChunk2(K2U) -> 0x%X\n", ShbError); + Ret = kEplEventPostError; + goto Exit; + } + } + +#else + Ret = EplEventuProcess(pEvent_p); +#endif + + break; + } + + default: + { + Ret = kEplEventUnknownSink; + } + + + }// end of switch(pEvent_p->m_EventSink) + +#ifndef EPL_NO_FIFO +Exit: +#endif + return Ret; + +} +//--------------------------------------------------------------------------- +// +// Function: EplEventuPostError +// +// Description: post errorevent from userspace +// +// +// +// Parameters: EventSource_p = source-module of the errorevent +// EplError_p = code of occured error +// uiArgSize_p = size of the argument +// pArg_p = pointer to the argument +// +// +// Returns: tEpKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplEventuPostError(tEplEventSource EventSource_p, + tEplKernel EplError_p, + unsigned int uiArgSize_p, + void* pArg_p) +{ +tEplKernel Ret; +BYTE abBuffer[EPL_MAX_EVENT_ARG_SIZE]; +tEplEventError* pEventError = (tEplEventError*) abBuffer; +tEplEvent EplEvent; + + Ret = kEplSuccessful; + + // create argument + pEventError->m_EventSource = EventSource_p; + pEventError->m_EplError = EplError_p; + EPL_MEMCPY(&pEventError->m_Arg, pArg_p, uiArgSize_p); + + // create event + EplEvent.m_EventType = kEplEventTypeError; + EplEvent.m_EventSink = kEplEventSinkApi; + EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(EplEvent.m_NetTime)); + EplEvent.m_uiSize = (sizeof(EventSource_p)+ sizeof(EplError_p)+ uiArgSize_p); + EplEvent.m_pArg = &abBuffer[0]; + + // post errorevent + Ret = EplEventuPost(&EplEvent); + + return Ret; +} + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplEventuRxSignalHandlerCb() +// +// Description: Callback-function for evets from kernelspace +// +// +// +// Parameters: pShbRxInstance_p = Instance-pointer for buffer +// ulDataSize_p = size of data +// +// +// Returns: void +// +// +// State: +// +//--------------------------------------------------------------------------- +#ifndef EPL_NO_FIFO +static void EplEventuRxSignalHandlerCb ( + tShbInstance pShbRxInstance_p, + unsigned long ulDataSize_p) +{ +tEplEvent *pEplEvent; +tShbError ShbError; +//unsigned long ulBlockCount; +//unsigned long ulDataSize; +BYTE abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE]; + // d.k.: abDataBuffer contains the complete tEplEvent structure + // and behind this the argument + + TGT_DBG_SIGNAL_TRACE_POINT(21); + +// d.k. not needed because it is already done in SharedBuff +/* do + { + BENCHMARK_MOD_28_SET(1); // 4 µs until reset + // get messagesize + ShbError = ShbCirGetReadDataSize (pShbRxInstance_p, &ulDataSize); + if(ShbError != kShbOk) + { + // error goto exit + goto Exit; + } + + BENCHMARK_MOD_28_RESET(1); // 14 µs until set +*/ + // copy data from event queue + ShbError = ShbCirReadDataBlock (pShbRxInstance_p, + &abDataBuffer[0], + sizeof(abDataBuffer), + &ulDataSize_p); + if(ShbError != kShbOk) + { + // error goto exit + goto Exit; + } + + // resolve the pointer to the event structure + pEplEvent = (tEplEvent *) abDataBuffer; + // set Datasize + pEplEvent->m_uiSize = (ulDataSize_p - sizeof(tEplEvent)); + if(pEplEvent->m_uiSize > 0) + { + // set pointer to argument + pEplEvent->m_pArg = &abDataBuffer[sizeof(tEplEvent)]; + } + else + { + //set pointer to NULL + pEplEvent->m_pArg = NULL; + } + + BENCHMARK_MOD_28_SET(1); + // call processfunction + EplEventuProcess(pEplEvent); + + BENCHMARK_MOD_28_RESET(1); + // read number of left messages to process +// d.k. not needed because it is already done in SharedBuff +/* ShbError = ShbCirGetReadBlockCount (pShbRxInstance_p, &ulBlockCount); + if (ShbError != kShbOk) + { + // error goto exit + goto Exit; + } + } while (ulBlockCount > 0); +*/ +Exit: + return; +} +#endif + +// EOF + diff --git a/drivers/staging/epl/EplFrame.h b/drivers/staging/epl/EplFrame.h new file mode 100644 index 0000000..1e5cb3d --- /dev/null +++ b/drivers/staging/epl/EplFrame.h @@ -0,0 +1,374 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for EPL frames + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplFrame.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/06/23 14:56:33 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/05/22 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_FRAME_H_ +#define _EPL_FRAME_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +// defines for EplFrame.m_wFlag +#define EPL_FRAME_FLAG1_RD 0x01 // ready (PReq, PRes) +#define EPL_FRAME_FLAG1_ER 0x02 // exception reset (error signalling) (SoA) +#define EPL_FRAME_FLAG1_EA 0x04 // exception acknowledge (error signalling) (PReq, SoA) +#define EPL_FRAME_FLAG1_EC 0x08 // exception clear (error signalling) (StatusRes) +#define EPL_FRAME_FLAG1_EN 0x10 // exception new (error signalling) (PRes, StatusRes) +#define EPL_FRAME_FLAG1_MS 0x20 // multiplexed slot (PReq) +#define EPL_FRAME_FLAG1_PS 0x40 // prescaled slot (SoC) +#define EPL_FRAME_FLAG1_MC 0x80 // multiplexed cycle completed (SoC) +#define EPL_FRAME_FLAG2_RS 0x07 // number of pending requests to send (PRes, StatusRes, IdentRes) +#define EPL_FRAME_FLAG2_PR 0x38 // priority of requested asynch. frame (PRes, StatusRes, IdentRes) +#define EPL_FRAME_FLAG2_PR_SHIFT 3 // shift of priority of requested asynch. frame + +// error history/status entry types +#define EPL_ERR_ENTRYTYPE_STATUS 0x8000 +#define EPL_ERR_ENTRYTYPE_HISTORY 0x0000 +#define EPL_ERR_ENTRYTYPE_EMCY 0x4000 +#define EPL_ERR_ENTRYTYPE_MODE_ACTIVE 0x1000 +#define EPL_ERR_ENTRYTYPE_MODE_CLEARED 0x2000 +#define EPL_ERR_ENTRYTYPE_MODE_OCCURRED 0x3000 +#define EPL_ERR_ENTRYTYPE_MODE_MASK 0x3000 +#define EPL_ERR_ENTRYTYPE_PROF_VENDOR 0x0001 +#define EPL_ERR_ENTRYTYPE_PROF_EPL 0x0002 +#define EPL_ERR_ENTRYTYPE_PROF_MASK 0x0FFF + +// defines for EPL version / PDO version +#define EPL_VERSION_SUB 0x0F // sub version +#define EPL_VERSION_MAIN 0xF0 // main version + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +// $$$ d.k.: move this definition to global.h +// byte-align structures +#ifdef _MSC_VER +# pragma pack( push, packing ) +# pragma pack( 1 ) +# define PACK_STRUCT +#elif defined( __GNUC__ ) +# define PACK_STRUCT __attribute__((packed)) +#else +# error you must byte-align these structures with the appropriate compiler directives +#endif + + +typedef struct +{ + // Offset 17 + BYTE m_le_bRes1; // reserved + // Offset 18 + BYTE m_le_bFlag1; // Flags: MC, PS + // Offset 19 + BYTE m_le_bFlag2; // Flags: res + // Offset 20 + tEplNetTime m_le_NetTime; // supported if D_NMT_NetTimeIsRealTime_BOOL is set + // Offset 28 + QWORD m_le_RelativeTime; // in us (supported if D_NMT_RelativeTime_BOOL is set) + +} PACK_STRUCT tEplSocFrame; + +typedef struct +{ + // Offset 17 + BYTE m_le_bRes1; // reserved + // Offset 18 + BYTE m_le_bFlag1; // Flags: MS, EA, RD + // Offset 19 + BYTE m_le_bFlag2; // Flags: res + // Offset 20 + BYTE m_le_bPdoVersion; + // Offset 21 + BYTE m_le_bRes2; // reserved + // Offset 22 + WORD m_le_wSize; + // Offset 24 + BYTE m_le_abPayload[256 /*D_NMT_IsochrRxMaxPayload_U16*/]; + +} PACK_STRUCT tEplPreqFrame; + +typedef struct +{ + // Offset 17 + BYTE m_le_bNmtStatus; // NMT state + // Offset 18 + BYTE m_le_bFlag1; // Flags: MS, EN, RD + // Offset 19 + BYTE m_le_bFlag2; // Flags: PR, RS + // Offset 20 + BYTE m_le_bPdoVersion; + // Offset 21 + BYTE m_le_bRes2; // reserved + // Offset 22 + WORD m_le_wSize; + // Offset 24 + BYTE m_le_abPayload[256 /*D_NMT_IsochrRxMaxPayload_U16 + / D_NMT_IsochrTxMaxPayload_U16*/]; + +} PACK_STRUCT tEplPresFrame; + +typedef struct +{ + // Offset 17 + BYTE m_le_bNmtStatus; // NMT state + // Offset 18 + BYTE m_le_bFlag1; // Flags: EA, ER + // Offset 19 + BYTE m_le_bFlag2; // Flags: res + // Offset 20 + BYTE m_le_bReqServiceId; + // Offset 21 + BYTE m_le_bReqServiceTarget; + // Offset 22 + BYTE m_le_bEplVersion; + +} PACK_STRUCT tEplSoaFrame; + +typedef struct +{ + WORD m_wEntryType; + WORD m_wErrorCode; + tEplNetTime m_TimeStamp; + BYTE m_abAddInfo[8]; + +} PACK_STRUCT tEplErrHistoryEntry; + +typedef struct +{ + // Offset 18 + BYTE m_le_bFlag1; // Flags: EN, EC + BYTE m_le_bFlag2; // Flags: PR, RS + BYTE m_le_bNmtStatus; // NMT state + BYTE m_le_bRes1[3]; + QWORD m_le_qwStaticError; // static error bit field + tEplErrHistoryEntry m_le_aErrHistoryEntry[14]; + +} PACK_STRUCT tEplStatusResponse; + +typedef struct +{ + // Offset 18 + BYTE m_le_bFlag1; // Flags: res + BYTE m_le_bFlag2; // Flags: PR, RS + BYTE m_le_bNmtStatus; // NMT state + BYTE m_le_bIdentRespFlags; // Flags: FW + BYTE m_le_bEplProfileVersion; + BYTE m_le_bRes1; + DWORD m_le_dwFeatureFlags; // NMT_FeatureFlags_U32 + WORD m_le_wMtu; // NMT_CycleTiming_REC.AsyncMTU_U16: C_IP_MIN_MTU - C_IP_MAX_MTU + WORD m_le_wPollInSize; // NMT_CycleTiming_REC.PReqActPayload_U16 + WORD m_le_wPollOutSize; // NMT_CycleTiming_REC.PResActPayload_U16 + DWORD m_le_dwResponseTime; // NMT_CycleTiming_REC.PResMaxLatency_U32 + WORD m_le_wRes2; + DWORD m_le_dwDeviceType; // NMT_DeviceType_U32 + DWORD m_le_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32 + DWORD m_le_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32 + DWORD m_le_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32 + DWORD m_le_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32 + QWORD m_le_qwVendorSpecificExt1; + DWORD m_le_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 + DWORD m_le_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 + DWORD m_le_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device + DWORD m_le_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device + DWORD m_le_dwIpAddress; + DWORD m_le_dwSubnetMask; + DWORD m_le_dwDefaultGateway; + BYTE m_le_sHostname[32]; + BYTE m_le_abVendorSpecificExt2[48]; + +} PACK_STRUCT tEplIdentResponse; + +typedef struct +{ + // Offset 18 + BYTE m_le_bNmtCommandId; + BYTE m_le_bRes1; + BYTE m_le_abNmtCommandData[32]; + +} PACK_STRUCT tEplNmtCommandService; + +typedef struct +{ + BYTE m_le_bReserved; + BYTE m_le_bTransactionId; + BYTE m_le_bFlags; + BYTE m_le_bCommandId; + WORD m_le_wSegmentSize; + WORD m_le_wReserved; + BYTE m_le_abCommandData[8]; // just reserve a minimum number of bytes as a placeholder + +}PACK_STRUCT tEplAsySdoCom; + + +// asynchronous SDO Sequence Header +typedef struct +{ + BYTE m_le_bRecSeqNumCon; + BYTE m_le_bSendSeqNumCon; + BYTE m_le_abReserved[2]; + tEplAsySdoCom m_le_abSdoSeqPayload; + +} PACK_STRUCT tEplAsySdoSeq; + +typedef struct +{ + // Offset 18 + BYTE m_le_bNmtCommandId; + BYTE m_le_bTargetNodeId; + BYTE m_le_abNmtCommandData[32]; + +} PACK_STRUCT tEplNmtRequestService; + + +typedef union +{ + // Offset 18 + tEplStatusResponse m_StatusResponse; + tEplIdentResponse m_IdentResponse; + tEplNmtCommandService m_NmtCommandService; + tEplNmtRequestService m_NmtRequestService; + tEplAsySdoSeq m_SdoSequenceFrame; + BYTE m_le_abPayload[256 /*D_NMT_ASndTxMaxPayload_U16 + / D_NMT_ASndRxMaxPayload_U16*/]; + +} tEplAsndPayload; + +typedef struct +{ + // Offset 17 + BYTE m_le_bServiceId; + // Offset 18 + tEplAsndPayload m_Payload; + +} PACK_STRUCT tEplAsndFrame; + +typedef union +{ + // Offset 17 + tEplSocFrame m_Soc; + tEplPreqFrame m_Preq; + tEplPresFrame m_Pres; + tEplSoaFrame m_Soa; + tEplAsndFrame m_Asnd; + +} tEplFrameData; + +typedef struct +{ + // Offset 0 + BYTE m_be_abDstMac[6]; // MAC address of the addressed nodes + // Offset 6 + BYTE m_be_abSrcMac[6]; // MAC address of the transmitting node + // Offset 12 + WORD m_be_wEtherType; // Ethernet message type (big endian) + // Offset 14 + BYTE m_le_bMessageType; // EPL message type + // Offset 15 + BYTE m_le_bDstNodeId; // EPL node ID of the addressed nodes + // Offset 16 + BYTE m_le_bSrcNodeId; // EPL node ID of the transmitting node + // Offset 17 + tEplFrameData m_Data; + +} PACK_STRUCT tEplFrame; + +// un-byte-align structures +#ifdef _MSC_VER +# pragma pack( pop, packing ) +#endif + + +typedef enum +{ + kEplMsgTypeNonEpl = 0x00, + kEplMsgTypeSoc = 0x01, + kEplMsgTypePreq = 0x03, + kEplMsgTypePres = 0x04, + kEplMsgTypeSoa = 0x05, + kEplMsgTypeAsnd = 0x06, + +} tEplMsgType; + + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPL_FRAME_H_ + + diff --git a/drivers/staging/epl/EplIdentu.c b/drivers/staging/epl/EplIdentu.c new file mode 100644 index 0000000..5ab7eba --- /dev/null +++ b/drivers/staging/epl/EplIdentu.c @@ -0,0 +1,497 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for Identu-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplIdentu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/11/21 09:00:38 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/11/15 d.k.: start of the implementation + +****************************************************************************/ + +#include "user/EplIdentu.h" +#include "user/EplDlluCal.h" + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <xxxxx> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ + tEplIdentResponse* m_apIdentResponse[254]; // the IdentResponse are managed dynamically + tEplIdentuCbResponse m_apfnCbResponse[254]; + +} tEplIdentuInstance; + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +static tEplIdentuInstance EplIdentuInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplIdentuCbIdentResponse(tEplFrameInfo * pFrameInfo_p); + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplIdentuInit +// +// Description: init first instance of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplIdentuInit() +{ +tEplKernel Ret; + + Ret = EplIdentuAddInstance(); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplIdentuAddInstance +// +// Description: init other instances of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplIdentuAddInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // reset instance structure + EPL_MEMSET(&EplIdentuInstance_g, 0, sizeof (EplIdentuInstance_g)); + + // register IdentResponse callback function + Ret = EplDlluCalRegAsndService(kEplDllAsndIdentResponse, EplIdentuCbIdentResponse, kEplDllAsndFilterAny); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplIdentuDelInstance +// +// Description: delete instance +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplIdentuDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // deregister IdentResponse callback function + Ret = EplDlluCalRegAsndService(kEplDllAsndIdentResponse, NULL, kEplDllAsndFilterNone); + + Ret = EplIdentuReset(); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplIdentuReset +// +// Description: resets this instance +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplIdentuReset() +{ +tEplKernel Ret; +int iIndex; + + Ret = kEplSuccessful; + + for (iIndex = 0; iIndex < tabentries (EplIdentuInstance_g.m_apIdentResponse); iIndex++) + { + if (EplIdentuInstance_g.m_apIdentResponse[iIndex] != NULL) + { // free memory + EPL_FREE(EplIdentuInstance_g.m_apIdentResponse[iIndex]); + } + } + + EPL_MEMSET(&EplIdentuInstance_g, 0, sizeof (EplIdentuInstance_g)); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplIdentuGetIdentResponse +// +// Description: returns the IdentResponse for the specified node. +// +// Parameters: uiNodeId_p = IN: node ID +// ppIdentResponse_p = OUT: pointer to pointer of IdentResponse +// equals NULL, if no IdentResponse available +// +// Return: tEplKernel = error code +// +// State: not tested +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplIdentuGetIdentResponse( + unsigned int uiNodeId_p, + tEplIdentResponse** ppIdentResponse_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // decrement node ID, because array is zero based + uiNodeId_p--; + if (uiNodeId_p < tabentries (EplIdentuInstance_g.m_apIdentResponse)) + { + *ppIdentResponse_p = EplIdentuInstance_g.m_apIdentResponse[uiNodeId_p]; + } + else + { // invalid node ID specified + *ppIdentResponse_p = NULL; + Ret = kEplInvalidNodeId; + } + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplIdentuRequestIdentResponse +// +// Description: returns the IdentResponse for the specified node. +// +// Parameters: uiNodeId_p = IN: node ID +// pfnCbResponse_p = IN: function pointer to callback function +// which will be called if IdentResponse is received +// +// Return: tEplKernel = error code +// +// State: not tested +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplIdentuRequestIdentResponse( + unsigned int uiNodeId_p, + tEplIdentuCbResponse pfnCbResponse_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // decrement node ID, because array is zero based + uiNodeId_p--; + if (uiNodeId_p < tabentries (EplIdentuInstance_g.m_apfnCbResponse)) + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + if (EplIdentuInstance_g.m_apfnCbResponse[uiNodeId_p] != NULL) + { // request already issued (maybe by someone else) + Ret = kEplInvalidOperation; + } + else + { + EplIdentuInstance_g.m_apfnCbResponse[uiNodeId_p] = pfnCbResponse_p; + Ret = EplDlluCalIssueRequest(kEplDllReqServiceIdent, (uiNodeId_p + 1), 0xFF); + } +#else + Ret = kEplInvalidOperation; +#endif + } + else + { // invalid node ID specified + Ret = kEplInvalidNodeId; + } + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplIdentuGetRunningRequests +// +// Description: returns a bit field with the running requests for node-ID 1-32 +// just for debugging purposes +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT DWORD PUBLIC EplIdentuGetRunningRequests(void) +{ +DWORD dwReqs = 0; +unsigned int uiIndex; + + for (uiIndex = 0; uiIndex < 32; uiIndex++) + { + if (EplIdentuInstance_g.m_apfnCbResponse[uiIndex] != NULL) + { + dwReqs |= (1 << uiIndex); + } + } + + return dwReqs; +} + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplIdentuCbIdentResponse +// +// Description: callback funktion for IdentResponse +// +// +// +// Parameters: pFrameInfo_p = Frame with the IdentResponse +// +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplIdentuCbIdentResponse(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiNodeId; +unsigned int uiIndex; +tEplIdentuCbResponse pfnCbResponse; + + uiNodeId = AmiGetByteFromLe(&pFrameInfo_p->m_pFrame->m_le_bSrcNodeId); + + uiIndex = uiNodeId - 1; + + if (uiIndex < tabentries (EplIdentuInstance_g.m_apfnCbResponse)) + { + // memorize pointer to callback function + pfnCbResponse = EplIdentuInstance_g.m_apfnCbResponse[uiIndex]; + // reset callback function pointer so that caller may issue next request immediately + EplIdentuInstance_g.m_apfnCbResponse[uiIndex] = NULL; + + if (pFrameInfo_p->m_uiFrameSize < EPL_C_DLL_MINSIZE_IDENTRES) + { // IdentResponse not received or it has invalid size + if (pfnCbResponse == NULL) + { // response was not requested + goto Exit; + } + Ret = pfnCbResponse(uiNodeId, NULL); + } + else + { // IdentResponse received + if (EplIdentuInstance_g.m_apIdentResponse[uiIndex] == NULL) + { // memory for IdentResponse must be allocated + EplIdentuInstance_g.m_apIdentResponse[uiIndex] = EPL_MALLOC(sizeof (tEplIdentResponse)); + if (EplIdentuInstance_g.m_apIdentResponse[uiIndex] == NULL) + { // malloc failed + if (pfnCbResponse == NULL) + { // response was not requested + goto Exit; + } + Ret = pfnCbResponse(uiNodeId, &pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse); + goto Exit; + } + } + // copy IdentResponse to instance structure + EPL_MEMCPY(EplIdentuInstance_g.m_apIdentResponse[uiIndex], &pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_IdentResponse, sizeof(tEplIdentResponse)); + if (pfnCbResponse == NULL) + { // response was not requested + goto Exit; + } + Ret = pfnCbResponse(uiNodeId, EplIdentuInstance_g.m_apIdentResponse[uiIndex]); + } + } + +Exit: + return Ret; +} + +// EOF + diff --git a/drivers/staging/epl/EplInc.h b/drivers/staging/epl/EplInc.h new file mode 100644 index 0000000..cfe90e9 --- /dev/null +++ b/drivers/staging/epl/EplInc.h @@ -0,0 +1,398 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: basic include file for internal EPL stack modules + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplInc.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/11/17 16:40:39 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/05/22 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_INC_H_ +#define _EPL_INC_H_ + +// ============================================================================ +// include files +// ============================================================================ +#if defined(WIN32) || defined(_WIN32) + + #ifdef UNDER_RTSS + // RTX header + #include <windows.h> + #include <process.h> + #include <rtapi.h> + + #elif __BORLANDC__ + // borland C header + #include <windows.h> + #include <process.h> + + #elif WINCE + #include <windows.h> + + #else + // MSVC needs to include windows.h at first + // the following defines ar necessary for function prototypes for waitable timers + #define _WIN32_WINDOWS 0x0401 + #define _WIN32_WINNT 0x0400 + #include <windows.h> + #include <process.h> + #endif + +#endif + +// defines for module integration +// possible other include file needed +// These constants defines modules which can be included in the Epl application. +// Use this constants for define EPL_MODULE_INTEGRATION in file EplCfg.h. +#define EPL_MODULE_OBDK 0x00000001L // OBD kernel part module +#define EPL_MODULE_PDOK 0x00000002L // PDO kernel part module +#define EPL_MODULE_NMT_MN 0x00000004L // NMT MN module +#define EPL_MODULE_SDOS 0x00000008L // SDO Server module +#define EPL_MODULE_SDOC 0x00000010L // SDO Client module +#define EPL_MODULE_SDO_ASND 0x00000020L // SDO over Asnd module +#define EPL_MODULE_SDO_UDP 0x00000040L // SDO over UDP module +#define EPL_MODULE_SDO_PDO 0x00000080L // SDO in PDO module +#define EPL_MODULE_NMT_CN 0x00000100L // NMT CN module +#define EPL_MODULE_NMTU 0x00000200L // NMT user part module +#define EPL_MODULE_NMTK 0x00000400L // NMT kernel part module +#define EPL_MODULE_DLLK 0x00000800L // DLL kernel part module +#define EPL_MODULE_DLLU 0x00001000L // DLL user part module +#define EPL_MODULE_OBDU 0x00002000L // OBD user part module +#define EPL_MODULE_CFGMA 0x00004000L // Configuartioan Manager module +#define EPL_MODULE_VETH 0x00008000L // virtual ethernet driver module +#define EPL_MODULE_PDOU 0x00010000L // PDO user part module +#define EPL_MODULE_LEDU 0x00020000L // LED user part module + +#include "EplCfg.h" // EPL configuration file (configuration from application) + +#include "global.h" // global definitions + +#include "EplDef.h" // EPL configuration file (default configuration) +#include "EplInstDef.h" // defines macros for instance types and table +#include "Debug.h" // debug definitions + +#include "EplErrDef.h" // EPL error codes for API funtions + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +// IEEE 1588 conformant net time structure +typedef struct +{ + DWORD m_dwSec; + DWORD m_dwNanoSec; + +} tEplNetTime; + + +#include "EplTarget.h" // target specific functions and definitions + +#include "EplAmi.h" + +// ------------------------------------------------------------------------- +// macros +// ------------------------------------------------------------------------- + +#define EPL_SPEC_VERSION 0x20 // ETHERNET Powerlink V. 2.0 +#define EPL_STACK_VERSION(ver,rev,rel) ((((DWORD)(ver)) & 0xFF)|((((DWORD)(rev))&0xFF)<<8)|(((DWORD)(rel))<<16)) +#define EPL_OBJ1018_VERSION(ver,rev,rel) ((((DWORD)(ver))<<16) |(((DWORD)(rev))&0xFFFF)) +#define EPL_STRING_VERSION(ver,rev,rel) "V" #ver "." #rev " r" #rel + +#include "EplVersion.h" + +// defines for EPL FeatureFlags +#define EPL_FEATURE_ISOCHR 0x00000001 +#define EPL_FEATURE_SDO_UDP 0x00000002 +#define EPL_FEATURE_SDO_ASND 0x00000004 +#define EPL_FEATURE_SDO_PDO 0x00000008 +#define EPL_FEATURE_NMT_INFO 0x00000010 +#define EPL_FEATURE_NMT_EXT 0x00000020 +#define EPL_FEATURE_PDO_DYN 0x00000040 +#define EPL_FEATURE_NMT_UDP 0x00000080 +#define EPL_FEATURE_CFGMA 0x00000100 +#define EPL_FEATURE_DLL_MULTIPLEX 0x00000200 +#define EPL_FEATURE_NODEID_SW 0x00000400 +#define EPL_FEATURE_NMT_BASICETH 0x00000800 +#define EPL_FEATURE_RT1 0x00001000 +#define EPL_FEATURE_RT2 0x00002000 + + +// generate EPL NMT_FeatureFlags_U32 +#ifndef EPL_DEF_FEATURE_ISOCHR + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + #define EPL_DEF_FEATURE_ISOCHR (EPL_FEATURE_ISOCHR) + #else + #define EPL_DEF_FEATURE_ISOCHR 0 + #endif +#endif + +#ifndef EPL_DEF_FEATURE_SDO_ASND + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + #define EPL_DEF_FEATURE_SDO_ASND (EPL_FEATURE_SDO_ASND) + #else + #define EPL_DEF_FEATURE_SDO_ASND 0 + #endif +#endif + +#ifndef EPL_DEF_FEATURE_SDO_UDP + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + #define EPL_DEF_FEATURE_SDO_UDP (EPL_FEATURE_SDO_UDP) + #else + #define EPL_DEF_FEATURE_SDO_UDP 0 + #endif +#endif + +#ifndef EPL_DEF_FEATURE_SDO_PDO + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_PDO)) != 0) + #define EPL_DEF_FEATURE_SDO_PDO (EPL_FEATURE_SDO_PDO) + #else + #define EPL_DEF_FEATURE_SDO_PDO 0 + #endif +#endif + +#ifndef EPL_DEF_FEATURE_PDO_DYN + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + #define EPL_DEF_FEATURE_PDO_DYN (EPL_FEATURE_PDO_DYN) + #else + #define EPL_DEF_FEATURE_PDO_DYN 0 + #endif +#endif + +#ifndef EPL_DEF_FEATURE_CFGMA + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_CFGMA)) != 0) + #define EPL_DEF_FEATURE_CFGMA (EPL_FEATURE_CFGMA) + #else + #define EPL_DEF_FEATURE_CFGMA 0 + #endif +#endif + +#define EPL_DEF_FEATURE_FLAGS (EPL_DEF_FEATURE_ISOCHR \ + | EPL_DEF_FEATURE_SDO_ASND \ + | EPL_DEF_FEATURE_SDO_UDP \ + | EPL_DEF_FEATURE_SDO_PDO \ + | EPL_DEF_FEATURE_PDO_DYN \ + | EPL_DEF_FEATURE_CFGMA) + + +#ifndef tabentries +#define tabentries(a) (sizeof(a)/sizeof(*(a))) +#endif + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// definitions for DLL export +#if ((DEV_SYSTEM == _DEV_WIN32_) || (DEV_SYSTEM == _DEV_WIN_CE_)) && defined (COP_LIB) + + #define EPLDLLEXPORT __declspec (dllexport) + +#else + + #define EPLDLLEXPORT + +#endif + + +// ============================================================================ +// common debug macros +// ============================================================================ +// for using macro DEBUG_TRACEx() +// +// Example: +// DEBUG_TRACE1 (EPL_DBGLVL_OBD, "Value is %d\n" , wObjectIndex); +// +// This message only will be printed if: +// - NDEBUG is not defined AND !!! +// - flag 0x00000004L is set in DEF_DEBUG_LVL (can be defined in copcfg.h) +// +// default level is defined in copdef.h + +// debug-level and TRACE-macros // standard-level // flags for DEF_DEBUG_LVL +#define EPL_DBGLVL_EDRV DEBUG_LVL_01 // 0x00000001L +#define EPL_DBGLVL_EDRV_TRACE0 DEBUG_LVL_01_TRACE0 +#define EPL_DBGLVL_EDRV_TRACE1 DEBUG_LVL_01_TRACE1 +#define EPL_DBGLVL_EDRV_TRACE2 DEBUG_LVL_01_TRACE2 +#define EPL_DBGLVL_EDRV_TRACE3 DEBUG_LVL_01_TRACE3 +#define EPL_DBGLVL_EDRV_TRACE4 DEBUG_LVL_01_TRACE4 + +#define EPL_DBGLVL_DLL DEBUG_LVL_02 // 0x00000002L +#define EPL_DBGLVL_DLL_TRACE0 DEBUG_LVL_02_TRACE0 +#define EPL_DBGLVL_DLL_TRACE1 DEBUG_LVL_02_TRACE1 +#define EPL_DBGLVL_DLL_TRACE2 DEBUG_LVL_02_TRACE2 +#define EPL_DBGLVL_DLL_TRACE3 DEBUG_LVL_02_TRACE3 +#define EPL_DBGLVL_DLL_TRACE4 DEBUG_LVL_02_TRACE4 + +#define EPL_DBGLVL_OBD DEBUG_LVL_03 // 0x00000004L +#define EPL_DBGLVL_OBD_TRACE0 DEBUG_LVL_03_TRACE0 +#define EPL_DBGLVL_OBD_TRACE1 DEBUG_LVL_03_TRACE1 +#define EPL_DBGLVL_OBD_TRACE2 DEBUG_LVL_03_TRACE2 +#define EPL_DBGLVL_OBD_TRACE3 DEBUG_LVL_03_TRACE3 +#define EPL_DBGLVL_OBD_TRACE4 DEBUG_LVL_03_TRACE4 + +#define EPL_DBGLVL_NMTK DEBUG_LVL_04 // 0x00000008L +#define EPL_DBGLVL_NMTK_TRACE0 DEBUG_LVL_04_TRACE0 +#define EPL_DBGLVL_NMTK_TRACE1 DEBUG_LVL_04_TRACE1 +#define EPL_DBGLVL_NMTK_TRACE2 DEBUG_LVL_04_TRACE2 +#define EPL_DBGLVL_NMTK_TRACE3 DEBUG_LVL_04_TRACE3 +#define EPL_DBGLVL_NMTK_TRACE4 DEBUG_LVL_04_TRACE4 + +#define EPL_DBGLVL_NMTCN DEBUG_LVL_05 // 0x00000010L +#define EPL_DBGLVL_NMTCN_TRACE0 DEBUG_LVL_05_TRACE0 +#define EPL_DBGLVL_NMTCN_TRACE1 DEBUG_LVL_05_TRACE1 +#define EPL_DBGLVL_NMTCN_TRACE2 DEBUG_LVL_05_TRACE2 +#define EPL_DBGLVL_NMTCN_TRACE3 DEBUG_LVL_05_TRACE3 +#define EPL_DBGLVL_NMTCN_TRACE4 DEBUG_LVL_05_TRACE4 + +#define EPL_DBGLVL_NMTU DEBUG_LVL_06 // 0x00000020L +#define EPL_DBGLVL_NMTU_TRACE0 DEBUG_LVL_06_TRACE0 +#define EPL_DBGLVL_NMTU_TRACE1 DEBUG_LVL_06_TRACE1 +#define EPL_DBGLVL_NMTU_TRACE2 DEBUG_LVL_06_TRACE2 +#define EPL_DBGLVL_NMTU_TRACE3 DEBUG_LVL_06_TRACE3 +#define EPL_DBGLVL_NMTU_TRACE4 DEBUG_LVL_06_TRACE4 + +#define EPL_DBGLVL_NMTMN DEBUG_LVL_07 // 0x00000040L +#define EPL_DBGLVL_NMTMN_TRACE0 DEBUG_LVL_07_TRACE0 +#define EPL_DBGLVL_NMTMN_TRACE1 DEBUG_LVL_07_TRACE1 +#define EPL_DBGLVL_NMTMN_TRACE2 DEBUG_LVL_07_TRACE2 +#define EPL_DBGLVL_NMTMN_TRACE3 DEBUG_LVL_07_TRACE3 +#define EPL_DBGLVL_NMTMN_TRACE4 DEBUG_LVL_07_TRACE4 + +//... + +#define EPL_DBGLVL_SDO DEBUG_LVL_25 // 0x01000000 +#define EPL_DBGLVL_SDO_TRACE0 DEBUG_LVL_25_TRACE0 +#define EPL_DBGLVL_SDO_TRACE1 DEBUG_LVL_25_TRACE1 +#define EPL_DBGLVL_SDO_TRACE2 DEBUG_LVL_25_TRACE2 +#define EPL_DBGLVL_SDO_TRACE3 DEBUG_LVL_25_TRACE3 +#define EPL_DBGLVL_SDO_TRACE4 DEBUG_LVL_25_TRACE4 + +#define EPL_DBGLVL_VETH DEBUG_LVL_26 // 0x02000000 +#define EPL_DBGLVL_VETH_TRACE0 DEBUG_LVL_26_TRACE0 +#define EPL_DBGLVL_VETH_TRACE1 DEBUG_LVL_26_TRACE1 +#define EPL_DBGLVL_VETH_TRACE2 DEBUG_LVL_26_TRACE2 +#define EPL_DBGLVL_VETH_TRACE3 DEBUG_LVL_26_TRACE3 +#define EPL_DBGLVL_VETH_TRACE4 DEBUG_LVL_26_TRACE4 + +#define EPL_DBGLVL_EVENTK DEBUG_LVL_27 // 0x04000000 +#define EPL_DBGLVL_EVENTK_TRACE0 DEBUG_LVL_27_TRACE0 +#define EPL_DBGLVL_EVENTK_TRACE1 DEBUG_LVL_27_TRACE1 +#define EPL_DBGLVL_EVENTK_TRACE2 DEBUG_LVL_27_TRACE2 +#define EPL_DBGLVL_EVENTK_TRACE3 DEBUG_LVL_27_TRACE3 +#define EPL_DBGLVL_EVENTK_TRACE4 DEBUG_LVL_27_TRACE4 + +#define EPL_DBGLVL_EVENTU DEBUG_LVL_28 // 0x08000000 +#define EPL_DBGLVL_EVENTU_TRACE0 DEBUG_LVL_28_TRACE0 +#define EPL_DBGLVL_EVENTU_TRACE1 DEBUG_LVL_28_TRACE1 +#define EPL_DBGLVL_EVENTU_TRACE2 DEBUG_LVL_28_TRACE2 +#define EPL_DBGLVL_EVENTU_TRACE3 DEBUG_LVL_28_TRACE3 +#define EPL_DBGLVL_EVENTU_TRACE4 DEBUG_LVL_28_TRACE4 + +// SharedBuff +#define EPL_DBGLVL_SHB DEBUG_LVL_29 // 0x10000000 +#define EPL_DBGLVL_SHB_TRACE0 DEBUG_LVL_29_TRACE0 +#define EPL_DBGLVL_SHB_TRACE1 DEBUG_LVL_29_TRACE1 +#define EPL_DBGLVL_SHB_TRACE2 DEBUG_LVL_29_TRACE2 +#define EPL_DBGLVL_SHB_TRACE3 DEBUG_LVL_29_TRACE3 +#define EPL_DBGLVL_SHB_TRACE4 DEBUG_LVL_29_TRACE4 + +#define EPL_DBGLVL_ASSERT DEBUG_LVL_ASSERT // 0x20000000L +#define EPL_DBGLVL_ASSERT_TRACE0 DEBUG_LVL_ASSERT_TRACE0 +#define EPL_DBGLVL_ASSERT_TRACE1 DEBUG_LVL_ASSERT_TRACE1 +#define EPL_DBGLVL_ASSERT_TRACE2 DEBUG_LVL_ASSERT_TRACE2 +#define EPL_DBGLVL_ASSERT_TRACE3 DEBUG_LVL_ASSERT_TRACE3 +#define EPL_DBGLVL_ASSERT_TRACE4 DEBUG_LVL_ASSERT_TRACE4 + +#define EPL_DBGLVL_ERROR DEBUG_LVL_ERROR // 0x40000000L +#define EPL_DBGLVL_ERROR_TRACE0 DEBUG_LVL_ERROR_TRACE0 +#define EPL_DBGLVL_ERROR_TRACE1 DEBUG_LVL_ERROR_TRACE1 +#define EPL_DBGLVL_ERROR_TRACE2 DEBUG_LVL_ERROR_TRACE2 +#define EPL_DBGLVL_ERROR_TRACE3 DEBUG_LVL_ERROR_TRACE3 +#define EPL_DBGLVL_ERROR_TRACE4 DEBUG_LVL_ERROR_TRACE4 + +#define EPL_DBGLVL_ALWAYS DEBUG_LVL_ALWAYS // 0x80000000L +#define EPL_DBGLVL_ALWAYS_TRACE0 DEBUG_LVL_ALWAYS_TRACE0 +#define EPL_DBGLVL_ALWAYS_TRACE1 DEBUG_LVL_ALWAYS_TRACE1 +#define EPL_DBGLVL_ALWAYS_TRACE2 DEBUG_LVL_ALWAYS_TRACE2 +#define EPL_DBGLVL_ALWAYS_TRACE3 DEBUG_LVL_ALWAYS_TRACE3 +#define EPL_DBGLVL_ALWAYS_TRACE4 DEBUG_LVL_ALWAYS_TRACE4 + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPL_INC_H_ + + diff --git a/drivers/staging/epl/EplInstDef.h b/drivers/staging/epl/EplInstDef.h new file mode 100644 index 0000000..ab9bafa --- /dev/null +++ b/drivers/staging/epl/EplInstDef.h @@ -0,0 +1,386 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: definitions for generating instances + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplInstDef.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + ... + + ------------------------------------------------------------------------- + + Revision History: + + r.d.: first implementation + +****************************************************************************/ + +#ifndef _EPLINSTDEF_H_ +#define _EPLINSTDEF_H_ + + +// ========================================================================= +// types and macros for generating instances +// ========================================================================= + +typedef enum +{ + kStateUnused = 0, + kStateDeleted = 1, + kStateUsed = 0xFF + +} tInstState; + +//------------------------------------------------------------------------------------------ + +typedef void MEM* tEplPtrInstance; +typedef BYTE tEplInstanceHdl; + +// define const for illegale values +#define CCM_ILLINSTANCE NULL +#define CCM_ILLINSTANCE_HDL 0xFF + +//------------------------------------------------------------------------------------------ +// if more than one instance then use this macros +#if (EPL_MAX_INSTANCES > 1) + + //-------------------------------------------------------------------------------------- + // macro definition for instance table definition + //-------------------------------------------------------------------------------------- + + // memory attributes for instance table + #define INST_NEAR // faster access to variables + #define INST_FAR // variables wich have to located in xdata + #define STATIC // prevent warnings for variables with same name + + #define INSTANCE_TYPE_BEGIN typedef struct { + #define INSTANCE_TYPE_END } tEplInstanceInfo; + + + //-------------------------------------------------------------------------------------- + // macro definition for API interface + //-------------------------------------------------------------------------------------- + + // declaration: + + // macros for declaration within function header or prototype of API functions + #define CCM_DECL_INSTANCE_HDL tEplInstanceHdl InstanceHandle + #define CCM_DECL_INSTANCE_HDL_ tEplInstanceHdl InstanceHandle, + + // macros for declaration of pointer to instance handle within function header or prototype of API functions + #define CCM_DECL_PTR_INSTANCE_HDL tEplInstanceHdl MEM* pInstanceHandle + #define CCM_DECL_PTR_INSTANCE_HDL_ tEplInstanceHdl MEM* pInstanceHandle, + + // macros for declaration instance as lokacl variable within functions + #define CCM_DECL_INSTANCE_PTR_LOCAL tCcmInstanceInfo MEM* pInstance; + #define CCM_DECL_PTR_INSTANCE_HDL_LOCAL tEplInstanceHdl MEM* pInstanceHandle; + + // reference: + + // macros for reference of instance handle for function parameters + #define CCM_INSTANCE_HDL InstanceHandle + #define CCM_INSTANCE_HDL_ InstanceHandle, + + // macros for reference of instance parameter for function parameters + #define CCM_INSTANCE_PARAM(par) par + #define CCM_INSTANCE_PARAM_(par) par, + + // macros for reference of instance parameter for writing or reading values + #define CCM_INST_ENTRY (*((tEplPtrInstance)pInstance)) + + // processing: + + // macros for process instance handle + #define CCM_CHECK_INSTANCE_HDL() if (InstanceHandle >= EPL_MAX_INSTANCES) \ + {return (kEplIllegalInstance);} + + + // macros for process pointer to instance handle + #define CCM_CHECK_PTR_INSTANCE_HDL() if (pInstanceHandle == NULL) \ + {return (kEplInvalidInstanceParam);} + + // This macro returned the handle and pointer to next free instance. + #define CCM_GET_FREE_INSTANCE_AND_HDL() pInstance = CcmGetFreeInstanceAndHandle (pInstanceHandle); \ + ASSERT (*pInstanceHandle != CCM_ILLINSTANCE_HDL); + + #define CCM_CHECK_INSTANCE_PTR() if (pInstance == CCM_ILLINSTANCE) \ + {return (kEplNoFreeInstance);} + + #define CCM_GET_INSTANCE_PTR() pInstance = CcmGetInstancePtr (InstanceHandle); + #define CCM_GET_FREE_INSTANCE_PTR() pInstance = GetFreeInstance (); \ + ASSERT (pInstance != CCM_ILLINSTANCE); + + + //-------------------------------------------------------------------------------------- + // macro definition for stack interface + //-------------------------------------------------------------------------------------- + + // macros for declaration within the function header, prototype or local var list + // Declaration of pointers within function paramater list must defined as void MEM* + // pointer. + #define EPL_MCO_DECL_INSTANCE_PTR void MEM* pInstance + #define EPL_MCO_DECL_INSTANCE_PTR_ void MEM* pInstance, + #define EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplPtrInstance pInstance; + + // macros for reference of pointer to instance + // These macros are used for parameter passing to called function. + #define EPL_MCO_INSTANCE_PTR pInstance + #define EPL_MCO_INSTANCE_PTR_ pInstance, + #define EPL_MCO_ADDR_INSTANCE_PTR_ &pInstance, + + // macro for access of struct members of one instance + // An access to a member of instance table must be casted by the local + // defined type of instance table. + #define EPL_MCO_INST_ENTRY (*(tEplPtrInstance)pInstance) + #define EPL_MCO_GLB_VAR(var) (((tEplPtrInstance)pInstance)->var) + + // macros for process pointer to instance + #define EPL_MCO_GET_INSTANCE_PTR() pInstance = (tEplPtrInstance) GetInstancePtr (InstanceHandle); + #define EPL_MCO_GET_FREE_INSTANCE_PTR() pInstance = (tEplPtrInstance) GetFreeInstance (); \ + ASSERT (pInstance != CCM_ILLINSTANCE); + + // This macro should be used to check the passed pointer to an public function + #define EPL_MCO_CHECK_INSTANCE_STATE() ASSERT (pInstance != NULL); \ + ASSERT (((tEplPtrInstance)pInstance)->m_InstState == kStateUsed); + + // macros for declaration of pointer to instance pointer + #define EPL_MCO_DECL_PTR_INSTANCE_PTR void MEM* MEM* pInstancePtr + #define EPL_MCO_DECL_PTR_INSTANCE_PTR_ void MEM* MEM* pInstancePtr, + + // macros for reference of pointer to instance pointer + // These macros are used for parameter passing to called function. + #define EPL_MCO_PTR_INSTANCE_PTR pInstancePtr + #define EPL_MCO_PTR_INSTANCE_PTR_ pInstancePtr, + + // macros for process pointer to instance pointer + #define EPL_MCO_CHECK_PTR_INSTANCE_PTR() ASSERT (pInstancePtr != NULL); + #define EPL_MCO_SET_PTR_INSTANCE_PTR() (*pInstancePtr = pInstance); + + #define EPL_MCO_INSTANCE_PARAM(a) (a) + #define EPL_MCO_INSTANCE_PARAM_(a) (a), + #define EPL_MCO_INSTANCE_PARAM_IDX_() EPL_MCO_INSTANCE_PARAM_ (EPL_MCO_GLB_VAR (m_bInstIndex)) + #define EPL_MCO_INSTANCE_PARAM_IDX() EPL_MCO_INSTANCE_PARAM (EPL_MCO_GLB_VAR (m_bInstIndex)) + #define EPL_MCO_WRITE_INSTANCE_STATE(a) EPL_MCO_GLB_VAR (m_InstState) = a; + + // this macro deletes all instance entries as unused + #define EPL_MCO_DELETE_INSTANCE_TABLE() \ + { \ + tEplInstanceInfo MEM* pInstance = &aEplInstanceTable_g[0]; \ + tFastByte InstNumber = 0; \ + tFastByte i = EPL_MAX_INSTANCES; \ + do { \ + pInstance->m_InstState = (BYTE) kStateUnused; \ + pInstance->m_bInstIndex = (BYTE) InstNumber; \ + pInstance++; InstNumber++; i--; \ + } while (i != 0); \ + } + + // definition of functions which has to be defined in each module of CANopen stack + #define EPL_MCO_DEFINE_INSTANCE_FCT() \ + static tEplPtrInstance GetInstancePtr (tEplInstanceHdl InstHandle_p); \ + static tEplPtrInstance GetFreeInstance (void); + #define EPL_MCO_DECL_INSTANCE_FCT() \ + static tEplPtrInstance GetInstancePtr (tEplInstanceHdl InstHandle_p) { \ + return &aEplInstanceTable_g[InstHandle_p]; } \ + static tEplPtrInstance GetFreeInstance (void) { \ + tEplInstanceInfo MEM* pInstance = &aEplInstanceTable_g[0]; \ + tFastByte i = EPL_MAX_INSTANCES; \ + do { if (pInstance->m_InstState != kStateUsed) { \ + return (tEplPtrInstance) pInstance; } \ + pInstance++; i--; } \ + while (i != 0); \ + return CCM_ILLINSTANCE; } + + // this macro defines the instance table. Each entry is reserved for an instance of CANopen. + #define EPL_MCO_DECL_INSTANCE_VAR() \ + static tEplInstanceInfo MEM aEplInstanceTable_g [EPL_MAX_INSTANCES]; + + // this macro defines member variables in instance table which are needed in + // all modules of Epl stack + #define EPL_MCO_DECL_INSTANCE_MEMBER() \ + STATIC BYTE m_InstState; \ + STATIC BYTE m_bInstIndex; + + #define EPL_MCO_INSTANCE_PARAM_IDX_() EPL_MCO_INSTANCE_PARAM_ (EPL_MCO_GLB_VAR (m_bInstIndex)) + #define EPL_MCO_INSTANCE_PARAM_IDX() EPL_MCO_INSTANCE_PARAM (EPL_MCO_GLB_VAR (m_bInstIndex)) + +#else // only one instance is used + + // Memory attributes for instance table. + #define INST_NEAR NEAR // faster access to variables + #define INST_FAR MEM // variables wich have to located in xdata + #define STATIC static // prevent warnings for variables with same name + + #define INSTANCE_TYPE_BEGIN + #define INSTANCE_TYPE_END + +// macros for declaration, initializing and member access for instance handle +// This class of macros are used by API function to inform CCM-modul which +// instance is to be used. + + // macros for reference of instance handle + // These macros are used for parameter passing to CANopen API function. + #define CCM_INSTANCE_HDL + #define CCM_INSTANCE_HDL_ + + #define CCM_DECL_INSTANCE_PTR_LOCAL + + // macros for declaration within the function header or prototype + #define CCM_DECL_INSTANCE_HDL void + #define CCM_DECL_INSTANCE_HDL_ + + // macros for process instance handle + #define CCM_CHECK_INSTANCE_HDL() + + // macros for declaration of pointer to instance handle + #define CCM_DECL_PTR_INSTANCE_HDL void + #define CCM_DECL_PTR_INSTANCE_HDL_ + + // macros for process pointer to instance handle + #define CCM_CHECK_PTR_INSTANCE_HDL() + + // This macro returned the handle and pointer to next free instance. + #define CCM_GET_FREE_INSTANCE_AND_HDL() + + #define CCM_CHECK_INSTANCE_PTR() + + #define CCM_GET_INSTANCE_PTR() + #define CCM_GET_FREE_INSTANCE_PTR() + + #define CCM_INSTANCE_PARAM(par) + #define CCM_INSTANCE_PARAM_(par) + + #define CCM_INST_ENTRY aCcmInstanceTable_g[0] + +// macros for declaration, initializing and member access for instance pointer +// This class of macros are used by CANopen internal function to point to one instance. + + // macros for declaration within the function header, prototype or local var list + #define EPL_MCO_DECL_INSTANCE_PTR void + #define EPL_MCO_DECL_INSTANCE_PTR_ + #define EPL_MCO_DECL_INSTANCE_PTR_LOCAL + + // macros for reference of pointer to instance + // These macros are used for parameter passing to called function. + #define EPL_MCO_INSTANCE_PTR + #define EPL_MCO_INSTANCE_PTR_ + #define EPL_MCO_ADDR_INSTANCE_PTR_ + + // macros for process pointer to instance + #define EPL_MCO_GET_INSTANCE_PTR() + #define EPL_MCO_GET_FREE_INSTANCE_PTR() + + // This macro should be used to check the passed pointer to an public function + #define EPL_MCO_CHECK_INSTANCE_STATE() + + // macros for declaration of pointer to instance pointer + #define EPL_MCO_DECL_PTR_INSTANCE_PTR void + #define EPL_MCO_DECL_PTR_INSTANCE_PTR_ + + // macros for reference of pointer to instance pointer + // These macros are used for parameter passing to called function. + #define EPL_MCO_PTR_INSTANCE_PTR + #define EPL_MCO_PTR_INSTANCE_PTR_ + + // macros for process pointer to instance pointer + #define EPL_MCO_CHECK_PTR_INSTANCE_PTR() + #define EPL_MCO_SET_PTR_INSTANCE_PTR() + + #define EPL_MCO_INSTANCE_PARAM(a) + #define EPL_MCO_INSTANCE_PARAM_(a) + #define EPL_MCO_INSTANCE_PARAM_IDX_() + #define EPL_MCO_INSTANCE_PARAM_IDX() + + // macro for access of struct members of one instance + #define EPL_MCO_INST_ENTRY aEplInstanceTable_g[0] + #define EPL_MCO_GLB_VAR(var) (var) + #define EPL_MCO_WRITE_INSTANCE_STATE(a) + + // this macro deletes all instance entries as unused + #define EPL_MCO_DELETE_INSTANCE_TABLE() + + // definition of functions which has to be defined in each module of CANopen stack + #define EPL_MCO_DEFINE_INSTANCE_FCT() + #define EPL_MCO_DECL_INSTANCE_FCT() + + // this macro defines the instance table. Each entry is reserved for an instance of CANopen. + #define EPL_MCO_DECL_INSTANCE_VAR() + + // this macro defines member variables in instance table which are needed in + // all modules of CANopen stack + #define EPL_MCO_DECL_INSTANCE_MEMBER() + +#endif + + +/* +#if (CDRV_MAX_INSTANCES > 1) + + #define CDRV_REENTRANT REENTRANT + +#else + + #define CDRV_REENTRANT + +#endif +*/ + + +#endif // _EPLINSTDEF_H_ + +// Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler +// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder). + diff --git a/drivers/staging/epl/EplLed.h b/drivers/staging/epl/EplLed.h new file mode 100644 index 0000000..390d6db --- /dev/null +++ b/drivers/staging/epl/EplLed.h @@ -0,0 +1,104 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for status and error LED + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplLed.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.1 $ $Date: 2008/11/17 16:40:39 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2008/11/17 d.k.: start of the implementation + + +****************************************************************************/ + + +#ifndef _EPLLED_H_ +#define _EPLLED_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +typedef enum +{ + kEplLedTypeStatus = 0x00, + kEplLedTypeError = 0x01, + +} tEplLedType; + + + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPLLED_H_ + + diff --git a/drivers/staging/epl/EplNmt.h b/drivers/staging/epl/EplNmt.h new file mode 100644 index 0000000..7b9e58e --- /dev/null +++ b/drivers/staging/epl/EplNmt.h @@ -0,0 +1,248 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: global include file for EPL-NMT-Modules + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmt.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/11/17 16:40:39 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/09 k.t.: start of the implementation + + +****************************************************************************/ + +#ifndef _EPLNMT_H_ +#define _EPLNMT_H_ + +#include "EplInc.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// define super-states and masks to identify a super-state +#define EPL_NMT_GS_POWERED 0x0008 // super state +#define EPL_NMT_GS_INITIALISATION 0x0009 // super state +#define EPL_NMT_GS_COMMUNICATING 0x000C // super state +#define EPL_NMT_CS_EPLMODE 0x000D // super state +#define EPL_NMT_MS_EPLMODE 0x000D // super state + +#define EPL_NMT_SUPERSTATE_MASK 0x000F // mask to select state + +#define EPL_NMT_TYPE_UNDEFINED 0x0000 // type of NMT state is still undefined +#define EPL_NMT_TYPE_CS 0x0100 // CS type of NMT state +#define EPL_NMT_TYPE_MS 0x0200 // MS type of NMT state +#define EPL_NMT_TYPE_MASK 0x0300 // mask to select type of NMT state (i.e. CS or MS) + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +// the lower Byte of the NMT-State is encoded +// like the values in the EPL-Standard +// the higher byte is used to encode MN +// (Bit 1 of the higher byte = 1) or CN (Bit 0 of the +// higher byte = 1) +// the super-states are not mentioned in this +// enum because they are no real states +// --> there are masks defined to indentify the +// super-states + +typedef enum +{ + kEplNmtGsOff = 0x0000, + kEplNmtGsInitialising = 0x0019, + kEplNmtGsResetApplication = 0x0029, + kEplNmtGsResetCommunication = 0x0039, + kEplNmtGsResetConfiguration = 0x0079, + kEplNmtCsNotActive = 0x011C, + kEplNmtCsPreOperational1 = 0x011D, + kEplNmtCsStopped = 0x014D, + kEplNmtCsPreOperational2 = 0x015D, + kEplNmtCsReadyToOperate = 0x016D, + kEplNmtCsOperational = 0x01FD, + kEplNmtCsBasicEthernet = 0x011E, + kEplNmtMsNotActive = 0x021C, + kEplNmtMsPreOperational1 = 0x021D, + kEplNmtMsPreOperational2 = 0x025D, + kEplNmtMsReadyToOperate = 0x026D, + kEplNmtMsOperational = 0x02FD, + kEplNmtMsBasicEthernet = 0x021E + +} tEplNmtState; + +// NMT-events +typedef enum +{ + // Events from DLL + // Events defined by EPL V2 specification + kEplNmtEventNoEvent = 0x00, +// kEplNmtEventDllMePres = 0x01, + kEplNmtEventDllMePresTimeout = 0x02, +// kEplNmtEventDllMeAsnd = 0x03, +// kEplNmtEventDllMeAsndTimeout = 0x04, + kEplNmtEventDllMeSoaSent = 0x04, + kEplNmtEventDllMeSocTrig = 0x05, + kEplNmtEventDllMeSoaTrig = 0x06, + kEplNmtEventDllCeSoc = 0x07, + kEplNmtEventDllCePreq = 0x08, + kEplNmtEventDllCePres = 0x09, + kEplNmtEventDllCeSoa = 0x0A, + kEplNmtEventDllCeAsnd = 0x0B, + kEplNmtEventDllCeFrameTimeout = 0x0C, + + // Events triggered by NMT-Commands + kEplNmtEventSwReset = 0x10, // NMT_GT1, NMT_GT2, NMT_GT8 + kEplNmtEventResetNode = 0x11, + kEplNmtEventResetCom = 0x12, + kEplNmtEventResetConfig = 0x13, + kEplNmtEventEnterPreOperational2= 0x14, + kEplNmtEventEnableReadyToOperate= 0x15, + kEplNmtEventStartNode = 0x16, // NMT_CT7 + kEplNmtEventStopNode = 0x17, + + // Events triggered by higher layer + kEplNmtEventEnterResetApp = 0x20, + kEplNmtEventEnterResetCom = 0x21, + kEplNmtEventInternComError = 0x22, // NMT_GT6, internal communication error -> enter ResetCommunication + kEplNmtEventEnterResetConfig = 0x23, + kEplNmtEventEnterCsNotActive = 0x24, + kEplNmtEventEnterMsNotActive = 0x25, + kEplNmtEventTimerBasicEthernet = 0x26, // NMT_CT3; timer triggered state change (NotActive -> BasicEth) + kEplNmtEventTimerMsPreOp1 = 0x27, // enter PreOp1 on MN (NotActive -> MsPreOp1) + kEplNmtEventNmtCycleError = 0x28, // NMT_CT11, NMT_MT6; error during cycle -> enter PreOp1 + kEplNmtEventTimerMsPreOp2 = 0x29, // enter PreOp2 on MN (MsPreOp1 -> MsPreOp2 if kEplNmtEventAllMandatoryCNIdent) + kEplNmtEventAllMandatoryCNIdent = 0x2A, // enter PreOp2 on MN if kEplNmtEventTimerMsPreOp2 + kEplNmtEventEnterReadyToOperate = 0x2B, // application ready for the state ReadyToOp + kEplNmtEventEnterMsOperational = 0x2C, // enter Operational on MN + kEplNmtEventSwitchOff = 0x2D, // enter state Off + kEplNmtEventCriticalError = 0x2E, // enter state Off because of critical error + +} tEplNmtEvent; + + +// type for argument of event kEplEventTypeNmtStateChange +typedef struct +{ + tEplNmtState m_NewNmtState; + tEplNmtEvent m_NmtEvent; + +} tEplEventNmtStateChange; + + +// structure for kEplEventTypeHeartbeat +typedef struct +{ + unsigned int m_uiNodeId; // NodeId + tEplNmtState m_NmtState; // NMT state (remember distinguish between MN / CN) + WORD m_wErrorCode; // EPL error code in case of NMT state NotActive + +} tEplHeartbeatEvent; + + +typedef enum +{ + kEplNmtNodeEventFound = 0x00, + kEplNmtNodeEventUpdateSw = 0x01, // application shall update software on CN + kEplNmtNodeEventCheckConf = 0x02, // application / Configuration Manager shall check and update configuration on CN + kEplNmtNodeEventUpdateConf = 0x03, // application / Configuration Manager shall update configuration on CN (check was done by NmtMn module) + kEplNmtNodeEventVerifyConf = 0x04, // application / Configuration Manager shall verify configuration of CN + kEplNmtNodeEventReadyToStart= 0x05, // issued if EPL_NMTST_NO_STARTNODE set + // application must call EplNmtMnuSendNmtCommand(kEplNmtCmdStartNode) manually + kEplNmtNodeEventNmtState = 0x06, + kEplNmtNodeEventError = 0x07, // NMT error of CN + +} tEplNmtNodeEvent; + + +typedef enum +{ + kEplNmtNodeCommandBoot = 0x01, // if EPL_NODEASSIGN_START_CN not set it must be issued after kEplNmtNodeEventFound + kEplNmtNodeCommandSwOk = 0x02, // application updated software on CN successfully + kEplNmtNodeCommandSwUpdated = 0x03, // application updated software on CN successfully + kEplNmtNodeCommandConfOk = 0x04, // application / Configuration Manager has updated configuration on CN successfully + kEplNmtNodeCommandConfReset = 0x05, // application / Configuration Manager has updated configuration on CN successfully + // and CN needs ResetConf so that the configuration gets actived + kEplNmtNodeCommandConfErr = 0x06, // application / Configuration Manager failed on updating configuration on CN + kEplNmtNodeCommandStart = 0x07, // if EPL_NMTST_NO_STARTNODE set it must be issued after kEplNmtNodeEventReadyToStart + +} tEplNmtNodeCommand; + + +typedef enum +{ + kEplNmtBootEventBootStep1Finish = 0x00, // PreOp2 is possible + kEplNmtBootEventBootStep2Finish = 0x01, // ReadyToOp is possible + kEplNmtBootEventCheckComFinish = 0x02, // Operational is possible + kEplNmtBootEventOperational = 0x03, // all mandatory CNs are Operational + kEplNmtBootEventError = 0x04, // boot process halted because of an error + +} tEplNmtBootEvent; + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPLNMT_H_ + + diff --git a/drivers/staging/epl/EplNmtCnu.c b/drivers/staging/epl/EplNmtCnu.c new file mode 100644 index 0000000..7effc7c --- /dev/null +++ b/drivers/staging/epl/EplNmtCnu.c @@ -0,0 +1,691 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for NMT-CN-Userspace-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtCnu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/09 k.t.: start of the implementation + +****************************************************************************/ + +#include "EplInc.h" +#include "user/EplNmtCnu.h" +#include "user/EplDlluCal.h" + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ + unsigned int m_uiNodeId; + tEplNmtuCheckEventCallback m_pfnCheckEventCb; + +} tEplNmtCnuInstance; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +static tEplNmtCnuInstance EplNmtCnuInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static tEplNmtCommand EplNmtCnuGetNmtCommand(tEplFrameInfo * pFrameInfo_p); + +static BOOL EplNmtCnuNodeIdList(BYTE* pbNmtCommandDate_p); + +static tEplKernel PUBLIC EplNmtCnuCommandCb(tEplFrameInfo * pFrameInfo_p); + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplNmtCnuInit +// +// Description: init the first instance of the module +// +// +// +// Parameters: uiNodeId_p = NodeId of the local node +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuInit(unsigned int uiNodeId_p) +{ +tEplKernel Ret; + + Ret = EplNmtCnuAddInstance(uiNodeId_p); + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtCnuAddInstance +// +// Description: init the add new instance of the module +// +// +// +// Parameters: uiNodeId_p = NodeId of the local node +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuAddInstance(unsigned int uiNodeId_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // reset instance structure + EPL_MEMSET(&EplNmtCnuInstance_g, 0, sizeof (EplNmtCnuInstance_g)); + + // save nodeid + EplNmtCnuInstance_g.m_uiNodeId = uiNodeId_p; + + // register callback-function for NMT-commands +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + Ret = EplDlluCalRegAsndService(kEplDllAsndNmtCommand, + EplNmtCnuCommandCb, + kEplDllAsndFilterLocal); +#endif + + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtCnuDelInstance +// +// Description: delte instance of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + // deregister callback function from DLL + Ret = EplDlluCalRegAsndService(kEplDllAsndNmtCommand, + NULL, + kEplDllAsndFilterNone); +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtCnuSendNmtRequest +// +// Description: Send an NMT-Request to the MN +// +// +// +// Parameters: uiNodeId_p = NodeId of the local node +// NmtCommand_p = requested NMT-Command +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuSendNmtRequest( + unsigned int uiNodeId_p, + tEplNmtCommand NmtCommand_p) +{ +tEplKernel Ret; +tEplFrameInfo NmtRequestFrameInfo; +tEplFrame NmtRequestFrame; + + + Ret = kEplSuccessful; + + // build frame + EPL_MEMSET(&NmtRequestFrame.m_be_abDstMac[0], 0x00, sizeof(NmtRequestFrame.m_be_abDstMac)); // set by DLL + EPL_MEMSET(&NmtRequestFrame.m_be_abSrcMac[0], 0x00, sizeof(NmtRequestFrame.m_be_abSrcMac)); // set by DLL + AmiSetWordToBe(&NmtRequestFrame.m_be_wEtherType, EPL_C_DLL_ETHERTYPE_EPL); + AmiSetByteToLe(&NmtRequestFrame.m_le_bDstNodeId, (BYTE) EPL_C_ADR_MN_DEF_NODE_ID); // node id of the MN + AmiSetByteToLe(&NmtRequestFrame.m_le_bMessageType, (BYTE)kEplMsgTypeAsnd); + AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_le_bServiceId, (BYTE) kEplDllAsndNmtRequest); + AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_Payload.m_NmtRequestService.m_le_bNmtCommandId, + (BYTE)NmtCommand_p); + AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_Payload.m_NmtRequestService.m_le_bTargetNodeId, + (BYTE)uiNodeId_p); // target for the nmt command + EPL_MEMSET(&NmtRequestFrame.m_Data.m_Asnd.m_Payload.m_NmtRequestService.m_le_abNmtCommandData[0], 0x00, sizeof(NmtRequestFrame.m_Data.m_Asnd.m_Payload.m_NmtRequestService.m_le_abNmtCommandData)); + + + + // build info-structure + NmtRequestFrameInfo.m_NetTime.m_dwNanoSec = 0; + NmtRequestFrameInfo.m_NetTime.m_dwSec = 0; + NmtRequestFrameInfo.m_pFrame = &NmtRequestFrame; + NmtRequestFrameInfo.m_uiFrameSize = EPL_C_DLL_MINSIZE_NMTREQ; // sizeof(NmtRequestFrame); + + // send NMT-Request +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + Ret = EplDlluCalAsyncSend(&NmtRequestFrameInfo, // pointer to frameinfo + kEplDllAsyncReqPrioNmt); // priority +#endif + + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtCnuRegisterStateChangeCb +// +// Description: register Callback-function go get informed about a +// NMT-Change-State-Event +// +// +// +// Parameters: pfnEplNmtStateChangeCb_p = functionpointer +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuRegisterCheckEventCb( + tEplNmtuCheckEventCallback pfnEplNmtCheckEventCb_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // save callback-function in modul global var + EplNmtCnuInstance_g.m_pfnCheckEventCb = pfnEplNmtCheckEventCb_p; + + return Ret; + +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtCnuCommandCb +// +// Description: callback funktion for NMT-Commands +// +// +// +// Parameters: pFrameInfo_p = Frame with the NMT-Commando +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel PUBLIC EplNmtCnuCommandCb(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplNmtCommand NmtCommand; +BOOL fNodeIdInList; +tEplNmtEvent NmtEvent = kEplNmtEventNoEvent; + + + if(pFrameInfo_p == NULL) + { + Ret = kEplNmtInvalidFramePointer; + goto Exit; + } + + NmtCommand = EplNmtCnuGetNmtCommand(pFrameInfo_p); + + // check NMT-Command + switch(NmtCommand) + { + + //------------------------------------------------------------------------ + // plain NMT state commands + case kEplNmtCmdStartNode: + { // send NMT-Event to state maschine kEplNmtEventStartNode + NmtEvent = kEplNmtEventStartNode; + break; + } + + case kEplNmtCmdStopNode: + { // send NMT-Event to state maschine kEplNmtEventStopNode + NmtEvent = kEplNmtEventStopNode; + break; + } + + case kEplNmtCmdEnterPreOperational2: + { // send NMT-Event to state maschine kEplNmtEventEnterPreOperational2 + NmtEvent = kEplNmtEventEnterPreOperational2; + break; + } + + case kEplNmtCmdEnableReadyToOperate: + { // send NMT-Event to state maschine kEplNmtEventEnableReadyToOperate + NmtEvent = kEplNmtEventEnableReadyToOperate; + break; + } + + case kEplNmtCmdResetNode: + { // send NMT-Event to state maschine kEplNmtEventResetNode + NmtEvent = kEplNmtEventResetNode; + break; + } + + case kEplNmtCmdResetCommunication: + { // send NMT-Event to state maschine kEplNmtEventResetCom + NmtEvent = kEplNmtEventResetCom; + break; + } + + case kEplNmtCmdResetConfiguration: + { // send NMT-Event to state maschine kEplNmtEventResetConfig + NmtEvent = kEplNmtEventResetConfig; + break; + } + + case kEplNmtCmdSwReset: + { // send NMT-Event to state maschine kEplNmtEventSwReset + NmtEvent = kEplNmtEventSwReset; + break; + } + + //------------------------------------------------------------------------ + // extended NMT state commands + + case kEplNmtCmdStartNodeEx: + { + // check if own nodeid is in EPL node list + fNodeIdInList = EplNmtCnuNodeIdList(&(pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_abNmtCommandData[0])); + if(fNodeIdInList != FALSE) + { // own nodeid in list + // send event to process command + NmtEvent = kEplNmtEventStartNode; + } + break; + } + + case kEplNmtCmdStopNodeEx: + { // check if own nodeid is in EPL node list + fNodeIdInList = EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_abNmtCommandData[0]); + if(fNodeIdInList != FALSE) + { // own nodeid in list + // send event to process command + NmtEvent = kEplNmtEventStopNode; + } + break; + } + + case kEplNmtCmdEnterPreOperational2Ex: + { // check if own nodeid is in EPL node list + fNodeIdInList = EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_abNmtCommandData[0]); + if(fNodeIdInList != FALSE) + { // own nodeid in list + // send event to process command + NmtEvent = kEplNmtEventEnterPreOperational2; + } + break; + } + + case kEplNmtCmdEnableReadyToOperateEx: + { // check if own nodeid is in EPL node list + fNodeIdInList = EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_abNmtCommandData[0]); + if(fNodeIdInList != FALSE) + { // own nodeid in list + // send event to process command + NmtEvent = kEplNmtEventEnableReadyToOperate; + } + break; + } + + case kEplNmtCmdResetNodeEx: + {// check if own nodeid is in EPL node list + fNodeIdInList = EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_abNmtCommandData[0]); + if(fNodeIdInList != FALSE) + { // own nodeid in list + // send event to process command + NmtEvent = kEplNmtEventResetNode; + } + break; + } + + case kEplNmtCmdResetCommunicationEx: + { // check if own nodeid is in EPL node list + fNodeIdInList = EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_abNmtCommandData[0]); + if(fNodeIdInList != FALSE) + { // own nodeid in list + // send event to process command + NmtEvent = kEplNmtEventResetCom; + } + break; + } + + case kEplNmtCmdResetConfigurationEx: + { // check if own nodeid is in EPL node list + fNodeIdInList = EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_abNmtCommandData[0]); + if(fNodeIdInList != FALSE) + { // own nodeid in list + // send event to process command + NmtEvent = kEplNmtEventResetConfig; + } + break; + } + + case kEplNmtCmdSwResetEx: + { // check if own nodeid is in EPL node list + fNodeIdInList = EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_abNmtCommandData[0]); + if(fNodeIdInList != FALSE) + { // own nodeid in list + // send event to process command + NmtEvent = kEplNmtEventSwReset; + } + break; + } + + //------------------------------------------------------------------------ + // NMT managing commands + + // TODO: add functions to process managing command (optional) + + case kEplNmtCmdNetHostNameSet: + { + break; + } + + case kEplNmtCmdFlushArpEntry: + { + break; + } + + //------------------------------------------------------------------------ + // NMT info services + + // TODO: forward event with infos to the application (optional) + + case kEplNmtCmdPublishConfiguredCN: + { + break; + } + + case kEplNmtCmdPublishActiveCN: + { + break; + } + + case kEplNmtCmdPublishPreOperational1: + { + break; + } + + case kEplNmtCmdPublishPreOperational2: + { + break; + } + + case kEplNmtCmdPublishReadyToOperate: + { + break; + } + + case kEplNmtCmdPublishOperational: + { + break; + } + + case kEplNmtCmdPublishStopped: + { + break; + } + + case kEplNmtCmdPublishEmergencyNew: + { + break; + } + + case kEplNmtCmdPublishTime: + { + break; + } + + //----------------------------------------------------------------------- + // error from MN + // -> requested command not supported by MN + case kEplNmtCmdInvalidService: + { + + // TODO: errorevent to application + break; + } + + //------------------------------------------------------------------------ + // default + default: + { + Ret = kEplNmtUnknownCommand; + goto Exit; + } + + }// end of switch(NmtCommand) + + if (NmtEvent != kEplNmtEventNoEvent) + { + if (EplNmtCnuInstance_g.m_pfnCheckEventCb != NULL) + { + Ret = EplNmtCnuInstance_g.m_pfnCheckEventCb(NmtEvent); + if (Ret == kEplReject) + { + Ret = kEplSuccessful; + goto Exit; + } + else if (Ret != kEplSuccessful) + { + goto Exit; + } + } +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + Ret = EplNmtuNmtEvent(NmtEvent); +#endif + } + +Exit: + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtCnuGetNmtCommand() +// +// Description: returns the NMT-Command from the frame +// +// +// +// Parameters: pFrameInfo_p = pointer to the Frame +// with the NMT-Command +// +// +// Returns: tEplNmtCommand = NMT-Command +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplNmtCommand EplNmtCnuGetNmtCommand(tEplFrameInfo * pFrameInfo_p) +{ +tEplNmtCommand NmtCommand; +tEplNmtCommandService* pNmtCommandService; + + pNmtCommandService = &pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService; + + NmtCommand = (tEplNmtCommand)AmiGetByteFromLe(&pNmtCommandService->m_le_bNmtCommandId); + + return NmtCommand; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtCnuNodeIdList() +// +// Description: check if the own nodeid is set in EPL Node List +// +// +// +// Parameters: pbNmtCommandDate_p = pointer to the data of the NMT Command +// +// +// Returns: BOOL = TRUE if nodeid is set in EPL Node List +// FALSE if nodeid not set in EPL Node List +// +// +// State: +// +//--------------------------------------------------------------------------- +static BOOL EplNmtCnuNodeIdList(BYTE* pbNmtCommandDate_p) +{ +BOOL fNodeIdInList; +unsigned int uiByteOffset; +BYTE bBitOffset; +BYTE bNodeListByte; + + // get byte-offset of the own nodeid in NodeIdList + // devide though 8 + uiByteOffset = (unsigned int)(EplNmtCnuInstance_g.m_uiNodeId >> 3); + // get bitoffset + bBitOffset = (BYTE) EplNmtCnuInstance_g.m_uiNodeId % 8; + + bNodeListByte = AmiGetByteFromLe(&pbNmtCommandDate_p[uiByteOffset]); + if((bNodeListByte & bBitOffset) == 0) + { + fNodeIdInList = FALSE; + } + else + { + fNodeIdInList = TRUE; + } + +return fNodeIdInList; +} + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplNmtMnu.c b/drivers/staging/epl/EplNmtMnu.c new file mode 100644 index 0000000..8045360 --- /dev/null +++ b/drivers/staging/epl/EplNmtMnu.c @@ -0,0 +1,2798 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for NMT-MN-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtMnu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.18 $ $Date: 2008/11/19 09:52:24 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/09 k.t.: start of the implementation + +****************************************************************************/ + +#include "user/EplNmtMnu.h" +#include "user/EplTimeru.h" +#include "user/EplIdentu.h" +#include "user/EplStatusu.h" +#include "user/EplObdu.h" +#include "user/EplDlluCal.h" +#include "Benchmark.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE) +#error "EPL NmtMnu module needs EPL module OBDU or OBDK!" +#endif + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// TracePoint support for realtime-debugging +#ifdef _DBG_TRACE_POINTS_ + void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); + void PUBLIC TgtDbgPostTraceValue (DWORD dwTraceValue_p); + #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) + #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) +#else + #define TGT_DBG_SIGNAL_TRACE_POINT(p) + #define TGT_DBG_POST_TRACE_VALUE(v) +#endif +#define EPL_NMTMNU_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \ + TGT_DBG_POST_TRACE_VALUE((kEplEventSinkNmtMnu << 28) | (Event_p << 24) \ + | (uiNodeId_p << 16) | wErrorCode_p) + + +// defines for flags in node info structure +#define EPL_NMTMNU_NODE_FLAG_ISOCHRON 0x0001 // CN is being accessed isochronously +#define EPL_NMTMNU_NODE_FLAG_NOT_SCANNED 0x0002 // CN was not scanned once -> decrement SignalCounter and reset flag +#define EPL_NMTMNU_NODE_FLAG_HALTED 0x0004 // boot process for this CN is halted +#define EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED 0x0008 // NMT command was just issued, wrong NMT states will be tolerated +#define EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ 0x0300 // counter for StatusRequest timer handle +#define EPL_NMTMNU_NODE_FLAG_COUNT_LONGER 0x0C00 // counter for longer timeouts timer handle +#define EPL_NMTMNU_NODE_FLAG_INC_STATREQ 0x0100 // increment for StatusRequest timer handle +#define EPL_NMTMNU_NODE_FLAG_INC_LONGER 0x0400 // increment for longer timeouts timer handle + // These counters will be incremented at every timer start + // and copied to timerarg. When the timer event occures + // both will be compared and if unequal the timer event + // will be discarded, because it is an old one. + +// defines for timer arguments to draw a distinction between serveral events +#define EPL_NMTMNU_TIMERARG_NODE_MASK 0x000000FFL // mask that contains the node-ID +#define EPL_NMTMNU_TIMERARG_IDENTREQ 0x00010000L // timer event is for IdentRequest +#define EPL_NMTMNU_TIMERARG_STATREQ 0x00020000L // timer event is for StatusRequest +#define EPL_NMTMNU_TIMERARG_LONGER 0x00040000L // timer event is for longer timeouts +#define EPL_NMTMNU_TIMERARG_STATE_MON 0x00080000L // timer event for StatusRequest to monitor execution of NMT state changes +#define EPL_NMTMNU_TIMERARG_COUNT_SR 0x00000300L // counter for StatusRequest +#define EPL_NMTMNU_TIMERARG_COUNT_LO 0x00000C00L // counter for longer timeouts + // The counters must have the same position as in the node flags above. + +#define EPL_NMTMNU_SET_FLAGS_TIMERARG_STATREQ(pNodeInfo_p, uiNodeId_p, TimerArg_p) \ + pNodeInfo_p->m_wFlags = \ + ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \ + & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \ + | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \ + TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p | \ + (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \ + TimerArg_p.m_EventSink = kEplEventSinkNmtMnu; + +#define EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ(pNodeInfo_p, uiNodeId_p, TimerArg_p) \ + pNodeInfo_p->m_wFlags = \ + ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \ + & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \ + | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \ + TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_IDENTREQ | uiNodeId_p | \ + (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \ + TimerArg_p.m_EventSink = kEplEventSinkNmtMnu; + +#define EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p, TimerArg_p) \ + pNodeInfo_p->m_wFlags = \ + ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_LONGER) \ + & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) \ + | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_LONGER); \ + TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p | \ + (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER); \ + TimerArg_p.m_EventSink = kEplEventSinkNmtMnu; + +#define EPL_NMTMNU_SET_FLAGS_TIMERARG_STATE_MON(pNodeInfo_p, uiNodeId_p, TimerArg_p) \ + pNodeInfo_p->m_wFlags = \ + ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \ + & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \ + | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \ + TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_STATE_MON | uiNodeId_p | \ + (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \ + TimerArg_p.m_EventSink = kEplEventSinkNmtMnu; + + +// defines for global flags +#define EPL_NMTMNU_FLAG_HALTED 0x0001 // boot process is halted +#define EPL_NMTMNU_FLAG_APP_INFORMED 0x0002 // application was informed about possible NMT state change + +// return pointer to node info structure for specified node ID +// d.k. may be replaced by special (hash) function if node ID array is smaller than 254 +#define EPL_NMTMNU_GET_NODEINFO(uiNodeId_p) (&EplNmtMnuInstance_g.m_aNodeInfo[uiNodeId_p - 1]) + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef enum +{ + kEplNmtMnuIntNodeEventNoIdentResponse = 0x00, + kEplNmtMnuIntNodeEventIdentResponse = 0x01, + kEplNmtMnuIntNodeEventBoot = 0x02, + kEplNmtMnuIntNodeEventExecReset = 0x03, + kEplNmtMnuIntNodeEventConfigured = 0x04, + kEplNmtMnuIntNodeEventNoStatusResponse = 0x05, + kEplNmtMnuIntNodeEventStatusResponse = 0x06, + kEplNmtMnuIntNodeEventHeartbeat = 0x07, + kEplNmtMnuIntNodeEventNmtCmdSent = 0x08, + kEplNmtMnuIntNodeEventTimerIdentReq = 0x09, + kEplNmtMnuIntNodeEventTimerStatReq = 0x0A, + kEplNmtMnuIntNodeEventTimerStateMon = 0x0B, + kEplNmtMnuIntNodeEventTimerLonger = 0x0C, + kEplNmtMnuIntNodeEventError = 0x0D, + +} tEplNmtMnuIntNodeEvent; + + +typedef enum +{ + kEplNmtMnuNodeStateUnknown = 0x00, + kEplNmtMnuNodeStateIdentified = 0x01, + kEplNmtMnuNodeStateResetConf = 0x02, // CN reset after configuration update + kEplNmtMnuNodeStateConfigured = 0x03, // BootStep1 completed + kEplNmtMnuNodeStateReadyToOp = 0x04, // BootStep2 completed + kEplNmtMnuNodeStateComChecked = 0x05, // Communication checked successfully + kEplNmtMnuNodeStateOperational = 0x06, // CN is in NMT state OPERATIONAL + +} tEplNmtMnuNodeState; + + +typedef struct +{ + tEplTimerHdl m_TimerHdlStatReq; // timer to delay StatusRequests and IdentRequests + tEplTimerHdl m_TimerHdlLonger; // 2nd timer for NMT command EnableReadyToOp and CheckCommunication + tEplNmtMnuNodeState m_NodeState; // internal node state (kind of sub state of NMT state) + DWORD m_dwNodeCfg; // subindex from 0x1F81 + WORD m_wFlags; // flags: CN is being accessed isochronously + +} tEplNmtMnuNodeInfo; + + +typedef struct +{ + tEplNmtMnuNodeInfo m_aNodeInfo[EPL_NMT_MAX_NODE_ID]; + tEplTimerHdl m_TimerHdlNmtState; // timeout for stay in NMT state + unsigned int m_uiMandatorySlaveCount; + unsigned int m_uiSignalSlaveCount; + unsigned long m_ulStatusRequestDelay; // in [ms] (object 0x1006 * EPL_C_NMT_STATREQ_CYCLE) + unsigned long m_ulTimeoutReadyToOp; // in [ms] (object 0x1F89/5) + unsigned long m_ulTimeoutCheckCom; // in [ms] (object 0x1006 * MultiplexedCycleCount) + WORD m_wFlags; // global flags + DWORD m_dwNmtStartup; // object 0x1F80 NMT_StartUp_U32 + tEplNmtMnuCbNodeEvent m_pfnCbNodeEvent; + tEplNmtMnuCbBootEvent m_pfnCbBootEvent; + +} tEplNmtMnuInstance; + + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +static tEplNmtMnuInstance EplNmtMnuInstance_g; + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p); + +static tEplKernel PUBLIC EplNmtMnuCbIdentResponse( + unsigned int uiNodeId_p, + tEplIdentResponse* pIdentResponse_p); + +static tEplKernel PUBLIC EplNmtMnuCbStatusResponse( + unsigned int uiNodeId_p, + tEplStatusResponse* pStatusResponse_p); + +static tEplKernel EplNmtMnuCheckNmtState( + unsigned int uiNodeId_p, + tEplNmtMnuNodeInfo* pNodeInfo_p, + tEplNmtState NodeNmtState_p, + WORD wErrorCode_p, + tEplNmtState LocalNmtState_p); + +static tEplKernel EplNmtMnuStartBootStep1(void); + +static tEplKernel EplNmtMnuStartBootStep2(void); + +static tEplKernel EplNmtMnuStartCheckCom(void); + +static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p, tEplNmtMnuNodeInfo* pNodeInfo_p); + +static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p, tEplNmtMnuNodeInfo* pNodeInfo_p); + +static tEplKernel EplNmtMnuStartNodes(void); + +static tEplKernel EplNmtMnuProcessInternalEvent( + unsigned int uiNodeId_p, + tEplNmtState NodeNmtState_p, + WORD wErrorCode_p, + tEplNmtMnuIntNodeEvent NodeEvent_p); + +static tEplKernel EplNmtMnuReset(void); + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuInit +// +// Description: init first instance of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p, + tEplNmtMnuCbBootEvent pfnCbBootEvent_p) +{ +tEplKernel Ret; + + Ret = EplNmtMnuAddInstance(pfnCbNodeEvent_p, pfnCbBootEvent_p); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuAddInstance +// +// Description: init other instances of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p, + tEplNmtMnuCbBootEvent pfnCbBootEvent_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // reset instance structure + EPL_MEMSET(&EplNmtMnuInstance_g, 0, sizeof (EplNmtMnuInstance_g)); + + if ((pfnCbNodeEvent_p == NULL) || (pfnCbBootEvent_p == NULL)) + { + Ret = kEplNmtInvalidParam; + goto Exit; + } + EplNmtMnuInstance_g.m_pfnCbNodeEvent = pfnCbNodeEvent_p; + EplNmtMnuInstance_g.m_pfnCbBootEvent = pfnCbBootEvent_p; + + // initialize StatusRequest delay + EplNmtMnuInstance_g.m_ulStatusRequestDelay = 5000L; + + // register NmtMnResponse callback function + Ret = EplDlluCalRegAsndService(kEplDllAsndNmtRequest, EplNmtMnuCbNmtRequest, kEplDllAsndFilterLocal); + +Exit: + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuDelInstance +// +// Description: delete instance +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplNmtMnuDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // deregister NmtMnResponse callback function + Ret = EplDlluCalRegAsndService(kEplDllAsndNmtRequest, NULL, kEplDllAsndFilterNone); + + Ret = EplNmtMnuReset(); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuSendNmtCommandEx +// +// Description: sends the specified NMT command to the specified node. +// +// Parameters: uiNodeId_p = node ID to which the NMT command will be sent +// NmtCommand_p = NMT command +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplNmtMnuSendNmtCommandEx(unsigned int uiNodeId_p, + tEplNmtCommand NmtCommand_p, + void* pNmtCommandData_p, + unsigned int uiDataSize_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplFrameInfo FrameInfo; +BYTE abBuffer[EPL_C_DLL_MINSIZE_NMTCMDEXT]; +tEplFrame* pFrame = (tEplFrame*) abBuffer; +BOOL fSoftDeleteNode = FALSE; + + if ((uiNodeId_p == 0) || (uiNodeId_p > EPL_C_ADR_BROADCAST)) + { // invalid node ID specified + Ret = kEplInvalidNodeId; + goto Exit; + } + + if ((pNmtCommandData_p != NULL) && (uiDataSize_p > (EPL_C_DLL_MINSIZE_NMTCMDEXT - EPL_C_DLL_MINSIZE_NMTCMD))) + { + Ret = kEplNmtInvalidParam; + goto Exit; + } + + // $$$ d.k. may be check in future versions if the caller wants to perform prohibited state transitions + // the CN should not perform these transitions, but the expected NMT state will be changed and never fullfilled. + + // build frame + EPL_MEMSET(pFrame, 0x00, sizeof(abBuffer)); + AmiSetByteToLe(&pFrame->m_le_bDstNodeId, (BYTE) uiNodeId_p); + AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId, (BYTE) kEplDllAsndNmtCommand); + AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_bNmtCommandId, + (BYTE)NmtCommand_p); + if ((pNmtCommandData_p != NULL) && (uiDataSize_p > 0)) + { // copy command data to frame + EPL_MEMCPY(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_abNmtCommandData[0], pNmtCommandData_p, uiDataSize_p); + } + + // build info structure + FrameInfo.m_NetTime.m_dwNanoSec = 0; + FrameInfo.m_NetTime.m_dwSec = 0; + FrameInfo.m_pFrame = pFrame; + FrameInfo.m_uiFrameSize = sizeof(abBuffer); + + // send NMT-Request +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + Ret = EplDlluCalAsyncSend(&FrameInfo, // pointer to frameinfo + kEplDllAsyncReqPrioNmt); // priority +#endif + if (Ret != kEplSuccessful) + { + goto Exit; + } + + EPL_DBGLVL_NMTMN_TRACE2("NMTCmd(%02X->%02X)\n", NmtCommand_p, uiNodeId_p); + + switch (NmtCommand_p) + { + case kEplNmtCmdStartNode: + case kEplNmtCmdEnterPreOperational2: + case kEplNmtCmdEnableReadyToOperate: + { + // nothing left to do, + // because any further processing is done + // when the NMT command is actually sent + goto Exit; + } + + case kEplNmtCmdStopNode: + { + fSoftDeleteNode = TRUE; + break; + } + + case kEplNmtCmdResetNode: + case kEplNmtCmdResetCommunication: + case kEplNmtCmdResetConfiguration: + case kEplNmtCmdSwReset: + { + break; + } + + default: + goto Exit; + } + + // remove CN from isochronous phase; + // This must be done here and not when NMT command is actually sent + // because it will be too late and may cause unwanted errors + if (uiNodeId_p != EPL_C_ADR_BROADCAST) + { + if (fSoftDeleteNode == FALSE) + { // remove CN immediately from isochronous phase + Ret = EplDlluCalDeleteNode(uiNodeId_p); + } + else + { // remove CN from isochronous phase softly + Ret = EplDlluCalSoftDeleteNode(uiNodeId_p); + } + } + else + { // do it for all active CNs + for (uiNodeId_p = 1; uiNodeId_p <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiNodeId_p++) + { + if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId_p)->m_dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS)) != 0) + { + if (fSoftDeleteNode == FALSE) + { // remove CN immediately from isochronous phase + Ret = EplDlluCalDeleteNode(uiNodeId_p); + } + else + { // remove CN from isochronous phase softly + Ret = EplDlluCalSoftDeleteNode(uiNodeId_p); + } + } + } + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuSendNmtCommand +// +// Description: sends the specified NMT command to the specified node. +// +// Parameters: uiNodeId_p = node ID to which the NMT command will be sent +// NmtCommand_p = NMT command +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p, + tEplNmtCommand NmtCommand_p) +{ +tEplKernel Ret = kEplSuccessful; + + Ret = EplNmtMnuSendNmtCommandEx(uiNodeId_p, NmtCommand_p, NULL, 0); + +//Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuTriggerStateChange +// +// Description: triggers the specified node command for the specified node. +// +// Parameters: uiNodeId_p = node ID for which the node command will be executed +// NodeCommand_p = node command +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p, + tEplNmtNodeCommand NodeCommand_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplNmtMnuIntNodeEvent NodeEvent; +tEplObdSize ObdSize; +BYTE bNmtState; +WORD wErrorCode = EPL_E_NO_ERROR; + + if ((uiNodeId_p == 0) || (uiNodeId_p >= EPL_C_ADR_BROADCAST)) + { + Ret = kEplInvalidNodeId; + goto Exit; + } + + switch (NodeCommand_p) + { + case kEplNmtNodeCommandBoot: + { + NodeEvent = kEplNmtMnuIntNodeEventBoot; + break; + } + + case kEplNmtNodeCommandConfOk: + { + NodeEvent = kEplNmtMnuIntNodeEventConfigured; + break; + } + + case kEplNmtNodeCommandConfErr: + { + NodeEvent = kEplNmtMnuIntNodeEventError; + wErrorCode = EPL_E_NMT_BPO1_CF_VERIFY; + break; + } + + case kEplNmtNodeCommandConfReset: + { + NodeEvent = kEplNmtMnuIntNodeEventExecReset; + break; + } + + default: + { // invalid node command + goto Exit; + } + } + + // fetch current NMT state + ObdSize = 1; + Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtState, &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, + (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS), + wErrorCode, + NodeEvent); + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuCbNmtStateChange +// +// Description: callback function for NMT state changes +// +// Parameters: NmtStateChange_p = NMT state change event +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p) +{ +tEplKernel Ret = kEplSuccessful; + + // do work which must be done in that state + switch (NmtStateChange_p.m_NewNmtState) + { + // EPL stack is not running +/* case kEplNmtGsOff: + break; + + // first init of the hardware + case kEplNmtGsInitialising: + break; + + // init of the manufacturer-specific profile area and the + // standardised device profile area + case kEplNmtGsResetApplication: + { + break; + } + + // init of the communication profile area + case kEplNmtGsResetCommunication: + { + break; + } +*/ + // build the configuration with infos from OD + case kEplNmtGsResetConfiguration: + { + DWORD dwTimeout; + tEplObdSize ObdSize; + + // read object 0x1F80 NMT_StartUp_U32 + ObdSize = 4; + Ret = EplObduReadEntry(0x1F80, 0, &EplNmtMnuInstance_g.m_dwNmtStartup, &ObdSize); + if (Ret != kEplSuccessful) + { + break; + } + + // compute StatusReqDelay = object 0x1006 * EPL_C_NMT_STATREQ_CYCLE + ObdSize = sizeof (dwTimeout); + Ret = EplObduReadEntry(0x1006, 0, &dwTimeout, &ObdSize); + if (Ret != kEplSuccessful) + { + break; + } + if (dwTimeout != 0L) + { + EplNmtMnuInstance_g.m_ulStatusRequestDelay = dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L; + if (EplNmtMnuInstance_g.m_ulStatusRequestDelay == 0L) + { + EplNmtMnuInstance_g.m_ulStatusRequestDelay = 1L; // at least 1 ms + } + + // $$$ fetch and use MultiplexedCycleCount from OD + EplNmtMnuInstance_g.m_ulTimeoutCheckCom = dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L; + if (EplNmtMnuInstance_g.m_ulTimeoutCheckCom == 0L) + { + EplNmtMnuInstance_g.m_ulTimeoutCheckCom = 1L; // at least 1 ms + } + } + + // fetch ReadyToOp Timeout from OD + ObdSize = sizeof (dwTimeout); + Ret = EplObduReadEntry(0x1F89, 5, &dwTimeout, &ObdSize); + if (Ret != kEplSuccessful) + { + break; + } + if (dwTimeout != 0L) + { + // convert [us] to [ms] + dwTimeout /= 1000L; + if (dwTimeout == 0L) + { + dwTimeout = 1L; // at least 1 ms + } + EplNmtMnuInstance_g.m_ulTimeoutReadyToOp = dwTimeout; + } + else + { + EplNmtMnuInstance_g.m_ulTimeoutReadyToOp = 0L; + } + break; + } +/* + //----------------------------------------------------------- + // CN part of the state machine + + // node liste for EPL-Frames and check timeout + case kEplNmtCsNotActive: + { + break; + } + + // node process only async frames + case kEplNmtCsPreOperational1: + { + break; + } + + // node process isochronus and asynchronus frames + case kEplNmtCsPreOperational2: + { + break; + } + + // node should be configured und application is ready + case kEplNmtCsReadyToOperate: + { + break; + } + + // normal work state + case kEplNmtCsOperational: + { + break; + } + + // node stopped by MN + // -> only process asynchronus frames + case kEplNmtCsStopped: + { + break; + } + + // no EPL cycle + // -> normal ethernet communication + case kEplNmtCsBasicEthernet: + { + break; + } +*/ + //----------------------------------------------------------- + // MN part of the state machine + + // node listens for EPL-Frames and check timeout + case kEplNmtMsNotActive: + { + break; + } + + // node processes only async frames + case kEplNmtMsPreOperational1: + { + DWORD dwTimeout; + tEplTimerArg TimerArg; + tEplObdSize ObdSize; + tEplEvent Event; + + // clear global flags, e.g. reenable boot process + EplNmtMnuInstance_g.m_wFlags = 0; + + // reset IdentResponses and running IdentRequests and StatusRequests + Ret = EplIdentuReset(); + Ret = EplStatusuReset(); + + // reset timers + Ret = EplNmtMnuReset(); + + // 2008/11/18 d.k. reset internal node info is not necessary, + // because timer flags are important and other + // things are reset by EplNmtMnuStartBootStep1(). +/* + EPL_MEMSET(EplNmtMnuInstance_g.m_aNodeInfo, + 0, + sizeof (EplNmtMnuInstance_g.m_aNodeInfo)); +*/ + + // inform DLL about NMT state change, + // so that it can clear the asynchonous queues and start the reduced cycle + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkStartReducedCycle; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = NULL; + Event.m_uiSize = 0; + Ret = EplEventuPost(&Event); + if (Ret != kEplSuccessful) + { + break; + } + + // reset all nodes + // d.k.: skip this step if was just done before, e.g. because of a ResetNode command from a diagnostic node + if (NmtStateChange_p.m_NmtEvent == kEplNmtEventTimerMsPreOp1) + { + BENCHMARK_MOD_07_TOGGLE(9); + + EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, + EPL_C_ADR_BROADCAST, + kEplNmtCmdResetNode); + + Ret = EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST, kEplNmtCmdResetNode); + if (Ret != kEplSuccessful) + { + break; + } + } + // start network scan + Ret = EplNmtMnuStartBootStep1(); + + // start timer for 0x1F89/2 MNTimeoutPreOp1_U32 + ObdSize = sizeof (dwTimeout); + Ret = EplObduReadEntry(0x1F89, 2, &dwTimeout, &ObdSize); + if (Ret != kEplSuccessful) + { + break; + } + if (dwTimeout != 0L) + { + dwTimeout /= 1000L; + if (dwTimeout == 0L) + { + dwTimeout = 1L; // at least 1 ms + } + TimerArg.m_EventSink = kEplEventSinkNmtMnu; + TimerArg.m_ulArg = 0; + Ret = EplTimeruModifyTimerMs(&EplNmtMnuInstance_g.m_TimerHdlNmtState, dwTimeout, TimerArg); + } + break; + } + + // node processes isochronous and asynchronous frames + case kEplNmtMsPreOperational2: + { + // add identified CNs to isochronous phase + // send EnableReadyToOp to all identified CNs + Ret = EplNmtMnuStartBootStep2(); + + // wait for NMT state change of CNs + break; + } + + // node should be configured und application is ready + case kEplNmtMsReadyToOperate: + { + // check if PRes of CNs are OK + // d.k. that means wait CycleLength * MultiplexCycleCount (i.e. start timer) + // because Dllk checks PRes of CNs automatically in ReadyToOp + Ret = EplNmtMnuStartCheckCom(); + break; + } + + // normal work state + case kEplNmtMsOperational: + { + // send StartNode to CNs + // wait for NMT state change of CNs + Ret = EplNmtMnuStartNodes(); + break; + } + + // no EPL cycle + // -> normal ethernet communication + case kEplNmtMsBasicEthernet: + { + break; + } + + default: + { +// TRACE0("EplNmtMnuCbNmtStateChange(): unhandled NMT state\n"); + } + } + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuCbCheckEvent +// +// Description: callback funktion for NMT events before they are actually executed. +// The EPL API layer must forward NMT events from NmtCnu module. +// This module will reject some NMT commands while MN. +// +// Parameters: NmtEvent_p = outstanding NMT event for approval +// +// Returns: tEplKernel = error code +// kEplReject = reject the NMT event +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p) +{ +tEplKernel Ret = kEplSuccessful; + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtuProcessEvent +// +// Description: processes events from event queue +// +// Parameters: pEvent_p = pointer to event +// +// Returns: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent( + tEplEvent* pEvent_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // process event + switch(pEvent_p->m_EventType) + { + // timer event + case kEplEventTypeTimer: + { + tEplTimerEventArg* pTimerEventArg = (tEplTimerEventArg*)pEvent_p->m_pArg; + unsigned int uiNodeId; + + uiNodeId = (unsigned int) (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_NODE_MASK); + if (uiNodeId != 0) + { + tEplObdSize ObdSize; + BYTE bNmtState; + tEplNmtMnuNodeInfo* pNodeInfo; + + pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId); + + ObdSize = 1; + Ret = EplObduReadEntry(0x1F8E, uiNodeId, &bNmtState, &ObdSize); + if (Ret != kEplSuccessful) + { + break; + } + + if ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_IDENTREQ) != 0L) + { + if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) + != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) + { // this is an old (already deleted or modified) timer + // but not the current timer + // so discard it + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerIdentReq, + uiNodeId, + ((pNodeInfo->m_NodeState << 8) + | 0xFF)); + + break; + } +/* + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerIdentReq, + uiNodeId, + ((pNodeInfo->m_NodeState << 8) + | 0x80 + | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6) + | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8))); +*/ + Ret = EplNmtMnuProcessInternalEvent(uiNodeId, + (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS), + EPL_E_NO_ERROR, + kEplNmtMnuIntNodeEventTimerIdentReq); + } + + else if ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_STATREQ) != 0L) + { + if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) + != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) + { // this is an old (already deleted or modified) timer + // but not the current timer + // so discard it + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq, + uiNodeId, + ((pNodeInfo->m_NodeState << 8) + | 0xFF)); + + break; + } +/* + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq, + uiNodeId, + ((pNodeInfo->m_NodeState << 8) + | 0x80 + | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6) + | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8))); +*/ + Ret = EplNmtMnuProcessInternalEvent(uiNodeId, + (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS), + EPL_E_NO_ERROR, + kEplNmtMnuIntNodeEventTimerStatReq); + } + + else if ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_STATE_MON) != 0L) + { + if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) + != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) + { // this is an old (already deleted or modified) timer + // but not the current timer + // so discard it + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStateMon, + uiNodeId, + ((pNodeInfo->m_NodeState << 8) + | 0xFF)); + + break; + } +/* + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq, + uiNodeId, + ((pNodeInfo->m_NodeState << 8) + | 0x80 + | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6) + | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8))); +*/ + Ret = EplNmtMnuProcessInternalEvent(uiNodeId, + (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS), + EPL_E_NO_ERROR, + kEplNmtMnuIntNodeEventTimerStateMon); + } + + else if ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_LONGER) != 0L) + { + if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) + != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO)) + { // this is an old (already deleted or modified) timer + // but not the current timer + // so discard it + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerLonger, + uiNodeId, + ((pNodeInfo->m_NodeState << 8) + | 0xFF)); + + break; + } +/* + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerLonger, + uiNodeId, + ((pNodeInfo->m_NodeState << 8) + | 0x80 + | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) >> 6) + | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO) >> 8))); +*/ + Ret = EplNmtMnuProcessInternalEvent(uiNodeId, + (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS), + EPL_E_NO_ERROR, + kEplNmtMnuIntNodeEventTimerLonger); + } + + } + else + { // global timer event + } + break; + } + + case kEplEventTypeHeartbeat: + { + tEplHeartbeatEvent* pHeartbeatEvent = (tEplHeartbeatEvent*)pEvent_p->m_pArg; + + Ret = EplNmtMnuProcessInternalEvent(pHeartbeatEvent->m_uiNodeId, + pHeartbeatEvent->m_NmtState, + pHeartbeatEvent->m_wErrorCode, + kEplNmtMnuIntNodeEventHeartbeat); + break; + } + + case kEplEventTypeNmtMnuNmtCmdSent: + { + tEplFrame* pFrame = (tEplFrame*)pEvent_p->m_pArg; + unsigned int uiNodeId; + tEplNmtCommand NmtCommand; + BYTE bNmtState; + + uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId); + NmtCommand = (tEplNmtCommand) AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.m_le_bNmtCommandId); + + switch (NmtCommand) + { + case kEplNmtCmdStartNode: + bNmtState = (BYTE) (kEplNmtCsOperational & 0xFF); + break; + + case kEplNmtCmdStopNode: + bNmtState = (BYTE) (kEplNmtCsStopped & 0xFF); + break; + + case kEplNmtCmdEnterPreOperational2: + bNmtState = (BYTE) (kEplNmtCsPreOperational2 & 0xFF); + break; + + case kEplNmtCmdEnableReadyToOperate: + // d.k. do not change expected node state, because of DS 1.0.0 7.3.1.2.1 Plain NMT State Command + // and because node may not change NMT state within EPL_C_NMT_STATE_TOLERANCE + bNmtState = (BYTE) (kEplNmtCsPreOperational2 & 0xFF); + break; + + case kEplNmtCmdResetNode: + case kEplNmtCmdResetCommunication: + case kEplNmtCmdResetConfiguration: + case kEplNmtCmdSwReset: + bNmtState = (BYTE) (kEplNmtCsNotActive & 0xFF); + // EplNmtMnuProcessInternalEvent() sets internal node state to kEplNmtMnuNodeStateUnknown + // after next unresponded IdentRequest/StatusRequest + break; + + default: + goto Exit; + } + + // process as internal event which update expected NMT state in OD + if (uiNodeId != EPL_C_ADR_BROADCAST) + { + Ret = EplNmtMnuProcessInternalEvent(uiNodeId, + (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS), + 0, + kEplNmtMnuIntNodeEventNmtCmdSent); + + } + else + { // process internal event for all active nodes (except myself) + + for (uiNodeId = 1; uiNodeId <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiNodeId++) + { + if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId)->m_dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS)) != 0) + { + Ret = EplNmtMnuProcessInternalEvent(uiNodeId, + (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS), + 0, + kEplNmtMnuIntNodeEventNmtCmdSent); + + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + } + } + + break; + } + + default: + { + Ret = kEplNmtInvalidEvent; + } + + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuGetRunningTimerStatReq +// +// Description: returns a bit field with running StatReq timers +// just for debugging purposes +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplNmtMnuGetDiagnosticInfo(unsigned int* puiMandatorySlaveCount_p, + unsigned int* puiSignalSlaveCount_p, + WORD* pwFlags_p) +{ +tEplKernel Ret = kEplSuccessful; + + if ((puiMandatorySlaveCount_p == NULL) + || (puiSignalSlaveCount_p == NULL) + || (pwFlags_p == NULL)) + { + Ret = kEplNmtInvalidParam; + goto Exit; + } + + *puiMandatorySlaveCount_p = EplNmtMnuInstance_g.m_uiMandatorySlaveCount; + *puiSignalSlaveCount_p = EplNmtMnuInstance_g.m_uiSignalSlaveCount; + *pwFlags_p = EplNmtMnuInstance_g.m_wFlags; + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuGetRunningTimerStatReq +// +// Description: returns a bit field with running StatReq timers +// just for debugging purposes +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- +/* +DWORD EplNmtMnuGetRunningTimerStatReq(void) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiIndex; +tEplNmtMnuNodeInfo* pNodeInfo; + + pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo; + for (uiIndex = 1; uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiIndex++, pNodeInfo++) + { + if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateConfigured) + { + // reset flag "scanned once" + pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_SCANNED; + + Ret = EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo); + if (Ret != kEplSuccessful) + { + goto Exit; + } + EplNmtMnuInstance_g.m_uiSignalSlaveCount++; + // signal slave counter shall be decremented if StatusRequest was sent once to a CN + // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp + } + } + +Exit: + return Ret; +} +*/ + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuCbNmtRequest +// +// Description: callback funktion for NmtRequest +// +// Parameters: pFrameInfo_p = Frame with the NmtRequest +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; + + // $$$ perform NMTRequest + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuCbIdentResponse +// +// Description: callback funktion for IdentResponse +// +// Parameters: uiNodeId_p = node ID for which IdentReponse was received +// pIdentResponse_p = pointer to IdentResponse +// is NULL if node did not answer +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplNmtMnuCbIdentResponse( + unsigned int uiNodeId_p, + tEplIdentResponse* pIdentResponse_p) +{ +tEplKernel Ret = kEplSuccessful; + + if (pIdentResponse_p == NULL) + { // node did not answer + Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, + kEplNmtCsNotActive, + EPL_E_NMT_NO_IDENT_RES, // was EPL_E_NO_ERROR + kEplNmtMnuIntNodeEventNoIdentResponse); + } + else + { // node answered IdentRequest + tEplObdSize ObdSize; + DWORD dwDevType; + WORD wErrorCode = EPL_E_NO_ERROR; + tEplNmtState NmtState = (tEplNmtState) (AmiGetByteFromLe(&pIdentResponse_p->m_le_bNmtStatus) | EPL_NMT_TYPE_CS); + + // check IdentResponse $$$ move to ProcessIntern, because this function may be called also if CN + + // check DeviceType (0x1F84) + ObdSize = 4; + Ret = EplObduReadEntry(0x1F84, uiNodeId_p, &dwDevType, &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + if (dwDevType != 0L) + { // actually compare it with DeviceType from IdentResponse + if (AmiGetDwordFromLe(&pIdentResponse_p->m_le_dwDeviceType) != dwDevType) + { // wrong DeviceType + NmtState = kEplNmtCsNotActive; + wErrorCode = EPL_E_NMT_BPO1_DEVICE_TYPE; + } + } + + Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, + NmtState, + wErrorCode, + kEplNmtMnuIntNodeEventIdentResponse); + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuCbStatusResponse +// +// Description: callback funktion for StatusResponse +// +// Parameters: uiNodeId_p = node ID for which IdentReponse was received +// pIdentResponse_p = pointer to IdentResponse +// is NULL if node did not answer +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplNmtMnuCbStatusResponse( + unsigned int uiNodeId_p, + tEplStatusResponse* pStatusResponse_p) +{ +tEplKernel Ret = kEplSuccessful; + + if (pStatusResponse_p == NULL) + { // node did not answer + Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, + kEplNmtCsNotActive, + EPL_E_NMT_NO_STATUS_RES, // was EPL_E_NO_ERROR + kEplNmtMnuIntNodeEventNoStatusResponse); + } + else + { // node answered StatusRequest + Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, + (tEplNmtState) (AmiGetByteFromLe(&pStatusResponse_p->m_le_bNmtStatus) | EPL_NMT_TYPE_CS), + EPL_E_NO_ERROR, + kEplNmtMnuIntNodeEventStatusResponse); + } + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuStartBootStep1 +// +// Description: starts BootStep1 +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplNmtMnuStartBootStep1(void) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiSubIndex; +unsigned int uiLocalNodeId; +DWORD dwNodeCfg; +tEplObdSize ObdSize; + + // $$$ d.k.: save current time for 0x1F89/2 MNTimeoutPreOp1_U32 + + // start network scan + EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0; + EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0; + // check 0x1F81 + uiLocalNodeId = EplObduGetNodeId(); + for (uiSubIndex = 1; uiSubIndex <= 254; uiSubIndex++) + { + ObdSize = 4; + Ret = EplObduReadEntry(0x1F81, uiSubIndex, &dwNodeCfg, &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + if (uiSubIndex != uiLocalNodeId) + { + // reset flags "not scanned" and "isochronous" + EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags &= ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON | EPL_NMTMNU_NODE_FLAG_NOT_SCANNED); + + if (uiSubIndex == EPL_C_ADR_DIAG_DEF_NODE_ID) + { // diagnostic node must be scanned by MN in any case + dwNodeCfg |= (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS); + // and it must be isochronously accessed + dwNodeCfg &= ~EPL_NODEASSIGN_ASYNCONLY_NODE; + } + + // save node config in local node info structure + EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_dwNodeCfg = dwNodeCfg; + EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_NodeState = kEplNmtMnuNodeStateUnknown; + + if ((dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS)) != 0) + { // node is configured as CN + // identify the node + Ret = EplIdentuRequestIdentResponse(uiSubIndex, EplNmtMnuCbIdentResponse); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // set flag "not scanned" + EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags |= EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + EplNmtMnuInstance_g.m_uiSignalSlaveCount++; + // signal slave counter shall be decremented if IdentRequest was sent once to a CN + + if ((dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) + { // node is a mandatory CN + EplNmtMnuInstance_g.m_uiMandatorySlaveCount++; + // mandatory slave counter shall be decremented if mandatory CN was configured successfully + } + } + } + else + { // subindex of MN + if ((dwNodeCfg & (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS)) != 0) + { // MN shall send PRes + tEplDllNodeInfo DllNodeInfo; + + EPL_MEMSET(&DllNodeInfo, 0, sizeof (DllNodeInfo)); + DllNodeInfo.m_uiNodeId = uiLocalNodeId; + + Ret = EplDlluCalAddNode(&DllNodeInfo); + } + } + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuStartBootStep2 +// +// Description: starts BootStep2. +// That means add nodes to isochronous phase and send +// NMT EnableReadyToOp. +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplNmtMnuStartBootStep2(void) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiIndex; +tEplNmtMnuNodeInfo* pNodeInfo; + + + if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) + { // boot process is not halted + // add nodes to isochronous phase and send NMT EnableReadyToOp + EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0; + EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0; + // reset flag that application was informed about possible state change + EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED; + + pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo; + for (uiIndex = 1; uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiIndex++, pNodeInfo++) + { + if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateConfigured) + { + Ret = EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // set flag "not scanned" + pNodeInfo->m_wFlags |= EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + + EplNmtMnuInstance_g.m_uiSignalSlaveCount++; + // signal slave counter shall be decremented if StatusRequest was sent once to a CN + + if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) + { // node is a mandatory CN + EplNmtMnuInstance_g.m_uiMandatorySlaveCount++; + } + + // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp + } + } + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuNodeBootStep2 +// +// Description: starts BootStep2 for the specified node. +// This means the CN is added to isochronous phase if not +// async-only and it gets the NMT command EnableReadyToOp. +// The CN must be in node state Configured, when it enters +// BootStep2. When BootStep2 finishes, the CN is in node state +// ReadyToOp. +// If TimeoutReadyToOp in object 0x1F89/5 is configured, +// TimerHdlLonger will be started with this timeout. +// +// Parameters: uiNodeId_p = node ID +// pNodeInfo_p = pointer to internal node info structure +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p, tEplNmtMnuNodeInfo* pNodeInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplDllNodeInfo DllNodeInfo; +DWORD dwNodeCfg; +tEplObdSize ObdSize; +tEplTimerArg TimerArg; + + dwNodeCfg = pNodeInfo_p->m_dwNodeCfg; + if ((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0) + { // add node to isochronous phase + DllNodeInfo.m_uiNodeId = uiNodeId_p; + ObdSize = 4; + Ret = EplObduReadEntry(0x1F92, uiNodeId_p, &DllNodeInfo.m_dwPresTimeout, &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + ObdSize = 2; + Ret = EplObduReadEntry(0x1F8B, uiNodeId_p, &DllNodeInfo.m_wPreqPayloadLimit, &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + ObdSize = 2; + Ret = EplObduReadEntry(0x1F8D, uiNodeId_p, &DllNodeInfo.m_wPresPayloadLimit, &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + pNodeInfo_p->m_wFlags |= EPL_NMTMNU_NODE_FLAG_ISOCHRON; + + Ret = EplDlluCalAddNode(&DllNodeInfo); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + } + + EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, + uiNodeId_p, + kEplNmtCmdEnableReadyToOperate); + + Ret = EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdEnableReadyToOperate); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + if (EplNmtMnuInstance_g.m_ulTimeoutReadyToOp != 0L) + { // start timer + // when the timer expires the CN must be ReadyToOp + EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER( + pNodeInfo_p, uiNodeId_p, TimerArg); +// TimerArg.m_EventSink = kEplEventSinkNmtMnu; +// TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p; + Ret = EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger, EplNmtMnuInstance_g.m_ulTimeoutReadyToOp, TimerArg); + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuStartCheckCom +// +// Description: starts CheckCommunication +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplNmtMnuStartCheckCom(void) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiIndex; +tEplNmtMnuNodeInfo* pNodeInfo; + + + if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) + { // boot process is not halted + // wait some time and check that no communication error occurs + EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0; + EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0; + // reset flag that application was informed about possible state change + EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED; + + pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo; + for (uiIndex = 1; uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiIndex++, pNodeInfo++) + { + if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateReadyToOp) + { + Ret = EplNmtMnuNodeCheckCom(uiIndex, pNodeInfo); + if (Ret == kEplReject) + { // timer was started + // wait until it expires + if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) + { // node is a mandatory CN + EplNmtMnuInstance_g.m_uiMandatorySlaveCount++; + } + } + else if (Ret != kEplSuccessful) + { + goto Exit; + } + + // set flag "not scanned" + pNodeInfo->m_wFlags |= EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + + EplNmtMnuInstance_g.m_uiSignalSlaveCount++; + // signal slave counter shall be decremented if timeout elapsed and regardless of an error + // mandatory slave counter shall be decremented if timeout elapsed and no error occured + } + } + } + + Ret = kEplSuccessful; + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuNodeCheckCom +// +// Description: checks communication of the specified node. +// That means wait some time and if no error occured everything +// is OK. +// +// Parameters: uiNodeId_p = node ID +// pNodeInfo_p = pointer to internal node info structure +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p, tEplNmtMnuNodeInfo* pNodeInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +DWORD dwNodeCfg; +tEplTimerArg TimerArg; + + dwNodeCfg = pNodeInfo_p->m_dwNodeCfg; + if (((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0) + && (EplNmtMnuInstance_g.m_ulTimeoutCheckCom != 0L)) + { // CN is not async-only and timeout for CheckCom was set + + // check communication, + // that means wait some time and if no error occured everything is OK; + + // start timer (when the timer expires the CN must be still ReadyToOp) + EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER( + pNodeInfo_p, uiNodeId_p, TimerArg); +// TimerArg.m_EventSink = kEplEventSinkNmtMnu; +// TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p; + Ret = EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger, EplNmtMnuInstance_g.m_ulTimeoutCheckCom, TimerArg); + + // update mandatory slave counter, because timer was started + if (Ret == kEplSuccessful) + { + Ret = kEplReject; + } + } + else + { // timer was not started + // assume everything is OK + pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateComChecked; + } + +//Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuStartNodes +// +// Description: really starts all nodes which are ReadyToOp and CheckCom did not fail +// +// Parameters: (none) +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplNmtMnuStartNodes(void) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiIndex; +tEplNmtMnuNodeInfo* pNodeInfo; + + + if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) + { // boot process is not halted + // send NMT command Start Node + EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0; + EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0; + // reset flag that application was informed about possible state change + EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED; + + pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo; + for (uiIndex = 1; uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiIndex++, pNodeInfo++) + { + if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateComChecked) + { + if ((EplNmtMnuInstance_g.m_dwNmtStartup & EPL_NMTST_STARTALLNODES) == 0) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, + uiIndex, + kEplNmtCmdStartNode); + + Ret = EplNmtMnuSendNmtCommand(uiIndex, kEplNmtCmdStartNode); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + + if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) + { // node is a mandatory CN + EplNmtMnuInstance_g.m_uiMandatorySlaveCount++; + } + + // set flag "not scanned" + pNodeInfo->m_wFlags |= EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + + EplNmtMnuInstance_g.m_uiSignalSlaveCount++; + // signal slave counter shall be decremented if StatusRequest was sent once to a CN + // mandatory slave counter shall be decremented if mandatory CN is OPERATIONAL + } + } + + // $$$ inform application if EPL_NMTST_NO_STARTNODE is set + + if ((EplNmtMnuInstance_g.m_dwNmtStartup & EPL_NMTST_STARTALLNODES) != 0) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, + EPL_C_ADR_BROADCAST, + kEplNmtCmdStartNode); + + Ret = EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST, kEplNmtCmdStartNode); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuProcessInternalEvent +// +// Description: processes internal node events +// +// Parameters: uiNodeId_p = node ID +// NodeNmtState_p = NMT state of CN +// NodeEvent_p = occured events +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplNmtMnuProcessInternalEvent( + unsigned int uiNodeId_p, + tEplNmtState NodeNmtState_p, + WORD wErrorCode_p, + tEplNmtMnuIntNodeEvent NodeEvent_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplNmtState NmtState; +tEplNmtMnuNodeInfo* pNodeInfo; +tEplTimerArg TimerArg; + + pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId_p); + NmtState = EplNmtuGetNmtState(); + if (NmtState <= kEplNmtMsNotActive) + { // MN is not active + goto Exit; + } + + switch (NodeEvent_p) + { + case kEplNmtMnuIntNodeEventIdentResponse: + { + BYTE bNmtState; + + EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, + uiNodeId_p, + pNodeInfo->m_NodeState); + + if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) + { + pNodeInfo->m_NodeState = kEplNmtMnuNodeStateIdentified; + } + + // reset flags ISOCHRON and NMT_CMD_ISSUED + pNodeInfo->m_wFlags &= ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON + | EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED); + + if ((NmtState == kEplNmtMsPreOperational1) + && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0)) + { + // decrement only signal slave count + EplNmtMnuInstance_g.m_uiSignalSlaveCount--; + pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + } + + // update object 0x1F8F NMT_MNNodeExpState_AU8 to PreOp1 (even if local state >= PreOp2) + bNmtState = (BYTE) (kEplNmtCsPreOperational1 & 0xFF); + Ret = EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 1); + + // check NMT state of CN + Ret = EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo, NodeNmtState_p, wErrorCode_p, NmtState); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + Ret = kEplSuccessful; + } + break; + } + + // request StatusResponse immediately, + // because we want a fast boot-up of CNs + Ret = EplStatusuRequestStatusResponse(uiNodeId_p, EplNmtMnuCbStatusResponse); + if (Ret != kEplSuccessful) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, + uiNodeId_p, + Ret); + + if (Ret == kEplInvalidOperation) + { // the only situation when this should happen is, when + // StatusResponse was already requested from within + // the StatReq timer event. + // so ignore this error. + Ret = kEplSuccessful; + } + else + { + break; + } + } + + if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) + { + // inform application + Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p, + kEplNmtNodeEventFound, + NodeNmtState_p, + EPL_E_NO_ERROR, + (pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0); + if (Ret == kEplReject) + { // interrupt boot process on user request + EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, + uiNodeId_p, + ((pNodeInfo->m_NodeState << 8) + | Ret)); + + Ret = kEplSuccessful; + break; + } + else if (Ret != kEplSuccessful) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, + uiNodeId_p, + ((pNodeInfo->m_NodeState << 8) + | Ret)); + + break; + } + } + + // continue BootStep1 + } + + case kEplNmtMnuIntNodeEventBoot: + { + + // $$$ check identification (vendor ID, product code, revision no, serial no) + + if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateIdentified) + { + // $$$ check software + + // check/start configuration + // inform application + Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p, + kEplNmtNodeEventCheckConf, + NodeNmtState_p, + EPL_E_NO_ERROR, + (pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0); + if (Ret == kEplReject) + { // interrupt boot process on user request + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventBoot, + uiNodeId_p, + ((pNodeInfo->m_NodeState << 8) + | Ret)); + + Ret = kEplSuccessful; + break; + } + else if (Ret != kEplSuccessful) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventBoot, + uiNodeId_p, + ((pNodeInfo->m_NodeState << 8) + | Ret)); + + break; + } + } + else if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) + { // wrong CN state + // ignore event + break; + } + + // $$$ d.k.: currently we assume configuration is OK + + // continue BootStep1 + } + + case kEplNmtMnuIntNodeEventConfigured: + { + if ((pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) + && (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf)) + { // wrong CN state + // ignore event + break; + } + + pNodeInfo->m_NodeState = kEplNmtMnuNodeStateConfigured; + + if (NmtState == kEplNmtMsPreOperational1) + { + if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) + { // decrement mandatory CN counter + EplNmtMnuInstance_g.m_uiMandatorySlaveCount--; + } + } + else + { + // put optional node to next step (BootStep2) + Ret = EplNmtMnuNodeBootStep2(uiNodeId_p, pNodeInfo); + } + break; + } + + case kEplNmtMnuIntNodeEventNoIdentResponse: + { + if ((NmtState == kEplNmtMsPreOperational1) + && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0)) + { + // decrement only signal slave count + EplNmtMnuInstance_g.m_uiSignalSlaveCount--; + pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + } + + if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) + { + pNodeInfo->m_NodeState = kEplNmtMnuNodeStateUnknown; + } + + // $$$ d.k. check start time for 0x1F89/2 MNTimeoutPreOp1_U32 + // $$$ d.k. check individual timeout 0x1F89/6 MNIdentificationTimeout_U32 + // if mandatory node and timeout elapsed -> halt boot procedure + // trigger IdentRequest again (if >= PreOp2, after delay) + if (NmtState >= kEplNmtMsPreOperational2) + { // start timer + EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ( + pNodeInfo, uiNodeId_p, TimerArg); +// TimerArg.m_EventSink = kEplEventSinkNmtMnu; +// TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_IDENTREQ | uiNodeId_p; +/* + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventNoIdentResponse, + uiNodeId_p, + ((pNodeInfo->m_NodeState << 8) + | 0x80 + | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6) + | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8))); +*/ + Ret = EplTimeruModifyTimerMs(&pNodeInfo->m_TimerHdlStatReq, EplNmtMnuInstance_g.m_ulStatusRequestDelay, TimerArg); + } + else + { // trigger IdentRequest immediately + Ret = EplIdentuRequestIdentResponse(uiNodeId_p, EplNmtMnuCbIdentResponse); + } + break; + } + + case kEplNmtMnuIntNodeEventStatusResponse: + { + if ((NmtState >= kEplNmtMsPreOperational2) + && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0)) + { + // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational + EplNmtMnuInstance_g.m_uiSignalSlaveCount--; + pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + } + + // check NMT state of CN + Ret = EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo, NodeNmtState_p, wErrorCode_p, NmtState); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + Ret = kEplSuccessful; + } + break; + } + + if (NmtState == kEplNmtMsPreOperational1) + { + // request next StatusResponse immediately + Ret = EplStatusuRequestStatusResponse(uiNodeId_p, EplNmtMnuCbStatusResponse); + if (Ret != kEplSuccessful) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, + uiNodeId_p, + Ret); + } + + } + else if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_ISOCHRON) == 0) + { // start timer + // not isochronously accessed CN (e.g. async-only or stopped CN) + EPL_NMTMNU_SET_FLAGS_TIMERARG_STATREQ( + pNodeInfo, uiNodeId_p, TimerArg); +// TimerArg.m_EventSink = kEplEventSinkNmtMnu; +// TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p; +/* + EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventStatusResponse, + uiNodeId_p, + ((pNodeInfo->m_NodeState << 8) + | 0x80 + | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6) + | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8))); +*/ + Ret = EplTimeruModifyTimerMs(&pNodeInfo->m_TimerHdlStatReq, EplNmtMnuInstance_g.m_ulStatusRequestDelay, TimerArg); + } + + break; + } + + case kEplNmtMnuIntNodeEventNoStatusResponse: + { + // function CheckNmtState sets node state to unknown if necessary +/* + if ((NmtState >= kEplNmtMsPreOperational2) + && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0)) + { + // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational + EplNmtMnuInstance_g.m_uiSignalSlaveCount--; + pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + } +*/ + // check NMT state of CN + Ret = EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo, NodeNmtState_p, wErrorCode_p, NmtState); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + Ret = kEplSuccessful; + } + break; + } + + break; + } + + case kEplNmtMnuIntNodeEventError: + { // currently only issued on kEplNmtNodeCommandConfErr + + if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) + { // wrong CN state + // ignore event + break; + } + + // check NMT state of CN + Ret = EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo, kEplNmtCsNotActive, wErrorCode_p, NmtState); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + Ret = kEplSuccessful; + } + break; + } + + break; + } + + case kEplNmtMnuIntNodeEventExecReset: + { + if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) + { // wrong CN state + // ignore event + break; + } + + pNodeInfo->m_NodeState = kEplNmtMnuNodeStateResetConf; + + EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, + uiNodeId_p, + (((NodeNmtState_p & 0xFF) << 8) + | kEplNmtCmdResetConfiguration)); + + // send NMT reset configuration to CN for activation of configuration + Ret = EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdResetConfiguration); + + break; + } + + case kEplNmtMnuIntNodeEventHeartbeat: + { +/* + if ((NmtState >= kEplNmtMsPreOperational2) + && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0)) + { + // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational + EplNmtMnuInstance_g.m_uiSignalSlaveCount--; + pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + } +*/ + // check NMT state of CN + Ret = EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo, NodeNmtState_p, wErrorCode_p, NmtState); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + Ret = kEplSuccessful; + } + break; + } + + break; + } + + case kEplNmtMnuIntNodeEventTimerIdentReq: + { + EPL_DBGLVL_NMTMN_TRACE1("TimerStatReq->IdentReq(%02X)\n", uiNodeId_p); + // trigger IdentRequest again + Ret = EplIdentuRequestIdentResponse(uiNodeId_p, EplNmtMnuCbIdentResponse); + if (Ret != kEplSuccessful) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, + uiNodeId_p, + (((NodeNmtState_p & 0xFF) << 8) + | Ret)); + if (Ret == kEplInvalidOperation) + { // this can happen because of a bug in EplTimeruLinuxKernel.c + // so ignore this error. + Ret = kEplSuccessful; + } + } + + break; + } + + case kEplNmtMnuIntNodeEventTimerStateMon: + { + // reset NMT state change flag + // because from now on the CN must have the correct NMT state + pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED; + + // continue with normal StatReq processing + } + + case kEplNmtMnuIntNodeEventTimerStatReq: + { + EPL_DBGLVL_NMTMN_TRACE1("TimerStatReq->StatReq(%02X)\n", uiNodeId_p); + // request next StatusResponse + Ret = EplStatusuRequestStatusResponse(uiNodeId_p, EplNmtMnuCbStatusResponse); + if (Ret != kEplSuccessful) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, + uiNodeId_p, + (((NodeNmtState_p & 0xFF) << 8) + | Ret)); + if (Ret == kEplInvalidOperation) + { // the only situation when this should happen is, when + // StatusResponse was already requested while processing + // event IdentResponse. + // so ignore this error. + Ret = kEplSuccessful; + } + } + + break; + } + + case kEplNmtMnuIntNodeEventTimerLonger: + { + switch (pNodeInfo->m_NodeState) + { + case kEplNmtMnuNodeStateConfigured: + { // node should be ReadyToOp but it is not + + // check NMT state which shall be intentionally wrong, so that ERROR_TREATMENT will be started + Ret = EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo, kEplNmtCsNotActive, EPL_E_NMT_BPO2, NmtState); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + Ret = kEplSuccessful; + } + break; + } + + break; + } + + case kEplNmtMnuNodeStateReadyToOp: + { // CheckCom finished successfully + + pNodeInfo->m_NodeState = kEplNmtMnuNodeStateComChecked; + + if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0) + { + // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational + EplNmtMnuInstance_g.m_uiSignalSlaveCount--; + pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + } + + if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) + { + // decrement mandatory slave counter + EplNmtMnuInstance_g.m_uiMandatorySlaveCount--; + } + if (NmtState != kEplNmtMsReadyToOperate) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, + uiNodeId_p, + (((NodeNmtState_p & 0xFF) << 8) + | kEplNmtCmdStartNode)); + + // start optional CN + Ret = EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdStartNode); + } + break; + } + + default: + { + break; + } + } + break; + } + + case kEplNmtMnuIntNodeEventNmtCmdSent: + { + BYTE bNmtState; + + // update expected NMT state with the one that results + // from the sent NMT command + bNmtState = (BYTE) (NodeNmtState_p & 0xFF); + + // write object 0x1F8F NMT_MNNodeExpState_AU8 + Ret = EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 1); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + if (NodeNmtState_p == kEplNmtCsNotActive) + { // restart processing with IdentRequest + EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ( + pNodeInfo, uiNodeId_p, TimerArg); + } + else + { // monitor NMT state change with StatusRequest after + // the corresponding delay; + // until then wrong NMT states will be ignored + EPL_NMTMNU_SET_FLAGS_TIMERARG_STATE_MON( + pNodeInfo, uiNodeId_p, TimerArg); + + // set NMT state change flag + pNodeInfo->m_wFlags |= EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED; + } + + Ret = EplTimeruModifyTimerMs(&pNodeInfo->m_TimerHdlStatReq, EplNmtMnuInstance_g.m_ulStatusRequestDelay, TimerArg); + + // finish processing, because NmtState_p is the expected and not the current state + goto Exit; + } + + default: + { + break; + } + } + + // check if network is ready to change local NMT state and this was not done before + if ((EplNmtMnuInstance_g.m_wFlags & (EPL_NMTMNU_FLAG_HALTED | EPL_NMTMNU_FLAG_APP_INFORMED)) == 0) + { // boot process is not halted + switch (NmtState) + { + case kEplNmtMsPreOperational1: + { + if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount == 0) + && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) + { // all optional CNs scanned once and all mandatory CNs configured successfully + EplNmtMnuInstance_g.m_wFlags |= EPL_NMTMNU_FLAG_APP_INFORMED; + // inform application + Ret = EplNmtMnuInstance_g.m_pfnCbBootEvent(kEplNmtBootEventBootStep1Finish, + NmtState, + EPL_E_NO_ERROR); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + // wait for application + Ret = kEplSuccessful; + } + break; + } + // enter PreOp2 + Ret = EplNmtuNmtEvent(kEplNmtEventAllMandatoryCNIdent); + } + break; + } + + case kEplNmtMsPreOperational2: + { + if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount == 0) + && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) + { // all optional CNs checked once for ReadyToOp and all mandatory CNs are ReadyToOp + EplNmtMnuInstance_g.m_wFlags |= EPL_NMTMNU_FLAG_APP_INFORMED; + // inform application + Ret = EplNmtMnuInstance_g.m_pfnCbBootEvent(kEplNmtBootEventBootStep2Finish, + NmtState, + EPL_E_NO_ERROR); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + // wait for application + Ret = kEplSuccessful; + } + break; + } + // enter ReadyToOp + Ret = EplNmtuNmtEvent(kEplNmtEventEnterReadyToOperate); + } + break; + } + + case kEplNmtMsReadyToOperate: + { + if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount == 0) + && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) + { // all CNs checked for errorless communication + EplNmtMnuInstance_g.m_wFlags |= EPL_NMTMNU_FLAG_APP_INFORMED; + // inform application + Ret = EplNmtMnuInstance_g.m_pfnCbBootEvent(kEplNmtBootEventCheckComFinish, + NmtState, + EPL_E_NO_ERROR); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + // wait for application + Ret = kEplSuccessful; + } + break; + } + // enter Operational + Ret = EplNmtuNmtEvent(kEplNmtEventEnterMsOperational); + } + break; + } + + case kEplNmtMsOperational: + { + if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount == 0) + && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) + { // all optional CNs scanned once and all mandatory CNs are OPERATIONAL + EplNmtMnuInstance_g.m_wFlags |= EPL_NMTMNU_FLAG_APP_INFORMED; + // inform application + Ret = EplNmtMnuInstance_g.m_pfnCbBootEvent(kEplNmtBootEventOperational, + NmtState, + EPL_E_NO_ERROR); + if (Ret != kEplSuccessful) + { + if (Ret == kEplReject) + { + // ignore error code + Ret = kEplSuccessful; + } + break; + } + } + break; + } + + default: + { + break; + } + } + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuCheckNmtState +// +// Description: checks the NMT state, i.e. evaluates it with object 0x1F8F +// NMT_MNNodeExpState_AU8 and updates object 0x1F8E +// NMT_MNNodeCurrState_AU8. +// It manipulates m_NodeState in internal node info structure. +// +// Parameters: uiNodeId_p = node ID +// NodeNmtState_p = NMT state of CN +// +// Returns: tEplKernel = error code +// kEplReject = CN was in wrong state and has been reset +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplNmtMnuCheckNmtState( + unsigned int uiNodeId_p, + tEplNmtMnuNodeInfo* pNodeInfo_p, + tEplNmtState NodeNmtState_p, + WORD wErrorCode_p, + tEplNmtState LocalNmtState_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplObdSize ObdSize; +BYTE bNmtState; +BYTE bNmtStatePrev; +tEplNmtState ExpNmtState; + + ObdSize = 1; + // read object 0x1F8F NMT_MNNodeExpState_AU8 + Ret = EplObduReadEntry(0x1F8F, uiNodeId_p, &bNmtState, &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // compute expected NMT state + ExpNmtState = (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS); + // compute BYTE of current NMT state + bNmtState = ((BYTE) NodeNmtState_p & 0xFF); + + if (ExpNmtState == kEplNmtCsNotActive) + { // ignore the current state, because the CN shall be not active + Ret = kEplReject; + goto Exit; + } + else if ((ExpNmtState == kEplNmtCsPreOperational2) + && (NodeNmtState_p == kEplNmtCsReadyToOperate)) + { // CN switched to ReadyToOp + // delete timer for timeout handling + Ret = EplTimeruDeleteTimer(&pNodeInfo_p->m_TimerHdlLonger); + if (Ret != kEplSuccessful) + { + goto Exit; + } + pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateReadyToOp; + + // update object 0x1F8F NMT_MNNodeExpState_AU8 to ReadyToOp + Ret = EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 1); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) + { // node is a mandatory CN -> decrement counter + EplNmtMnuInstance_g.m_uiMandatorySlaveCount--; + } + if (LocalNmtState_p >= kEplNmtMsReadyToOperate) + { // start procedure CheckCommunication for this node + Ret = EplNmtMnuNodeCheckCom(uiNodeId_p, pNodeInfo_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + if ((LocalNmtState_p == kEplNmtMsOperational) + && (pNodeInfo_p->m_NodeState == kEplNmtMnuNodeStateComChecked)) + { + EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, + uiNodeId_p, + (((NodeNmtState_p & 0xFF) << 8) + | kEplNmtCmdStartNode)); + + // immediately start optional CN, because communication is always OK (e.g. async-only CN) + Ret = EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdStartNode); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + } + + } + else if ((ExpNmtState == kEplNmtCsReadyToOperate) + && (NodeNmtState_p == kEplNmtCsOperational)) + { // CN switched to OPERATIONAL + pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateOperational; + + if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) + { // node is a mandatory CN -> decrement counter + EplNmtMnuInstance_g.m_uiMandatorySlaveCount--; + } + + } + else if ((ExpNmtState != NodeNmtState_p) + && !((ExpNmtState == kEplNmtCsPreOperational1) + && (NodeNmtState_p == kEplNmtCsPreOperational2))) + { // CN is not in expected NMT state (without the exceptions above) + WORD wbeErrorCode; + + if ((pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0) + { + // decrement only signal slave count if checked once + EplNmtMnuInstance_g.m_uiSignalSlaveCount--; + pNodeInfo_p->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; + } + + if (pNodeInfo_p->m_NodeState == kEplNmtMnuNodeStateUnknown) + { // CN is already in state unknown, which means that it got + // NMT reset command earlier + goto Exit; + } + + // -> CN is in wrong NMT state + pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateUnknown; + + if (wErrorCode_p == 0) + { // assume wrong NMT state error + if ((pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED) != 0) + { // NMT command has been just issued; + // ignore wrong NMT state until timer expires; + // other errors like LOSS_PRES_TH are still processed + goto Exit; + } + + wErrorCode_p = EPL_E_NMT_WRONG_STATE; + } + + BENCHMARK_MOD_07_TOGGLE(9); + + // $$$ start ERROR_TREATMENT and inform application + Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p, + kEplNmtNodeEventError, + NodeNmtState_p, + wErrorCode_p, + (pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, + uiNodeId_p, + (((NodeNmtState_p & 0xFF) << 8) + | kEplNmtCmdResetNode)); + + // reset CN + // store error code in NMT command data for diagnostic purpose + AmiSetWordToLe(&wbeErrorCode, wErrorCode_p); + Ret = EplNmtMnuSendNmtCommandEx(uiNodeId_p, kEplNmtCmdResetNode, &wbeErrorCode, sizeof (wbeErrorCode)); + if (Ret == kEplSuccessful) + { + Ret = kEplReject; + } + + goto Exit; + } + + // check if NMT_MNNodeCurrState_AU8 has to be changed + ObdSize = 1; + Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtStatePrev, &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + if (bNmtState != bNmtStatePrev) + { + // update object 0x1F8E NMT_MNNodeCurrState_AU8 + Ret = EplObduWriteEntry(0x1F8E, uiNodeId_p, &bNmtState, 1); + if (Ret != kEplSuccessful) + { + goto Exit; + } + Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p, + kEplNmtNodeEventNmtState, + NodeNmtState_p, + wErrorCode_p, + (pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtMnuReset +// +// Description: reset internal structures, e.g. timers +// +// Parameters: void +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplNmtMnuReset(void) +{ +tEplKernel Ret; +int iIndex; + + Ret = EplTimeruDeleteTimer(&EplNmtMnuInstance_g.m_TimerHdlNmtState); + + for (iIndex = 1; iIndex <= tabentries (EplNmtMnuInstance_g.m_aNodeInfo); iIndex++) + { + // delete timer handles + Ret = EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->m_TimerHdlStatReq); + Ret = EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->m_TimerHdlLonger); + } + + return Ret; +} + + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplNmtk.c b/drivers/staging/epl/EplNmtk.c new file mode 100644 index 0000000..8bfa59a --- /dev/null +++ b/drivers/staging/epl/EplNmtk.c @@ -0,0 +1,1750 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for NMT-Kernelspace-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtk.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.12 $ $Date: 2008/11/13 17:13:09 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/09 k.t.: start of the implementation + +****************************************************************************/ + +#include "kernel/EplNmtk.h" +#include "kernel/EplTimerk.h" + +#include "kernel/EplDllk.h" // for EplDllkProcess() + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// TracePoint support for realtime-debugging +#ifdef _DBG_TRACE_POINTS_ + void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); + void PUBLIC TgtDbgPostTraceValue (DWORD dwTraceValue_p); + #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) + #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) +#else + #define TGT_DBG_SIGNAL_TRACE_POINT(p) + #define TGT_DBG_POST_TRACE_VALUE(v) +#endif +#define EPL_NMTK_DBG_POST_TRACE_VALUE(NmtEvent_p, OldNmtState_p, NewNmtState_p) \ + TGT_DBG_POST_TRACE_VALUE((kEplEventSinkNmtk << 28) | (NmtEvent_p << 16) \ + | ((OldNmtState_p & 0xFF) << 8) \ + | (NewNmtState_p & 0xFF)) + + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- +// struct for instance table +INSTANCE_TYPE_BEGIN + + EPL_MCO_DECL_INSTANCE_MEMBER () + + STATIC volatile tEplNmtState INST_FAR m_NmtState; + STATIC volatile BOOL INST_FAR m_fEnableReadyToOperate; + STATIC volatile BOOL INST_FAR m_fAppReadyToOperate; + STATIC volatile BOOL INST_FAR m_fTimerMsPreOp2; + STATIC volatile BOOL INST_FAR m_fAllMandatoryCNIdent; + STATIC volatile BOOL INST_FAR m_fFrozen; + +INSTANCE_TYPE_END +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- +// This macro replace the unspecific pointer to an instance through +// the modul specific type for the local instance table. This macro +// must defined in each modul. +//#define tEplPtrInstance tEplInstanceInfo MEM* + +EPL_MCO_DECL_INSTANCE_VAR () + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- +EPL_MCO_DEFINE_INSTANCE_FCT () + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <NMT_Kernel-Module> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: This module realize the NMT-State-Machine of the EPL-Stack +// +// +/***************************************************************************/ +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// +//--------------------------------------------------------------------------- +// +// Function: EplNmtkInit +// +// Description: initializes the first instance +// +// +// +// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR = Instance pointer +// uiNodeId_p = Node Id of the lokal node +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR) +{ +tEplKernel Ret; + + Ret = EplNmtkAddInstance (EPL_MCO_PTR_INSTANCE_PTR); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtkAddInstance +// +// Description: adds a new instance +// +// +// +// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR = Instance pointer +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) +{ +EPL_MCO_DECL_INSTANCE_PTR_LOCAL +tEplKernel Ret; +//tEplEvent Event; +//tEplEventNmtStateChange NmtStateChange; + + // check if pointer to instance pointer valid + // get free instance and set the globale instance pointer + // set also the instance addr to parameterlist + EPL_MCO_CHECK_PTR_INSTANCE_PTR (); + EPL_MCO_GET_FREE_INSTANCE_PTR (); + EPL_MCO_SET_PTR_INSTANCE_PTR (); + + // sign instance as used + EPL_MCO_WRITE_INSTANCE_STATE (kStateUsed); + + + Ret = kEplSuccessful; + + // initialize intern vaiables + // 2006/07/31 d.k.: set NMT-State to kEplNmtGsOff + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + // set NMT-State to kEplNmtGsInitialising + //EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + + // set flags to FALSE + EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_fTimerMsPreOp2) = FALSE; + EPL_MCO_GLB_VAR(m_fAllMandatoryCNIdent) = FALSE; + EPL_MCO_GLB_VAR(m_fFrozen) = FALSE; + +// EPL_MCO_GLB_VAR(m_TimerHdl) = 0; + + // inform higher layer about state change + // 2006/07/31 d.k.: The EPL API layer/application has to start NMT state + // machine via NmtEventSwReset after initialisation of + // all modules has been completed. DLL has to be initialised + // after NMTk because NMT state shall not be uninitialised + // at that time. +/* NmtStateChange.m_NewNmtState = EPL_MCO_GLB_VAR(m_NmtState); + NmtStateChange.m_NmtEvent = kEplNmtEventNoEvent; + Event.m_EventSink = kEplEventSinkNmtu; + Event.m_EventType = kEplEventTypeNmtStateChange; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = &NmtStateChange; + Event.m_uiSize = sizeof(NmtStateChange); + Ret = EplEventkPost(&Event); +*/ + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtkDelInstance +// +// Description: delete instance +// +// +// +// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR = Instance pointer +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if (EPL_USE_DELETEINST_FUNC != FALSE) +EPLDLLEXPORT tEplKernel PUBLIC EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) +{ +tEplKernel Ret = kEplSuccessful; + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + // set NMT-State to kEplNmtGsOff + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + + // sign instance as unused + EPL_MCO_WRITE_INSTANCE_STATE (kStateUnused); + + // delete timer +// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); + + return Ret; +} +#endif // (EPL_USE_DELETEINST_FUNC != FALSE) + + +//--------------------------------------------------------------------------- +// +// Function: EplNmtkProcess +// +// Description: main process function +// -> process NMT-State-Maschine und read NMT-Events from Queue +// +// +// +// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR_ = Instance pointer +// pEvent_p = Epl-Event with NMT-event to process +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_ + tEplEvent* pEvent_p) +{ +tEplKernel Ret; +tEplNmtState OldNmtState; +tEplNmtEvent NmtEvent; +tEplEvent Event; +tEplEventNmtStateChange NmtStateChange; + + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + Ret = kEplSuccessful; + + switch(pEvent_p->m_EventType) + { + case kEplEventTypeNmtEvent: + { + NmtEvent = *((tEplNmtEvent*)pEvent_p->m_pArg); + break; + } + + case kEplEventTypeTimer: + { + NmtEvent = (tEplNmtEvent)((tEplTimerEventArg*)pEvent_p->m_pArg)->m_ulArg; + break; + } + default: + { + Ret = kEplNmtInvalidEvent; + goto Exit; + } + } + + // save NMT-State + // needed for later comparison to + // inform hgher layer about state change + OldNmtState = EPL_MCO_GLB_VAR(m_NmtState); + + // NMT-State-Maschine + switch(EPL_MCO_GLB_VAR(m_NmtState)) + { + //----------------------------------------------------------- + // general part of the statemaschine + + // first init of the hardware + case kEplNmtGsOff: + { + // leave this state only if higher layer says so + if(NmtEvent == kEplNmtEventSwReset) + { // new state kEplNmtGsInitialising + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + } + break; + } + + // first init of the hardware + case kEplNmtGsInitialising: + { + // leave this state only if higher layer says so + + // check events + switch(NmtEvent) + { + // 2006/07/31 d.k.: react also on NMT reset commands in ResetApp state + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // new state kEplNmtGsResetApplication + case kEplNmtEventEnterResetApp: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + default: + { + break; + } + } + break; + } + + // init of the manufacturer-specific profile area and the + // standardised device profile area + case kEplNmtGsResetApplication: + { + // check events + switch(NmtEvent) + { + // 2006/07/31 d.k.: react also on NMT reset commands in ResetApp state + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // leave this state only if higher layer + // say so + case kEplNmtEventEnterResetCom: + { + // new state kEplNmtGsResetCommunication + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + default: + { + break; + } + } + break; + } + + // init of the communication profile area + case kEplNmtGsResetCommunication: + { + // check events + switch(NmtEvent) + { + // 2006/07/31 d.k.: react also on NMT reset commands in ResetComm state + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // leave this state only if higher layer + // say so + case kEplNmtEventEnterResetConfig: + { + // new state kEplNmtGsResetCommunication + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + default: + { + break; + } + } + break; + } + + // build the configuration with infos from OD + case kEplNmtGsResetConfiguration: + { + // reset flags + EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_fFrozen) = FALSE; + + // check events + switch(NmtEvent) + { + // 2006/07/31 d.k.: react also on NMT reset commands in ResetConf state + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + case kEplNmtEventResetCom: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // leave this state only if higher layer says so + case kEplNmtEventEnterCsNotActive: + { // Node should be CN + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsNotActive; + break; + + } + + case kEplNmtEventEnterMsNotActive: + { // Node should be CN + #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0) + // no MN functionality + // TODO: -create error E_NMT_BA1_NO_MN_SUPPORT + EPL_MCO_GLB_VAR(m_fFrozen) = TRUE; + #else + + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsNotActive; + #endif + break; + + } + + default: + { + break; + } + } + break; + } + + //----------------------------------------------------------- + // CN part of the statemaschine + + // node liste for EPL-Frames and check timeout + case kEplNmtCsNotActive: + { + + // check events + switch(NmtEvent) + { + // 2006/07/31 d.k.: react also on NMT reset commands in NotActive state + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; +// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; +// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; +// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); + break; + } + + // NMT Command Reset Configuration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; +// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); + break; + } + + // see if SoA or SoC received + // k.t. 20.07.2006: only SoA forces change of state + // see EPL V2 DS 1.0.0 p.267 + // case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCeSoa: + { // new state PRE_OPERATIONAL1 + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; +// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); + break; + } + // timeout for SoA and Soc + case kEplNmtEventTimerBasicEthernet: + { + // new state BASIC_ETHERNET + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsBasicEthernet; + break; + } + + default: + { + break; + } + }// end of switch(NmtEvent) + + break; + } + + // node processes only async frames + case kEplNmtCsPreOperational1: + { + + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command Reset Configuration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // NMT Command StopNode + case kEplNmtEventStopNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsStopped; + break; + } + + // check if SoC received + case kEplNmtEventDllCeSoc: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational2; + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + + break; + } + + // node processes isochronous and asynchronous frames + case kEplNmtCsPreOperational2: + { + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command Reset Configuration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // NMT Command StopNode + case kEplNmtEventStopNode: + { + // reset flags + EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsStopped; + break; + } + + // error occured + case kEplNmtEventNmtCycleError: + { + // reset flags + EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; + break; + } + + // check if application is ready to operate + case kEplNmtEventEnterReadyToOperate: + { + // check if command NMTEnableReadyToOperate from MN was received + if(EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) == TRUE) + { // reset flags + EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; + // change state + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsReadyToOperate; + } + else + { // set Flag + EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = TRUE; + } + break; + } + + // NMT Commando EnableReadyToOperate + case kEplNmtEventEnableReadyToOperate: + { + // check if application is ready + if(EPL_MCO_GLB_VAR(m_fAppReadyToOperate) == TRUE) + { // reset flags + EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; + EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; + // change state + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsReadyToOperate; + } + else + { // set Flag + EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = TRUE; + } + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + break; + } + + // node should be configured und application is ready + case kEplNmtCsReadyToOperate: + { + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // NMT Command StopNode + case kEplNmtEventStopNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsStopped; + break; + } + + // error occured + case kEplNmtEventNmtCycleError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; + break; + } + + // NMT Command StartNode + case kEplNmtEventStartNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsOperational; + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + break; + } + + // normal work state + case kEplNmtCsOperational: + { + + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // NMT Command StopNode + case kEplNmtEventStopNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsStopped; + break; + } + + // NMT Command EnterPreOperational2 + case kEplNmtEventEnterPreOperational2: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational2; + break; + } + + // error occured + case kEplNmtEventNmtCycleError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + break; + } + + // node stopped by MN + // -> only process asynchronous frames + case kEplNmtCsStopped: + { + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // NMT Command EnterPreOperational2 + case kEplNmtEventEnterPreOperational2: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational2; + break; + } + + // error occured + case kEplNmtEventNmtCycleError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + break; + } + + // no epl cycle + // -> normal ethernet communication + case kEplNmtCsBasicEthernet: + { + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // error occured + // d.k.: how does this error occur? on CRC errors +/* case kEplNmtEventNmtCycleError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; + break; + } +*/ + case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCePreq: + case kEplNmtEventDllCePres: + case kEplNmtEventDllCeSoa: + { // Epl-Frame on net -> stop any communication + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + + break; + } + + //----------------------------------------------------------- + // MN part of the statemaschine + + // MN listen to network + // -> if no EPL traffic go to next state + case kEplNmtMsNotActive: + { + #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0) + // no MN functionality + // TODO: -create error E_NMT_BA1_NO_MN_SUPPORT + EPL_MCO_GLB_VAR(m_fFrozen) = TRUE; + #else + + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // EPL frames received + case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCeSoa: + { // other MN in network + // $$$ d.k.: generate error history entry + EPL_MCO_GLB_VAR(m_fFrozen) = TRUE; + break; + } + + // timeout event + case kEplNmtEventTimerBasicEthernet: + { + if (EPL_MCO_GLB_VAR(m_fFrozen) == FALSE) + { // new state BasicEthernet + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsBasicEthernet; + } + break; + } + + // timeout event + case kEplNmtEventTimerMsPreOp1: + { + if (EPL_MCO_GLB_VAR(m_fFrozen) == FALSE) + { // new state PreOp1 + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational1; + EPL_MCO_GLB_VAR(m_fTimerMsPreOp2) = FALSE; + EPL_MCO_GLB_VAR(m_fAllMandatoryCNIdent) = FALSE; + + } + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + + #endif // ((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0) + + break; + } +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // MN process reduces epl cycle + case kEplNmtMsPreOperational1: + { + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // EPL frames received + case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCeSoa: + { // other MN in network + // $$$ d.k.: generate error history entry + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // error occured + // d.k. MSPreOp1->CSPreOp1: nonsense -> keep state + /* + case kEplNmtEventNmtCycleError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; + break; + } + */ + + case kEplNmtEventAllMandatoryCNIdent: + { // all mandatory CN identified + if (EPL_MCO_GLB_VAR(m_fTimerMsPreOp2) != FALSE) + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational2; + } + else + { + EPL_MCO_GLB_VAR(m_fAllMandatoryCNIdent) = TRUE; + } + break; + } + + case kEplNmtEventTimerMsPreOp2: + { // residence time for PreOp1 is elapsed + if (EPL_MCO_GLB_VAR(m_fAllMandatoryCNIdent) != FALSE) + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational2; + } + else + { + EPL_MCO_GLB_VAR(m_fTimerMsPreOp2) = TRUE; + } + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + break; + } + + // MN process full epl cycle + case kEplNmtMsPreOperational2: + { + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // EPL frames received + case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCeSoa: + { // other MN in network + // $$$ d.k.: generate error history entry + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // error occured + case kEplNmtEventNmtCycleError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational1; + break; + } + + case kEplNmtEventEnterReadyToOperate: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsReadyToOperate; + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + + break; + } + + // all madatory nodes ready to operate + // -> MN process full epl cycle + case kEplNmtMsReadyToOperate: + { + + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // EPL frames received + case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCeSoa: + { // other MN in network + // $$$ d.k.: generate error history entry + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // error occured + case kEplNmtEventNmtCycleError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational1; + break; + } + + case kEplNmtEventEnterMsOperational: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsOperational; + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + + break; + } + + // normal eplcycle processing + case kEplNmtMsOperational: + { + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // EPL frames received + case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCeSoa: + { // other MN in network + // $$$ d.k.: generate error history entry + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // error occured + case kEplNmtEventNmtCycleError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational1; + break; + } + + default: + { + break; + } + + }// end of switch(NmtEvent) + break; + } + + // normal ethernet traffic + case kEplNmtMsBasicEthernet: + { + + // check events + switch(NmtEvent) + { + // NMT Command SwitchOff + case kEplNmtEventCriticalError: + case kEplNmtEventSwitchOff: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; + break; + } + + // NMT Command SwReset + case kEplNmtEventSwReset: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; + break; + } + + // NMT Command ResetNode + case kEplNmtEventResetNode: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + break; + } + + // NMT Command ResetCommunication + // or internal Communication error + case kEplNmtEventResetCom: + case kEplNmtEventInternComError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // NMT Command ResetConfiguration + case kEplNmtEventResetConfig: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; + break; + } + + // EPL frames received + case kEplNmtEventDllCeSoc: + case kEplNmtEventDllCeSoa: + { // other MN in network + // $$$ d.k.: generate error history entry + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; + break; + } + + // error occured + // d.k. BE->PreOp1 on cycle error? No +/* case kEplNmtEventNmtCycleError: + { + EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; + break; + } +*/ + default: + { + break; + } + + }// end of switch(NmtEvent) + break; + } +#endif //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + default: + { + //DEBUG_EPL_DBGLVL_NMTK_TRACE0(EPL_DBGLVL_NMT ,"Error in EplNmtProcess: Unknown NMT-State"); + //EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; + Ret = kEplNmtInvalidState; + goto Exit; + } + + }// end of switch(NmtEvent) + + // inform higher layer about State-Change if needed + if(OldNmtState != EPL_MCO_GLB_VAR(m_NmtState)) + { + EPL_NMTK_DBG_POST_TRACE_VALUE(NmtEvent, OldNmtState, EPL_MCO_GLB_VAR(m_NmtState)); + + // d.k.: memorize NMT state before posting any events + NmtStateChange.m_NewNmtState = EPL_MCO_GLB_VAR(m_NmtState); + + // inform DLL + if ((OldNmtState > kEplNmtGsResetConfiguration) + && (EPL_MCO_GLB_VAR(m_NmtState) <= kEplNmtGsResetConfiguration)) + { + // send DLL DEINIT + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkDestroy; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = &OldNmtState; + Event.m_uiSize = sizeof (OldNmtState); + // d.k.: directly call DLLk process function, because + // 1. execution of process function is still synchonized and serialized, + // 2. it is the same as without event queues (i.e. well tested), + // 3. DLLk will get those necessary events even if event queue is full, + // 4. event queue is very inefficient +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + Ret = EplDllkProcess(&Event); +#else + Ret = EplEventkPost(&Event); +#endif + } + else if ((OldNmtState <= kEplNmtGsResetConfiguration) + && (EPL_MCO_GLB_VAR(m_NmtState) > kEplNmtGsResetConfiguration)) + { + // send DLL INIT + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkCreate; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = &NmtStateChange.m_NewNmtState; + Event.m_uiSize = sizeof (NmtStateChange.m_NewNmtState); + // d.k.: directly call DLLk process function, because + // 1. execution of process function is still synchonized and serialized, + // 2. it is the same as without event queues (i.e. well tested), + // 3. DLLk will get those necessary events even if event queue is full + // 4. event queue is very inefficient +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + Ret = EplDllkProcess(&Event); +#else + Ret = EplEventkPost(&Event); +#endif + } + else if ((EPL_MCO_GLB_VAR(m_NmtState) == kEplNmtCsBasicEthernet) + || (EPL_MCO_GLB_VAR(m_NmtState) == kEplNmtMsBasicEthernet)) + { + tEplDllAsyncReqPriority AsyncReqPriority; + + // send DLL Fill Async Tx Buffer, because state BasicEthernet was entered + Event.m_EventSink = kEplEventSinkDllk; + Event.m_EventType = kEplEventTypeDllkFillTx; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + AsyncReqPriority = kEplDllAsyncReqPrioGeneric; + Event.m_pArg = &AsyncReqPriority; + Event.m_uiSize = sizeof (AsyncReqPriority); + // d.k.: directly call DLLk process function, because + // 1. execution of process function is still synchonized and serialized, + // 2. it is the same as without event queues (i.e. well tested), + // 3. DLLk will get those necessary events even if event queue is full + // 4. event queue is very inefficient +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + Ret = EplDllkProcess(&Event); +#else + Ret = EplEventkPost(&Event); +#endif + } + + // inform higher layer about state change + NmtStateChange.m_NmtEvent = NmtEvent; + Event.m_EventSink = kEplEventSinkNmtu; + Event.m_EventType = kEplEventTypeNmtStateChange; + EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); + Event.m_pArg = &NmtStateChange; + Event.m_uiSize = sizeof(NmtStateChange); + Ret = EplEventkPost(&Event); + EPL_DBGLVL_NMTK_TRACE2("EplNmtkProcess(NMT-Event = 0x%04X): New NMT-State = 0x%03X\n", NmtEvent, NmtStateChange.m_NewNmtState); + + + } + +Exit: + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtkGetNmtState +// +// Description: return the actuell NMT-State and the bits +// to for MN- or CN-mode +// +// +// +// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR_ = Instancepointer +// +// +// Returns: tEplNmtState = NMT-State +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplNmtState PUBLIC EplNmtkGetNmtState(EPL_MCO_DECL_PTR_INSTANCE_PTR) +{ +tEplNmtState NmtState; + + NmtState = EPL_MCO_GLB_VAR(m_NmtState); + + return NmtState; + +} + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// +EPL_MCO_DECL_INSTANCE_FCT () +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplNmtkCal.c b/drivers/staging/epl/EplNmtkCal.c new file mode 100644 index 0000000..2881c3c --- /dev/null +++ b/drivers/staging/epl/EplNmtkCal.c @@ -0,0 +1,157 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for communication abstraction layer of the + NMT-Kernel-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtkCal.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + KEIL uVision 2 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/16 -k.t.: start of the implementation + +****************************************************************************/ + +#include "kernel/EplNmtkCal.h" + + +// TODO: init function needed to prepare EplNmtkGetNmtState for +// io-controll-call from EplNmtuCal-Modul + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + + + +// EOF + diff --git a/drivers/staging/epl/EplNmtu.c b/drivers/staging/epl/EplNmtu.c new file mode 100644 index 0000000..52a7e20 --- /dev/null +++ b/drivers/staging/epl/EplNmtu.c @@ -0,0 +1,681 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for NMT-Userspace-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/11/10 17:17:42 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/09 k.t.: start of the implementation + +****************************************************************************/ + + +#include "EplInc.h" +#include "user/EplNmtu.h" +#include "user/EplObdu.h" +#include "user/EplTimeru.h" +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) +#include "kernel/EplNmtk.h" +#endif + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ + tEplNmtuStateChangeCallback m_pfnNmtChangeCb; + tEplTimerHdl m_TimerHdl; + +} tEplNmtuInstance; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +static tEplNmtuInstance EplNmtuInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplNmtuInit +// +// Description: init first instance of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuInit() +{ +tEplKernel Ret; + + Ret = EplNmtuAddInstance(); + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtuAddInstance +// +// Description: init other instances of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuAddInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + EplNmtuInstance_g.m_pfnNmtChangeCb = NULL; + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtuDelInstance +// +// Description: delete instance +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + EplNmtuInstance_g.m_pfnNmtChangeCb = NULL; + + // delete timer + Ret = EplTimeruDeleteTimer(&EplNmtuInstance_g.m_TimerHdl); + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtuNmtEvent +// +// Description: sends the NMT-Event to the NMT-State-Maschine +// +// +// +// Parameters: NmtEvent_p = NMT-Event to send +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p) +{ +tEplKernel Ret; +tEplEvent Event; + + Event.m_EventSink = kEplEventSinkNmtk; + Event.m_NetTime.m_dwNanoSec = 0; + Event.m_NetTime.m_dwSec = 0; + Event.m_EventType = kEplEventTypeNmtEvent; + Event.m_pArg = &NmtEvent_p; + Event.m_uiSize = sizeof(NmtEvent_p); + + Ret = EplEventuPost(&Event); + + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtuGetNmtState +// +// Description: returns the actuell NMT-State +// +// +// +// Parameters: +// +// +// Returns: tEplNmtState = NMT-State +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplNmtState PUBLIC EplNmtuGetNmtState() +{ +tEplNmtState NmtState; + + // $$$ call function of communication abstraction layer +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) + NmtState = EplNmtkGetNmtState(); +#else + NmtState = 0; +#endif + + return NmtState; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtuProcessEvent +// +// Description: processes events from event queue +// +// +// +// Parameters: pEplEvent_p = pointer to event +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent( + tEplEvent* pEplEvent_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // process event + switch(pEplEvent_p->m_EventType) + { + // state change of NMT-Module + case kEplEventTypeNmtStateChange: + { + tEplEventNmtStateChange* pNmtStateChange; + + // delete timer + Ret = EplTimeruDeleteTimer(&EplNmtuInstance_g.m_TimerHdl); + + pNmtStateChange = (tEplEventNmtStateChange*)pEplEvent_p->m_pArg; + + // call cb-functions to inform higher layer + if(EplNmtuInstance_g.m_pfnNmtChangeCb != NULL) + { + Ret = EplNmtuInstance_g.m_pfnNmtChangeCb(*pNmtStateChange); + } + + if (Ret == kEplSuccessful) + { // everything is OK, so switch to next state if necessary + switch (pNmtStateChange->m_NewNmtState) + { + // EPL stack is not running + case kEplNmtGsOff: + break; + + // first init of the hardware + case kEplNmtGsInitialising: + { + Ret = EplNmtuNmtEvent(kEplNmtEventEnterResetApp); + break; + } + + // init of the manufacturer-specific profile area and the + // standardised device profile area + case kEplNmtGsResetApplication: + { + Ret = EplNmtuNmtEvent(kEplNmtEventEnterResetCom); + break; + } + + // init of the communication profile area + case kEplNmtGsResetCommunication: + { + Ret = EplNmtuNmtEvent(kEplNmtEventEnterResetConfig); + break; + } + + // build the configuration with infos from OD + case kEplNmtGsResetConfiguration: + { + unsigned int uiNodeId; + + // get node ID from OD +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) + uiNodeId = EplObduGetNodeId(EPL_MCO_PTR_INSTANCE_PTR); +#else + uiNodeId = 0; +#endif + //check node ID if not should be master or slave + if (uiNodeId == EPL_C_ADR_MN_DEF_NODE_ID) + { // node shall be MN +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + Ret = EplNmtuNmtEvent(kEplNmtEventEnterMsNotActive); +#else + TRACE0("EplNmtuProcess(): no MN functionality implemented\n"); +#endif + } + else + { // node shall be CN + Ret = EplNmtuNmtEvent(kEplNmtEventEnterCsNotActive); + } + break; + } + + //----------------------------------------------------------- + // CN part of the state machine + + // node listens for EPL-Frames and check timeout + case kEplNmtCsNotActive: + { + DWORD dwBuffer; + tEplObdSize ObdSize; + tEplTimerArg TimerArg; + + // create timer to switch automatically to BasicEthernet if no MN available in network + + // read NMT_CNBasicEthernetTimerout_U32 from OD + ObdSize = sizeof(dwBuffer); +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) + Ret = EplObduReadEntry(EPL_MCO_PTR_INSTANCE_PTR_ + 0x1F99, + 0x00, + &dwBuffer, + &ObdSize); +#else + Ret = kEplObdIndexNotExist; +#endif + if(Ret != kEplSuccessful) + { + break; + } + if (dwBuffer != 0) + { // BasicEthernet is enabled + // convert us into ms + dwBuffer = dwBuffer / 1000; + if (dwBuffer == 0) + { // timer was below one ms + // set one ms + dwBuffer = 1; + } + TimerArg.m_EventSink = kEplEventSinkNmtk; + TimerArg.m_ulArg = (unsigned long) kEplNmtEventTimerBasicEthernet; + Ret = EplTimeruModifyTimerMs(&EplNmtuInstance_g.m_TimerHdl, (unsigned long) dwBuffer, TimerArg); + // potential error is forwarded to event queue which generates error event + } + break; + } + + // node processes only async frames + case kEplNmtCsPreOperational1: + { + break; + } + + // node processes isochronous and asynchronous frames + case kEplNmtCsPreOperational2: + { + Ret = EplNmtuNmtEvent(kEplNmtEventEnterReadyToOperate); + break; + } + + // node should be configured und application is ready + case kEplNmtCsReadyToOperate: + { + break; + } + + // normal work state + case kEplNmtCsOperational: + { + break; + } + + // node stopped by MN + // -> only process asynchronous frames + case kEplNmtCsStopped: + { + break; + } + + // no EPL cycle + // -> normal ethernet communication + case kEplNmtCsBasicEthernet: + { + break; + } + + //----------------------------------------------------------- + // MN part of the state machine + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // node listens for EPL-Frames and check timeout + case kEplNmtMsNotActive: + { + DWORD dwBuffer; + tEplObdSize ObdSize; + tEplTimerArg TimerArg; + + // create timer to switch automatically to BasicEthernet/PreOp1 if no other MN active in network + + // check NMT_StartUp_U32.Bit13 + // read NMT_StartUp_U32 from OD + ObdSize = sizeof(dwBuffer); +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) + Ret = EplObduReadEntry(EPL_MCO_PTR_INSTANCE_PTR_ + 0x1F80, + 0x00, + &dwBuffer, + &ObdSize); +#else + Ret = kEplObdIndexNotExist; +#endif + if(Ret != kEplSuccessful) + { + break; + } + + if((dwBuffer & EPL_NMTST_BASICETHERNET) == 0) + { // NMT_StartUp_U32.Bit13 == 0 + // new state PreOperational1 + TimerArg.m_ulArg = (unsigned long) kEplNmtEventTimerMsPreOp1; + } + else + { // NMT_StartUp_U32.Bit13 == 1 + // new state BasicEthernet + TimerArg.m_ulArg = (unsigned long) kEplNmtEventTimerBasicEthernet; + } + + // read NMT_BootTime_REC.MNWaitNotAct_U32 from OD + ObdSize = sizeof(dwBuffer); +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) + Ret = EplObduReadEntry(EPL_MCO_PTR_INSTANCE_PTR_ + 0x1F89, + 0x01, + &dwBuffer, + &ObdSize); +#else + Ret = kEplObdIndexNotExist; +#endif + if(Ret != kEplSuccessful) + { + break; + } + // convert us into ms + dwBuffer = dwBuffer / 1000; + if (dwBuffer == 0) + { // timer was below one ms + // set one ms + dwBuffer = 1; + } + TimerArg.m_EventSink = kEplEventSinkNmtk; + Ret = EplTimeruModifyTimerMs(&EplNmtuInstance_g.m_TimerHdl, (unsigned long) dwBuffer, TimerArg); + // potential error is forwarded to event queue which generates error event + break; + } + + // node processes only async frames + case kEplNmtMsPreOperational1: + { + DWORD dwBuffer = 0; + tEplObdSize ObdSize; + tEplTimerArg TimerArg; + + // create timer to switch automatically to PreOp2 if MN identified all mandatory CNs + + // read NMT_BootTime_REC.MNWaitPreOp1_U32 from OD + ObdSize = sizeof(dwBuffer); +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE) + Ret = EplObduReadEntry(EPL_MCO_PTR_INSTANCE_PTR_ + 0x1F89, + 0x03, + &dwBuffer, + &ObdSize); + if(Ret != kEplSuccessful) + { + // ignore error, because this timeout is optional + dwBuffer = 0; + } +#endif + if (dwBuffer == 0) + { // delay is deactivated + // immediately post timer event + Ret = EplNmtuNmtEvent(kEplNmtEventTimerMsPreOp2); + break; + } + // convert us into ms + dwBuffer = dwBuffer / 1000; + if (dwBuffer == 0) + { // timer was below one ms + // set one ms + dwBuffer = 1; + } + TimerArg.m_EventSink = kEplEventSinkNmtk; + TimerArg.m_ulArg = (unsigned long) kEplNmtEventTimerMsPreOp2; + Ret = EplTimeruModifyTimerMs(&EplNmtuInstance_g.m_TimerHdl, (unsigned long) dwBuffer, TimerArg); + // potential error is forwarded to event queue which generates error event + break; + } + + // node processes isochronous and asynchronous frames + case kEplNmtMsPreOperational2: + { + break; + } + + // node should be configured und application is ready + case kEplNmtMsReadyToOperate: + { + break; + } + + // normal work state + case kEplNmtMsOperational: + { + break; + } + + // no EPL cycle + // -> normal ethernet communication + case kEplNmtMsBasicEthernet: + { + break; + } +#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + + default: + { + TRACE1("EplNmtuProcess(): unhandled NMT state 0x%X\n", pNmtStateChange->m_NewNmtState); + } + } + } + else if (Ret == kEplReject) + { // application wants to change NMT state itself + // it's OK + Ret = kEplSuccessful; + } + + EPL_DBGLVL_NMTU_TRACE0("EplNmtuProcessEvent(): NMT-State-Maschine announce change of NMT State\n"); + break; + } + + default: + { + Ret = kEplNmtInvalidEvent; + } + + } + +//Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplNmtuRegisterStateChangeCb +// +// Description: register Callback-function go get informed about a +// NMT-Change-State-Event +// +// +// +// Parameters: pfnEplNmtStateChangeCb_p = functionpointer +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuRegisterStateChangeCb( + tEplNmtuStateChangeCallback pfnEplNmtStateChangeCb_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // save callback-function in modul global var + EplNmtuInstance_g.m_pfnNmtChangeCb = pfnEplNmtStateChangeCb_p; + + return Ret; + +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + + +// EOF + diff --git a/drivers/staging/epl/EplNmtuCal.c b/drivers/staging/epl/EplNmtuCal.c new file mode 100644 index 0000000..e76f250 --- /dev/null +++ b/drivers/staging/epl/EplNmtuCal.c @@ -0,0 +1,164 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for communication abstraction layer of the + NMT-Userspace-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtuCal.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + KEIL uVision 2 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/16 -k.t.: start of the implementation + +****************************************************************************/ + +#include "user/EplNmtuCal.h" + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplNmtkCalGetNmtState +// +// Description: return current NMT-State +// -> encapsulate access to kernelspace +// +// +// +// Parameters: +// +// +// Returns: tEplNmtState = current NMT-State +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplNmtState PUBLIC EplNmtkCalGetNmtState() +{ +tEplNmtState NmtState; + // for test direkt call for EplNmtkGetNmtState() +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) + NmtState = EplNmtkGetNmtState(); +#else + NmtState = 0; +#endif +return NmtState; +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + + + +// EOF + diff --git a/drivers/staging/epl/EplObd.c b/drivers/staging/epl/EplObd.c new file mode 100644 index 0000000..0f4db89 --- /dev/null +++ b/drivers/staging/epl/EplObd.c @@ -0,0 +1,3505 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for api function of EplOBD-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObd.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.12 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + Microsoft VC7 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/02 k.t.: start of the implementation, version 1.00 + ->based on CANopen OBD-Modul + +****************************************************************************/ + +#include "EplInc.h" +#include "kernel/EplObdk.h" // function prototyps of the EplOBD-Modul + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// float definitions and macros +#define _SHIFTED_EXPONENT_MASK_SP 0xff +#define _BIAS_SP 126 +#define T_SP 23 +#define EXPONENT_DENORM_SP (-_BIAS_SP) +#define BASE_TO_THE_T_SP ((float) 8388608.0) +#define GET_EXPONENT_SP(x) ((((x) >> T_SP) & _SHIFTED_EXPONENT_MASK_SP) - _BIAS_SP) + + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +// struct for instance table +INSTANCE_TYPE_BEGIN + + EPL_MCO_DECL_INSTANCE_MEMBER () + + STATIC tEplObdInitParam INST_FAR m_ObdInitParam; + STATIC tEplObdStoreLoadObjCallback INST_NEAR m_fpStoreLoadObjCallback; + +INSTANCE_TYPE_END + +// decomposition of float +typedef union +{ + tEplObdReal32 m_flRealPart; + int m_nIntegerPart; + +} tEplObdRealParts; + + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +// This macro replace the unspecific pointer to an instance through +// the modul specific type for the local instance table. This macro +// must defined in each modul. +//#define tEplPtrInstance tEplInstanceInfo MEM* + +EPL_MCO_DECL_INSTANCE_VAR () + +BYTE MEM abEplObdTrashObject_g[8]; + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +EPL_MCO_DEFINE_INSTANCE_FCT () + +static tEplKernel EplObdCallObjectCallback (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdCallback fpCallback_p, + tEplObdCbParam MEM* pCbParam_p); + +static tEplObdSize EplObdGetDataSizeIntern (tEplObdSubEntryPtr pSubIndexEntry_p); + +static tEplObdSize EplObdGetStrLen (void* pObjData_p, + tEplObdSize ObjLen_p, + tEplObdType ObjType_p); + +#if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE) +static tEplKernel EplObdCheckObjectRange ( + tEplObdSubEntryPtr pSubindexEntry_p, + void * pData_p); +#endif + +static tEplKernel EplObdGetVarEntry ( + tEplObdSubEntryPtr pSubindexEntry_p, + tEplObdVarEntry MEM** ppVarEntry_p); + +static tEplKernel EplObdGetEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdEntryPtr* ppObdEntry_p, + tEplObdSubEntryPtr* ppObdSubEntry_p); + +static tEplObdSize EplObdGetObjectSize (tEplObdSubEntryPtr pSubIndexEntry_p); + +static tEplKernel EplObdGetIndexIntern ( + tEplObdInitParam MEM* pInitParam_p, + unsigned int uiIndex_p, + tEplObdEntryPtr* ppObdEntry_p); + +static tEplKernel EplObdGetSubindexIntern ( + tEplObdEntryPtr pObdEntry_p, + unsigned int uiSubIndex_p, + tEplObdSubEntryPtr* ppObdSubEntry_p); + +static tEplKernel EplObdAccessOdPartIntern (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdPart CurrentOdPart_p, + tEplObdEntryPtr pObdEnty_p, + tEplObdDir Direction_p); + +static void * EplObdGetObjectDefaultPtr (tEplObdSubEntryPtr pSubIndexEntry_p); +static void MEM* EplObdGetObjectCurrentPtr (tEplObdSubEntryPtr pSubIndexEntry_p); + +#if (EPL_OBD_USE_STORE_RESTORE != FALSE) + + static tEplKernel EplObdCallStoreCallback (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdCbStoreParam MEM* pCbStoreParam_p); + +#endif // (EPL_OBD_USE_STORE_RESTORE != FALSE) + +static void EplObdCopyObjectData ( + void MEM* pDstData_p, + void * pSrcData_p, + tEplObdSize ObjSize_p, + tEplObdType ObjType_p); + +void * EplObdGetObjectDataPtrIntern (tEplObdSubEntryPtr pSubindexEntry_p); + +static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p, + BOOL* pfEntryNumerical_p); + +static tEplKernel PUBLIC EplObdWriteEntryPre (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + void** ppDstData_p, + tEplObdSize Size_p, + tEplObdEntryPtr* ppObdEntry_p, + tEplObdSubEntryPtr* ppSubEntry_p, + tEplObdCbParam MEM* pCbParam_p, + tEplObdSize* pObdSize_p); + +static tEplKernel PUBLIC EplObdWriteEntryPost (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdEntryPtr pObdEntry_p, + tEplObdSubEntryPtr pSubEntry_p, + tEplObdCbParam MEM* pCbParam_p, + void * pSrcData_p, + void * pDstData_p, + tEplObdSize ObdSize_p); + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplObdInit() +// +// Description: initializes the first instance +// +// Parameters: pInitParam_p = init parameter +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplObdInit (EPL_MCO_DECL_PTR_INSTANCE_PTR_ + tEplObdInitParam MEM* pInitParam_p) +{ + +tEplKernel Ret; +EPL_MCO_DELETE_INSTANCE_TABLE (); + + if (pInitParam_p == NULL) + { + Ret = kEplSuccessful; + goto Exit; + } + + Ret = EplObdAddInstance (EPL_MCO_PTR_INSTANCE_PTR_ + pInitParam_p); + +Exit: + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdAddInstance() +// +// Description: adds a new instance +// +// Parameters: pInitParam_p +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplObdAddInstance (EPL_MCO_DECL_PTR_INSTANCE_PTR_ + tEplObdInitParam MEM* pInitParam_p) +{ + +EPL_MCO_DECL_INSTANCE_PTR_LOCAL +tEplKernel Ret; + + // check if pointer to instance pointer valid + // get free instance and set the globale instance pointer + // set also the instance addr to parameterlist + EPL_MCO_CHECK_PTR_INSTANCE_PTR (); + EPL_MCO_GET_FREE_INSTANCE_PTR (); + EPL_MCO_SET_PTR_INSTANCE_PTR (); + + // save init parameters + EPL_MEMCPY (&EPL_MCO_GLB_VAR (m_ObdInitParam), pInitParam_p, sizeof (tEplObdInitParam)); + + // clear callback function for command LOAD and STORE + EPL_MCO_GLB_VAR (m_fpStoreLoadObjCallback) = NULL; + + // sign instance as used + EPL_MCO_WRITE_INSTANCE_STATE (kStateUsed); + + // initialize object dictionary + // so all all VarEntries will be initialized to trash object and default values will be set to current data + Ret = EplObdAccessOdPart (EPL_MCO_INSTANCE_PTR_ + kEplObdPartAll, kEplObdDirInit); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdDeleteInstance() +// +// Description: delete instance +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- +#if (EPL_USE_DELETEINST_FUNC != FALSE) +EPLDLLEXPORT tEplKernel PUBLIC EplObdDeleteInstance (EPL_MCO_DECL_INSTANCE_PTR) +{ + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + // sign instance as unused + EPL_MCO_WRITE_INSTANCE_STATE (kStateUnused); + + return kEplSuccessful; + +} +#endif // (EPL_USE_DELETEINST_FUNC != FALSE) + + +//--------------------------------------------------------------------------- +// +// Function: EplObdWriteEntry() +// +// Description: Function writes data to an OBD entry. Strings +// are stored with added '\0' character. +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ +// uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pSrcData_p = Pointer to the data to write +// Size_p = Size of the data in Byte +// +// Return: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p) +{ + +tEplKernel Ret; +tEplObdEntryPtr pObdEntry; +tEplObdSubEntryPtr pSubEntry; +tEplObdCbParam MEM CbParam; +void MEM* pDstData; +tEplObdSize ObdSize; + + + Ret = EplObdWriteEntryPre (EPL_MCO_INSTANCE_PTR_ + uiIndex_p, + uiSubIndex_p, + pSrcData_p, + &pDstData, + Size_p, + &pObdEntry, + &pSubEntry, + &CbParam, + &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + Ret = EplObdWriteEntryPost (EPL_MCO_INSTANCE_PTR_ + pObdEntry, + pSubEntry, + &CbParam, + pSrcData_p, + pDstData, + ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + +Exit: + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdReadEntry() +// +// Description: The function reads an object entry. The application +// can always read the data even if attrib kEplObdAccRead +// is not set. The attrib is only checked up for SDO transfer. +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ +// uiIndex_p = Index oof the OD entry to read +// uiSubIndex_p = Subindex to read +// pDstData_p = pointer to the buffer for data +// Offset_p = offset in data for read access +// pSize_p = IN: Size of the buffer +// OUT: number of readed Bytes +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize * pSize_p) +{ + +tEplKernel Ret; +tEplObdEntryPtr pObdEntry; +tEplObdSubEntryPtr pSubEntry; +tEplObdCbParam MEM CbParam; +void * pSrcData; +tEplObdSize ObdSize; + + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + ASSERT (pDstData_p != NULL); + ASSERT (pSize_p != NULL); + + // get address of index and subindex entry + Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_ + uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // get pointer to object data + pSrcData = EplObdGetObjectDataPtrIntern (pSubEntry); + + // check source pointer + if (pSrcData == NULL) + { + Ret = kEplObdReadViolation; + goto Exit; + } + + //------------------------------------------------------------------------ + // address of source data to structure of callback parameters + // so callback function can change this data before reading + CbParam.m_uiIndex = uiIndex_p; + CbParam.m_uiSubIndex= uiSubIndex_p; + CbParam.m_pArg = pSrcData; + CbParam.m_ObdEvent = kEplObdEvPreRead; + Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_ + pObdEntry->m_fpCallback, &CbParam); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // get size of data and check if application has reserved enough memory + ObdSize = EplObdGetDataSizeIntern (pSubEntry); + // check if offset given and calc correct number of bytes to read + if (*pSize_p < ObdSize) + { + Ret = kEplObdValueLengthError; + goto Exit; + } + + // read value from object + EPL_MEMCPY (pDstData_p, pSrcData, ObdSize); + *pSize_p = ObdSize; + + // write address of destination data to structure of callback parameters + // so callback function can change this data after reading + CbParam.m_pArg = pDstData_p; + CbParam.m_ObdEvent = kEplObdEvPostRead; + Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_ + pObdEntry->m_fpCallback, &CbParam); + +Exit: + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdAccessOdPart() +// +// Description: restores default values of one part of OD +// +// Parameters: ObdPart_p +// Direction_p +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplObdAccessOdPart (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdPart ObdPart_p, + tEplObdDir Direction_p) +{ + +tEplKernel Ret = kEplSuccessful; +BOOL fPartFount; +tEplObdEntryPtr pObdEntry; + + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + // part always has to be unequal to NULL + pObdEntry = EPL_MCO_GLB_VAR (m_ObdInitParam.m_pPart); + ASSERTMSG (pObdEntry != NULL, "EplObdAccessOdPart(): no OD part is defined!\n"); + + // if ObdPart_p is not valid fPartFound keeps FALSE and function returns kEplObdIllegalPart + fPartFount = FALSE; + + // access to part + if ((ObdPart_p & kEplObdPartGen) != 0) + { + fPartFount = TRUE; + + Ret = EplObdAccessOdPartIntern (EPL_MCO_INSTANCE_PTR_ + kEplObdPartGen, pObdEntry, Direction_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + + // access to manufacturer part + pObdEntry = EPL_MCO_GLB_VAR (m_ObdInitParam.m_pManufacturerPart); + + if ( ((ObdPart_p & kEplObdPartMan) != 0) && + (pObdEntry != NULL) ) + { + fPartFount = TRUE; + + Ret = EplObdAccessOdPartIntern (EPL_MCO_INSTANCE_PTR_ + kEplObdPartMan, pObdEntry, Direction_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + + // access to device part + pObdEntry = EPL_MCO_GLB_VAR (m_ObdInitParam.m_pDevicePart); + + if ( ((ObdPart_p & kEplObdPartDev) != 0) && + (pObdEntry != NULL) ) + { + fPartFount = TRUE; + + Ret = EplObdAccessOdPartIntern (EPL_MCO_INSTANCE_PTR_ + kEplObdPartDev, pObdEntry, Direction_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + + #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) + { + // access to user part + pObdEntry = EPL_MCO_GLB_VAR (m_ObdInitParam.m_pUserPart); + + if ( ((ObdPart_p & kEplObdPartUsr) != 0) && + (pObdEntry != NULL) ) + { + fPartFount = TRUE; + + Ret = EplObdAccessOdPartIntern (EPL_MCO_INSTANCE_PTR_ + kEplObdPartUsr, pObdEntry, Direction_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + } + #endif + + // no access to an OD part was done? illegal OD part was specified! + if (fPartFount == FALSE) + { + Ret = kEplObdIllegalPart; + } + +Exit: + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdDefineVar() +// +// Description: defines a variable in OD +// +// Parameters: pEplVarParam_p +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplObdDefineVar (EPL_MCO_DECL_INSTANCE_PTR_ + tEplVarParam MEM* pVarParam_p) +{ + +tEplKernel Ret; +tEplObdVarEntry MEM* pVarEntry; +tEplVarParamValid VarValid; +tEplObdSubEntryPtr pSubindexEntry; + + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + ASSERT (pVarParam_p != NULL); // is not allowed to be NULL + + // get address of subindex entry + Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_ + pVarParam_p->m_uiIndex, + pVarParam_p->m_uiSubindex, + NULL, &pSubindexEntry); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // get var entry + Ret = EplObdGetVarEntry (pSubindexEntry, &pVarEntry); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + VarValid = pVarParam_p->m_ValidFlag; + + // copy only this values, which valid flag is set + if ((VarValid & kVarValidSize) != 0) + { + if (pSubindexEntry->m_Type != kEplObdTypDomain) + { + tEplObdSize DataSize; + + // check passed size parameter + DataSize = EplObdGetObjectSize(pSubindexEntry); + if (DataSize != pVarParam_p->m_Size) + { // size of variable does not match + Ret = kEplObdValueLengthError; + goto Exit; + } + } + else + { // size can be set only for objects of type DOMAIN + pVarEntry->m_Size = pVarParam_p->m_Size; + } + } + + if ((VarValid & kVarValidData) != 0) + { + pVarEntry->m_pData = pVarParam_p->m_pData; + } +/* + #if (EPL_PDO_USE_STATIC_MAPPING == FALSE) + { + if ((VarValid & kVarValidCallback) != 0) + { + pVarEntry->m_fpCallback = pVarParam_p->m_fpCallback; + } + + if ((VarValid & kVarValidArg) != 0) + { + pVarEntry->m_pArg = pVarParam_p->m_pArg; + } + } + #endif +*/ + // Ret is already set to kEplSuccessful from ObdGetVarIntern() + +Exit: + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetObjectDataPtr() +// +// Description: It returnes the current data pointer. But if object is an +// constant object it returnes the default pointer. +// +// Parameters: uiIndex_p = Index of the entry +// uiSubindex_p = Subindex of the entry +// +// Return: void * = pointer to object data +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT void * PUBLIC EplObdGetObjectDataPtr (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p) + { +tEplKernel Ret; +void * pData; +tEplObdEntryPtr pObdEntry; +tEplObdSubEntryPtr pObdSubEntry; + + + // get pointer to index structure + Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam), + uiIndex_p, + &pObdEntry); + if(Ret != kEplSuccessful) + { + pData = NULL; + goto Exit; + } + + // get pointer to subindex structure + Ret = EplObdGetSubindexIntern (pObdEntry, + uiSubIndex_p, + &pObdSubEntry); + if(Ret != kEplSuccessful) + { + pData = NULL; + goto Exit; + } + // get Datapointer + pData = EplObdGetObjectDataPtrIntern(pObdSubEntry); + +Exit: + return pData; + +} + + +#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) + +//--------------------------------------------------------------------------- +// +// Function: EplObdRegisterUserOd() +// +// Description: function registers the user OD +// +// Parameters: pUserOd_p =pointer to user ODd +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdRegisterUserOd (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdEntryPtr pUserOd_p) +{ + + EPL_MCO_CHECK_INSTANCE_STATE (); + + EPL_MCO_GLB_VAR (m_ObdInitParam.m_pUserPart) = pUserOd_p; + + return kEplSuccessful; + +} + +#endif + + +//--------------------------------------------------------------------------- +// +// Function: EplObdInitVarEntry() +// +// Description: function to initialize VarEntry dependened on object type +// +// Parameters: pVarEntry_p = pointer to var entry structure +// Type_p = object type +// ObdSize_p = size of object data +// +// Returns: none +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT void PUBLIC EplObdInitVarEntry (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdVarEntry MEM* pVarEntry_p, + tEplObdType Type_p, tEplObdSize ObdSize_p) +{ +/* + #if (EPL_PDO_USE_STATIC_MAPPING == FALSE) + { + // reset pointer to VAR callback and argument + pVarEntry_p->m_fpCallback = NULL; + pVarEntry_p->m_pArg = NULL; + } + #endif +*/ + +// 10-dec-2004 r.d.: this function will not be used for strings + if ((Type_p == kEplObdTypDomain)) +// (bType_p == kEplObdTypVString) /* || +// (bType_p == kEplObdTypOString) || +// (bType_p == kEplObdTypUString) */ ) + { + // variables which are defined as DOMAIN or VSTRING should not point to + // trash object, because this trash object contains only 8 bytes. DOMAINS or + // STRINGS can be longer. + pVarEntry_p->m_pData = NULL; + pVarEntry_p->m_Size = 0; + } + else + { + // set address to variable data to trash object + // This prevents an access violation if user forgets to call EplObdDefineVar() + // for this variable but mappes it in a PDO. + pVarEntry_p->m_pData = &abEplObdTrashObject_g[0]; + pVarEntry_p->m_Size = ObdSize_p; + } + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetDataSize() +// +// Description: function to initialize VarEntry dependened on object type +// +// gets the data size of an object +// for string objects it returnes the string length +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer +// uiIndex_p = Index +// uiSubIndex_p= Subindex +// +// Return: tEplObdSize +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplObdSize PUBLIC EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p) +{ +tEplKernel Ret; +tEplObdSize ObdSize; +tEplObdEntryPtr pObdEntry; +tEplObdSubEntryPtr pObdSubEntry; + + + // get pointer to index structure + Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam), + uiIndex_p, + &pObdEntry); + if(Ret != kEplSuccessful) + { + ObdSize = 0; + goto Exit; + } + + // get pointer to subindex structure + Ret = EplObdGetSubindexIntern (pObdEntry, + uiSubIndex_p, + &pObdSubEntry); + if(Ret != kEplSuccessful) + { + ObdSize = 0; + goto Exit; + } + + // get size + ObdSize = EplObdGetDataSizeIntern (pObdSubEntry); +Exit: + return ObdSize; +} +//--------------------------------------------------------------------------- +// +// Function: EplObdGetNodeId() +// +// Description: function returns nodeid from entry 0x1F93 +// +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR = Instancepointer +// +// Return: unsigned int = Node Id +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT unsigned int PUBLIC EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR) +{ +tEplKernel Ret; +tEplObdSize ObdSize; +BYTE bNodeId; + + bNodeId = 0; + ObdSize = sizeof(bNodeId); + Ret = EplObdReadEntry(EPL_MCO_PTR_INSTANCE_PTR_ + EPL_OBD_NODE_ID_INDEX, + EPL_OBD_NODE_ID_SUBINDEX, + &bNodeId, + &ObdSize); + if(Ret != kEplSuccessful) + { + bNodeId = EPL_C_ADR_INVALID; + goto Exit; + } + +Exit: + return (unsigned int) bNodeId; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdSetNodeId() +// +// Description: function sets nodeid in entry 0x1F93 +// +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer +// uiNodeId_p = Node Id to set +// NodeIdType_p= Type on which way the Node Id was set +// +// Return: tEplKernel = Errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_ + unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p) +{ +tEplKernel Ret; +tEplObdSize ObdSize; +BYTE fHwBool; +BYTE bNodeId; + + // check Node Id + if(uiNodeId_p == EPL_C_ADR_INVALID) + { + Ret = kEplInvalidNodeId; + goto Exit; + } + bNodeId = (BYTE)uiNodeId_p; + ObdSize = sizeof(BYTE); + // write NodeId to OD entry + Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR_ + EPL_OBD_NODE_ID_INDEX, + EPL_OBD_NODE_ID_SUBINDEX, + &bNodeId, + ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // set HWBOOL-Flag in Subindex EPL_OBD_NODE_ID_HWBOOL_SUBINDEX + switch (NodeIdType_p) + { + // type unknown + case kEplObdNodeIdUnknown: + { + fHwBool = OBD_FALSE; + break; + } + + case kEplObdNodeIdSoftware: + { + fHwBool = OBD_FALSE; + break; + } + + case kEplObdNodeIdHardware: + { + fHwBool = OBD_TRUE; + break; + } + + default: + { + fHwBool = OBD_FALSE; + } + + } // end of switch (NodeIdType_p) + + // write flag + ObdSize = sizeof(fHwBool); + Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR + EPL_OBD_NODE_ID_INDEX, + EPL_OBD_NODE_ID_HWBOOL_SUBINDEX, + &fHwBool, + ObdSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdIsNumerical() +// +// Description: function checks if a entry is numerical or not +// +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer +// uiIndex_p = Index +// uiSubIndex_p = Subindex +// pfEntryNumerical_p = pointer to BOOL for returnvalue +// -> TRUE if entry a numerical value +// -> FALSE if entry not a numerical value +// +// Return: tEplKernel = Errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + BOOL* pfEntryNumerical_p) +{ +tEplKernel Ret; +tEplObdEntryPtr pObdEntry; +tEplObdSubEntryPtr pObdSubEntry; + + + // get pointer to index structure + Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam), + uiIndex_p, + &pObdEntry); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // get pointer to subindex structure + Ret = EplObdGetSubindexIntern (pObdEntry, + uiSubIndex_p, + &pObdSubEntry); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + Ret = EplObdIsNumericalIntern(pObdSubEntry, pfEntryNumerical_p); + + +Exit: + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdReadEntryToLe() +// +// Description: The function reads an object entry from the byteoder +// of the system to the little endian byteorder for numerical values. +// For other types a normal read will be processed. This is usefull for +// the PDO and SDO module. The application +// can always read the data even if attrib kEplObdAccRead +// is not set. The attrib is only checked up for SDO transfer. +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ +// uiIndex_p = Index of the OD entry to read +// uiSubIndex_p = Subindex to read +// pDstData_p = pointer to the buffer for data +// Offset_p = offset in data for read access +// pSize_p = IN: Size of the buffer +// OUT: number of readed Bytes +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize * pSize_p) +{ +tEplKernel Ret; +tEplObdEntryPtr pObdEntry; +tEplObdSubEntryPtr pSubEntry; +tEplObdCbParam MEM CbParam; +void * pSrcData; +tEplObdSize ObdSize; + + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + ASSERT (pDstData_p != NULL); + ASSERT (pSize_p != NULL); + + // get address of index and subindex entry + Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_ + uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // get pointer to object data + pSrcData = EplObdGetObjectDataPtrIntern (pSubEntry); + + // check source pointer + if (pSrcData == NULL) + { + Ret = kEplObdReadViolation; + goto Exit; + } + + //------------------------------------------------------------------------ + // address of source data to structure of callback parameters + // so callback function can change this data before reading + CbParam.m_uiIndex = uiIndex_p; + CbParam.m_uiSubIndex= uiSubIndex_p; + CbParam.m_pArg = pSrcData; + CbParam.m_ObdEvent = kEplObdEvPreRead; + Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_ + pObdEntry->m_fpCallback, &CbParam); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // get size of data and check if application has reserved enough memory + ObdSize = EplObdGetDataSizeIntern (pSubEntry); + // check if offset given and calc correct number of bytes to read + if (*pSize_p < ObdSize) + { + Ret = kEplObdValueLengthError; + goto Exit; + } + + // check if numerical type + switch(pSubEntry->m_Type) + { + //----------------------------------------------- + // types without ami + case kEplObdTypVString: + case kEplObdTypOString: + case kEplObdTypDomain: + default: + { + // read value from object + EPL_MEMCPY (pDstData_p, pSrcData, ObdSize); + break; + } + + //----------------------------------------------- + // numerical type which needs ami-write + // 8 bit or smaller values + case kEplObdTypBool: + case kEplObdTypInt8: + case kEplObdTypUInt8: + { + AmiSetByteToLe(pDstData_p, *((BYTE*)pSrcData)); + break; + } + + // 16 bit values + case kEplObdTypInt16: + case kEplObdTypUInt16: + { + AmiSetWordToLe(pDstData_p, *((WORD*)pSrcData)); + break; + } + + // 24 bit values + case kEplObdTypInt24: + case kEplObdTypUInt24: + { + AmiSetDword24ToLe(pDstData_p, *((DWORD*)pSrcData)); + break; + } + + // 32 bit values + case kEplObdTypInt32: + case kEplObdTypUInt32: + case kEplObdTypReal32: + { + AmiSetDwordToLe(pDstData_p, *((DWORD*)pSrcData)); + break; + } + + // 40 bit values + case kEplObdTypInt40: + case kEplObdTypUInt40: + { + AmiSetQword40ToLe(pDstData_p, *((QWORD*)pSrcData)); + break; + } + + // 48 bit values + case kEplObdTypInt48: + case kEplObdTypUInt48: + { + AmiSetQword48ToLe(pDstData_p, *((QWORD*)pSrcData)); + break; + } + + // 56 bit values + case kEplObdTypInt56: + case kEplObdTypUInt56: + { + AmiSetQword56ToLe(pDstData_p, *((QWORD*)pSrcData)); + break; + } + + // 64 bit values + case kEplObdTypInt64: + case kEplObdTypUInt64: + case kEplObdTypReal64: + { + AmiSetQword64ToLe(pDstData_p, *((QWORD*)pSrcData)); + break; + } + + // time of day + case kEplObdTypTimeOfDay: + case kEplObdTypTimeDiff: + { + AmiSetTimeOfDay(pDstData_p, ((tTimeOfDay*)pSrcData)); + break; + } + + }// end of switch(pSubEntry->m_Type) + + *pSize_p = ObdSize; + + + // write address of destination data to structure of callback parameters + // so callback function can change this data after reading + CbParam.m_pArg = pDstData_p; + CbParam.m_ObdEvent = kEplObdEvPostRead; + Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_ + pObdEntry->m_fpCallback, &CbParam); + +Exit: + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdWriteEntryFromLe() +// +// Description: Function writes data to an OBD entry from a source with +// little endian byteorder to the od with system specuific +// byteorder. Not numerical values will only by copied. Strings +// are stored with added '\0' character. +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ +// uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pSrcData_p = Pointer to the data to write +// Size_p = Size of the data in Byte +// +// Return: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p) +{ +tEplKernel Ret; +tEplObdEntryPtr pObdEntry; +tEplObdSubEntryPtr pSubEntry; +tEplObdCbParam MEM CbParam; +void MEM* pDstData; +tEplObdSize ObdSize; +QWORD qwBuffer; +void* pBuffer = &qwBuffer; + + + Ret = EplObdWriteEntryPre (EPL_MCO_INSTANCE_PTR_ + uiIndex_p, + uiSubIndex_p, + pSrcData_p, + &pDstData, + Size_p, + &pObdEntry, + &pSubEntry, + &CbParam, + &ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + + // check if numerical type + switch(pSubEntry->m_Type) + { + //----------------------------------------------- + // types without ami + default: + { // do nothing, i.e. use the given source pointer + pBuffer = pSrcData_p; + break; + } + + //----------------------------------------------- + // numerical type which needs ami-write + // 8 bit or smaller values + case kEplObdTypBool: + case kEplObdTypInt8: + case kEplObdTypUInt8: + { + *((BYTE*)pBuffer) = AmiGetByteFromLe(pSrcData_p); + break; + } + + // 16 bit values + case kEplObdTypInt16: + case kEplObdTypUInt16: + { + *((WORD*)pBuffer) = AmiGetWordFromLe(pSrcData_p); + break; + } + + // 24 bit values + case kEplObdTypInt24: + case kEplObdTypUInt24: + { + *((DWORD*)pBuffer) = AmiGetDword24FromLe(pSrcData_p); + break; + } + + // 32 bit values + case kEplObdTypInt32: + case kEplObdTypUInt32: + case kEplObdTypReal32: + { + *((DWORD*)pBuffer) = AmiGetDwordFromLe(pSrcData_p); + break; + } + + // 40 bit values + case kEplObdTypInt40: + case kEplObdTypUInt40: + { + *((QWORD*)pBuffer) = AmiGetQword40FromLe(pSrcData_p); + break; + } + + // 48 bit values + case kEplObdTypInt48: + case kEplObdTypUInt48: + { + *((QWORD*)pBuffer) = AmiGetQword48FromLe(pSrcData_p); + break; + } + + // 56 bit values + case kEplObdTypInt56: + case kEplObdTypUInt56: + { + *((QWORD*)pBuffer) = AmiGetQword56FromLe(pSrcData_p); + break; + } + + // 64 bit values + case kEplObdTypInt64: + case kEplObdTypUInt64: + case kEplObdTypReal64: + { + *((QWORD*)pBuffer) = AmiGetQword64FromLe(pSrcData_p); + break; + } + + // time of day + case kEplObdTypTimeOfDay: + case kEplObdTypTimeDiff: + { + AmiGetTimeOfDay(pBuffer, ((tTimeOfDay*)pSrcData_p)); + break; + } + + }// end of switch(pSubEntry->m_Type) + + + Ret = EplObdWriteEntryPost (EPL_MCO_INSTANCE_PTR_ + pObdEntry, + pSubEntry, + &CbParam, + pBuffer, + pDstData, + ObdSize); + if (Ret != kEplSuccessful) + { + goto Exit; + } + +Exit: + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetAccessType() +// +// Description: Function returns accesstype of the entry +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ +// uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pAccessTyp_p = pointer to buffer to store accesstype +// +// Return: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess* pAccessTyp_p) + +{ +tEplKernel Ret; +tEplObdEntryPtr pObdEntry; +tEplObdSubEntryPtr pObdSubEntry; + + + // get pointer to index structure + Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam), + uiIndex_p, + &pObdEntry); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // get pointer to subindex structure + Ret = EplObdGetSubindexIntern (pObdEntry, + uiSubIndex_p, + &pObdSubEntry); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // get accessType + *pAccessTyp_p = pObdSubEntry->m_Access; + + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdSearchVarEntry() +// +// Description: gets variable from OD +// +// Parameters: uiIndex_p = index of the var entry to search +// uiSubindex_p = subindex of var entry to search +// ppVarEntry_p = pointer to the pointer to the varentry +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplObdSearchVarEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry MEM** ppVarEntry_p) +{ + +tEplKernel Ret; +tEplObdSubEntryPtr pSubindexEntry; + + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + // get address of subindex entry + Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_ + uiIndex_p, uiSubindex_p, NULL, &pSubindexEntry); + if (Ret == kEplSuccessful) + { + // get var entry + Ret = EplObdGetVarEntry (pSubindexEntry, ppVarEntry_p); + } + + return Ret; + +} +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +EPL_MCO_DECL_INSTANCE_FCT () +//--------------------------------------------------------------------------- +// +// Function: EplObdCallObjectCallback() +// +// Description: calls callback function of an object or of a variable +// +// Parameters: fpCallback_p +// pCbParam_p +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplObdCallObjectCallback (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdCallback fpCallback_p, + tEplObdCbParam MEM* pCbParam_p) +{ + +tEplKernel Ret; +tEplObdCallback MEM fpCallback; + + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + ASSERT (pCbParam_p != NULL); + + Ret = kEplSuccessful; + + // check address of callback function before calling it + if (fpCallback_p != NULL) + { + // KEIL C51 V6.01 has a bug. + // Therefore the parameter fpCallback_p has to be copied in local variable fpCallback. + fpCallback = fpCallback_p; + + // call callback function for this object + Ret = fpCallback (EPL_MCO_INSTANCE_PARAM_IDX_() + pCbParam_p); + } + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetDataSizeIntern() +// +// Description: gets the data size of an object +// for string objects it returnes the string length +// +// Parameters: pSubIndexEntry_p +// +// Return: tEplObdSize +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplObdSize EplObdGetDataSizeIntern (tEplObdSubEntryPtr pSubIndexEntry_p) +{ + +tEplObdSize DataSize; +void MEM* pData; + + // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING + // then the current pointer is always NULL. The function + // returns the length of default string. + DataSize = EplObdGetObjectSize (pSubIndexEntry_p); + + if (pSubIndexEntry_p->m_Type == kEplObdTypVString) + { + // The pointer to current value can be received from EplObdGetObjectCurrentPtr() + pData = ((void MEM*) EplObdGetObjectCurrentPtr (pSubIndexEntry_p)); + if (pData != NULL) + { + DataSize = EplObdGetStrLen ((void *) pData, DataSize, pSubIndexEntry_p->m_Type); + } + + } + + return DataSize; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetStrLen() +// +// Description: The function calculates the length of string. The '\0' +// character is included!! +// +// Parameters: pObjData_p = pointer to string +// ObjLen_p = max. length of objectr entry +// bObjType_p = object type (VSTRING, ...) +// +// Returns: string length + 1 +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplObdSize EplObdGetStrLen (void * pObjData_p, + tEplObdSize ObjLen_p, + tEplObdType ObjType_p) +{ + +tEplObdSize StrLen = 0; +BYTE * pbString; + + if (pObjData_p == NULL) + { + goto Exit; + } + + //---------------------------------------- + // Visible String: data format byte + if (ObjType_p == kEplObdTypVString) + { + pbString = pObjData_p; + + for (StrLen = 0; StrLen < ObjLen_p; StrLen++) + { + if (*pbString == '\0') + { + StrLen++; + break; + } + + pbString++; + } + } + + //---------------------------------------- + // other string types ... + +Exit: + return (StrLen); + +} + + + +#if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE) + +//--------------------------------------------------------------------------- +// +// Function: EplObdCheckObjectRange() +// +// Description: function to check value range of object data +// +// NOTICE: The pointer of data (pData_p) must point out to an even address, +// if ObjType is unequal to kEplObdTypInt8 or kEplObdTypUInt8! But it is +// always realiced because pointer m_pDefault points always to an +// array of the SPECIFIED type. +// +// Parameters: pSubindexEntry_p +// pData_p +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplObdCheckObjectRange ( + tEplObdSubEntryPtr pSubindexEntry_p, + void * pData_p) +{ + +tEplKernel Ret; +void * pRangeData; + + ASSERTMSG (pSubindexEntry_p != NULL, + "EplObdCheckObjectRange(): no address to subindex struct!\n"); + + Ret = kEplSuccessful; + + // check if data range has to be checked + if ((pSubindexEntry_p->m_Access & kEplObdAccRange) == 0) + { + goto Exit; + } + + // get address of default data + pRangeData = pSubindexEntry_p->m_pDefault; + + // jump to called object type + switch ((tEplObdType) pSubindexEntry_p->m_Type) + { + // ----------------------------------------------------------------- + // ObdType kEplObdTypBool will not be checked because there are only + // two possible values 0 or 1. + + // ----------------------------------------------------------------- + // ObdTypes which has to be check up because numerical values + case kEplObdTypInt8: + + // switch to lower limit + pRangeData = ((tEplObdInteger8 *) pRangeData) + 1; + + // check if value is to low + if (*((tEplObdInteger8 *) pData_p) < *((tEplObdInteger8 *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((tEplObdInteger8 *) pRangeData) + 1; + + // check if value is to high + if (*((tEplObdInteger8 *) pData_p) > *((tEplObdInteger8 *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + case kEplObdTypUInt8: + + // switch to lower limit + pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1; + + // check if value is to low + if (*((tEplObdUnsigned8 *) pData_p) < *((tEplObdUnsigned8 *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((tEplObdUnsigned8*) pRangeData) + 1; + + // check if value is to high + if (*((tEplObdUnsigned8 *) pData_p) > *((tEplObdUnsigned8 *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + case kEplObdTypInt16: + + // switch to lower limit + pRangeData = ((tEplObdInteger16 *) pRangeData) + 1; + + // check if value is to low + if (*((tEplObdInteger16 *) pData_p) < *((tEplObdInteger16 *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((tEplObdInteger16 *) pRangeData) + 1; + + // check if value is to high + if (*((tEplObdInteger16 *) pData_p) > *((tEplObdInteger16 *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + case kEplObdTypUInt16: + + // switch to lower limit + pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1; + + // check if value is to low + if (*((tEplObdUnsigned16 *) pData_p) < *((tEplObdUnsigned16 *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1; + + // check if value is to high + if (*((tEplObdUnsigned16 *) pData_p) > *((tEplObdUnsigned16 *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + case kEplObdTypInt32: + + // switch to lower limit + pRangeData = ((tEplObdInteger32 *) pRangeData) + 1; + + // check if value is to low + if (*((tEplObdInteger32 *) pData_p) < *((tEplObdInteger32 *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((tEplObdInteger32 *) pRangeData) + 1; + + // check if value is to high + if (*((tEplObdInteger32 *) pData_p) > *((tEplObdInteger32 *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + case kEplObdTypUInt32: + + // switch to lower limit + pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1; + + // check if value is to low + if (*((tEplObdUnsigned32 *) pData_p) < *((tEplObdUnsigned32 *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1; + + // check if value is to high + if (*((tEplObdUnsigned32 *) pData_p) > *((tEplObdUnsigned32 *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + case kEplObdTypReal32: + + // switch to lower limit + pRangeData = ((tEplObdReal32 *) pRangeData) + 1; + + // check if value is to low + if (*((tEplObdReal32 *) pData_p) < *((tEplObdReal32 *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((tEplObdReal32 *) pRangeData) + 1; + + // check if value is to high + if (*((tEplObdReal32 *) pData_p) > *((tEplObdReal32 *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + // ----------------------------------------------------------------- + case kEplObdTypInt40: + case kEplObdTypInt48: + case kEplObdTypInt56: + case kEplObdTypInt64: + + // switch to lower limit + pRangeData = ((signed QWORD *) pRangeData) + 1; + + // check if value is to low + if (*((signed QWORD *) pData_p) < *((signed QWORD *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((signed QWORD *) pRangeData) + 1; + + // check if value is to high + if (*((signed QWORD *) pData_p) > *((signed QWORD *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + // ----------------------------------------------------------------- + case kEplObdTypUInt40: + case kEplObdTypUInt48: + case kEplObdTypUInt56: + case kEplObdTypUInt64: + + // switch to lower limit + pRangeData = ((unsigned QWORD *) pRangeData) + 1; + + // check if value is to low + if (*((unsigned QWORD *) pData_p) < *((unsigned QWORD *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((unsigned QWORD *) pRangeData) + 1; + + // check if value is to high + if (*((unsigned QWORD *) pData_p) > *((unsigned QWORD *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + // ----------------------------------------------------------------- + case kEplObdTypReal64: + + // switch to lower limit + pRangeData = ((tEplObdReal64 *) pRangeData) + 1; + + // check if value is to low + if (*((tEplObdReal64 *) pData_p) < *((tEplObdReal64 *) pRangeData)) + { + Ret = kEplObdValueTooLow; + break; + } + + // switch to higher limit + pRangeData = ((tEplObdReal64 *) pRangeData) + 1; + + // check if value is to high + if (*((tEplObdReal64 *) pData_p) > *((tEplObdReal64 *) pRangeData)) + { + Ret = kEplObdValueTooHigh; + } + + break; + + // ----------------------------------------------------------------- + case kEplObdTypTimeOfDay: + case kEplObdTypTimeDiff: + break; + + // ----------------------------------------------------------------- + // ObdTypes kEplObdTypXString and kEplObdTypDomain can not be checkt because + // they have no numerical value. + default: + + Ret = kEplObdUnknownObjectType; + break; + } + +Exit: + + return Ret; + +} +#endif // (EPL_OBD_CHECK_OBJECT_RANGE != FALSE) + +//--------------------------------------------------------------------------- +// +// Function: EplObdWriteEntryPre() +// +// Description: Function prepares write of data to an OBD entry. Strings +// are stored with added '\0' character. +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ +// uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pSrcData_p = Pointer to the data to write +// Size_p = Size of the data in Byte +// +// Return: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplObdWriteEntryPre (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + void** ppDstData_p, + tEplObdSize Size_p, + tEplObdEntryPtr* ppObdEntry_p, + tEplObdSubEntryPtr* ppSubEntry_p, + tEplObdCbParam MEM* pCbParam_p, + tEplObdSize* pObdSize_p) +{ + +tEplKernel Ret; +tEplObdEntryPtr pObdEntry; +tEplObdSubEntryPtr pSubEntry; +tEplObdAccess Access; +void MEM* pDstData; +tEplObdSize ObdSize; +BOOL fEntryNumerical; + +#if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE) + tEplObdVStringDomain MEM MemVStringDomain; + void MEM* pCurrData; +#endif + + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + ASSERT (pSrcData_p != NULL); // should never be NULL + + //------------------------------------------------------------------------ + // get address of index and subindex entry + Ret = EplObdGetEntry (EPL_MCO_INSTANCE_PTR_ + uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // get pointer to object data + pDstData = (void MEM*) EplObdGetObjectDataPtrIntern (pSubEntry); + + Access = (tEplObdAccess) pSubEntry->m_Access; + + // check access for write + // access violation if adress to current value is NULL + if ( ((Access & kEplObdAccConst) != 0) || + (pDstData == NULL) ) + { + Ret = kEplObdAccessViolation; + goto Exit; + } + + //------------------------------------------------------------------------ + // get size of object + // -as ObdSize = ObdGetObjectSize (pSubEntry); + + //------------------------------------------------------------------------ + // To use the same callback function for ObdWriteEntry as well as for + // an SDO download call at first (kEplObdEvPre...) the callback function + // with the argument pointer to object size. + pCbParam_p->m_uiIndex = uiIndex_p; + pCbParam_p->m_uiSubIndex = uiSubIndex_p; + + // Because object size and object pointer are + // adapted by user callback function, re-read + // this values. + ObdSize = EplObdGetObjectSize (pSubEntry); + pDstData = (void MEM*) EplObdGetObjectDataPtrIntern (pSubEntry); + + // 09-dec-2004 r.d.: + // Function EplObdWriteEntry() calls new event kEplObdEvWrStringDomain + // for String or Domain which lets called module directly change + // the data pointer or size. This prevents a recursive call to + // the callback function if it calls EplObdGetEntry(). + #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE) + if ( (pSubEntry->m_Type == kEplObdTypVString) || + (pSubEntry->m_Type == kEplObdTypDomain) || + (pSubEntry->m_Type == kEplObdTypOString)) + { + if (pSubEntry->m_Type == kEplObdTypVString) + { + // reserve one byte for 0-termination + // -as ObdSize -= 1; + Size_p += 1; + } + + // fill out new arg-struct + MemVStringDomain.m_DownloadSize = Size_p; + MemVStringDomain.m_ObjSize = ObdSize; + MemVStringDomain.m_pData = pDstData; + + pCbParam_p->m_ObdEvent = kEplObdEvWrStringDomain; + pCbParam_p->m_pArg = &MemVStringDomain; + // call user callback + Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_ + pObdEntry->m_fpCallback, pCbParam_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // write back new settings + pCurrData = pSubEntry->m_pCurrent; + if ((pSubEntry->m_Type == kEplObdTypVString) + ||(pSubEntry->m_Type == kEplObdTypOString)) + { + ((tEplObdVString MEM*) pCurrData)->m_Size = MemVStringDomain.m_ObjSize; + ((tEplObdVString MEM*) pCurrData)->m_pString = MemVStringDomain.m_pData; + } + else // if (pSdosTableEntry_p->m_bObjType == kEplObdTypDomain) + { + ((tEplObdVarEntry MEM*) pCurrData)->m_Size = MemVStringDomain.m_ObjSize; + ((tEplObdVarEntry MEM*) pCurrData)->m_pData = (void MEM*) MemVStringDomain.m_pData; + } + + // Because object size and object pointer are + // adapted by user callback function, re-read + // this values. + ObdSize = MemVStringDomain.m_ObjSize; + pDstData = (void MEM*) MemVStringDomain.m_pData; + } + #endif //#if (OBD_USE_STRING_DOMAIN_IN_RAM != FALSE) + + // 07-dec-2004 r.d.: size from application is needed because callback function can change the object size + // -as 16.11.04 CbParam.m_pArg = &ObdSize; + // 09-dec-2004 r.d.: CbParam.m_pArg = &Size_p; + pCbParam_p->m_pArg = &ObdSize; + pCbParam_p->m_ObdEvent = kEplObdEvInitWrite; + Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_ + pObdEntry->m_fpCallback, pCbParam_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + if (Size_p > ObdSize) + { + Ret = kEplObdValueLengthError; + goto Exit; + } + + if (pSubEntry->m_Type == kEplObdTypVString) + { + if (((char MEM*) pSrcData_p)[Size_p - 1] == '\0') + { // last byte of source string contains null character + + // reserve one byte in destination for 0-termination + Size_p -= 1; + } + else if (Size_p >= ObdSize) + { // source string is not 0-terminated + // and destination buffer is too short + Ret = kEplObdValueLengthError; + goto Exit; + } + } + + Ret = EplObdIsNumericalIntern(pSubEntry, &fEntryNumerical); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + if ((fEntryNumerical != FALSE) + && (Size_p != ObdSize)) + { + // type is numerical, therefor size has to fit, but it does not. + Ret = kEplObdValueLengthError; + goto Exit; + } + + // use given size, because non-numerical objects can be written with shorter values + ObdSize = Size_p; + + // set output parameters + *pObdSize_p = ObdSize; + *ppObdEntry_p = pObdEntry; + *ppSubEntry_p = pSubEntry; + *ppDstData_p = pDstData; + + // all checks are done + // the caller may now convert the numerial source value to platform byte order in a temporary buffer + +Exit: + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdWriteEntryPost() +// +// Description: Function finishes write of data to an OBD entry. Strings +// are stored with added '\0' character. +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ +// uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pSrcData_p = Pointer to the data to write +// Size_p = Size of the data in Byte +// +// Return: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplObdWriteEntryPost (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdEntryPtr pObdEntry_p, + tEplObdSubEntryPtr pSubEntry_p, + tEplObdCbParam MEM* pCbParam_p, + void * pSrcData_p, + void * pDstData_p, + tEplObdSize ObdSize_p) +{ + +tEplKernel Ret; + + + // caller converted the source value to platform byte order + // now the range of the value may be checked + + #if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE) + { + // check data range + Ret = EplObdCheckObjectRange (pSubEntry_p, pSrcData_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + #endif + + // now call user callback function to check value + // write address of source data to structure of callback parameters + // so callback function can check this data + pCbParam_p->m_pArg = pSrcData_p; + pCbParam_p->m_ObdEvent = kEplObdEvPreWrite; + Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_ + pObdEntry_p->m_fpCallback, pCbParam_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // copy object data to OBD + EPL_MEMCPY (pDstData_p, pSrcData_p, ObdSize_p); + + // terminate string with 0 + if (pSubEntry_p->m_Type == kEplObdTypVString) + { + ((char MEM*) pDstData_p)[ObdSize_p] = '\0'; + } + + // write address of destination to structure of callback parameters + // so callback function can change data subsequently + pCbParam_p->m_pArg = pDstData_p; + pCbParam_p->m_ObdEvent = kEplObdEvPostWrite; + Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_ + pObdEntry_p->m_fpCallback, pCbParam_p); + +Exit: + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetObjectSize() +// +// Description: function to get size of object +// The function determines if an object type an fixed data type (BYTE, WORD, ...) +// or non fixed object (string, domain). This information is used to decide +// if download data are stored temporary or not. For objects with fixed data length +// and types a value range checking can process. +// For strings the function returns the whole object size not the +// length of string. +// +// Parameters: pSubIndexEntry_p +// +// Return: tEplObdSize +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplObdSize EplObdGetObjectSize (tEplObdSubEntryPtr pSubIndexEntry_p) +{ + +tEplObdSize DataSize = 0; +void * pData; + + switch (pSubIndexEntry_p->m_Type) + { + // ----------------------------------------------------------------- + case kEplObdTypBool: + + DataSize = 1; + break; + + // ----------------------------------------------------------------- + // ObdTypes which has to be check because numerical values + case kEplObdTypInt8: + DataSize = sizeof (tEplObdInteger8); + break; + + // ----------------------------------------------------------------- + case kEplObdTypUInt8: + DataSize = sizeof (tEplObdUnsigned8); + break; + + // ----------------------------------------------------------------- + case kEplObdTypInt16: + DataSize = sizeof (tEplObdInteger16); + break; + + // ----------------------------------------------------------------- + case kEplObdTypUInt16: + DataSize = sizeof (tEplObdUnsigned16); + break; + + // ----------------------------------------------------------------- + case kEplObdTypInt32: + DataSize = sizeof (tEplObdInteger32); + break; + + // ----------------------------------------------------------------- + case kEplObdTypUInt32: + DataSize = sizeof (tEplObdUnsigned32); + break; + + // ----------------------------------------------------------------- + case kEplObdTypReal32: + DataSize = sizeof (tEplObdReal32); + break; + + // ----------------------------------------------------------------- + // ObdTypes which has to be not checked because not NUM values + case kEplObdTypDomain: + + pData = (void *) pSubIndexEntry_p->m_pCurrent; + if ((void MEM*) pData != (void MEM*) NULL) + { + DataSize = ((tEplObdVarEntry MEM*) pData)->m_Size; + } + break; + + // ----------------------------------------------------------------- + case kEplObdTypVString: + //case kEplObdTypUString: + + // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING + // then the current pointer is always NULL. The function + // returns the length of default string. + pData = (void *) pSubIndexEntry_p->m_pCurrent; + if ((void MEM*) pData != (void MEM*) NULL) + { + // The max. size of strings defined by STRING-Macro is stored in + // tEplObdVString of current value. + // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members) + DataSize = ((tEplObdVString MEM*) pData)->m_Size; + } + else + { + // The current position is not decleared. The string + // is located in ROM, therefor use default pointer. + pData = (void *) pSubIndexEntry_p->m_pDefault; + if ((CONST void ROM*) pData != (CONST void ROM*) NULL) + { + // The max. size of strings defined by STRING-Macro is stored in + // tEplObdVString of default value. + DataSize = ((CONST tEplObdVString ROM*) pData)->m_Size; + } + } + + break; + + // ----------------------------------------------------------------- + case kEplObdTypOString: + + pData = (void *) pSubIndexEntry_p->m_pCurrent; + if ((void MEM*) pData != (void MEM*) NULL) + { + // The max. size of strings defined by STRING-Macro is stored in + // tEplObdVString of current value. + // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members) + DataSize = ((tEplObdOString MEM*) pData)->m_Size; + } + else + { + // The current position is not decleared. The string + // is located in ROM, therefor use default pointer. + pData = (void *) pSubIndexEntry_p->m_pDefault; + if ((CONST void ROM*) pData != (CONST void ROM*) NULL) + { + // The max. size of strings defined by STRING-Macro is stored in + // tEplObdVString of default value. + DataSize = ((CONST tEplObdOString ROM*) pData)->m_Size; + } + } + break; + + // ----------------------------------------------------------------- + case kEplObdTypInt24: + case kEplObdTypUInt24: + + DataSize = 3; + break; + + + // ----------------------------------------------------------------- + case kEplObdTypInt40: + case kEplObdTypUInt40: + + DataSize = 5; + break; + + // ----------------------------------------------------------------- + case kEplObdTypInt48: + case kEplObdTypUInt48: + + DataSize = 6; + break; + + // ----------------------------------------------------------------- + case kEplObdTypInt56: + case kEplObdTypUInt56: + + DataSize = 7; + break; + + // ----------------------------------------------------------------- + case kEplObdTypInt64: + case kEplObdTypUInt64: + case kEplObdTypReal64: + + DataSize = 8; + break; + + // ----------------------------------------------------------------- + case kEplObdTypTimeOfDay: + case kEplObdTypTimeDiff: + + DataSize = 6; + break; + + // ----------------------------------------------------------------- + default: + break; + } + + return DataSize; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetObjectDefaultPtr() +// +// Description: function to get the default pointer (type specific) +// +// Parameters: pSubIndexEntry_p = pointer to subindex structure +// +// Returns: (void *) = pointer to default value +// +// State: +// +//--------------------------------------------------------------------------- + +static void * EplObdGetObjectDefaultPtr (tEplObdSubEntryPtr pSubIndexEntry_p) +{ + +void * pDefault; +tEplObdType Type; + + ASSERTMSG (pSubIndexEntry_p != NULL, "EplObdGetObjectDefaultPtr(): pointer to SubEntry not valid!\n"); + + // get address to default data from default pointer + pDefault = pSubIndexEntry_p->m_pDefault; + if (pDefault != NULL) + { + // there are some special types, whose default pointer always is NULL or has to get from other structure + // get type from subindex structure + Type = pSubIndexEntry_p->m_Type; + + // check if object type is a string value + if ((Type == kEplObdTypVString) /* || + (Type == kEplObdTypUString) */ ) + { + + // EPL_OBD_SUBINDEX_RAM_VSTRING + // tEplObdSize m_Size; --> size of default string + // char * m_pDefString; --> pointer to default string + // char * m_pString; --> pointer to string in RAM + // + pDefault = (void *) ((tEplObdVString *) pDefault)->m_pString; + } + else if(Type == kEplObdTypOString) + { + pDefault = (void *) ((tEplObdOString *) pDefault)->m_pString; + } + } + + return pDefault; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetVarEntry() +// +// Description: gets a variable entry of an object +// +// Parameters: pSubindexEntry_p +// ppVarEntry_p +// +// Return: tCopKernel +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplObdGetVarEntry ( + tEplObdSubEntryPtr pSubindexEntry_p, + tEplObdVarEntry MEM** ppVarEntry_p) +{ + +tEplKernel Ret = kEplObdVarEntryNotExist; + + ASSERT (ppVarEntry_p != NULL); // is not allowed to be NULL + ASSERT (pSubindexEntry_p != NULL); + + // check VAR-Flag - only this object points to variables + if ((pSubindexEntry_p->m_Access & kEplObdAccVar) != 0) + { + // check if object is an array + if ((pSubindexEntry_p->m_Access & kEplObdAccArray) != 0) + { + *ppVarEntry_p = &((tEplObdVarEntry MEM*) pSubindexEntry_p->m_pCurrent)[pSubindexEntry_p->m_uiSubIndex - 1]; + } + else + { + *ppVarEntry_p = (tEplObdVarEntry MEM*) pSubindexEntry_p->m_pCurrent; + } + + Ret = kEplSuccessful; + } + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetEntry() +// +// Description: gets a index entry from OD +// +// Parameters: uiIndex_p = Index number +// uiSubindex_p = Subindex number +// ppObdEntry_p = pointer to the pointer to the entry +// ppObdSubEntry_p = pointer to the pointer to the subentry +// +// Return: tEplKernel + +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplObdGetEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdEntryPtr* ppObdEntry_p, + tEplObdSubEntryPtr* ppObdSubEntry_p) +{ + +tEplObdEntryPtr pObdEntry; +tEplObdCbParam MEM CbParam; +tEplKernel Ret; + + // check for all API function if instance is valid + EPL_MCO_CHECK_INSTANCE_STATE (); + + //------------------------------------------------------------------------ + // get address of entry of index + Ret = EplObdGetIndexIntern (&EPL_MCO_GLB_VAR (m_ObdInitParam), uiIndex_p, &pObdEntry); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + //------------------------------------------------------------------------ + // get address of entry of subindex + Ret = EplObdGetSubindexIntern (pObdEntry, uiSubindex_p, ppObdSubEntry_p); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + //------------------------------------------------------------------------ + // call callback function to inform user/stack that an object will be searched + // if the called module returnes an error then we abort the searching with kEplObdIndexNotExist + CbParam.m_uiIndex = uiIndex_p; + CbParam.m_uiSubIndex = uiSubindex_p; + CbParam.m_pArg = NULL; + CbParam.m_ObdEvent = kEplObdEvCheckExist; + Ret = EplObdCallObjectCallback (EPL_MCO_INSTANCE_PTR_ + pObdEntry->m_fpCallback, &CbParam); + if (Ret != kEplSuccessful) + { + Ret = kEplObdIndexNotExist; + goto Exit; + } + + //------------------------------------------------------------------------ + // it is allowed to set ppObdEntry_p to NULL + // if so, no address will be written to calling function + if (ppObdEntry_p != NULL) + { + *ppObdEntry_p = pObdEntry; + } + +Exit: + + return Ret; + +} +//--------------------------------------------------------------------------- +// +// Function: EplObdGetObjectCurrentPtr() +// +// Description: function to get Current pointer (type specific) +// +// Parameters: pSubIndexEntry_p +// +// Return: void MEM* +// +// State: +// +//--------------------------------------------------------------------------- + +static void MEM* EplObdGetObjectCurrentPtr (tEplObdSubEntryPtr pSubIndexEntry_p) +{ + +void MEM* pData; +unsigned int uiArrayIndex; +tEplObdSize Size; + + pData = pSubIndexEntry_p->m_pCurrent; + + // check if constant object + if (pData != NULL) + { + // check if object is an array + if ((pSubIndexEntry_p->m_Access & kEplObdAccArray) != 0) + { + // calculate correct data pointer + uiArrayIndex = pSubIndexEntry_p->m_uiSubIndex - 1; + if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) + { + Size = sizeof (tEplObdVarEntry); + } + else + { + Size = EplObdGetObjectSize (pSubIndexEntry_p); + } + pData = ((BYTE MEM*) pData) + (Size * uiArrayIndex); + } + + // check if VarEntry + if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) + { + // The data pointer is stored in VarEntry->pData + pData = ((tEplObdVarEntry MEM*) pData)->m_pData; + } + + // the default pointer is stored for strings in tEplObdVString + else if ((pSubIndexEntry_p->m_Type == kEplObdTypVString) /* || + (pSubIndexEntry_p->m_Type == kEplObdTypUString) */ ) + { + pData = (void MEM*) ((tEplObdVString MEM*) pData)->m_pString; + } + else if (pSubIndexEntry_p->m_Type == kEplObdTypOString) + { + pData = (void MEM*) ((tEplObdOString MEM*) pData)->m_pString; + } + } + + return pData; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetIndexIntern() +// +// Description: gets a index entry from OD +// +// Parameters: pInitParam_p +// uiIndex_p +// ppObdEntry_p +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplObdGetIndexIntern ( + tEplObdInitParam MEM* pInitParam_p, + unsigned int uiIndex_p, + tEplObdEntryPtr* ppObdEntry_p) +{ + +tEplObdEntryPtr pObdEntry; +tEplKernel Ret; +unsigned int uiIndex; + +#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) + +unsigned int nLoop; + + // if user OD is used then objekts also has to be searched in user OD + // there is less code need if we do this in a loop + nLoop = 2; + +#endif + + ASSERTMSG (ppObdEntry_p != NULL, "EplObdGetIndexIntern(): pointer to index entry is NULL!\n"); + + Ret = kEplObdIndexNotExist; + + // get start address of OD part + // start address depends on object index because + // object dictionary is divided in 3 parts + if ((uiIndex_p >= 0x1000) && (uiIndex_p < 0x2000)) + { + pObdEntry = pInitParam_p->m_pPart; + } + else if ((uiIndex_p >= 0x2000) && (uiIndex_p < 0x6000)) + { + pObdEntry = pInitParam_p->m_pManufacturerPart; + } + + // index range 0xA000 to 0xFFFF is reserved for DSP-405 + // DS-301 defines that range 0x6000 to 0x9FFF (!!!) is stored if "store" was written to 0x1010/3. + // Therefore default configuration is OBD_INCLUDE_A000_TO_DEVICE_PART = FALSE. + // But a CANopen Application which does not implement dynamic OD or user-OD but wants to use static objets 0xA000... + // should set OBD_INCLUDE_A000_TO_DEVICE_PART to TRUE. + +#if (EPL_OBD_INCLUDE_A000_TO_DEVICE_PART == FALSE) + else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0x9FFF)) +#else + else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0xFFFF)) +#endif + { + pObdEntry = pInitParam_p->m_pDevicePart; + } + + +#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) + + // if index does not match in static OD then index only has to be searched in user OD + else + { + // begin from first entry of user OD part + pObdEntry = pInitParam_p->m_pUserPart; + + // no user OD is available + if (pObdEntry == NULL) + { + goto Exit; + } + + // loop must only run once + nLoop = 1; + } + + do + { + +#else + + // no user OD is available + // so other object can be found in OD + else + { + Ret = kEplObdIllegalPart; + goto Exit; + } + +#endif + + // note: + // The end of Index table is marked with m_uiIndex = 0xFFFF. + // If this function will be called with wIndex_p = 0xFFFF, entry + // should not be found. Therefor it is important to use + // while{} instead of do{}while !!! + + // get first index of index table + uiIndex = pObdEntry->m_uiIndex; + + // search Index in OD part + while (uiIndex != EPL_OBD_TABLE_INDEX_END) + { + // go to the end of this function if index is found + if (uiIndex_p == uiIndex) + { + // write address of OD entry to calling function + *ppObdEntry_p = pObdEntry; + Ret = kEplSuccessful; + goto Exit; + } + + // objects are sorted in OD + // if the current index in OD is greater than the index which is to search then break loop + // in this case user OD has to be search too + if (uiIndex_p < uiIndex) + { + break; + } + + // next entry in index table + pObdEntry++; + + // get next index of index table + uiIndex = pObdEntry->m_uiIndex; + } + +#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) + + // begin from first entry of user OD part + pObdEntry = pInitParam_p->m_pUserPart; + + // no user OD is available + if (pObdEntry == NULL) + { + goto Exit; + } + + // switch next loop for user OD + nLoop--; + + } while (nLoop > 0); + +#endif + + // in this line Index was not found + +Exit: + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdGetSubindexIntern() +// +// Description: gets a subindex entry from a index entry +// +// Parameters: pObdEntry_p +// bSubIndex_p +// ppObdSubEntry_p +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplObdGetSubindexIntern ( + tEplObdEntryPtr pObdEntry_p, + unsigned int uiSubIndex_p, + tEplObdSubEntryPtr* ppObdSubEntry_p) +{ + +tEplObdSubEntryPtr pSubEntry; +unsigned int nSubIndexCount; +tEplKernel Ret; + + ASSERTMSG (pObdEntry_p != NULL, "EplObdGetSubindexIntern(): pointer to index is NULL!\n"); + ASSERTMSG (ppObdSubEntry_p != NULL, "EplObdGetSubindexIntern(): pointer to subindex is NULL!\n"); + + Ret = kEplObdSubindexNotExist; + + // get start address of subindex table and count of subindices + pSubEntry = pObdEntry_p->m_pSubIndex; + nSubIndexCount = pObdEntry_p->m_uiCount; + ASSERTMSG ((pSubEntry != NULL) && (nSubIndexCount > 0), + "ObdGetSubindexIntern(): invalid subindex table within index table!\n"); // should never be NULL + + // search subindex in subindex table + while (nSubIndexCount > 0) + { + // check if array is found + if ((pSubEntry->m_Access & kEplObdAccArray) != 0) + { + // check if subindex is in range + if (uiSubIndex_p < pObdEntry_p->m_uiCount) + { + // update subindex number (subindex entry of an array is always in RAM !!!) + pSubEntry->m_uiSubIndex = uiSubIndex_p; + *ppObdSubEntry_p = pSubEntry; + Ret = kEplSuccessful; + goto Exit; + } + } + + // go to the end of this function if subindex is found + else if (uiSubIndex_p == pSubEntry->m_uiSubIndex) + { + *ppObdSubEntry_p = pSubEntry; + Ret = kEplSuccessful; + goto Exit; + } + + // objects are sorted in OD + // if the current subindex in OD is greater than the subindex which is to search then break loop + // in this case user OD has to be search too + if (uiSubIndex_p < pSubEntry->m_uiSubIndex) + { + break; + } + + pSubEntry++; + nSubIndexCount--; + } + + // in this line SubIndex was not fount + +Exit: + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdSetStoreLoadObjCallback() +// +// Description: function set address to callbackfunction for command Store and Load +// +// Parameters: fpCallback_p +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- +#if (EPL_OBD_USE_STORE_RESTORE != FALSE) +EPLDLLEXPORT tEplKernel PUBLIC EplObdSetStoreLoadObjCallback (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdStoreLoadObjCallback fpCallback_p) +{ + + EPL_MCO_CHECK_INSTANCE_STATE (); + + // set new address of callback function + EPL_MCO_GLB_VAR (m_fpStoreLoadObjCallback) = fpCallback_p; + + return kEplSuccessful; + +} +#endif // (EPL_OBD_USE_STORE_RESTORE != FALSE) + + +//--------------------------------------------------------------------------- +// +// Function: EplObdAccessOdPartIntern() +// +// Description: runs through OD and executes a job +// +// Parameters: CurrentOdPart_p +// pObdEnty_p +// Direction_p = what is to do (load values from flash or EEPROM, store, ...) +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplObdAccessOdPartIntern (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdPart CurrentOdPart_p, + tEplObdEntryPtr pObdEnty_p, + tEplObdDir Direction_p) +{ + +tEplObdSubEntryPtr pSubIndex; +unsigned int nSubIndexCount; +tEplObdAccess Access; +void MEM* pDstData; +void * pDefault; +tEplObdSize ObjSize; +tEplKernel Ret; +tEplObdCbStoreParam MEM CbStore; +tEplObdVarEntry MEM* pVarEntry; + + ASSERT (pObdEnty_p != NULL); + + Ret = kEplSuccessful; + + // prepare structure for STORE RESTORE callback function + CbStore.m_bCurrentOdPart = (BYTE) CurrentOdPart_p; + CbStore.m_pData = NULL; + CbStore.m_ObjSize = 0; + + // command of first action depends on direction to access + #if (EPL_OBD_USE_STORE_RESTORE != FALSE) + if (Direction_p == kEplObdDirLoad) + { + CbStore.m_bCommand = (BYTE) kEplObdCommOpenRead; + + // call callback function for previous command + Ret = EplObdCallStoreCallback (EPL_MCO_INSTANCE_PTR_ + &CbStore); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // set command for index and subindex loop + CbStore.m_bCommand = (BYTE) kEplObdCommReadObj; + } + else if (Direction_p == kEplObdDirStore) + { + CbStore.m_bCommand = (BYTE) kEplObdCommOpenWrite; + + // call callback function for previous command + Ret = EplObdCallStoreCallback (EPL_MCO_INSTANCE_PTR_ + &CbStore); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + // set command for index and subindex loop + CbStore.m_bCommand = (BYTE) kEplObdCommWriteObj; + } + #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE) + + // we should not restore the OD values here + // the next NMT command "Reset Node" or "Reset Communication" resets the OD data + if (Direction_p != kEplObdDirRestore) + { + // walk through OD part till end is found + while (pObdEnty_p->m_uiIndex != EPL_OBD_TABLE_INDEX_END) + { + // get address to subindex table and count of subindices + pSubIndex = pObdEnty_p->m_pSubIndex; + nSubIndexCount = pObdEnty_p->m_uiCount; + ASSERT ((pSubIndex != NULL) && (nSubIndexCount > 0)); // should never be NULL + + // walk through subindex table till all subinices were restored + while (nSubIndexCount != 0) + { + Access = (tEplObdAccess) pSubIndex->m_Access; + + // get pointer to current and default data + pDefault = EplObdGetObjectDefaultPtr (pSubIndex); + pDstData = EplObdGetObjectCurrentPtr (pSubIndex); + + // NOTE (for kEplObdTypVString): + // The function returnes the max. number of bytes for a + // current string. + // r.d.: For stings the default-size will be read in other lines following (kEplObdDirInit). + ObjSize = EplObdGetObjectSize (pSubIndex); + + // switch direction of OD access + switch (Direction_p) + { + // -------------------------------------------------------------------------- + // VarEntry structures has to be initialized + case kEplObdDirInit: + + // If VAR-Flag is set, m_pCurrent means not address of data + // but address of tEplObdVarEntry. Address of data has to be get from + // this structure. + if ((Access & kEplObdAccVar) != 0) + { + EplObdGetVarEntry (pSubIndex, &pVarEntry); + EplObdInitVarEntry (pVarEntry, pSubIndex->m_Type, ObjSize); +/* + if ((Access & kEplObdAccArray) == 0) + { + EplObdInitVarEntry (pSubIndex->m_pCurrent, pSubIndex->m_Type, ObjSize); + } + else + { + EplObdInitVarEntry ((tEplObdVarEntry MEM*) (((BYTE MEM*) pSubIndex->m_pCurrent) + (sizeof (tEplObdVarEntry) * pSubIndex->m_uiSubIndex)), + pSubIndex->m_Type, ObjSize); + } +*/ + // at this time no application variable is defined !!! + // therefore data can not be copied. + break; + } + else if (pSubIndex->m_Type == kEplObdTypVString) + { + // If pointer m_pCurrent is not equal to NULL then the + // string was defined with EPL_OBD_SUBINDEX_RAM_VSTRING. The current + // pointer points to struct tEplObdVString located in MEM. + // The element size includes the max. number of + // bytes. The element m_pString includes the pointer + // to string in MEM. The memory location of default string + // must be copied to memory location of current string. + + pDstData = pSubIndex->m_pCurrent; + if (pDstData != NULL) + { + // 08-dec-2004: code optimization !!! + // entries ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_pString + // and ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read + // twice. thats not necessary! + + // For copying data we have to set the destination pointer to the real RAM string. This + // pointer to RAM string is located in default string info structure. (translated r.d.) + pDstData = (void MEM*) ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_pString; + ObjSize = ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_Size; + + + ((tEplObdVString MEM*) pSubIndex->m_pCurrent)->m_pString = pDstData; + ((tEplObdVString MEM*) pSubIndex->m_pCurrent)->m_Size = ObjSize; + } + + } + else if(pSubIndex->m_Type == kEplObdTypOString) + { + pDstData = pSubIndex->m_pCurrent; + if (pDstData != NULL) + { + // 08-dec-2004: code optimization !!! + // entries ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_pString + // and ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read + // twice. thats not necessary! + + // For copying data we have to set the destination pointer to the real RAM string. This + // pointer to RAM string is located in default string info structure. (translated r.d.) + pDstData = (void MEM*) ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_pString; + ObjSize = ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_Size; + + + ((tEplObdOString MEM*) pSubIndex->m_pCurrent)->m_pString = pDstData; + ((tEplObdOString MEM*) pSubIndex->m_pCurrent)->m_Size = ObjSize; + } + + } + + + // no break !! because copy of data has to done too. + + // -------------------------------------------------------------------------- + // all objects has to be restored with default values + case kEplObdDirRestore: + + // 09-dec-2004 r.d.: optimization! the same code for kEplObdDirRestore and kEplObdDirLoad + // is replaced to function ObdCopyObjectData() with a new parameter. + + + // restore object data for init phase + EplObdCopyObjectData (pDstData, pDefault, ObjSize, pSubIndex->m_Type); + break; + + // -------------------------------------------------------------------------- + // objects with attribute kEplObdAccStore has to be load from EEPROM or from a file + case kEplObdDirLoad: + + // restore object data for init phase + EplObdCopyObjectData (pDstData, pDefault, ObjSize, pSubIndex->m_Type); + + // no break !! because callback function has to be called too. + + // -------------------------------------------------------------------------- + // objects with attribute kEplObdAccStore has to be stored in EEPROM or in a file + case kEplObdDirStore: + + // when attribute kEplObdAccStore is set, then call callback function + #if (EPL_OBD_USE_STORE_RESTORE != FALSE) + if ((Access & kEplObdAccStore) != 0) + { + // fill out data pointer and size of data + CbStore.m_pData = pDstData; + CbStore.m_ObjSize = ObjSize; + + // call callback function for read or write object + Ret = ObdCallStoreCallback (EPL_MCO_INSTANCE_PTR_ + &CbStore); + if (Ret != kEplSuccessful) + { + goto Exit; + } + } + #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE) + break; + + + // -------------------------------------------------------------------------- + // if OD Builder key has to be checked no access to subindex and data should be made + case kEplObdDirOBKCheck: + + // no break !! because we want to break the second loop too. + + + // -------------------------------------------------------------------------- + // unknown Direction + default: + + // so we can break the second loop earler + nSubIndexCount = 1; + break; + } + + nSubIndexCount--; + + // next subindex entry + if ((Access & kEplObdAccArray) == 0) + { + pSubIndex++; + if ((nSubIndexCount > 0) + && ((pSubIndex->m_Access & kEplObdAccArray) != 0)) + { + // next subindex points to an array + // reset subindex number + pSubIndex->m_uiSubIndex = 1; + } + } + else + { + if (nSubIndexCount > 0) + { + // next subindex points to an array + // increment subindex number + pSubIndex->m_uiSubIndex++; + } + } + } + + // next index entry + pObdEnty_p++; + } + } + + // ----------------------------------------------------------------------------------------- + // command of last action depends on direction to access + if (Direction_p == kEplObdDirOBKCheck) + { + + goto Exit; + } + #if (EPL_OBD_USE_STORE_RESTORE != FALSE) + else + { + if (Direction_p == kEplObdDirLoad) + { + CbStore.m_bCommand = (BYTE) kEplObdCommCloseRead; + } + else if (Direction_p == kEplObdDirStore) + { + CbStore.m_bCommand = (BYTE) kEplObdCommCloseWrite; + } + else if (Direction_p == kEplObdDirRestore) + { + CbStore.m_bCommand = (BYTE) kEplObdCommClear; + } + else + { + goto Exit; + } + + // call callback function for last command + Ret = EplObdCallStoreCallback (EPL_MCO_INSTANCE_PTR_ + &CbStore); + } + #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE) + +// goto Exit; + +Exit: + + return Ret; + +} + + +// ---------------------------------------------------------------------------- +// Function: EplObdCopyObjectData() +// +// Description: checks pointers to object data and copy them from source to destination +// +// Parameters: pDstData_p = destination pointer +// pSrcData_p = source pointer +// ObjSize_p = size of object +// ObjType_p = +// +// Returns: tEplKernel = error code +// ---------------------------------------------------------------------------- + +static void EplObdCopyObjectData ( + void MEM* pDstData_p, + void * pSrcData_p, + tEplObdSize ObjSize_p, + tEplObdType ObjType_p) +{ + + +tEplObdSize StrSize = 0; + + + // it is allowed to set default and current address to NULL (nothing to copy) + if (pDstData_p != NULL) + { + + if (ObjType_p == kEplObdTypVString) + { + // The function calculates the really number of characters of string. The + // object entry size can be bigger as string size of default string. + // The '\0'-termination is included. A string with no characters has a + // size of 1. + StrSize = EplObdGetStrLen ((void *) pSrcData_p, ObjSize_p, kEplObdTypVString); + + // If the string length is greater than or equal to the entry size in OD then only copy + // entry size - 1 and always set the '\0'-termination. + if (StrSize >= ObjSize_p) + { + StrSize = ObjSize_p - 1; + } + } + + if (pSrcData_p != NULL) + { + // copy data + EPL_MEMCPY (pDstData_p, pSrcData_p, ObjSize_p); + + if (ObjType_p == kEplObdTypVString) + { + ((char MEM*) pDstData_p)[StrSize] = '\0'; + } + } + } + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdIsNumericalIntern() +// +// Description: function checks if a entry is numerical or not +// +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer +// uiIndex_p = Index +// uiSubIndex_p = Subindex +// pfEntryNumerical_p = pointer to BOOL for returnvalue +// -> TRUE if entry a numerical value +// -> FALSE if entry not a numerical value +// +// Return: tEplKernel = Errorcode +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p, + BOOL* pfEntryNumerical_p) +{ +tEplKernel Ret = kEplSuccessful; + + + // get Type + if((pObdSubEntry_p->m_Type == kEplObdTypVString) + || (pObdSubEntry_p->m_Type == kEplObdTypOString) + || (pObdSubEntry_p->m_Type == kEplObdTypDomain)) + { // not numerical types + *pfEntryNumerical_p = FALSE; + } + else + { // numerical types + *pfEntryNumerical_p = TRUE; + } + + return Ret; + +} + + +// ------------------------------------------------------------------------- +// function to classify object type (fixed/non fixed) +// ------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Function: EplObdCallStoreCallback() +// +// Description: checks address to callback function and calles it when unequal +// to NULL +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = (instance pointer) +// pCbStoreParam_p = address to callback parameters +// +// Returns: tEplKernel = error code +// ---------------------------------------------------------------------------- +#if (EPL_OBD_USE_STORE_RESTORE != FALSE) +static tEplKernel EplObdCallStoreCallback (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdCbStoreParam MEM* pCbStoreParam_p) +{ + +tEplKernel Ret = kEplSuccessful; + + ASSERT (pCbStoreParam_p != NULL); + + // check if function pointer is NULL - if so, no callback should be called + if (EPL_MCO_GLB_VAR (m_fpStoreLoadObjCallback) != NULL) + { + Ret = EPL_MCO_GLB_VAR (m_fpStoreLoadObjCallback) (EPL_MCO_INSTANCE_PARAM_IDX_() + pCbStoreParam_p); + } + + return Ret; + +} +#endif // (EPL_OBD_USE_STORE_RESTORE != FALSE) +//--------------------------------------------------------------------------- +// +// Function: EplObdGetObjectDataPtrIntern() +// +// Description: Function gets the data pointer of an object. +// It returnes the current data pointer. But if object is an +// constant object it returnes the default pointer. +// +// Parameters: pSubindexEntry_p = pointer to subindex entry +// +// Return: void * = pointer to object data +// +// State: +// +//--------------------------------------------------------------------------- + +void * EplObdGetObjectDataPtrIntern (tEplObdSubEntryPtr pSubindexEntry_p) +{ + +void * pData; +tEplObdAccess Access; + + ASSERTMSG (pSubindexEntry_p != NULL, "EplObdGetObjectDataPtrIntern(): pointer to SubEntry not valid!\n"); + + // there are are some objects whose data pointer has to get from other structure + // get access type for this object + Access = pSubindexEntry_p->m_Access; + + // If object has access type = const, + // for data only exists default values. + if ((Access & kEplObdAccConst) != 0) + { + // The pointer to defualt value can be received from ObdGetObjectDefaultPtr() + pData = ((void *) EplObdGetObjectDefaultPtr (pSubindexEntry_p)); + } + else + { + // The pointer to current value can be received from ObdGetObjectCurrentPtr() + pData = ((void *) EplObdGetObjectCurrentPtr (pSubindexEntry_p)); + } + + return pData; + +} +#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) +// EOF + diff --git a/drivers/staging/epl/EplObd.h b/drivers/staging/epl/EplObd.h new file mode 100644 index 0000000..4adf680 --- /dev/null +++ b/drivers/staging/epl/EplObd.h @@ -0,0 +1,504 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for api function of EplOBD-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObd.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + Microsoft VC7 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/02 k.t.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#include "EplInc.h" + +#ifndef _EPLOBD_H_ +#define _EPLOBD_H_ + + +// ============================================================================ +// defines +// ============================================================================ + +#define EPL_OBD_TABLE_INDEX_END 0xFFFF + +// for the usage of BOOLEAN in OD +#define OBD_TRUE 0x01 +#define OBD_FALSE 0x00 + +// default OD index for Node id +#define EPL_OBD_NODE_ID_INDEX 0x1F93 +// default subindex for NodeId in OD +#define EPL_OBD_NODE_ID_SUBINDEX 0x01 +// default subindex for NodeIDByHW_BOOL +#define EPL_OBD_NODE_ID_HWBOOL_SUBINDEX 0x02 + +// ============================================================================ +// enums +// ============================================================================ + +// directions for access to object dictionary +typedef enum +{ + kEplObdDirInit = 0x00, // initialising after power on + kEplObdDirStore = 0x01, // store all object values to non volatile memory + kEplObdDirLoad = 0x02, // load all object values from non volatile memory + kEplObdDirRestore = 0x03, // deletes non volatile memory (restore) + kEplObdDirOBKCheck = 0xFF // reserved + +}tEplObdDir; + +// commands for store +typedef enum +{ + kEplObdCommNothing = 0x00, + kEplObdCommOpenWrite = 0x01, + kEplObdCommWriteObj = 0x02, + kEplObdCommCloseWrite = 0x03, + kEplObdCommOpenRead = 0x04, + kEplObdCommReadObj = 0x05, + kEplObdCommCloseRead = 0x06, + kEplObdCommClear = 0x07, + kEplObdCommUnknown = 0xFF +}tEplObdCommand; + +//----------------------------------------------------------------------------------------------------------- +// events of object callback function +typedef enum +{ +// m_pArg points to +// --------------------- + kEplObdEvCheckExist = 0x06, // checking if object does exist (reading and writing) NULL + kEplObdEvPreRead = 0x00, // before reading an object source data buffer in OD + kEplObdEvPostRead = 0x01, // after reading an object destination data buffer from caller + kEplObdEvWrStringDomain = 0x07, // event for changing string/domain data pointer or size struct tEplObdVStringDomain in RAM + kEplObdEvInitWrite = 0x04, // initializes writing an object (checking object size) size of object in OD (tEplObdSize) + kEplObdEvPreWrite = 0x02, // before writing an object source data buffer from caller + kEplObdEvPostWrite = 0x03, // after writing an object destination data buffer in OD +// kEplObdEvAbortSdo = 0x05 // after an abort of an SDO transfer + +} tEplObdEvent; + +// part of OD (bit oriented) +typedef unsigned int tEplObdPart; + +#define kEplObdPartNo 0x00 // nothing +#define kEplObdPartGen 0x01 // part (0x1000 - 0x1FFF) +#define kEplObdPartMan 0x02 // manufacturer part (0x2000 - 0x5FFF) +#define kEplObdPartDev 0x04 // device part (0x6000 - 0x9FFF) +#define kEplObdPartUsr 0x08 // dynamic part e.g. for ICE61131-3 + +// combinations +#define kEplObdPartApp ( kEplObdPartMan | kEplObdPartDev | kEplObdPartUsr) // manufacturer and device part (0x2000 - 0x9FFF) and user OD +#define kEplObdPartAll (kEplObdPartGen | kEplObdPartMan | kEplObdPartDev | kEplObdPartUsr) // whole OD + +//----------------------------------------------------------------------------------------------------------- +// access types for objects +// must be a difine because bit-flags +typedef unsigned int tEplObdAccess; + +#define kEplObdAccRead 0x01 // object can be read +#define kEplObdAccWrite 0x02 // object can be written +#define kEplObdAccConst 0x04 // object contains a constant value +#define kEplObdAccPdo 0x08 // object can be mapped in a PDO +#define kEplObdAccArray 0x10 // object contains an array of numerical values +#define kEplObdAccRange 0x20 // object contains lower and upper limit +#define kEplObdAccVar 0x40 // object data is placed in application +#define kEplObdAccStore 0x80 // object data can be stored to non volatile memory + +// combinations (not all combinations are required) +#define kEplObdAccR (0 | 0 | 0 | 0 | 0 | 0 | kEplObdAccRead) +#define kEplObdAccW (0 | 0 | 0 | 0 | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccRW (0 | 0 | 0 | 0 | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccCR (0 | 0 | 0 | 0 | kEplObdAccConst | 0 | kEplObdAccRead) +#define kEplObdAccGR (0 | 0 | kEplObdAccRange | 0 | 0 | 0 | kEplObdAccRead) +#define kEplObdAccGW (0 | 0 | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccGRW (0 | 0 | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccVR (0 | kEplObdAccVar | 0 | 0 | 0 | 0 | kEplObdAccRead) +#define kEplObdAccVW (0 | kEplObdAccVar | 0 | 0 | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccVRW (0 | kEplObdAccVar | 0 | 0 | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccVPR (0 | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | 0 | kEplObdAccRead) +#define kEplObdAccVPW (0 | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccVPRW (0 | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccVGR (0 | kEplObdAccVar | kEplObdAccRange | 0 | 0 | 0 | kEplObdAccRead) +#define kEplObdAccVGW (0 | kEplObdAccVar | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccVGRW (0 | kEplObdAccVar | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccVGPR (0 | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | 0 | kEplObdAccRead) +#define kEplObdAccVGPW (0 | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccVGPRW (0 | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccSR (kEplObdAccStore | 0 | 0 | 0 | 0 | 0 | kEplObdAccRead) +#define kEplObdAccSW (kEplObdAccStore | 0 | 0 | 0 | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccSRW (kEplObdAccStore | 0 | 0 | 0 | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccSCR (kEplObdAccStore | 0 | 0 | 0 | kEplObdAccConst | 0 | kEplObdAccRead) +#define kEplObdAccSGR (kEplObdAccStore | 0 | kEplObdAccRange | 0 | 0 | 0 | kEplObdAccRead) +#define kEplObdAccSGW (kEplObdAccStore | 0 | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccSGRW (kEplObdAccStore | 0 | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccSVR (kEplObdAccStore | kEplObdAccVar | 0 | 0 | 0 | 0 | kEplObdAccRead) +#define kEplObdAccSVW (kEplObdAccStore | kEplObdAccVar | 0 | 0 | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccSVRW (kEplObdAccStore | kEplObdAccVar | 0 | 0 | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccSVPR (kEplObdAccStore | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | 0 | kEplObdAccRead) +#define kEplObdAccSVPW (kEplObdAccStore | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccSVPRW (kEplObdAccStore | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccSVGR (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | 0 | 0 | 0 | kEplObdAccRead) +#define kEplObdAccSVGW (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccSVGRW (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | kEplObdAccRead) +#define kEplObdAccSVGPR (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | 0 | kEplObdAccRead) +#define kEplObdAccSVGPW (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | kEplObdAccWrite | 0 ) +#define kEplObdAccSVGPRW (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | kEplObdAccWrite | kEplObdAccRead) + + + +typedef unsigned int tEplObdSize; // For all objects as objects size are used an unsigned int. + + +// ------------------------------------------------------------------------- +// types for data types defined in DS301 +// ------------------------------------------------------------------------- + +// types of objects in object dictionary +// DS-301 defines these types as WORD +typedef enum +{ +// types which are always supported + kEplObdTypBool = 0x0001, + + kEplObdTypInt8 = 0x0002, + kEplObdTypInt16 = 0x0003, + kEplObdTypInt32 = 0x0004, + kEplObdTypUInt8 = 0x0005, + kEplObdTypUInt16 = 0x0006, + kEplObdTypUInt32 = 0x0007, + kEplObdTypReal32 = 0x0008, + kEplObdTypVString = 0x0009, + kEplObdTypOString = 0x000A, + kEplObdTypDomain = 0x000F, + + kEplObdTypInt24 = 0x0010, + kEplObdTypUInt24 = 0x0016, + + kEplObdTypReal64 = 0x0011, + kEplObdTypInt40 = 0x0012, + kEplObdTypInt48 = 0x0013, + kEplObdTypInt56 = 0x0014, + kEplObdTypInt64 = 0x0015, + kEplObdTypUInt40 = 0x0018, + kEplObdTypUInt48 = 0x0019, + kEplObdTypUInt56 = 0x001A, + kEplObdTypUInt64 = 0x001B, + kEplObdTypTimeOfDay = 0x000C, + kEplObdTypTimeDiff = 0x000D + +}tEplObdType; +// other types are not supported in this version + + +// ------------------------------------------------------------------------- +// types for data types defined in DS301 +// ------------------------------------------------------------------------- + +typedef unsigned char tEplObdBoolean; // 0001 +typedef signed char tEplObdInteger8; // 0002 +typedef signed short int tEplObdInteger16; // 0003 +typedef signed long tEplObdInteger32; // 0004 +typedef unsigned char tEplObdUnsigned8; // 0005 +typedef unsigned short int tEplObdUnsigned16; // 0006 +typedef unsigned long tEplObdUnsigned32; // 0007 +typedef float tEplObdReal32; // 0008 +typedef unsigned char tEplObdDomain; // 000F +typedef signed long tEplObdInteger24; // 0010 +typedef unsigned long tEplObdUnsigned24; // 0016 + +typedef signed QWORD tEplObdInteger40; // 0012 +typedef signed QWORD tEplObdInteger48; // 0013 +typedef signed QWORD tEplObdInteger56; // 0014 +typedef signed QWORD tEplObdInteger64; // 0015 + +typedef unsigned QWORD tEplObdUnsigned40; // 0018 +typedef unsigned QWORD tEplObdUnsigned48; // 0019 +typedef unsigned QWORD tEplObdUnsigned56; // 001A +typedef unsigned QWORD tEplObdUnsigned64; // 001B + +typedef double tEplObdReal64; // 0011 + +typedef tTimeOfDay tEplObdTimeOfDay; // 000C +typedef tTimeOfDay tEplObdTimeDifference; // 000D + + +// ------------------------------------------------------------------------- +// structur for defining a variable +// ------------------------------------------------------------------------- +// ------------------------------------------------------------------------- +typedef enum +{ + kVarValidSize = 0x01, + kVarValidData = 0x02, +// kVarValidCallback = 0x04, +// kVarValidArg = 0x08, + + kVarValidAll = 0x03 // currently only size and data are implemented and used + +}tEplVarParamValid; + + +typedef tEplKernel (PUBLIC ROM* tEplVarCallback) (CCM_DECL_INSTANCE_HDL_ + void * pParam_p); + +typedef struct +{ + tEplVarParamValid m_ValidFlag; + unsigned int m_uiIndex; + unsigned int m_uiSubindex; + tEplObdSize m_Size; + void MEM* m_pData; +// tEplVarCallback m_fpCallback; +// void * m_pArg; + +} tEplVarParam; + +typedef struct +{ + void MEM* m_pData; + tEplObdSize m_Size; +/* + #if (EPL_PDO_USE_STATIC_MAPPING == FALSE) + tEplVarCallback m_fpCallback; + void * m_pArg; + #endif +*/ +} tEplObdVarEntry; + +typedef struct +{ + tEplObdSize m_Size; + BYTE * m_pString; + +} tEplObdOString; // 000C + +typedef struct +{ + tEplObdSize m_Size; + char * m_pString; +} tEplObdVString; // 000D + + +typedef struct +{ + tEplObdSize m_Size; + char * m_pDefString; // $$$ d.k. it is unused, so we could delete it + char * m_pString; + +} tEplObdVStringDef; + +typedef struct +{ + tEplObdSize m_Size; + BYTE * m_pDefString; // $$$ d.k. it is unused, so we could delete it + BYTE * m_pString; + +} tEplObdOStringDef; + +//r.d. parameter struct for changing object size and/or pointer to data of Strings or Domains +typedef struct +{ + tEplObdSize m_DownloadSize; // download size from SDO or APP + tEplObdSize m_ObjSize; // current object size from OD - should be changed from callback function + void * m_pData; // current object ptr from OD - should be changed from callback function + +} tEplObdVStringDomain; // 000D + + +// ============================================================================ +// types +// ============================================================================ +// ------------------------------------------------------------------------- +// subindexstruct +// ------------------------------------------------------------------------- + +// Change not the order for this struct!!! +typedef struct +{ + unsigned int m_uiSubIndex; + tEplObdType m_Type; + tEplObdAccess m_Access; + void * m_pDefault; + void MEM* m_pCurrent; // points always to RAM + +} tEplObdSubEntry; + +// r.d.: has always to be because new OBD-Macros for arrays +typedef tEplObdSubEntry * tEplObdSubEntryPtr; + +// ------------------------------------------------------------------------- +// callback function for objdictionary modul +// ------------------------------------------------------------------------- + +// parameters for callback function +typedef struct +{ + tEplObdEvent m_ObdEvent; + unsigned int m_uiIndex; + unsigned int m_uiSubIndex; + void * m_pArg; + DWORD m_dwAbortCode; + +} tEplObdCbParam; + +// define type for callback function: pParam_p points to tEplObdCbParam +typedef tEplKernel (PUBLIC ROM* tEplObdCallback) (CCM_DECL_INSTANCE_HDL_ + tEplObdCbParam MEM* pParam_p); + +// do not change the order for this struct!!! + +typedef struct +{ + unsigned int m_uiIndex; + tEplObdSubEntryPtr m_pSubIndex; + unsigned int m_uiCount; + tEplObdCallback m_fpCallback; // function is called back if object access + +} tEplObdEntry; + + +// allways pointer +typedef tEplObdEntry * tEplObdEntryPtr; + + + +// ------------------------------------------------------------------------- +// structur to initialize OBD module +// ------------------------------------------------------------------------- + +typedef struct +{ + tEplObdEntryPtr m_pPart; + tEplObdEntryPtr m_pManufacturerPart; + tEplObdEntryPtr m_pDevicePart; + + #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) + + tEplObdEntryPtr m_pUserPart; + + #endif + +} tEplObdInitParam; + + +// ------------------------------------------------------------------------- +// structur for parameters of STORE RESTORE command +// ------------------------------------------------------------------------- + +typedef struct +{ + tEplObdCommand m_bCommand; + tEplObdPart m_bCurrentOdPart; + void MEM* m_pData; + tEplObdSize m_ObjSize; + +} tEplObdCbStoreParam; + + +typedef tEplKernel (PUBLIC ROM* tInitTabEntryCallback) ( + void MEM* pTabEntry_p, + unsigned int uiObjIndex_p); + +typedef tEplKernel (PUBLIC ROM* tEplObdStoreLoadObjCallback) (CCM_DECL_INSTANCE_HDL_ + tEplObdCbStoreParam MEM* pCbStoreParam_p); + +// ------------------------------------------------------------------------- +// this stucture is used for parameters for function ObdInitModuleTab() +// ------------------------------------------------------------------------- +typedef struct +{ + unsigned int m_uiLowerObjIndex; // lower limit of ObjIndex + unsigned int m_uiUpperObjIndex; // upper limit of ObjIndex + tInitTabEntryCallback m_fpInitTabEntry; // will be called if ObjIndex was found + void MEM* m_pTabBase; // base address of table + unsigned int m_uiEntrySize; // size of table entry // 25-feb-2005 r.d.: expansion from BYTE to WORD necessary for PDO bit mapping + unsigned int m_uiMaxEntries; // max. tabel entries + +} tEplObdModulTabParam; + +//------------------------------------------------------------------- +// enum for function EplObdSetNodeId +//------------------------------------------------------------------- +typedef enum +{ + kEplObdNodeIdUnknown = 0x00, // unknown how the node id was set + kEplObdNodeIdSoftware = 0x01, // node id set by software + kEplObdNodeIdHardware = 0x02 // node id set by hardware + +}tEplObdNodeIdType; + +// ============================================================================ +// global variables +// ============================================================================ + + + +// ============================================================================ +// public functions +// ============================================================================ + + +#endif // #ifndef _EPLOBD_H_ + + diff --git a/drivers/staging/epl/EplObdMacro.h b/drivers/staging/epl/EplObdMacro.h new file mode 100644 index 0000000..c15c360 --- /dev/null +++ b/drivers/staging/epl/EplObdMacro.h @@ -0,0 +1,362 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for macros of EplOBD-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObdMacro.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/05 k.t.: start of the implementation + -> based on CANopen ObdMacro.h + + + +****************************************************************************/ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#if defined (EPL_OBD_DEFINE_MACRO) + + //------------------------------------------------------------------------------------------- + #if defined (EPL_OBD_CREATE_ROM_DATA) + +// #pragma message ("EPL_OBD_CREATE_ROM_DATA") + + #define EPL_OBD_BEGIN() static DWORD dwObd_OBK_g = 0x0000; + #define EPL_OBD_END() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_PART_GENERIC() + #define EPL_OBD_BEGIN_PART_MANUFACTURER() + #define EPL_OBD_BEGIN_PART_DEVICE() + #define EPL_OBD_END_PART() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) + #define EPL_OBD_END_INDEX(ind) + #define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdUnsigned8 xDef##ind##_0x00_g = (cnt); \ + static dtyp xDef##ind##_0x01_g = (def); + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdUnsigned8 xDef##ind##_0x00_g = (cnt); \ + static dtyp xDef##ind##_0x01_g = (def); + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdUnsigned8 xDef##ind##_0x00_g = (cnt); + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) static dtyp xDef##ind##_##sub##_g = val; + #define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp xDef##ind##_##sub##_g[3] = {val,low,high}; + #define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) + #define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) static char MEM szCur##ind##_##sub##_g[size+1]; \ + static tEplObdVStringDef xDef##ind##_##sub##_g = {size, val, szCur##ind##_##sub##_g}; + + #define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) static BYTE MEM bCur##ind##_##sub##_g[size]; \ + static tEplObdOStringDef xDef##ind##_##sub##_g = {size, ((BYTE*)""), bCur##ind##_##sub##_g}; + #define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) + #define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) static dtyp xDef##ind##_##sub##_g = val; + #define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp xDef##ind##_##sub##_g[3] = {val,low,high}; + #define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) + +//------------------------------------------------------------------------------------------- + #elif defined (EPL_OBD_CREATE_RAM_DATA) + +// #pragma message ("EPL_OBD_CREATE_RAM_DATA") + + #define EPL_OBD_BEGIN() + #define EPL_OBD_END() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_PART_GENERIC() + #define EPL_OBD_BEGIN_PART_MANUFACTURER() + #define EPL_OBD_BEGIN_PART_DEVICE() + #define EPL_OBD_END_PART() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) + #define EPL_OBD_END_INDEX(ind) + #define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static dtyp MEM axCur##ind##_g[cnt]; + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdVarEntry MEM aVarEntry##ind##_g[cnt]; + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdVarEntry MEM aVarEntry##ind##_g[cnt]; + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) static dtyp MEM xCur##ind##_##sub##_g; + #define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp MEM xCur##ind##_##sub##_g; + #define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) static tEplObdVString MEM xCur##ind##_##sub##_g; + #define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) static tEplObdOString MEM xCur##ind##_##sub##_g; + #define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) static dtyp MEM xCur##ind##_##sub##_g; + #define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g; + #define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g; + #define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g; + #define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g; + + //------------------------------------------------------------------------------------------- + #elif defined (EPL_OBD_CREATE_SUBINDEX_TAB) + +// #pragma message ("EPL_OBD_CREATE_SUBINDEX_TAB") + + #define EPL_OBD_BEGIN() + #define EPL_OBD_END() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_PART_GENERIC() + #define EPL_OBD_BEGIN_PART_MANUFACTURER() + #define EPL_OBD_BEGIN_PART_DEVICE() + #define EPL_OBD_END_PART() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[cnt]= { + #define EPL_OBD_END_INDEX(ind) EPL_OBD_END_SUBINDEX()}; + #define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[]= { \ + {0, kEplObdTypUInt8, kEplObdAccCR, &xDef##ind##_0x00_g, NULL}, \ + {1, typ, (acc)|kEplObdAccArray, &xDef##ind##_0x01_g, &axCur##ind##_g[0]}, \ + EPL_OBD_END_SUBINDEX()}; + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[]= { \ + {0, kEplObdTypUInt8, kEplObdAccCR, &xDef##ind##_0x00_g, NULL}, \ + {1, typ, (acc)|kEplObdAccArray|kEplObdAccVar, &xDef##ind##_0x01_g, &aVarEntry##ind##_g[0]}, \ + EPL_OBD_END_SUBINDEX()}; + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[]= { \ + {0, kEplObdTypUInt8, kEplObdAccCR, &xDef##ind##_0x00_g, NULL}, \ + {1, typ, (acc)|kEplObdAccArray|kEplObdAccVar, NULL, &aVarEntry##ind##_g[0]}, \ + EPL_OBD_END_SUBINDEX()}; + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) {sub,typ, (acc), &xDef##ind##_##sub##_g, &xCur##ind##_##sub##_g}, + #define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) {sub,typ, (acc)|kEplObdAccRange, &xDef##ind##_##sub##_g[0],&xCur##ind##_##sub##_g}, + #define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) {sub,typ, (acc), NULL, &xCur##ind##_##sub##_g}, + #define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) {sub,kEplObdTypVString,(acc)/*|kEplObdAccVar*/, &xDef##ind##_##sub##_g, &xCur##ind##_##sub##_g}, + #define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) {sub,kEplObdTypOString,(acc)/*|kEplObdAccVar*/, &xDef##ind##_##sub##_g, &xCur##ind##_##sub##_g}, + #define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) {sub,kEplObdTypDomain, (acc)|kEplObdAccVar, NULL, &VarEntry##ind##_##sub##_g}, + #define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) {sub,typ, (acc)|kEplObdAccVar, &xDef##ind##_##sub##_g, &VarEntry##ind##_##sub##_g}, + #define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) {sub,typ, (acc)|kEplObdAccVar|kEplObdAccRange,&xDef##ind##_##sub##_g[0],&VarEntry##ind##_##sub##_g}, + #define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) {sub,typ, (acc)|kEplObdAccVar, NULL, &VarEntry##ind##_##sub##_g}, + + + //------------------------------------------------------------------------------------------- + #elif defined (EPL_OBD_CREATE_INDEX_TAB) + +// #pragma message ("EPL_OBD_CREATE_INDEX_TAB") + + #define EPL_OBD_BEGIN() + #define EPL_OBD_END() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_PART_GENERIC() static tEplObdEntry aObdTab_g[] = { + #define EPL_OBD_BEGIN_PART_MANUFACTURER() static tEplObdEntry aObdTabManufacturer_g[] = { + #define EPL_OBD_BEGIN_PART_DEVICE() static tEplObdEntry aObdTabDevice_g[] = { + #define EPL_OBD_END_PART() {EPL_OBD_TABLE_INDEX_END,(tEplObdSubEntryPtr)&dwObd_OBK_g,0,NULL}}; + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) {ind,(tEplObdSubEntryPtr)&aObdSubEntry##ind##Ram_g[0],cnt,(tEplObdCallback)call}, + #define EPL_OBD_END_INDEX(ind) + #define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) {ind,(tEplObdSubEntryPtr)&aObdSubEntry##ind##Ram_g[0],(cnt)+1,(tEplObdCallback)call}, + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) {ind,(tEplObdSubEntryPtr)&aObdSubEntry##ind##Ram_g[0],(cnt)+1,(tEplObdCallback)call}, + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) {ind,(tEplObdSubEntryPtr)&aObdSubEntry##ind##Ram_g[0],(cnt)+1,(tEplObdCallback)call}, + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) + #define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) + #define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) + #define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) + #define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) + #define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) + #define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) + #define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) + #define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) + + //------------------------------------------------------------------------------------------- + #elif defined (EPL_OBD_CREATE_INIT_FUNCTION) + +// #pragma message ("EPL_OBD_CREATE_INIT_FUNCTION") + + #define EPL_OBD_BEGIN() + #define EPL_OBD_END() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_PART_GENERIC() pInitParam->m_pPart = (tEplObdEntryPtr) &aObdTab_g[0]; + #define EPL_OBD_BEGIN_PART_MANUFACTURER() pInitParam->m_pManufacturerPart = (tEplObdEntryPtr) &aObdTabManufacturer_g[0]; + #define EPL_OBD_BEGIN_PART_DEVICE() pInitParam->m_pDevicePart = (tEplObdEntryPtr) &aObdTabDevice_g[0]; + #define EPL_OBD_END_PART() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) + #define EPL_OBD_END_INDEX(ind) + #define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) + #define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) + #define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) + #define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) + #define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) + #define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) + #define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) + #define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) + #define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) + + + //------------------------------------------------------------------------------------------- + #elif defined (EPL_OBD_CREATE_INIT_SUBINDEX) + +// #pragma message ("EPL_OBD_CREATE_INIT_SUBINDEX") + + #define EPL_OBD_BEGIN() + #define EPL_OBD_END() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_PART_GENERIC() + #define EPL_OBD_BEGIN_PART_MANUFACTURER() + #define EPL_OBD_BEGIN_PART_DEVICE() + #define EPL_OBD_END_PART() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) //CCM_SUBINDEX_RAM_ONLY (EPL_MEMCPY (&aObdSubEntry##ind##Ram_g[0],&aObdSubEntry##ind##Rom_g[0],sizeof(aObdSubEntry##ind##Ram_g))); + #define EPL_OBD_END_INDEX(ind) + #define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) //EPL_MEMCPY (&aObdSubEntry##ind##Ram_g[0],&aObdSubEntry##ind##Rom_g[0],sizeof(aObdSubEntry##ind##Ram_g)); + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) //EPL_MEMCPY (&aObdSubEntry##ind##Ram_g[0],&aObdSubEntry##ind##Rom_g[0],sizeof(aObdSubEntry##ind##Ram_g)); + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) //EPL_MEMCPY (&aObdSubEntry##ind##Ram_g[0],&aObdSubEntry##ind##Rom_g[0],sizeof(aObdSubEntry##ind##Ram_g)); + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) + #define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) + #define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) + #define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) + #define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) + #define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) + #define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) + #define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) + #define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) + + //------------------------------------------------------------------------------------------- + #else + +// #pragma message ("ELSE OF DEFINE") + + #define EPL_OBD_BEGIN() + #define EPL_OBD_END() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_PART_GENERIC() + #define EPL_OBD_BEGIN_PART_MANUFACTURER() + #define EPL_OBD_BEGIN_PART_DEVICE() + #define EPL_OBD_END_PART() + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) + #define EPL_OBD_END_INDEX(ind) + #define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) + #define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) + + //--------------------------------------------------------------------------------------- + #define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) + #define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) + #define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,sizes,val) + #define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) + #define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) + #define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) + #define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) + #define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) + #define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) + + #endif + + //------------------------------------------------------------------------------------------- +#elif defined (EPL_OBD_UNDEFINE_MACRO) + +// #pragma message ("EPL_OBD_UNDEFINE_MACRO") + + #undef EPL_OBD_BEGIN + #undef EPL_OBD_END + + //--------------------------------------------------------------------------------------- + #undef EPL_OBD_BEGIN_PART_GENERIC + #undef EPL_OBD_BEGIN_PART_MANUFACTURER + #undef EPL_OBD_BEGIN_PART_DEVICE + #undef EPL_OBD_END_PART + + //--------------------------------------------------------------------------------------- + #undef EPL_OBD_BEGIN_INDEX_RAM + #undef EPL_OBD_END_INDEX + #undef EPL_OBD_RAM_INDEX_RAM_ARRAY + #undef EPL_OBD_RAM_INDEX_RAM_VARARRAY + #undef EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT + + //--------------------------------------------------------------------------------------- + #undef EPL_OBD_SUBINDEX_RAM_VAR + #undef EPL_OBD_SUBINDEX_RAM_VAR_RG + #undef EPL_OBD_SUBINDEX_RAM_VSTRING + #undef EPL_OBD_SUBINDEX_RAM_OSTRING + #undef EPL_OBD_SUBINDEX_RAM_VAR_NOINIT + #undef EPL_OBD_SUBINDEX_RAM_DOMAIN + #undef EPL_OBD_SUBINDEX_RAM_USERDEF + #undef EPL_OBD_SUBINDEX_RAM_USERDEF_RG + #undef EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT + +#else + + #error "nothing defined" + + +#endif + + diff --git a/drivers/staging/epl/EplObdkCal.c b/drivers/staging/epl/EplObdkCal.c new file mode 100644 index 0000000..f94a150 --- /dev/null +++ b/drivers/staging/epl/EplObdkCal.c @@ -0,0 +1,154 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for communication abstraction layer + for the Epl-Obd-Kernelspace-Modul + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObdkCal.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + KEIL uVision 2 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/19 k.t.: start of the implementation + +****************************************************************************/ + +#include "EplInc.h" +#include "kernel/EplObdkCal.h" + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + + + +// EOF + diff --git a/drivers/staging/epl/EplObdu.c b/drivers/staging/epl/EplObdu.c new file mode 100644 index 0000000..46370cb --- /dev/null +++ b/drivers/staging/epl/EplObdu.c @@ -0,0 +1,512 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for Epl-Obd-Userspace-module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObdu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/19 k.t.: start of the implementation + +****************************************************************************/ + +#include "EplInc.h" +#include "user/EplObdu.h" +#include "user/EplObduCal.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplObduWriteEntry() +// +// Description: Function writes data to an OBD entry. Strings +// are stored with added '\0' character. +// +// Parameters: uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pSrcData_p = Pointer to the data to write +// Size_p = Size of the data in Byte +// +// Return: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntry (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p) +{ +tEplKernel Ret; + + Ret = EplObduCalWriteEntry(uiIndex_p, uiSubIndex_p, pSrcData_p, Size_p); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObduReadEntry() +// +// Description: The function reads an object entry. The application +// can always read the data even if attrib kEplObdAccRead +// is not set. The attrib is only checked up for SDO transfer. +// +// Parameters: uiIndex_p = Index oof the OD entry to read +// uiSubIndex_p = Subindex to read +// pDstData_p = pointer to the buffer for data +// Offset_p = offset in data for read access +// pSize_p = IN: Size of the buffer +// OUT: number of readed Bytes +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntry (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize* pSize_p) +{ +tEplKernel Ret; + + Ret = EplObduCalReadEntry(uiIndex_p, uiSubIndex_p, pDstData_p, pSize_p); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObdAccessOdPart() +// +// Description: restores default values of one part of OD +// +// Parameters: ObdPart_p = od-part to reset +// Direction_p = directory flag for +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduAccessOdPart (tEplObdPart ObdPart_p, + tEplObdDir Direction_p) +{ +tEplKernel Ret; + + Ret = EplObduCalAccessOdPart(ObdPart_p, Direction_p); + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduDefineVar() +// +// Description: defines a variable in OD +// +// Parameters: pEplVarParam_p = varentry +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduDefineVar (tEplVarParam MEM* pVarParam_p) +{ +tEplKernel Ret; + + Ret = EplObduCalDefineVar(pVarParam_p); + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduGetObjectDataPtr() +// +// Description: It returnes the current data pointer. But if object is an +// constant object it returnes the default pointer. +// +// Parameters: uiIndex_p = Index of the entry +// uiSubindex_p = Subindex of the entry +// +// Return: void * = pointer to object data +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT void* PUBLIC EplObduGetObjectDataPtr (unsigned int uiIndex_p, + unsigned int uiSubIndex_p) +{ +void* pData; + + pData = EplObduCalGetObjectDataPtr(uiIndex_p, uiSubIndex_p); + + return pData; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduRegisterUserOd() +// +// Description: function registers the user OD +// +// Parameters: pUserOd_p =pointer to user ODd +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- +#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) +EPLDLLEXPORT tEplKernel PUBLIC EplObduRegisterUserOd (tEplObdEntryPtr pUserOd_p) +{ +tEplKernel Ret; + + Ret = EplObduCalRegisterUserOd(pUserOd_p); + + return Ret; + +} +#endif +//--------------------------------------------------------------------------- +// +// Function: EplObduInitVarEntry() +// +// Description: function to initialize VarEntry dependened on object type +// +// Parameters: pVarEntry_p = pointer to var entry structure +// bType_p = object type +// ObdSize_p = size of object data +// +// Returns: none +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT void PUBLIC EplObduInitVarEntry (tEplObdVarEntry MEM* pVarEntry_p, + BYTE bType_p, tEplObdSize ObdSize_p) +{ + EplObduCalInitVarEntry(pVarEntry_p, bType_p, ObdSize_p); +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduGetDataSize() +// +// Description: function to initialize VarEntry dependened on object type +// +// gets the data size of an object +// for string objects it returnes the string length +// +// Parameters: uiIndex_p = Index +// uiSubIndex_p= Subindex +// +// Return: tEplObdSize +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplObdSize PUBLIC EplObduGetDataSize(unsigned int uiIndex_p, + unsigned int uiSubIndex_p) +{ +tEplObdSize Size; + + Size = EplObduCalGetDataSize(uiIndex_p, uiSubIndex_p); + + return Size; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduGetNodeId() +// +// Description: function returns nodeid from entry 0x1F93 +// +// +// Parameters: +// +// Return: unsigned int = Node Id +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT unsigned int PUBLIC EplObduGetNodeId() +{ +unsigned int uiNodeId; + + uiNodeId = EplObduCalGetNodeId(); + + return uiNodeId; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduSetNodeId() +// +// Description: function sets nodeid in entry 0x1F93 +// +// +// Parameters: uiNodeId_p = Node Id to set +// NodeIdType_p= Type on which way the Node Id was set +// +// Return: tEplKernel = Errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduSetNodeId(unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p) +{ +tEplKernel Ret; + + Ret = EplObduCalSetNodeId(uiNodeId_p, NodeIdType_p); + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduGetAccessType() +// +// Description: Function returns accesstype of the entry +// +// Parameters: uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pAccessTyp_p = pointer to buffer to store accesstyp +// +// Return: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduGetAccessType(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess* pAccessTyp_p) +{ +tEplObdAccess AccessType; + + AccessType = EplObduCalGetAccessType(uiIndex_p, uiSubIndex_p, pAccessTyp_p); + + return AccessType; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObdReaduEntryToLe() +// +// Description: The function reads an object entry from the byteoder +// of the system to the little endian byteorder for numeric values. +// For other types a normal read will be processed. This is usefull for +// the PDO and SDO module. The application +// can always read the data even if attrib kEplObdAccRead +// is not set. The attrib is only checked up for SDO transfer. +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ +// uiIndex_p = Index of the OD entry to read +// uiSubIndex_p = Subindex to read +// pDstData_p = pointer to the buffer for data +// Offset_p = offset in data for read access +// pSize_p = IN: Size of the buffer +// OUT: number of readed Bytes +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntryToLe (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize * pSize_p) +{ +tEplKernel Ret; + + Ret = EplObduCalReadEntryToLe(uiIndex_p, uiSubIndex_p, pDstData_p, pSize_p); + +return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduWriteEntryFromLe() +// +// Description: Function writes data to an OBD entry from a source with +// little endian byteorder to the od with system specuific +// byteorder. Not numeric values will only by copied. Strings +// are stored with added '\0' character. +// +// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ +// uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pSrcData_p = Pointer to the data to write +// Size_p = Size of the data in Byte +// +// Return: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntryFromLe (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p) +{ +tEplKernel Ret; + + Ret = EplObduCalWriteEntryFromLe(uiIndex_p, uiSubIndex_p, pSrcData_p, Size_p); + +return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduSearchVarEntry() +// +// Description: gets variable from OD +// +// Parameters: uiIndex_p = index of the var entry to search +// uiSubindex_p = subindex of var entry to search +// ppVarEntry_p = pointer to the pointer to the varentry +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduSearchVarEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry MEM** ppVarEntry_p) +{ +tEplKernel Ret; + + Ret = EplObduCalSearchVarEntry(uiIndex_p, uiSubindex_p, ppVarEntry_p); + +return Ret; +} +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplObduCal.c b/drivers/staging/epl/EplObduCal.c new file mode 100644 index 0000000..d309c5e --- /dev/null +++ b/drivers/staging/epl/EplObduCal.c @@ -0,0 +1,562 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for communication abstraction layer + for the Epl-Obd-Userspace-Modul + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObduCal.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/19 k.t.: start of the implementation + +****************************************************************************/ +#include "EplInc.h" +#include "user/EplObduCal.h" +#include "kernel/EplObdk.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) && (EPL_OBD_USE_KERNEL != FALSE) + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalWriteEntry() +// +// Description: Function encapsulate access of function EplObdWriteEntry +// +// Parameters: uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pSrcData_p = Pointer to the data to write +// Size_p = Size of the data in Byte +// +// Return: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntry ( + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p) +{ +tEplKernel Ret; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Ret = EplObdWriteEntry(uiIndex_p,uiSubIndex_p,pSrcData_p,Size_p); +#else + Ret = kEplSuccessful; +#endif + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalReadEntry() +// +// Description: Function encapsulate access of function EplObdReadEntry +// +// Parameters: uiIndex_p = Index oof the OD entry to read +// uiSubIndex_p = Subindex to read +// pDstData_p = pointer to the buffer for data +// Offset_p = offset in data for read access +// pSize_p = IN: Size of the buffer +// OUT: number of readed Bytes +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntry ( + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize *pSize_p) +{ +tEplKernel Ret; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Ret = EplObdReadEntry(uiIndex_p, uiSubIndex_p, pDstData_p, pSize_p); +#else + Ret = kEplSuccessful; +#endif + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalAccessOdPart() +// +// Description: Function encapsulate access of function EplObdAccessOdPart +// +// Parameters: ObdPart_p = od-part to reset +// Direction_p = directory flag for +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalAccessOdPart ( + tEplObdPart ObdPart_p, + tEplObdDir Direction_p) +{ +tEplKernel Ret; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Ret = EplObdAccessOdPart(ObdPart_p, Direction_p); +#else + Ret = kEplSuccessful; +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalDefineVar() +// +// Description: Function encapsulate access of function EplObdDefineVar +// +// Parameters: pEplVarParam_p = varentry +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalDefineVar (tEplVarParam MEM* pVarParam_p) +{ +tEplKernel Ret; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Ret = EplObdDefineVar(pVarParam_p); +#else + Ret = kEplSuccessful; +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalGetObjectDataPtr() +// +// Description: Function encapsulate access of function EplObdGetObjectDataPtr +// +// Parameters: uiIndex_p = Index of the entry +// uiSubindex_p = Subindex of the entry +// +// Return: void * = pointer to object data +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT void* PUBLIC EplObduCalGetObjectDataPtr ( unsigned int uiIndex_p, + unsigned int uiSubIndex_p) +{ +void* pData; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + pData = EplObdGetObjectDataPtr(uiIndex_p, uiSubIndex_p); +#else + pData = NULL; +#endif + + return pData; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalRegisterUserOd() +// +// Description: Function encapsulate access of function EplObdRegisterUserOd +// +// Parameters: pUserOd_p = pointer to user OD +// +// Return: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- +#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalRegisterUserOd (tEplObdEntryPtr pUserOd_p) +{ +tEplKernel Ret; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Ret = EplObdRegisterUserOd(pUserOd_p); +#else + Ret = kEplSuccessful; +#endif + + return Ret; + +} +#endif +//--------------------------------------------------------------------------- +// +// Function: EplObduCalInitVarEntry() +// +// Description: Function encapsulate access of function EplObdInitVarEntry +// +// Parameters: pVarEntry_p = pointer to var entry structure +// bType_p = object type +// ObdSize_p = size of object data +// +// Returns: none +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT void PUBLIC EplObduCalInitVarEntry (tEplObdVarEntry MEM* pVarEntry_p, + BYTE bType_p, tEplObdSize ObdSize_p) +{ +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + EplObdInitVarEntry(pVarEntry_p, bType_p, ObdSize_p); +#endif +} + + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalGetDataSize() +// +// Description: Function encapsulate access of function EplObdGetDataSize +// +// gets the data size of an object +// for string objects it returnes the string length +// +// Parameters: uiIndex_p = Index +// uiSubIndex_p= Subindex +// +// Return: tEplObdSize +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplObdSize PUBLIC EplObduCalGetDataSize(unsigned int uiIndex_p, + unsigned int uiSubIndex_p) +{ +tEplObdSize Size; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Size = EplObdGetDataSize(uiIndex_p, uiSubIndex_p); +#else + Size = 0; +#endif + + return Size; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalGetNodeId() +// +// Description: Function encapsulate access of function EplObdGetNodeId +// +// +// Parameters: +// +// Return: unsigned int = Node Id +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT unsigned int PUBLIC EplObduCalGetNodeId() +{ +unsigned int uiNodeId; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + uiNodeId = EplObdGetNodeId(); +#else + uiNodeId = 0; +#endif + + return uiNodeId; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalSetNodeId() +// +// Description: Function encapsulate access of function EplObdSetNodeId +// +// +// Parameters: uiNodeId_p = Node Id to set +// NodeIdType_p= Type on which way the Node Id was set +// +// Return: tEplKernel = Errorcode +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalSetNodeId(unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p) +{ +tEplKernel Ret; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Ret = EplObdSetNodeId(uiNodeId_p, NodeIdType_p); +#else + Ret = kEplSuccessful; +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalGetAccessType() +// +// Description: Function encapsulate access of function EplObdGetAccessType +// +// Parameters: uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pAccessTyp_p = pointer to buffer to store accesstype +// +// Return: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalGetAccessType(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess* pAccessTyp_p) + +{ +tEplObdAccess AccesType; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + AccesType = EplObdGetAccessType(uiIndex_p, uiSubIndex_p, pAccessTyp_p); +#else + AccesType = 0; +#endif + +return AccesType; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalReadEntryToLe() +// +// Description: Function encapsulate access of function EplObdReadEntryToLe +// +// Parameters: uiIndex_p = Index of the OD entry to read +// uiSubIndex_p = Subindex to read +// pDstData_p = pointer to the buffer for data +// Offset_p = offset in data for read access +// pSize_p = IN: Size of the buffer +// OUT: number of readed Bytes +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntryToLe (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize * pSize_p) +{ +tEplKernel Ret; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Ret = EplObdReadEntryToLe(uiIndex_p, uiSubIndex_p, pDstData_p, pSize_p); +#else + Ret = kEplSuccessful; +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalWriteEntryFromLe() +// +// Description: Function encapsulate access of function EplObdWriteEntryFromLe +// +// Parameters: uiIndex_p = Index of the OD entry +// uiSubIndex_p = Subindex of the OD Entry +// pSrcData_p = Pointer to the data to write +// Size_p = Size of the data in Byte +// +// Return: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntryFromLe (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p) +{ +tEplKernel Ret; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Ret = EplObdWriteEntryFromLe(uiIndex_p, uiSubIndex_p, pSrcData_p, Size_p); +#else + Ret = kEplSuccessful; +#endif + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplObduCalSearchVarEntry() +// +// Description: gets variable from OD +// +// Parameters: uiIndex_p = index of the var entry to search +// uiSubindex_p = subindex of var entry to search +// ppVarEntry_p = pointer to the pointer to the varentry +// +// Return: tEplKernel +// +// State: +// +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalSearchVarEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry MEM** ppVarEntry_p) +{ +tEplKernel Ret; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + Ret = EplObdSearchVarEntry(uiIndex_p, uiSubindex_p, ppVarEntry_p); +#else + Ret = kEplSuccessful; +#endif + return Ret; +} + + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + + +// EOF + diff --git a/drivers/staging/epl/EplObjDef.h b/drivers/staging/epl/EplObjDef.h new file mode 100644 index 0000000..5823c14 --- /dev/null +++ b/drivers/staging/epl/EplObjDef.h @@ -0,0 +1,220 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: defines objdict dictionary + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObjDef.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/06 k.t.: take ObjDef.h from CANopen and modify for EPL + +****************************************************************************/ + +#ifndef _EPLOBJDEF_H_ +#define _EPLOBJDEF_H_ + + +//--------------------------------------------------------------------------- +// security checks +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// macros to help building OD +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +#if (defined (EPL_OBD_USE_VARIABLE_SUBINDEX_TAB) && (EPL_OBD_USE_VARIABLE_SUBINDEX_TAB != FALSE)) + + #define CCM_SUBINDEX_RAM_ONLY(a) a; + #define CCM_SUBINDEX_RAM_ONEOF(a,b) a + +#else + + #define CCM_SUBINDEX_RAM_ONLY(a) + #define CCM_SUBINDEX_RAM_ONEOF(a,b) b + +#endif + + +//--------------------------------------------------------------------------- +// To prevent unused memory in subindex tables we need this macro. +// But not all compilers support to preset the last struct value followed by a comma. +// Compilers which does not support a comma after last struct value has to place in a dummy subindex. +#if ((DEV_SYSTEM & _DEV_COMMA_EXT_) != 0) + + #define EPL_OBD_END_SUBINDEX() + #define EPL_OBD_MAX_ARRAY_SUBENTRIES 2 + +#else + + #define EPL_OBD_END_SUBINDEX() {0,0,0,NULL,NULL} + #define EPL_OBD_MAX_ARRAY_SUBENTRIES 3 + +#endif + + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// globale vars +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +// ------------------------------------------------------------------------- +// creation of data in ROM memory +// ------------------------------------------------------------------------- +#define EPL_OBD_CREATE_ROM_DATA + #include "objdict.h" +#undef EPL_OBD_CREATE_ROM_DATA + + +// ------------------------------------------------------------------------- +// creation of data in RAM memory +// ------------------------------------------------------------------------- + +#define EPL_OBD_CREATE_RAM_DATA + #include "objdict.h" +#undef EPL_OBD_CREATE_RAM_DATA + + +// ------------------------------------------------------------------------- +// creation of subindex tables in ROM and RAM +// ------------------------------------------------------------------------- + +#define EPL_OBD_CREATE_SUBINDEX_TAB + #include "objdict.h" +#undef EPL_OBD_CREATE_SUBINDEX_TAB + + +// ------------------------------------------------------------------------- +// creation of index tables for generic, manufacturer and device part +// ------------------------------------------------------------------------- + +#define EPL_OBD_CREATE_INDEX_TAB + #include "objdict.h" +#undef EPL_OBD_CREATE_INDEX_TAB + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +// ---------------------------------------------------------------------------- +// +// Function: EPL_OBD_INIT_RAM_NAME() +// +// Description: function to initialize object dictionary +// +// Parameters: pInitParam_p = pointer to init param struct of Epl +// +// Returns: tEplKernel = error code +// +// State: +// +// ---------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EPL_OBD_INIT_RAM_NAME (tEplObdInitParam MEM* pInitParam_p) +{ + +tEplObdInitParam MEM* pInitParam = pInitParam_p; + + // check if pointer to parameter structure is valid + // if not then only copy subindex tables below + if (pInitParam != NULL) + { + // at first delete all parameters (all pointers will be set zu NULL) + EPL_MEMSET (pInitParam, 0, sizeof (tEplObdInitParam)); + + #define EPL_OBD_CREATE_INIT_FUNCTION + { + // inserts code to init pointer to index tables + #include "objdict.h" + } + #undef EPL_OBD_CREATE_INIT_FUNCTION + + #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) + { + // to begin no user OD is defined + pInitParam_p->m_pUserPart = NULL; + } + #endif + } + + #define EPL_OBD_CREATE_INIT_SUBINDEX + { + // inserts code to copy subindex tables + #include "objdict.h" + } + #undef EPL_OBD_CREATE_INIT_SUBINDEX + + return kEplSuccessful; + +} + + +#endif // _EPLOBJDEF_H_ + +// Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler +// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder). + diff --git a/drivers/staging/epl/EplPdo.h b/drivers/staging/epl/EplPdo.h new file mode 100644 index 0000000..0273a94 --- /dev/null +++ b/drivers/staging/epl/EplPdo.h @@ -0,0 +1,126 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for PDO module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplPdo.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/05/22 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_PDO_H_ +#define _EPL_PDO_H_ + +#include "EplInc.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +// invalid PDO-NodeId +#define EPL_PDO_INVALID_NODE_ID 0xFF +// NodeId for PReq RPDO +#define EPL_PDO_PREQ_NODE_ID 0x00 +// NodeId for PRes TPDO +#define EPL_PDO_PRES_NODE_ID 0x00 + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef struct +{ + void* m_pVar; + WORD m_wOffset; // in Bits + WORD m_wSize; // in Bits + BOOL m_fNumeric; // numeric value -> use AMI functions + +} tEplPdoMapping; + +typedef struct +{ + unsigned int m_uiSizeOfStruct; + unsigned int m_uiPdoId; + unsigned int m_uiNodeId; + // 0xFF=invalid, RPDO: 0x00=PReq, localNodeId=PRes, remoteNodeId=PRes + // TPDO: 0x00=PRes, MN: CnNodeId=PReq + + BOOL m_fTxRx; + BYTE m_bMappingVersion; + unsigned int m_uiMaxMappingEntries; // maximum number of mapping entries, i.e. size of m_aPdoMapping + tEplPdoMapping m_aPdoMapping[1]; + +} tEplPdoParam; + + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPL_PDO_H_ + + diff --git a/drivers/staging/epl/EplPdok.c b/drivers/staging/epl/EplPdok.c new file mode 100644 index 0000000..83c2f29 --- /dev/null +++ b/drivers/staging/epl/EplPdok.c @@ -0,0 +1,692 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for kernel PDO module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplPdok.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/05/22 d.k.: start of the implementation, version 1.00 + +****************************************************************************/ + +#include "kernel/EplPdok.h" +#include "kernel/EplPdokCal.h" +#include "kernel/EplEventk.h" +#include "kernel/EplObdk.h" + +#if (DEV_SYSTEM == _DEV_GNU_CF548X_) +#include "plccore.h" +#define PDO_LED 0x08 +#endif + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) == 0) + + #error 'ERROR: Missing DLLk-Modul!' + +#endif + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) == 0) + + #error 'ERROR: Missing OBDk-Modul!' + +#endif +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#define EPL_PDOK_OBD_IDX_RX_COMM_PARAM 0x1400 +#define EPL_PDOK_OBD_IDX_RX_MAPP_PARAM 0x1600 +#define EPL_PDOK_OBD_IDX_TX_COMM_PARAM 0x1800 +#define EPL_PDOK_OBD_IDX_TX_MAPP_PARAM 0x1A00 + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S EplPdok */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplPdokAddInstance() +// +// Description: add and initialize new instance of EPL stack +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokAddInstance(void) +{ + + return kEplSuccessful; +} + +//--------------------------------------------------------------------------- +// +// Function: EplPdokDelInstance() +// +// Description: deletes an instance of EPL stack +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokDelInstance(void) +{ + + return kEplSuccessful; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplPdokCbPdoReceived +// +// Description: This function is called by DLL if PRes or PReq frame was +// received. It posts the frame to the event queue. +// It is called in states NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL. +// The passed PDO needs not to be valid. +// +// Parameters: pFrameInfo_p = pointer to frame info structure +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokCbPdoReceived(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; + +#if (DEV_SYSTEM == _DEV_GNU_CF548X_) + // reset LED +// MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level +#endif + + Event.m_EventSink = kEplEventSinkPdok; + Event.m_EventType = kEplEventTypePdoRx; + // limit copied data to size of PDO (because from some CNs the frame is larger than necessary) + Event.m_uiSize = AmiGetWordFromLe(&pFrameInfo_p->m_pFrame->m_Data.m_Pres.m_le_wSize) + 24; // pFrameInfo_p->m_uiFrameSize; + Event.m_pArg = pFrameInfo_p->m_pFrame; + Ret = EplEventkPost(&Event); + +#if (DEV_SYSTEM == _DEV_GNU_CF548X_) + // set LED +// MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplPdokCbPdoTransmitted +// +// Description: This function is called by DLL if PRes or PReq frame was +// sent. It posts the pointer to the frame to the event queue. +// It is called in NMT_CS_PRE_OPERATIONAL_2, +// NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL. +// +// Parameters: pFrameInfo_p = pointer to frame info structure +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokCbPdoTransmitted(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; + +#if (DEV_SYSTEM == _DEV_GNU_CF548X_) + // reset LED + MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level +#endif + + Event.m_EventSink = kEplEventSinkPdok; + Event.m_EventType = kEplEventTypePdoTx; + Event.m_uiSize = sizeof (tEplFrameInfo); + Event.m_pArg = pFrameInfo_p; + Ret = EplEventkPost(&Event); + +#if (DEV_SYSTEM == _DEV_GNU_CF548X_) + // set LED + MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplPdokCbSoa +// +// Description: This function is called by DLL if SoA frame was +// received resp. sent. It posts this event to the event queue. +// +// Parameters: pFrameInfo_p = pointer to frame info structure +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokCbSoa(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplEvent Event; + + Event.m_EventSink = kEplEventSinkPdok; + Event.m_EventType = kEplEventTypePdoSoa; + Event.m_uiSize = 0; + Event.m_pArg = NULL; + Ret = EplEventkPost(&Event); + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplPdokProcess +// +// Description: This function processes all received and transmitted PDOs. +// This function must not be interrupted by any other task +// except ISRs (like the ethernet driver ISR, which may call +// EplPdokCbFrameReceived() or EplPdokCbFrameTransmitted()). +// +// Parameters: pEvent_p = pointer to event structure +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokProcess(tEplEvent * pEvent_p) +{ +tEplKernel Ret = kEplSuccessful; +WORD wPdoSize; +WORD wBitOffset; +WORD wBitSize; +WORD wVarSize; +QWORD qwObjectMapping; +BYTE bMappSubindex; +BYTE bObdSubindex; +WORD wObdMappIndex; +WORD wObdCommIndex; +WORD wPdoId; +BYTE bObdData; +BYTE bObjectCount; +BYTE bFrameData; +BOOL fValid; +tEplObdSize ObdSize; +tEplFrame *pFrame; +tEplFrameInfo *pFrameInfo; +unsigned int uiNodeId; +tEplMsgType MsgType; + + // 0xFF=invalid, RPDO: 0x00=PReq, localNodeId=PRes, remoteNodeId=PRes + // TPDO: 0x00=PRes, MN: CnNodeId=PReq + + switch (pEvent_p->m_EventType) + { + case kEplEventTypePdoRx: // RPDO received + pFrame = (tEplFrame *) pEvent_p->m_pArg; + + // check if received RPDO is valid + bFrameData = AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1); + if ((bFrameData & EPL_FRAME_FLAG1_RD) == 0) + { // RPDO invalid + goto Exit; + } + + // retrieve EPL message type + MsgType = AmiGetByteFromLe(&pFrame->m_le_bMessageType); + if (MsgType == kEplMsgTypePreq) + { // RPDO is PReq frame + uiNodeId = EPL_PDO_PREQ_NODE_ID; // 0x00 + } + else + { // RPDO is PRes frame + // retrieve node ID + uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId); + } + + // search for appropriate valid RPDO in OD + wObdMappIndex = EPL_PDOK_OBD_IDX_RX_MAPP_PARAM; + for (wObdCommIndex = EPL_PDOK_OBD_IDX_RX_COMM_PARAM; + wObdCommIndex < (EPL_PDOK_OBD_IDX_RX_COMM_PARAM + 0x00FF); + wObdCommIndex++, wObdMappIndex++) + { + ObdSize = 1; + // read node ID from OD + Ret = EplObdReadEntry(wObdCommIndex, 0x01, &bObdData, &ObdSize); + if ((Ret == kEplObdIndexNotExist) + || (Ret == kEplObdSubindexNotExist) + || (Ret == kEplObdIllegalPart)) + { // PDO does not exist; last PDO reached + Ret = kEplSuccessful; + goto Exit; + } + else if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + // entry read successfully + if (bObdData != uiNodeId) + { // node ID does not equal - wrong PDO, try next PDO in OD + continue; + } + ObdSize = 1; + // read number of mapped objects from OD; this indicates if the PDO is valid + Ret = EplObdReadEntry(wObdMappIndex, 0x00, &bObjectCount, &ObdSize); + if ((Ret == kEplObdIndexNotExist) + || (Ret == kEplObdSubindexNotExist) + || (Ret == kEplObdIllegalPart)) + { // PDO does not exist; last PDO reached + Ret = kEplSuccessful; + goto Exit; + } + else if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + // entry read successfully + if (bObjectCount == 0) + { // PDO in OD not valid, try next PDO in OD + continue; + } + + ObdSize = 1; + // check PDO mapping version + Ret = EplObdReadEntry(wObdCommIndex, 0x02, &bObdData, &ObdSize); + if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + // entry read successfully + // retrieve PDO version from frame + bFrameData = AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bPdoVersion); + if ((bObdData & EPL_VERSION_MAIN) != (bFrameData & EPL_VERSION_MAIN)) + { // PDO versions do not match + // $$$ raise PDO error + // termiate processing of this RPDO + goto Exit; + } + + // valid RPDO found + + // retrieve PDO size + wPdoSize = AmiGetWordFromLe(&pFrame->m_Data.m_Pres.m_le_wSize); + + // process mapping + for (bMappSubindex = 1; bMappSubindex <= bObjectCount; bMappSubindex++) + { + ObdSize = 8; // QWORD + // read object mapping from OD + Ret = EplObdReadEntry(wObdMappIndex, bMappSubindex, &qwObjectMapping, &ObdSize); + if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + + // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed + if (qwObjectMapping == 0) + { // invalid entry, continue with next entry + continue; + } + + // decode object mapping + wObdCommIndex = (WORD) (qwObjectMapping & 0x000000000000FFFFLL); + bObdSubindex = (BYTE) ((qwObjectMapping & 0x0000000000FF0000LL) >> 16); + wBitOffset = (WORD) ((qwObjectMapping & 0x0000FFFF00000000LL) >> 32); + wBitSize = (WORD) ((qwObjectMapping & 0xFFFF000000000000LL) >> 48); + + // check if object exceeds PDO size + if (((wBitOffset + wBitSize) >> 3) > wPdoSize) + { // wrong object mapping; PDO size is too low + // $$$ raise PDO error + // terminate processing of this RPDO + goto Exit; + } + + // copy object from RPDO to process/OD variable + ObdSize = wBitSize >> 3; + Ret = EplObdWriteEntryFromLe(wObdCommIndex, bObdSubindex, &pFrame->m_Data.m_Pres.m_le_abPayload[(wBitOffset >> 3)], ObdSize); + if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + + } + + // processing finished successfully + goto Exit; + } + break; + + case kEplEventTypePdoTx: // TPDO transmitted + pFrameInfo = (tEplFrameInfo *) pEvent_p->m_pArg; + pFrame = pFrameInfo->m_pFrame; + + // set TPDO invalid, so that only fully processed TPDOs are sent as valid + bFrameData = AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1); + AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bFlag1, (bFrameData & ~EPL_FRAME_FLAG1_RD)); + + // retrieve EPL message type + MsgType = AmiGetByteFromLe(&pFrame->m_le_bMessageType); + if (MsgType == kEplMsgTypePres) + { // TPDO is PRes frame + uiNodeId = EPL_PDO_PRES_NODE_ID; // 0x00 + } + else + { // TPDO is PReq frame + // retrieve node ID + uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId); + } + + // search for appropriate valid TPDO in OD + wObdMappIndex = EPL_PDOK_OBD_IDX_TX_MAPP_PARAM; + wObdCommIndex = EPL_PDOK_OBD_IDX_TX_COMM_PARAM; + for (wPdoId = 0; ; wPdoId++, wObdCommIndex++, wObdMappIndex++) + { + ObdSize = 1; + // read node ID from OD + Ret = EplObdReadEntry(wObdCommIndex, 0x01, &bObdData, &ObdSize); + if ((Ret == kEplObdIndexNotExist) + || (Ret == kEplObdSubindexNotExist) + || (Ret == kEplObdIllegalPart)) + { // PDO does not exist; last PDO reached + Ret = kEplSuccessful; + goto Exit; + } + else if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + // entry read successfully + if (bObdData != uiNodeId) + { // node ID does not equal - wrong PDO, try next PDO in OD + continue; + } + ObdSize = 1; + // read number of mapped objects from OD; this indicates if the PDO is valid + Ret = EplObdReadEntry(wObdMappIndex, 0x00, &bObjectCount, &ObdSize); + if ((Ret == kEplObdIndexNotExist) + || (Ret == kEplObdSubindexNotExist) + || (Ret == kEplObdIllegalPart)) + { // PDO does not exist; last PDO reached + Ret = kEplSuccessful; + goto Exit; + } + else if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + // entry read successfully + if (bObjectCount == 0) + { // PDO in OD not valid, try next PDO in OD + continue; + } + + // valid TPDO found + + ObdSize = 1; + // get PDO mapping version from OD + Ret = EplObdReadEntry(wObdCommIndex, 0x02, &bObdData, &ObdSize); + if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + // entry read successfully + // set PDO version in frame + AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bPdoVersion, bObdData); + + // calculate PDO size + wPdoSize = 0; + + // process mapping + for (bMappSubindex = 1; bMappSubindex <= bObjectCount; bMappSubindex++) + { + ObdSize = 8; // QWORD + // read object mapping from OD + Ret = EplObdReadEntry(wObdMappIndex, bMappSubindex, &qwObjectMapping, &ObdSize); + if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + + // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed + if (qwObjectMapping == 0) + { // invalid entry, continue with next entry + continue; + } + + // decode object mapping + wObdCommIndex = (WORD) (qwObjectMapping & 0x000000000000FFFFLL); + bObdSubindex = (BYTE) ((qwObjectMapping & 0x0000000000FF0000LL) >> 16); + wBitOffset = (WORD) ((qwObjectMapping & 0x0000FFFF00000000LL) >> 32); + wBitSize = (WORD) ((qwObjectMapping & 0xFFFF000000000000LL) >> 48); + + // calculate max PDO size + ObdSize = wBitSize >> 3; + wVarSize = (wBitOffset >> 3) + (WORD) ObdSize; + if ((unsigned int)(wVarSize + 24) > pFrameInfo->m_uiFrameSize) + { // TPDO is too short + // $$$ raise PDO error, set Ret + goto Exit; + } + if (wVarSize > wPdoSize) + { // memorize new PDO size + wPdoSize = wVarSize; + } + + // copy object from process/OD variable to TPDO + Ret = EplObdReadEntryToLe(wObdCommIndex, bObdSubindex, &pFrame->m_Data.m_Pres.m_le_abPayload[(wBitOffset >> 3)], &ObdSize); + if (Ret != kEplSuccessful) + { // other fatal error occured + goto Exit; + } + + } + + // set PDO size in frame + AmiSetWordToLe(&pFrame->m_Data.m_Pres.m_le_wSize, wPdoSize); + + Ret = EplPdokCalAreTpdosValid(&fValid); + if (fValid != FALSE) + { + // set TPDO valid + bFrameData = AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1); + AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bFlag1, (bFrameData | EPL_FRAME_FLAG1_RD)); + } + + // processing finished successfully + + goto Exit; + } + break; + + case kEplEventTypePdoSoa: // SoA received + + // invalidate TPDOs + Ret = EplPdokCalSetTpdosValid(FALSE); + break; + + default: + { + ASSERTMSG(FALSE, "EplPdokProcess(): unhandled event type!\n"); + } + } + +Exit: + return Ret; +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + +#endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplPdokCal.c b/drivers/staging/epl/EplPdokCal.c new file mode 100644 index 0000000..0dd9954 --- /dev/null +++ b/drivers/staging/epl/EplPdokCal.c @@ -0,0 +1,274 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for kernel PDO Communication Abstraction Layer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplPdokCal.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/27 d.k.: start of the implementation, version 1.00 + +****************************************************************************/ + +#include "kernel/EplPdokCal.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S EplPdokCal */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ + BOOL m_fTpdosValid; + +} tEplPdokCalInstance; + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +static tEplPdokCalInstance EplPdokCalInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplPdokCalAddInstance() +// +// Description: add and initialize new instance of EPL stack +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokCalAddInstance(void) +{ + + EPL_MEMSET(&EplPdokCalInstance_g, 0, sizeof(EplPdokCalInstance_g)); + + return kEplSuccessful; +} + +//--------------------------------------------------------------------------- +// +// Function: EplPdokCalDelInstance() +// +// Description: deletes an instance of EPL stack +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokCalDelInstance(void) +{ + + return kEplSuccessful; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplPdokCalSetTpdosValid() +// +// Description: This function sets the validity flag for TPDOs to the +// specified value. +// +// Parameters: fValid_p = validity flag +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokCalSetTpdosValid(BOOL fValid_p) +{ +tEplKernel Ret = kEplSuccessful; + + EplPdokCalInstance_g.m_fTpdosValid = fValid_p; + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplPdokCalAreTpdosValid() +// +// Description: This function returns the validity flag for TPDOs. +// +// Parameters: pfValid_p = OUT: validity flag +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdokCalAreTpdosValid(BOOL * pfValid_p) +{ +tEplKernel Ret = kEplSuccessful; + + *pfValid_p = EplPdokCalInstance_g.m_fTpdosValid; + + return Ret; +} + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + +#endif + +// EOF + diff --git a/drivers/staging/epl/EplPdou.c b/drivers/staging/epl/EplPdou.c new file mode 100644 index 0000000..289d25e --- /dev/null +++ b/drivers/staging/epl/EplPdou.c @@ -0,0 +1,608 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for user PDO module + Currently, this module just implements a OD callback function + to check if the PDO configuration is valid. + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplPdou.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/05/22 d.k.: start of the implementation, version 1.00 + +****************************************************************************/ + +#include "EplInc.h" +//#include "user/EplPdouCal.h" +#include "user/EplObdu.h" +#include "user/EplPdou.h" +#include "EplSdoAc.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0) + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE) +#error "EPL PDOu module needs EPL module OBDU or OBDK!" +#endif + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#define EPL_PDOU_OBD_IDX_RX_COMM_PARAM 0x1400 +#define EPL_PDOU_OBD_IDX_RX_MAPP_PARAM 0x1600 +#define EPL_PDOU_OBD_IDX_TX_COMM_PARAM 0x1800 +#define EPL_PDOU_OBD_IDX_TX_MAPP_PARAM 0x1A00 +#define EPL_PDOU_OBD_IDX_MAPP_PARAM 0x0200 +#define EPL_PDOU_OBD_IDX_MASK 0xFF00 +#define EPL_PDOU_PDO_ID_MASK 0x00FF + + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S EplPdou */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM* pParam_p, unsigned int uiIndex_p); + +static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p, + unsigned int* puiIndex_p, + unsigned int* puiSubIndex_p, + unsigned int* puiBitOffset_p, + unsigned int* puiBitSize_p); + +static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p, + tEplObdAccess AccessType_p, + DWORD* pdwAbortCode_p, + unsigned int* puiPdoSize_p); + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplPdouAddInstance() +// +// Description: add and initialize new instance of EPL stack +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdouAddInstance(void) +{ + + return kEplSuccessful; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplPdouDelInstance() +// +// Description: deletes an instance of EPL stack +// +// Parameters: none +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel EplPdouDelInstance(void) +{ + + return kEplSuccessful; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplPdouCbObdAccess +// +// Description: callback function for OD accesses +// +// Parameters: pParam_p = OBD parameter +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM* pParam_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiPdoId; +unsigned int uiIndexType; +tEplObdSize ObdSize; +BYTE bObjectCount; +QWORD qwObjectMapping; +tEplObdAccess AccessType; +BYTE bMappSubindex; +unsigned int uiCurPdoSize; +WORD wMaxPdoSize; +unsigned int uiSubIndex; + + // fetch PDO ID + uiPdoId = pParam_p->m_uiIndex & EPL_PDOU_PDO_ID_MASK; + + // fetch object index type + uiIndexType = pParam_p->m_uiIndex & EPL_PDOU_OBD_IDX_MASK; + + if (pParam_p->m_ObdEvent != kEplObdEvPreWrite) + { // read accesses, post write events etc. are OK + pParam_p->m_dwAbortCode = 0; + goto Exit; + } + + // check index type + switch (uiIndexType) + { + case EPL_PDOU_OBD_IDX_RX_COMM_PARAM: + // RPDO communication parameter accessed + case EPL_PDOU_OBD_IDX_TX_COMM_PARAM: + { // TPDO communication parameter accessed + Ret = EplPdouCheckPdoValidity(pParam_p, + (EPL_PDOU_OBD_IDX_MAPP_PARAM | pParam_p->m_uiIndex)); + if (Ret != kEplSuccessful) + { // PDO is valid or does not exist + goto Exit; + } + + goto Exit; + } + + case EPL_PDOU_OBD_IDX_RX_MAPP_PARAM: + { // RPDO mapping parameter accessed + + AccessType = kEplObdAccWrite; + break; + } + + case EPL_PDOU_OBD_IDX_TX_MAPP_PARAM: + { // TPDO mapping parameter accessed + + AccessType = kEplObdAccRead; + break; + } + + default: + { // this callback function is only for + // PDO mapping and communication parameters + pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR; + goto Exit; + } + } + + // RPDO and TPDO mapping parameter accessed + + if (pParam_p->m_uiSubIndex == 0) + { // object mapping count accessed + + // PDO is enabled or disabled + bObjectCount = *((BYTE*) pParam_p->m_pArg); + + if (bObjectCount == 0) + { // PDO shall be disabled + + // that is always possible + goto Exit; + } + + // PDO shall be enabled + // it should have been disabled for this operation + Ret = EplPdouCheckPdoValidity(pParam_p, pParam_p->m_uiIndex); + if (Ret != kEplSuccessful) + { // PDO is valid or does not exist + goto Exit; + } + + if (AccessType == kEplObdAccWrite) + { + uiSubIndex = 0x04; // PReqActPayloadLimit_U16 + } + else + { + uiSubIndex = 0x05; // PResActPayloadLimit_U16 + } + + // fetch maximum PDO size from Object 1F98h: NMT_CycleTiming_REC + ObdSize = sizeof (wMaxPdoSize); + Ret = EplObduReadEntry(0x1F98, uiSubIndex, &wMaxPdoSize, &ObdSize); + if (Ret != kEplSuccessful) + { // other fatal error occured + pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR; + goto Exit; + } + + // check all objectmappings + for (bMappSubindex = 1; bMappSubindex <= bObjectCount; bMappSubindex++) + { + // read object mapping from OD + ObdSize = sizeof (qwObjectMapping); // QWORD + Ret = EplObduReadEntry(pParam_p->m_uiIndex, + bMappSubindex, &qwObjectMapping, &ObdSize); + if (Ret != kEplSuccessful) + { // other fatal error occured + pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR; + goto Exit; + } + + // check object mapping + Ret = EplPdouCheckObjectMapping(qwObjectMapping, + AccessType, + &pParam_p->m_dwAbortCode, + &uiCurPdoSize); + if (Ret != kEplSuccessful) + { // illegal object mapping + goto Exit; + } + + if (uiCurPdoSize > wMaxPdoSize) + { // mapping exceeds object size + pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR; + Ret = kEplPdoVarNotFound; + } + + + } + + } + else + { // ObjectMapping + Ret = EplPdouCheckPdoValidity(pParam_p, pParam_p->m_uiIndex); + if (Ret != kEplSuccessful) + { // PDO is valid or does not exist + goto Exit; + } + + // check existence of object and validity of object length + + qwObjectMapping = *((QWORD*) pParam_p->m_pArg); + + Ret = EplPdouCheckObjectMapping(qwObjectMapping, + AccessType, + &pParam_p->m_dwAbortCode, + &uiCurPdoSize); + + } + +Exit: + return Ret; +} + + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplPdouCheckPdoValidity +// +// Description: check if PDO is valid +// +// Parameters: pParam_p = OBD parameter +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM* pParam_p, unsigned int uiIndex_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplObdSize ObdSize; +BYTE bObjectCount; + + ObdSize = 1; + // read number of mapped objects from OD; this indicates if the PDO is valid + Ret = EplObduReadEntry(uiIndex_p, 0x00, &bObjectCount, &ObdSize); + if (Ret != kEplSuccessful) + { // other fatal error occured + pParam_p->m_dwAbortCode = EPL_SDOAC_GEN_INTERNAL_INCOMPATIBILITY; + goto Exit; + } + // entry read successfully + if (bObjectCount != 0) + { // PDO in OD is still valid + pParam_p->m_dwAbortCode = EPL_SDOAC_GEN_PARAM_INCOMPATIBILITY; + Ret = kEplPdoNotExist; + goto Exit; + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplPdouDecodeObjectMapping +// +// Description: decodes the given object mapping entry into index, subindex, +// bit offset and bit size. +// +// Parameters: qwObjectMapping_p = object mapping entry +// puiIndex_p = [OUT] pointer to object index +// puiSubIndex_p = [OUT] pointer to subindex +// puiBitOffset_p = [OUT] pointer to bit offset +// puiBitSize_p = [OUT] pointer to bit size +// +// Returns: (void) +// +// State: +// +//--------------------------------------------------------------------------- + +static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p, + unsigned int* puiIndex_p, + unsigned int* puiSubIndex_p, + unsigned int* puiBitOffset_p, + unsigned int* puiBitSize_p) +{ + *puiIndex_p = (unsigned int) + (qwObjectMapping_p & 0x000000000000FFFFLL); + + *puiSubIndex_p = (unsigned int) + ((qwObjectMapping_p & 0x0000000000FF0000LL) >> 16); + + *puiBitOffset_p = (unsigned int) + ((qwObjectMapping_p & 0x0000FFFF00000000LL) >> 32); + + *puiBitSize_p = (unsigned int) + ((qwObjectMapping_p & 0xFFFF000000000000LL) >> 48); + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplPdouCheckObjectMapping +// +// Description: checks the given object mapping entry. +// +// Parameters: qwObjectMapping_p = object mapping entry +// AccessType_p = access type to mapped object: +// write = RPDO and read = TPDO +// puiPdoSize_p = [OUT] pointer to covered PDO size +// (offset + size) in byte; +// 0 if mapping failed +// pdwAbortCode_p = [OUT] pointer to SDO abort code; +// 0 if mapping is possible +// +// Returns: tEplKernel = error code +// +// State: +// +//--------------------------------------------------------------------------- + +static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p, + tEplObdAccess AccessType_p, + DWORD* pdwAbortCode_p, + unsigned int* puiPdoSize_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplObdSize ObdSize; +unsigned int uiIndex; +unsigned int uiSubIndex; +unsigned int uiBitOffset; +unsigned int uiBitSize; +tEplObdAccess AccessType; +BOOL fNumerical; + + if (qwObjectMapping_p == 0) + { // discard zero value + *puiPdoSize_p = 0; + goto Exit; + } + + // decode object mapping + EplPdouDecodeObjectMapping(qwObjectMapping_p, + &uiIndex, + &uiSubIndex, + &uiBitOffset, + &uiBitSize); + + if ((uiBitOffset & 0x7) != 0x0) + { // bit mapping is not supported + *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR; + Ret = kEplPdoGranularityMismatch; + goto Exit; + } + + if ((uiBitSize & 0x7) != 0x0) + { // bit mapping is not supported + *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR; + Ret = kEplPdoGranularityMismatch; + goto Exit; + } + + // check access type + Ret = EplObduGetAccessType(uiIndex, uiSubIndex, &AccessType); + if (Ret != kEplSuccessful) + { // entry doesn't exist + *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_EXIST; + goto Exit; + } + + if ((AccessType & kEplObdAccPdo) == 0) + { // object is not mappable + *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_MAPPABLE; + Ret = kEplPdoVarNotFound; + goto Exit; + } + + if ((AccessType & AccessType_p) == 0) + { // object is not writeable (RPDO) or readable (TPDO) respectively + *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_MAPPABLE; + Ret = kEplPdoVarNotFound; + goto Exit; + } + + ObdSize = EplObduGetDataSize(uiIndex, uiSubIndex); + if (ObdSize < (uiBitSize >> 3)) + { // object does not exist or has smaller size + *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR; + Ret = kEplPdoVarNotFound; + } + + Ret = EplObduIsNumerical(uiIndex, uiSubIndex, &fNumerical); + if (Ret != kEplSuccessful) + { // entry doesn't exist + *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_EXIST; + goto Exit; + } + + if ((fNumerical != FALSE) + && ((uiBitSize >> 3) != ObdSize)) + { + // object is numerical, + // therefor size has to fit, but it does not. + *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR; + Ret = kEplPdoVarNotFound; + goto Exit; + } + + // calucaled needed PDO size + *puiPdoSize_p = (uiBitOffset >> 3) + (uiBitSize >> 3); + +Exit: + return Ret; +} + + +#endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplSdo.h b/drivers/staging/epl/EplSdo.h new file mode 100644 index 0000000..c41b32c --- /dev/null +++ b/drivers/staging/epl/EplSdo.h @@ -0,0 +1,271 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for api function of the sdo module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdo.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/26 k.t.: start of the implementation + + +****************************************************************************/ + +#include "EplInc.h" +#include "EplFrame.h" +#include "EplSdoAc.h" + +#ifndef _EPLSDO_H_ +#define _EPLSDO_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- +// global defines +#ifndef EPL_SDO_MAX_PAYLOAD +#define EPL_SDO_MAX_PAYLOAD 256 +#endif + +// handle between Protocol Abstraction Layer and asynchronous SDO Sequence Layer +#define EPL_SDO_UDP_HANDLE 0x8000 +#define EPL_SDO_ASND_HANDLE 0x4000 +#define EPL_SDO_ASY_HANDLE_MASK 0xC000 +#define EPL_SDO_ASY_INVALID_HDL 0x3FFF + +// handle between SDO Sequence Layer and sdo command layer +#define EPL_SDO_ASY_HANDLE 0x8000 +#define EPL_SDO_PDO_HANDLE 0x4000 +#define EPL_SDO_SEQ_HANDLE_MASK 0xC000 +#define EPL_SDO_SEQ_INVALID_HDL 0x3FFF + +#define EPL_ASND_HEADER_SIZE 4 +//#define EPL_SEQ_HEADER_SIZE 4 +#define EPL_ETHERNET_HEADER_SIZE 14 + +#define EPL_SEQ_NUM_MASK 0xFC + +// size for send buffer and history +#define EPL_MAX_SDO_FRAME_SIZE EPL_C_IP_MIN_MTU +// size for receive frame +// -> needed because SND-Kit sends up to 1518 Byte +// without Sdo-Command: Maximum Segment Size +#define EPL_MAX_SDO_REC_FRAME_SIZE EPL_C_IP_MAX_MTU + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- +// handle between Protocol Abstraction Layer and asynchronuus SDO Sequence Layer +typedef unsigned int tEplSdoConHdl; + +// callback function pointer for Protocol Abstraction Layer to call +// asynchronuus SDO Sequence Layer +typedef tEplKernel (PUBLIC* tEplSequLayerReceiveCb ) ( + tEplSdoConHdl ConHdl_p, + tEplAsySdoSeq* pSdoSeqData_p, + unsigned int uiDataSize_p); + +// handle between asynchronuus SDO Sequence Layer and SDO Command layer +typedef unsigned int tEplSdoSeqConHdl; + +// callback function pointer for asynchronuus SDO Sequence Layer to call +// SDO Command layer for received data +typedef tEplKernel (PUBLIC* tEplSdoComReceiveCb) ( + tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoCom* pAsySdoCom_p, + unsigned int uiDataSize_p); + +// status of connection +typedef enum +{ + kAsySdoConStateConnected = 0x00, + kAsySdoConStateInitError = 0x01, + kAsySdoConStateConClosed = 0x02, + kAsySdoConStateAckReceived = 0x03, + kAsySdoConStateFrameSended = 0x04, + kAsySdoConStateTimeout = 0x05 + +}tEplAsySdoConState; + +// callback function pointer for asynchronuus SDO Sequence Layer to call +// SDO Command layer for connection status +typedef tEplKernel (PUBLIC* tEplSdoComConCb) ( + tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoConState AsySdoConState_p); + +// handle between SDO Command layer and application +typedef unsigned int tEplSdoComConHdl; + +// status of connection +typedef enum +{ + kEplSdoComTransferNotActive = 0x00, + kEplSdoComTransferRunning = 0x01, + kEplSdoComTransferTxAborted = 0x02, + kEplSdoComTransferRxAborted = 0x03, + kEplSdoComTransferFinished = 0x04, + kEplSdoComTransferLowerLayerAbort = 0x05 + +} tEplSdoComConState; + +// SDO Services and Command-Ids from DS 1.0.0 p.152 +typedef enum +{ + kEplSdoServiceNIL = 0x00, + kEplSdoServiceWriteByIndex = 0x01, + kEplSdoServiceReadByIndex = 0x02 + + //-------------------------------- + // the following services are optional and + // not supported now +/* + kEplSdoServiceWriteAllByIndex = 0x03, + kEplSdoServiceReadAllByIndex = 0x04, + kEplSdoServiceWriteByName = 0x05, + kEplSdoServiceReadByName = 0x06, + + kEplSdoServiceFileWrite = 0x20, + kEplSdoServiceFileRead = 0x21, + + kEplSdoServiceWriteMultiByIndex = 0x31, + kEplSdoServiceReadMultiByIndex = 0x32, + + kEplSdoServiceMaxSegSize = 0x70 + + // 0x80 - 0xFF manufacturer specific + + */ +} tEplSdoServiceType; + +// describes if read or write access +typedef enum +{ + kEplSdoAccessTypeRead = 0x00, + kEplSdoAccessTypeWrite = 0x01 + +} tEplSdoAccessType; + +typedef enum +{ + kEplSdoTypeAuto = 0x00, + kEplSdoTypeUdp = 0x01, + kEplSdoTypeAsnd = 0x02, + kEplSdoTypePdo = 0x03 + +}tEplSdoType; + +typedef enum +{ + kEplSdoTransAuto = 0x00, + kEplSdoTransExpedited = 0x01, + kEplSdoTransSegmented = 0x02 + + +} tEplSdoTransType; + + +// structure to inform application about finish of SDO transfer +typedef struct +{ + tEplSdoComConHdl m_SdoComConHdl; + tEplSdoComConState m_SdoComConState; + DWORD m_dwAbortCode; + tEplSdoAccessType m_SdoAccessType; + unsigned int m_uiNodeId; // NodeId of the target + unsigned int m_uiTargetIndex; // index which was accessed + unsigned int m_uiTargetSubIndex; // subindex which was accessed + unsigned int m_uiTransferredByte; // number of bytes transferred + void* m_pUserArg; // user definable argument pointer + +} tEplSdoComFinished; + + +// callback function pointer to inform application about connection +typedef tEplKernel (PUBLIC* tEplSdoFinishedCb) ( + tEplSdoComFinished* pSdoComFinished_p); + + +// structure to init SDO transfer to Read or Write by Index +typedef struct +{ + tEplSdoComConHdl m_SdoComConHdl; + unsigned int m_uiIndex; + unsigned int m_uiSubindex; + void* m_pData; + unsigned int m_uiDataSize; + unsigned int m_uiTimeout; // not used in this version + tEplSdoAccessType m_SdoAccessType; + tEplSdoFinishedCb m_pfnSdoFinishedCb; + void* m_pUserArg; // user definable argument pointer + +} tEplSdoComTransParamByIndex; + + + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPLSDO_H_ + + diff --git a/drivers/staging/epl/EplSdoAc.h b/drivers/staging/epl/EplSdoAc.h new file mode 100644 index 0000000..97de988 --- /dev/null +++ b/drivers/staging/epl/EplSdoAc.h @@ -0,0 +1,113 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: definitions for SDO Abort codes + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdoAc.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + ... + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/30 k.t.: first implementation + +****************************************************************************/ + +#ifndef _EPLSDOAC_H_ +#define _EPLSDOAC_H_ + + +// ========================================================================= +// SDO abort codes +// ========================================================================= + +#define EPL_SDOAC_TIME_OUT 0x05040000L +#define EPL_SDOAC_UNKNOWN_COMMAND_SPECIFIER 0x05040001L +#define EPL_SDOAC_INVALID_BLOCK_SIZE 0x05040002L +#define EPL_SDOAC_INVALID_SEQUENCE_NUMBER 0x05040003L +#define EPL_SDOAC_OUT_OF_MEMORY 0x05040005L +#define EPL_SDOAC_UNSUPPORTED_ACCESS 0x06010000L +#define EPL_SDOAC_READ_TO_WRITE_ONLY_OBJ 0x06010001L +#define EPL_SDOAC_WRITE_TO_READ_ONLY_OBJ 0x06010002L +#define EPL_SDOAC_OBJECT_NOT_EXIST 0x06020000L +#define EPL_SDOAC_OBJECT_NOT_MAPPABLE 0x06040041L +#define EPL_SDOAC_PDO_LENGTH_EXCEEDED 0x06040042L +#define EPL_SDOAC_GEN_PARAM_INCOMPATIBILITY 0x06040043L +#define EPL_SDOAC_INVALID_HEARTBEAT_DEC 0x06040044L +#define EPL_SDOAC_GEN_INTERNAL_INCOMPATIBILITY 0x06040047L +#define EPL_SDOAC_ACCESS_FAILED_DUE_HW_ERROR 0x06060000L +#define EPL_SDOAC_DATA_TYPE_LENGTH_NOT_MATCH 0x06070010L +#define EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH 0x06070012L +#define EPL_SDOAC_DATA_TYPE_LENGTH_TOO_LOW 0x06070013L +#define EPL_SDOAC_SUB_INDEX_NOT_EXIST 0x06090011L +#define EPL_SDOAC_VALUE_RANGE_EXCEEDED 0x06090030L +#define EPL_SDOAC_VALUE_RANGE_TOO_HIGH 0x06090031L +#define EPL_SDOAC_VALUE_RANGE_TOO_LOW 0x06090032L +#define EPL_SDOAC_MAX_VALUE_LESS_MIN_VALUE 0x06090036L +#define EPL_SDOAC_GENERAL_ERROR 0x08000000L +#define EPL_SDOAC_DATA_NOT_TRANSF_OR_STORED 0x08000020L +#define EPL_SDOAC_DATA_NOT_TRANSF_DUE_LOCAL_CONTROL 0x08000021L +#define EPL_SDOAC_DATA_NOT_TRANSF_DUE_DEVICE_STATE 0x08000022L +#define EPL_SDOAC_OBJECT_DICTIONARY_NOT_EXIST 0x08000023L +#define EPL_SDOAC_CONFIG_DATA_EMPTY 0x08000024L + + +#endif // _EPLSDOAC_H_ + +// Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler +// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder). diff --git a/drivers/staging/epl/EplSdoAsndu.c b/drivers/staging/epl/EplSdoAsndu.c new file mode 100644 index 0000000..54b1a17 --- /dev/null +++ b/drivers/staging/epl/EplSdoAsndu.c @@ -0,0 +1,509 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for SDO/Asnd-Protocolabstractionlayer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdoAsndu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.7 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/07 k.t.: start of the implementation + +****************************************************************************/ + +#include "user/EplSdoAsndu.h" +#include "user/EplDlluCal.h" + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#ifndef EPL_SDO_MAX_CONNECTION_ASND +#define EPL_SDO_MAX_CONNECTION_ASND 5 +#endif + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +// instance table +typedef struct +{ + unsigned int m_auiSdoAsndConnection[EPL_SDO_MAX_CONNECTION_ASND]; + tEplSequLayerReceiveCb m_fpSdoAsySeqCb; + + +} tEplSdoAsndInstance; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +static tEplSdoAsndInstance SdoAsndInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplSdoAsnduCb(tEplFrameInfo * pFrameInfo_p); + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <EPL SDO-Asnd Protocolabstraction layer> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: EPL SDO-Asnd Protocolabstraction layer +// +// +/***************************************************************************/ + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsnduInit +// +// Description: init first instance of the module +// +// +// +// Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer +// callback-function +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p) +{ +tEplKernel Ret; + + + Ret = EplSdoAsnduAddInstance(fpReceiveCb_p); + +return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsnduAddInstance +// +// Description: init additional instance of the module +// +// +// +// Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer +// callback-function +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // init control structure + EPL_MEMSET(&SdoAsndInstance_g, 0x00, sizeof(SdoAsndInstance_g)); + + // save pointer to callback-function + if (fpReceiveCb_p != NULL) + { + SdoAsndInstance_g.m_fpSdoAsySeqCb = fpReceiveCb_p; + } + else + { + Ret = kEplSdoUdpMissCb; + } + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + Ret = EplDlluCalRegAsndService(kEplDllAsndSdo, + EplSdoAsnduCb, + kEplDllAsndFilterLocal); +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsnduDelInstance +// +// Description: del instance of the module +// del socket and del Listen-Thread +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsnduDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + // deregister callback function from DLL + Ret = EplDlluCalRegAsndService(kEplDllAsndSdo, + NULL, + kEplDllAsndFilterNone); +#endif + +return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsnduInitCon +// +// Description: init a new connect +// +// +// +// Parameters: pSdoConHandle_p = pointer for the new connection handle +// uiTargetNodeId_p = NodeId of the target node +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsnduInitCon(tEplSdoConHdl* pSdoConHandle_p, + unsigned int uiTargetNodeId_p) +{ +tEplKernel Ret; +unsigned int uiCount; +unsigned int uiFreeCon; +unsigned int* puiConnection; + + Ret = kEplSuccessful; + + if ((uiTargetNodeId_p == EPL_C_ADR_INVALID) + || (uiTargetNodeId_p >= EPL_C_ADR_BROADCAST)) + { + Ret = kEplSdoAsndInvalidNodeId; + goto Exit; + } + + // get free entry in control structure + uiCount = 0; + uiFreeCon = EPL_SDO_MAX_CONNECTION_ASND; + puiConnection = &SdoAsndInstance_g.m_auiSdoAsndConnection[0]; + while(uiCount < EPL_SDO_MAX_CONNECTION_ASND) + { + if (*puiConnection == uiTargetNodeId_p) + { // existing connection to target node found + // save handle for higher layer + *pSdoConHandle_p = (uiCount | EPL_SDO_ASND_HANDLE ); + + goto Exit; + } + else if (*puiConnection == 0) + { // free entry-> save target nodeId + uiFreeCon = uiCount; + } + uiCount++; + puiConnection++; + } + + if (uiFreeCon == EPL_SDO_MAX_CONNECTION_ASND) + { + // no free connection + Ret = kEplSdoAsndNoFreeHandle; + } + else + { + puiConnection = &SdoAsndInstance_g.m_auiSdoAsndConnection[uiFreeCon]; + *puiConnection = uiTargetNodeId_p; + // save handle for higher layer + *pSdoConHandle_p = (uiFreeCon | EPL_SDO_ASND_HANDLE ); + + goto Exit; + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsnduSendData +// +// Description: send data using exisiting connection +// +// +// +// Parameters: SdoConHandle_p = connection handle +// pSrcData_p = pointer to data +// dwDataSize_p = number of databyte +// -> without asnd-header!!! +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p, + tEplFrame * pSrcData_p, + DWORD dwDataSize_p) +{ +tEplKernel Ret; +unsigned int uiArray; +tEplFrameInfo FrameInfo; + + Ret = kEplSuccessful; + + uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK); + + if(uiArray > EPL_SDO_MAX_CONNECTION_ASND) + { + Ret = kEplSdoAsndInvalidHandle; + goto Exit; + } + + // fillout Asnd header + // own node id not needed -> filled by DLL + + // set message type + AmiSetByteToLe(&pSrcData_p->m_le_bMessageType, (BYTE)kEplMsgTypeAsnd); // ASnd == 0x06 + // target node id + AmiSetByteToLe(&pSrcData_p->m_le_bDstNodeId, (BYTE) SdoAsndInstance_g.m_auiSdoAsndConnection[uiArray]); + // set source-nodeid (filled by DLL 0) + AmiSetByteToLe(&pSrcData_p->m_le_bSrcNodeId, 0x00); + + // calc size + dwDataSize_p += EPL_ASND_HEADER_SIZE; + + // send function of DLL + FrameInfo.m_uiFrameSize = dwDataSize_p; + FrameInfo.m_pFrame = pSrcData_p; + EPL_MEMSET(&FrameInfo.m_NetTime , 0x00, sizeof(tEplNetTime)); +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + Ret = EplDlluCalAsyncSend(&FrameInfo,kEplDllAsyncReqPrioGeneric); +#endif + +Exit: + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsnduDelCon +// +// Description: delete connection from intern structure +// +// +// +// Parameters: SdoConHandle_p = connection handle +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p) +{ +tEplKernel Ret; +unsigned int uiArray; + + Ret = kEplSuccessful; + + + uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK); + // check parameter + if(uiArray > EPL_SDO_MAX_CONNECTION_ASND) + { + Ret = kEplSdoAsndInvalidHandle; + goto Exit; + } + + // set target nodeId to 0 + SdoAsndInstance_g.m_auiSdoAsndConnection[uiArray] = 0; + +Exit: + return Ret; +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsnduCb +// +// Description: callback function for SDO ASnd frames +// +// +// +// Parameters: pFrameInfo_p = Frame with SDO payload +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsnduCb(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiCount; +unsigned int* puiConnection; +unsigned int uiNodeId; +unsigned int uiFreeEntry = 0xFFFF; +tEplSdoConHdl SdoConHdl; +tEplFrame* pFrame; + + pFrame = pFrameInfo_p->m_pFrame; + + uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId); + + // search corresponding entry in control structure + uiCount = 0; + puiConnection = &SdoAsndInstance_g.m_auiSdoAsndConnection[0]; + while (uiCount < EPL_SDO_MAX_CONNECTION_ASND) + { + if (uiNodeId == *puiConnection) + { + break; + } + else if ((*puiConnection == 0) + && (uiFreeEntry == 0xFFFF)) + { // free entry + uiFreeEntry = uiCount; + } + uiCount++; + puiConnection++; + } + + if (uiCount == EPL_SDO_MAX_CONNECTION_ASND) + { + if (uiFreeEntry != 0xFFFF) + { + puiConnection = &SdoAsndInstance_g.m_auiSdoAsndConnection[uiFreeEntry]; + *puiConnection = uiNodeId; + uiCount = uiFreeEntry; + } + else + { + EPL_DBGLVL_SDO_TRACE0("EplSdoAsnduCb(): no free handle\n"); + goto Exit; + } + } +// if (uiNodeId == *puiConnection) + { // entry found or created + SdoConHdl = (uiCount | EPL_SDO_ASND_HANDLE ); + + SdoAsndInstance_g.m_fpSdoAsySeqCb(SdoConHdl, &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame, (pFrameInfo_p->m_uiFrameSize - 18)); + } + +Exit: + return Ret; + +} + + +#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) +// EOF + diff --git a/drivers/staging/epl/EplSdoAsySequ.c b/drivers/staging/epl/EplSdoAsySequ.c new file mode 100644 index 0000000..8a4e1e2 --- /dev/null +++ b/drivers/staging/epl/EplSdoAsySequ.c @@ -0,0 +1,2401 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for asychronous SDO Sequence Layer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdoAsySequ.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.10 $ $Date: 2008/11/13 17:13:09 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/26 k.t.: start of the implementation + +****************************************************************************/ + +#include "user/EplSdoAsySequ.h" + + +#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) == 0) &&\ + (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) == 0) ) + + #error 'ERROR: At least UDP or Asnd module needed!' + +#endif +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#define EPL_SDO_HISTORY_SIZE 5 + +#ifndef EPL_MAX_SDO_SEQ_CON +#define EPL_MAX_SDO_SEQ_CON 10 +#endif + +#define EPL_SEQ_DEFAULT_TIMEOUT 5000 // in [ms] => 5 sec + +#define EPL_SEQ_RETRY_COUNT 5 // => max. Timeout 30 sec + +#define EPL_SEQ_NUM_THRESHOLD 100 // threshold which distinguishes between old and new sequence numbers + +// define frame with size of Asnd-Header-, SDO Sequenze Header size, SDO Command header +// and Ethernet-Header size +#define EPL_SEQ_FRAME_SIZE 24 +// size of the header of the asynchronus SDO Sequence layer +#define EPL_SEQ_HEADER_SIZE 4 + +// buffersize for one frame in history +#define EPL_SEQ_HISTROY_FRAME_SIZE EPL_MAX_SDO_FRAME_SIZE + +// mask to get scon and rcon +#define EPL_ASY_SDO_CON_MASK 0x03 + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +// events for processfunction +typedef enum +{ + kAsySdoSeqEventNoEvent = 0x00, // no Event + kAsySdoSeqEventInitCon = 0x01, // init connection + kAsySdoSeqEventFrameRec = 0x02, // frame received + kAsySdoSeqEventFrameSend= 0x03, // frame to send + kAsySdoSeqEventTimeout = 0x04, // Timeout for connection + kAsySdoSeqEventCloseCon = 0x05 // higher layer close connection + +}tEplAsySdoSeqEvent; + +// structure for History-Buffer +typedef struct +{ + BYTE m_bFreeEntries; + BYTE m_bWrite; // index of the next free buffer entry + BYTE m_bAck; // index of the next message which should become acknowledged + BYTE m_bRead; // index between m_bAck and m_bWrite to the next message for retransmission + BYTE m_aabHistoryFrame[EPL_SDO_HISTORY_SIZE][EPL_SEQ_HISTROY_FRAME_SIZE]; + unsigned int m_auiFrameSize[EPL_SDO_HISTORY_SIZE]; + +}tEplAsySdoConHistory; + +// state of the statemaschine +typedef enum +{ + kEplAsySdoStateIdle = 0x00, + kEplAsySdoStateInit1 = 0x01, + kEplAsySdoStateInit2 = 0x02, + kEplAsySdoStateInit3 = 0x03, + kEplAsySdoStateConnected = 0x04, + kEplAsySdoStateWaitAck = 0x05 + +}tEplAsySdoState; + +// connection control structure +typedef struct +{ + tEplSdoConHdl m_ConHandle; + tEplAsySdoState m_SdoState; + BYTE m_bRecSeqNum; // name from view of the communication partner + BYTE m_bSendSeqNum; // name from view of the communication partner + tEplAsySdoConHistory m_SdoConHistory; + tEplTimerHdl m_EplTimerHdl; + unsigned int m_uiRetryCount; // retry counter + unsigned int m_uiUseCount; // one sequence layer connection may be used by + // multiple command layer connections + +}tEplAsySdoSeqCon; + +// instance structure +typedef struct +{ + tEplAsySdoSeqCon m_AsySdoConnection[EPL_MAX_SDO_SEQ_CON]; + tEplSdoComReceiveCb m_fpSdoComReceiveCb; + tEplSdoComConCb m_fpSdoComConCb; + +#if defined(WIN32) || defined(_WIN32) + LPCRITICAL_SECTION m_pCriticalSection; + CRITICAL_SECTION m_CriticalSection; + + LPCRITICAL_SECTION m_pCriticalSectionReceive; + CRITICAL_SECTION m_CriticalSectionReceive; +#endif + +}tEplAsySdoSequInstance; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +static tEplAsySdoSequInstance AsySdoSequInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static tEplKernel EplSdoAsySeqProcess(unsigned int uiHandle_p, + unsigned int uiDataSize_p, + tEplFrame* pData_p, + tEplAsySdoSeq* pRecFrame_p, + tEplAsySdoSeqEvent Event_p); + +static tEplKernel EplSdoAsySeqSendIntern(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + unsigned int uiDataSize_p, + tEplFrame* pData_p, + BOOL fFrameInHistory); + +static tEplKernel EplSdoAsySeqSendLowerLayer(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + unsigned int uiDataSize_p, + tEplFrame* pEplFrame_p); + +tEplKernel PUBLIC EplSdoAsyReceiveCb (tEplSdoConHdl ConHdl_p, + tEplAsySdoSeq* pSdoSeqData_p, + unsigned int uiDataSize_p); + +static tEplKernel EplSdoAsyInitHistory(void); + +static tEplKernel EplSdoAsyAddFrameToHistory(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + tEplFrame* pFrame_p, + unsigned int uiSize_p); + +static tEplKernel EplSdoAsyAckFrameToHistory(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + BYTE bRecSeqNumber_p); + +static tEplKernel EplSdoAsyReadFromHistory(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + tEplFrame** ppFrame_p, + unsigned int* puiSize_p, + BOOL fInitRead); + +static unsigned int EplSdoAsyGetFreeEntriesFromHistory(tEplAsySdoSeqCon* pAsySdoSeqCon_p); + +static tEplKernel EplSdoAsySeqSetTimer(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + unsigned long ulTimeout); + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <EPL asychronus SDO Sequence layer> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: this module contains the asynchronus SDO Sequence Layer for +// the EPL SDO service +// +// +/***************************************************************************/ + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqInit +// +// Description: init first instance +// +// +// +// Parameters: fpSdoComCb_p = callback function to inform Command layer +// about new frames +// fpSdoComConCb_p = callback function to inform command layer +// about connection state +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p, + tEplSdoComConCb fpSdoComConCb_p) +{ +tEplKernel Ret; + + + Ret = EplSdoAsySeqAddInstance(fpSdoComCb_p, fpSdoComConCb_p); + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqAddInstance +// +// Description: init following instances +// +// +// +// Parameters: fpSdoComCb_p = callback function to inform Command layer +// about new frames +// fpSdoComConCb_p = callback function to inform command layer +// about connection state +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsySeqAddInstance (tEplSdoComReceiveCb fpSdoComCb_p, + tEplSdoComConCb fpSdoComConCb_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // check functionpointer + if(fpSdoComCb_p == NULL) + { + Ret = kEplSdoSeqMissCb; + goto Exit; + } + else + { + AsySdoSequInstance_g.m_fpSdoComReceiveCb = fpSdoComCb_p; + } + + // check functionpointer + if(fpSdoComConCb_p == NULL) + { + Ret = kEplSdoSeqMissCb; + goto Exit; + } + else + { + AsySdoSequInstance_g.m_fpSdoComConCb = fpSdoComConCb_p; + } + + // set controllstructure to 0 + EPL_MEMSET(&AsySdoSequInstance_g.m_AsySdoConnection[0], 0x00, sizeof(AsySdoSequInstance_g.m_AsySdoConnection)); + + // init History + Ret = EplSdoAsyInitHistory(); + if(Ret != kEplSuccessful) + { + goto Exit; + } + +#if defined(WIN32) || defined(_WIN32) + // create critical section for process function + AsySdoSequInstance_g.m_pCriticalSection = &AsySdoSequInstance_g.m_CriticalSection; + InitializeCriticalSection(AsySdoSequInstance_g.m_pCriticalSection); + + // init critical section for receive cb function + AsySdoSequInstance_g.m_pCriticalSectionReceive = &AsySdoSequInstance_g.m_CriticalSectionReceive; + InitializeCriticalSection(AsySdoSequInstance_g.m_pCriticalSectionReceive); +#endif + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + // init lower layer + Ret = EplSdoUdpuAddInstance(EplSdoAsyReceiveCb); + if(Ret != kEplSuccessful) + { + goto Exit; + } +#endif + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + // init lower layer + Ret = EplSdoAsnduAddInstance(EplSdoAsyReceiveCb); + if(Ret != kEplSuccessful) + { + goto Exit; + } +#endif + + + +Exit: + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqDelInstance +// +// Description: delete instances +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsySeqDelInstance() +{ +tEplKernel Ret; +unsigned int uiCount; +tEplAsySdoSeqCon* pAsySdoSeqCon; + + Ret = kEplSuccessful; + + // delete timer of open connections + uiCount = 0; + pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[0]; + while(uiCount < EPL_MAX_SDO_SEQ_CON) + { + if (pAsySdoSeqCon->m_ConHandle != 0) + { + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + } + uiCount++; + pAsySdoSeqCon++; + } + + +#if defined(WIN32) || defined(_WIN32) + // delete critical section for process function + DeleteCriticalSection(AsySdoSequInstance_g.m_pCriticalSection); +#endif + + // set instance-table to 0 + EPL_MEMSET(&AsySdoSequInstance_g, 0x00, sizeof(AsySdoSequInstance_g)); + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + // delete lower layer + Ret = EplSdoUdpuDelInstance(); +#endif + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + // delete lower layer + Ret = EplSdoAsnduDelInstance(); +#endif + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqInitCon +// +// Description: start initialization of a sequence layer connection. +// It tries to reuse an existing connection to the same node. +// +// +// Parameters: pSdoSeqConHdl_p = pointer to the variable for the connection handle +// uiNodeId_p = Node Id of the target +// SdoType = Type of the SDO connection +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsySeqInitCon(tEplSdoSeqConHdl* pSdoSeqConHdl_p, + unsigned int uiNodeId_p, + tEplSdoType SdoType) +{ +tEplKernel Ret; +unsigned int uiCount; +unsigned int uiFreeCon; +tEplSdoConHdl ConHandle; +tEplAsySdoSeqCon* pAsySdoSeqCon; + Ret = kEplSuccessful; + + // check SdoType + // call init function of the protcol abstraction layer + // which tries to find an existing connection to the same node + switch (SdoType) + { + // SDO over UDP + case kEplSdoTypeUdp: + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + Ret = EplSdoUdpuInitCon(&ConHandle, + uiNodeId_p); + if(Ret != kEplSuccessful) + { + goto Exit; + } +#else + Ret = kEplSdoSeqUnsupportedProt; +#endif + break; + } + + // SDO over Asnd + case kEplSdoTypeAsnd: + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + Ret = EplSdoAsnduInitCon(&ConHandle, + uiNodeId_p); + if(Ret != kEplSuccessful) + { + goto Exit; + } +#else + Ret = kEplSdoSeqUnsupportedProt; +#endif + break; + } + + // unsupported protocols + // -> auto should be replaced by command layer + case kEplSdoTypeAuto: + case kEplSdoTypePdo: + default: + { + Ret = kEplSdoSeqUnsupportedProt; + goto Exit; + } + + }// end of switch(SdoType) + + + // find existing connection to the same node or find empty entry for connection + uiCount = 0; + uiFreeCon = EPL_MAX_SDO_SEQ_CON; + pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[0]; + + while (uiCount < EPL_MAX_SDO_SEQ_CON) + { + if (pAsySdoSeqCon->m_ConHandle == ConHandle) + { // existing connection found + break; + } + if (pAsySdoSeqCon->m_ConHandle == 0) + { + uiFreeCon = uiCount; + } + uiCount++; + pAsySdoSeqCon++; + } + + if (uiCount == EPL_MAX_SDO_SEQ_CON) + { + if (uiFreeCon == EPL_MAX_SDO_SEQ_CON) + { // no free entry found + switch (SdoType) + { + // SDO over UDP + case kEplSdoTypeUdp: + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + Ret = EplSdoUdpuDelCon(ConHandle); + if(Ret != kEplSuccessful) + { + goto Exit; + } +#endif + break; + } + + // SDO over Asnd + case kEplSdoTypeAsnd: + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + Ret = EplSdoAsnduDelCon(ConHandle); + if(Ret != kEplSuccessful) + { + goto Exit; + } +#endif + break; + } + + // unsupported protocols + // -> auto should be replaced by command layer + case kEplSdoTypeAuto: + case kEplSdoTypePdo: + default: + { + Ret = kEplSdoSeqUnsupportedProt; + goto Exit; + } + + }// end of switch(SdoType) + + Ret = kEplSdoSeqNoFreeHandle; + goto Exit; + } + else + { // free entry found + pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[uiFreeCon]; + pAsySdoSeqCon->m_ConHandle = ConHandle; + uiCount = uiFreeCon; + } + } + + // set handle + *pSdoSeqConHdl_p = (uiCount | EPL_SDO_ASY_HANDLE); + + // increment use counter + pAsySdoSeqCon->m_uiUseCount++; + + // call intern process function + Ret = EplSdoAsySeqProcess(uiCount, + 0, + NULL, + NULL, + kAsySdoSeqEventInitCon); + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqSendData +// +// Description: send sata unsing a established connection +// +// +// +// Parameters: pSdoSeqConHdl_p = connection handle +// uiDataSize_p = Size of Frame to send +// -> wihtout SDO sequence layer header, Asnd header +// and ethernetnet +// ==> SDO Sequence layer payload +// SdoType = Type of the SDO connection +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p, + unsigned int uiDataSize_p, + tEplFrame* pabData_p ) +{ +tEplKernel Ret; +unsigned int uiHandle; + + + + uiHandle = (SdoSeqConHdl_p & ~EPL_SDO_SEQ_HANDLE_MASK); + + // check if connection ready + if(AsySdoSequInstance_g.m_AsySdoConnection[uiHandle].m_SdoState == kEplAsySdoStateIdle ) + { + // no connection with this handle + Ret = kEplSdoSeqInvalidHdl; + goto Exit; + } + else if(AsySdoSequInstance_g.m_AsySdoConnection[uiHandle].m_SdoState != kEplAsySdoStateConnected) + { + Ret = kEplSdoSeqConnectionBusy; + goto Exit; + } + + Ret = EplSdoAsySeqProcess(uiHandle, + uiDataSize_p, + pabData_p, + NULL, + kAsySdoSeqEventFrameSend); +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqProcessEvent +// +// Description: function processes extern events +// -> later needed for timeout controll with timer-module +// +// +// +// Parameters: pEvent_p = pointer to event +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsySeqProcessEvent(tEplEvent* pEvent_p) +{ +tEplKernel Ret; +tEplTimerEventArg* pTimerEventArg; +tEplAsySdoSeqCon* pAsySdoSeqCon; +tEplTimerHdl EplTimerHdl; +unsigned int uiCount; + + Ret = kEplSuccessful; + // check parameter + if(pEvent_p == NULL) + { + Ret = kEplSdoSeqInvalidEvent; + goto Exit; + } + + if(pEvent_p->m_EventType != kEplEventTypeTimer) + { + Ret = kEplSdoSeqInvalidEvent; + goto Exit; + } + + // get timerhdl + pTimerEventArg = (tEplTimerEventArg*)pEvent_p->m_pArg; + EplTimerHdl = pTimerEventArg->m_TimerHdl; + + // get pointer to intern control structure of connection + if(pTimerEventArg->m_ulArg == 0) + { + goto Exit; + } + pAsySdoSeqCon = (tEplAsySdoSeqCon*)pTimerEventArg->m_ulArg; + + // check if time is current + if(EplTimerHdl != pAsySdoSeqCon->m_EplTimerHdl) + { + // delete timer + EplTimeruDeleteTimer(&EplTimerHdl); + goto Exit; + } + + // delete timer + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + + // get indexnumber of control structure + uiCount = 0; + while((&AsySdoSequInstance_g.m_AsySdoConnection[uiCount]) != pAsySdoSeqCon) + { + uiCount++; + if(uiCount > EPL_MAX_SDO_SEQ_CON) + { + goto Exit; + } + } + + + // process event and call processfunction if needed + Ret = EplSdoAsySeqProcess(uiCount, + 0, + NULL, + NULL, + kAsySdoSeqEventTimeout); + +Exit: + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqDelCon +// +// Description: del and close one connection +// +// +// +// Parameters: SdoSeqConHdl_p = handle of connection +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsySeqDelCon(tEplSdoSeqConHdl SdoSeqConHdl_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiHandle; +tEplAsySdoSeqCon* pAsySdoSeqCon; + + uiHandle = (SdoSeqConHdl_p & ~EPL_SDO_SEQ_HANDLE_MASK); + + // check if handle invalid + if(uiHandle >= EPL_MAX_SDO_SEQ_CON) + { + Ret = kEplSdoSeqInvalidHdl; + goto Exit; + } + + // get pointer to connection + pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[uiHandle]; + + // decrement use counter + pAsySdoSeqCon->m_uiUseCount--; + + if (pAsySdoSeqCon->m_uiUseCount == 0) + { + // process close in processfunction + Ret = EplSdoAsySeqProcess(uiHandle, + 0, + NULL, + NULL, + kAsySdoSeqEventCloseCon); + + //check protocol + if((pAsySdoSeqCon->m_ConHandle & EPL_SDO_ASY_HANDLE_MASK) == EPL_SDO_UDP_HANDLE) + { + #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + // call close function of lower layer + EplSdoUdpuDelCon(pAsySdoSeqCon->m_ConHandle); + #endif// end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + } + else + { + #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + // call close function of lower layer + EplSdoAsnduDelCon(pAsySdoSeqCon->m_ConHandle); + #endif// end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + } + + // delete timer + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + + // clean controllstructure + EPL_MEMSET(pAsySdoSeqCon, 0x00, sizeof(tEplAsySdoSeqCon)); + pAsySdoSeqCon->m_SdoConHistory.m_bFreeEntries = EPL_SDO_HISTORY_SIZE; + } + +Exit: + return Ret; + +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplEplSdoAsySeqProcess +// +// Description: intern function to process the asynchronus SDO Sequence Layer +// state maschine +// +// +// +// Parameters: uiHandle_p = index of the control structure of the connection +// uiDataSize_p = size of data frame to process (can be 0) +// -> without size of sequence header and Asnd header!!! +// +// pData_p = pointer to frame to send (can be NULL) +// pRecFrame_p = pointer to received frame (can be NULL) +// Event_p = Event to process +// +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoAsySeqProcess(unsigned int uiHandle_p, + unsigned int uiDataSize_p, + tEplFrame* pData_p, + tEplAsySdoSeq* pRecFrame_p, + tEplAsySdoSeqEvent Event_p) + +{ +tEplKernel Ret; +unsigned int uiFrameSize; +tEplFrame* pEplFrame; +tEplAsySdoSeqCon* pAsySdoSeqCon; +tEplSdoSeqConHdl SdoSeqConHdl; +unsigned int uiFreeEntries; + +#if defined(WIN32) || defined(_WIN32) + // enter critical section for process function + EnterCriticalSection(AsySdoSequInstance_g.m_pCriticalSection); +#endif + + Ret = kEplSuccessful; + + // get handle for hinger layer + SdoSeqConHdl = uiHandle_p | EPL_SDO_ASY_HANDLE; + + // check if handle invalid + if((SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) == EPL_SDO_SEQ_INVALID_HDL) + { + Ret = kEplSdoSeqInvalidHdl; + goto Exit; + } + + // get pointer to connection + pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[uiHandle_p]; + + // check size + if((pData_p == NULL)&& (pRecFrame_p == NULL) && (uiDataSize_p != 0)) + { + Ret = kEplSdoSeqInvalidFrame; + goto Exit; + } + + // check state + switch(pAsySdoSeqCon->m_SdoState) + { + // idle state + case kEplAsySdoStateIdle: + { + // check event + switch(Event_p) + { + // new connection + // -> send init frame and change to + // kEplAsySdoStateInit1 + case kAsySdoSeqEventInitCon: + { + // set sending scon to 1 + pAsySdoSeqCon->m_bRecSeqNum = 0x01; + // set set send rcon to 0 + pAsySdoSeqCon->m_bSendSeqNum = 0x00; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // change state + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateInit1; + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + + break; + } + + // init con from extern + // check rcon and scon + // -> send answer + case kAsySdoSeqEventFrameRec: + { +/* + PRINTF3("%s scon=%u rcon=%u\n", + __FUNCTION__, + pRecFrame_p->m_le_bSendSeqNumCon, + pRecFrame_p->m_le_bRecSeqNumCon); +*/ + // check if scon == 1 and rcon == 0 + if(((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x00) + &&((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x01)) + { + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + // create answer and send answer + // set rcon to 1 (in send direction own scon) + pAsySdoSeqCon->m_bRecSeqNum++; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + // change state to kEplAsySdoStateInit2 + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateInit2; + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + } + else + { // error -> close + // delete timer + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + if (((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00) + || ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00)) + { // d.k. only answer with close message if the message sent was not a close message + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + } + + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateInitError); + } + break; + } + + default: + // d.k. do nothing + break; + + }// end of switch(Event_p) + break; + } + + // init connection step 1 + // wait for frame with scon = 1 + // and rcon = 1 + case kEplAsySdoStateInit1: + { +// PRINTF0("EplSdoAsySequ: StateInit1\n"); + + // check event + switch(Event_p) + { + // frame received + case kAsySdoSeqEventFrameRec: + { + // check scon == 1 and rcon == 1 + if(((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x01) + &&((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x01)) + { // create answer own scon = 2 + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + + pAsySdoSeqCon->m_bRecSeqNum++; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + // change state to kEplAsySdoStateInit3 + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateInit3; + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + + } + // check if scon == 1 and rcon == 0, i.e. other side wants me to be server + else if(((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x00) + &&((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x01)) + { + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + // create answer and send answer + // set rcon to 1 (in send direction own scon) + pAsySdoSeqCon->m_bRecSeqNum++; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + // change state to kEplAsySdoStateInit2 + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateInit2; + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + } + else + { // error -> Close + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // delete timer + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + if (((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00) + || ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00)) + { // d.k. only answer with close message if the message sent was not a close message + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + } + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateInitError); + } + break; + } + + // timeout + case kAsySdoSeqEventTimeout: + { // error -> Close + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateInitError); + break; + } + + default: + // d.k. do nothing + break; + + }// end of switch(Event_p) + break; + } + + // init connection step 2 + case kEplAsySdoStateInit2: + { +// PRINTF0("EplSdoAsySequ: StateInit2\n"); + + // check event + switch(Event_p) + { + // frame received + case kAsySdoSeqEventFrameRec: + { + // check scon == 2 and rcon == 1 + if(((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x01) + &&((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x02)) + { // create answer own rcon = 2 + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + + pAsySdoSeqCon->m_bRecSeqNum++; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + // change state to kEplAsySdoStateConnected + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateConnected; + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateConnected); + + } + // check scon == 1 and rcon == 1, i.e. other side wants me to initiate the connection + else if(((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x01) + &&((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x01)) + { + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + // create answer and send answer + // set rcon to 1 (in send direction own scon) + pAsySdoSeqCon->m_bRecSeqNum++; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + // change state to kEplAsySdoStateInit3 + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateInit3; + + } + else + { // error -> Close + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // delete timer + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + if (((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00) + || ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00)) + { // d.k. only answer with close message if the message sent was not a close message + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + } + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateInitError); + } + break; + } + + // timeout + case kAsySdoSeqEventTimeout: + { // error -> Close + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateInitError); + break; + } + + default: + // d.k. do nothing + break; + + }// end of switch(Event_p) + break; + } + + // init connection step 3 + case kEplAsySdoStateInit3: + { + // check event + switch(Event_p) + { + // frame received + case kAsySdoSeqEventFrameRec: + { + // check scon == 2 and rcon == 2 + if(((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x02) + &&((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x02)) + { + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + // change state to kEplAsySdoStateConnected + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateConnected; + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateConnected); + + } + // check scon == 2 and rcon == 1 + else if(((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x01) + &&((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x02)) + { // create answer own rcon = 2 + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + + pAsySdoSeqCon->m_bRecSeqNum++; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + // change state to kEplAsySdoStateConnected + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateConnected; + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateConnected); + + } + else + { // error -> Close + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // delete timer + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + if (((pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00) + || ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00)) + { // d.k. only answer with close message if the message sent was not a close message + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + } + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateInitError); + } + break; + } + + // timeout + case kAsySdoSeqEventTimeout: + { // error -> Close + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateInitError); + break; + } + + default: + // d.k. do nothing + break; + + }// end of switch(Event_p) + break; + } + + // connection established + case kEplAsySdoStateConnected: + { + // check event + switch(Event_p) + { + + // frame to send + case kAsySdoSeqEventFrameSend: + { + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + // check if data frame or ack + if(pData_p == NULL) + { // send ack + // inc scon + //pAsySdoSeqCon->m_bRecSeqNum += 4; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + } + else + { // send dataframe + // increment send sequence number + pAsySdoSeqCon->m_bRecSeqNum += 4; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + uiDataSize_p, + pData_p, + TRUE); + if(Ret == kEplSdoSeqRequestAckNeeded) + { // request ack + // change state to wait ack + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateWaitAck; + // set Ret to kEplSuccessful, because no error + // for higher layer + Ret = kEplSuccessful; + + } + else if(Ret != kEplSuccessful) + { + goto Exit; + } + else + { + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateFrameSended); + } + } + break; + }// end of case kAsySdoSeqEventFrameSend + + // frame received + case kAsySdoSeqEventFrameRec: + { + BYTE bSendSeqNumCon = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + // check scon + switch (bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) + { + // close from other node + case 0: + case 1: + { + // return to idle + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // delete timer + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateConClosed); + + break; + } + + // Request Ack or Error Ack + // possible contain data + case 3: + // normal frame + case 2: + { + if ((AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon) & EPL_ASY_SDO_CON_MASK) == 3) + { +// PRINTF0("EplSdoAsySequ: error response received\n"); + + // error response (retransmission request) + // resend frames from history + + // read frame from history + Ret = EplSdoAsyReadFromHistory(pAsySdoSeqCon, + &pEplFrame, + &uiFrameSize, + TRUE); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + while ((pEplFrame != NULL) + && (uiFrameSize != 0)) + { + // send frame + Ret = EplSdoAsySeqSendLowerLayer(pAsySdoSeqCon, + uiFrameSize, + pEplFrame); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // read next frame from history + Ret = EplSdoAsyReadFromHistory(pAsySdoSeqCon, + &pEplFrame, + &uiFrameSize, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + } // end of while((pabFrame != NULL) + } // end of if (error response) + + if (((pAsySdoSeqCon->m_bSendSeqNum + 4) & EPL_SEQ_NUM_MASK) == (bSendSeqNumCon & EPL_SEQ_NUM_MASK)) + { // next frame of sequence received + // save send sequence number (without ack request) + pAsySdoSeqCon->m_bSendSeqNum = bSendSeqNumCon & ~0x01; + + // check if ack or data-frame + //ignore ack -> already processed + if(uiDataSize_p > EPL_SEQ_HEADER_SIZE) + { + AsySdoSequInstance_g.m_fpSdoComReceiveCb( + SdoSeqConHdl, + ((tEplAsySdoCom*) &pRecFrame_p->m_le_abSdoSeqPayload), + (uiDataSize_p - EPL_SEQ_HEADER_SIZE)); + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateFrameSended); + + + } + else + { + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateAckReceived); + } + } + else if (((bSendSeqNumCon - pAsySdoSeqCon->m_bSendSeqNum - 4) & EPL_SEQ_NUM_MASK) < EPL_SEQ_NUM_THRESHOLD) + { // frame of sequence was lost, + // because difference of received and old value + // is less then halve of the values range. + + // send error frame with own rcon = 3 + pAsySdoSeqCon->m_bSendSeqNum |= 0x03; + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + // restore send sequence number + pAsySdoSeqCon->m_bSendSeqNum = (pAsySdoSeqCon->m_bSendSeqNum & EPL_SEQ_NUM_MASK) | 0x02; + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // break here, because a requested acknowledge + // was sent implicitly above + break; + } + // else, ignore repeated frame + + if ((bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 3) + { // ack request received + + // create ack with own scon = 2 + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + } + + break; + } + + } // switch(pAsySdoSeqCon->m_bSendSeqNum & EPL_ASY_SDO_CON_MASK) + break; + } // end of case kAsySdoSeqEventFrameRec: + + + //close event from higher layer + case kAsySdoSeqEventCloseCon: + { + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + + // delete timer + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + // call Command Layer Cb is not necessary, because the event came from there +// AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, +// kAsySdoConStateInitError); + break; + } + + // timeout + case kAsySdoSeqEventTimeout: + { + + uiFreeEntries = EplSdoAsyGetFreeEntriesFromHistory(pAsySdoSeqCon); + if ((uiFreeEntries < EPL_SDO_HISTORY_SIZE) + && (pAsySdoSeqCon->m_uiRetryCount < EPL_SEQ_RETRY_COUNT)) + { // unacknowlegded frames in history + // and retry counter not exceeded + + // resend data with acknowledge request + + // increment retry counter + pAsySdoSeqCon->m_uiRetryCount++; + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + + // read first frame from history + Ret = EplSdoAsyReadFromHistory(pAsySdoSeqCon, + &pEplFrame, + &uiFrameSize, + TRUE); + if (Ret != kEplSuccessful) + { + goto Exit; + } + + if ((pEplFrame != NULL) + && (uiFrameSize != 0)) + { + + // set ack request in scon + AmiSetByteToLe( &pEplFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_bSendSeqNumCon, + AmiGetByteFromLe( &pEplFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_bSendSeqNumCon) | 0x03); + + // send frame + Ret = EplSdoAsySeqSendLowerLayer(pAsySdoSeqCon, + uiFrameSize, + pEplFrame); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + } + } + else + { + // timeout, because of no traffic -> Close + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateTimeout); + } + + break; + } + + default: + // d.k. do nothing + break; + + }// end of switch(Event_p) + break; + } + + // wait for Acknowledge (history buffer full) + case kEplAsySdoStateWaitAck: + { + PRINTF0("EplSdoAsySequ: StateWaitAck\n"); + + // set timer + Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon, + EPL_SEQ_DEFAULT_TIMEOUT); + + //TODO: retry of acknowledge + if(Event_p == kAsySdoSeqEventFrameRec) + { + // check rcon + switch(pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) + { + // close-frome other node + case 0: + { + // return to idle + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // delete timer + EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl); + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateConClosed); + + break; + } + + // normal frame + case 2: + { + // should be ack + // -> change to state kEplAsySdoStateConnected + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateConnected; + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateAckReceived); + // send data to higher layer if needed + if(uiDataSize_p > EPL_SEQ_HEADER_SIZE) + { + AsySdoSequInstance_g.m_fpSdoComReceiveCb( + SdoSeqConHdl, + ((tEplAsySdoCom*) &pRecFrame_p->m_le_abSdoSeqPayload), + (uiDataSize_p - EPL_SEQ_HEADER_SIZE)); + } + break; + } + + // Request Ack or Error Ack + case 3: + { + // -> change to state kEplAsySdoStateConnected + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateConnected; + + if(pRecFrame_p->m_le_bRecSeqNumCon == pAsySdoSeqCon->m_bRecSeqNum ) + { // ack request + // -> send ack + // save sequence numbers + pAsySdoSeqCon->m_bRecSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bRecSeqNumCon); + pAsySdoSeqCon->m_bSendSeqNum = AmiGetByteFromLe(&pRecFrame_p->m_le_bSendSeqNumCon); + + // create answer own rcon = 2 + pAsySdoSeqCon->m_bRecSeqNum--; + + // check if ack or data-frame + if(uiDataSize_p > EPL_SEQ_HEADER_SIZE) + { + AsySdoSequInstance_g.m_fpSdoComReceiveCb( + SdoSeqConHdl, + ((tEplAsySdoCom*) &pRecFrame_p->m_le_abSdoSeqPayload), + (uiDataSize_p - EPL_SEQ_HEADER_SIZE)); + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateFrameSended); + + + } + else + { + Ret = EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + if(Ret != kEplSuccessful) + { + goto Exit; + } + } + + } + else + { + // error ack + // resend frames from history + + // read frame from history + Ret = EplSdoAsyReadFromHistory(pAsySdoSeqCon, + &pEplFrame, + &uiFrameSize, + TRUE); + while ((pEplFrame != NULL) + && (uiFrameSize != 0)) + { + // send frame + Ret = EplSdoAsySeqSendLowerLayer(pAsySdoSeqCon, + uiFrameSize, + pEplFrame); + if(Ret != kEplSuccessful) + { + goto Exit; + } + // read next frame + + // read frame from history + Ret = EplSdoAsyReadFromHistory(pAsySdoSeqCon, + &pEplFrame, + &uiFrameSize, + FALSE); + } // end of while((pabFrame != NULL) + } + break; + } + }// end of switch(pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK) + + } + else if(Event_p == kAsySdoSeqEventTimeout) + { // error -> Close + pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle; + // set rcon and scon to 0 + pAsySdoSeqCon->m_bSendSeqNum &= EPL_SEQ_NUM_MASK; + pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK; + // send frame + EplSdoAsySeqSendIntern(pAsySdoSeqCon, + 0, + NULL, + FALSE); + + // call Command Layer Cb + AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl, + kAsySdoConStateTimeout); + } + + break; + } + + // unknown state + default: + { + EPL_DBGLVL_SDO_TRACE0("Error: Unknown State in EplSdoAsySeqProcess\n"); + + } + }// end of switch(pAsySdoSeqCon->m_SdoState) + + + +Exit: + +#if defined(WIN32) || defined(_WIN32) + // leave critical section for process function + LeaveCriticalSection(AsySdoSequInstance_g.m_pCriticalSection); +#endif + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqSendIntern +// +// Description: intern function to create and send a frame +// -> if uiDataSize_p == 0 create a frame with infos from +// pAsySdoSeqCon_p +// +// +// +// Parameters: pAsySdoSeqCon_p = pointer to control structure of the connection +// uiDataSize_p = size of data frame to process (can be 0) +// -> without size of sequence header and Asnd header!!! +// pData_p = pointer to frame to process (can be NULL) +// fFrameInHistory = if TRUE frame is saved to history else not +// +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoAsySeqSendIntern(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + unsigned int uiDataSize_p, + tEplFrame* pData_p, + BOOL fFrameInHistory_p) +{ +tEplKernel Ret; +BYTE abFrame[EPL_SEQ_FRAME_SIZE]; +tEplFrame* pEplFrame; +unsigned int uiFreeEntries; + + if(pData_p == NULL) + { // set pointer to own frame + EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame)); + pEplFrame = (tEplFrame*)&abFrame[0]; + } + else + { // set pointer to frame from calling function + pEplFrame = pData_p; + } + + if(fFrameInHistory_p != FALSE) + { + // check if only one free entry in history buffer + uiFreeEntries = EplSdoAsyGetFreeEntriesFromHistory(pAsySdoSeqCon_p); + if(uiFreeEntries == 1) + { // request an acknowledge in dataframe + // own scon = 3 + pAsySdoSeqCon_p->m_bRecSeqNum |= 0x03; + } + } + + // fillin header informations + // set service id sdo + AmiSetByteToLe( &pEplFrame->m_Data.m_Asnd.m_le_bServiceId, 0x05); + AmiSetByteToLe( &pEplFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_abReserved,0x00); + // set receive sequence number and rcon + AmiSetByteToLe( &pEplFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_bRecSeqNumCon, pAsySdoSeqCon_p->m_bSendSeqNum); + // set send sequence number and scon + AmiSetByteToLe( &pEplFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_bSendSeqNumCon, pAsySdoSeqCon_p->m_bRecSeqNum); + + // add size + uiDataSize_p += EPL_SEQ_HEADER_SIZE; + + + // forward frame to appropriate lower layer + Ret = EplSdoAsySeqSendLowerLayer(pAsySdoSeqCon_p, + uiDataSize_p, + pEplFrame); // pointer to frame + + // check if all allright + if ((Ret == kEplSuccessful) + && (fFrameInHistory_p != FALSE)) + { + // set own scon to 2 if needed + if((pAsySdoSeqCon_p->m_bRecSeqNum & 0x03) == 0x03) + { + pAsySdoSeqCon_p->m_bRecSeqNum--; + } + + // save frame to history + Ret = EplSdoAsyAddFrameToHistory(pAsySdoSeqCon_p, + pEplFrame, + uiDataSize_p); + if (Ret == kEplSdoSeqNoFreeHistory) + { // request Ack needed + Ret = kEplSdoSeqRequestAckNeeded; + } + + } + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqSendLowerLayer +// +// Description: intern function to send a previously created frame to lower layer +// +// Parameters: pAsySdoSeqCon_p = pointer to control structure of the connection +// uiDataSize_p = size of data frame to process (can be 0) +// -> without size of Asnd header!!! +// pData_p = pointer to frame to process (can be NULL) +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoAsySeqSendLowerLayer(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + unsigned int uiDataSize_p, + tEplFrame* pEplFrame_p) +{ +tEplKernel Ret; + + // call send-function + // check handle for UDP or Asnd + if ((pAsySdoSeqCon_p->m_ConHandle & EPL_SDO_ASY_HANDLE_MASK) == EPL_SDO_UDP_HANDLE) + { // send over UDP +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + Ret = EplSdoUdpuSendData(pAsySdoSeqCon_p->m_ConHandle, + pEplFrame_p, // pointer to frame + uiDataSize_p); +#else + Ret = kEplSdoSeqUnsupportedProt; +#endif + + } + else if ((pAsySdoSeqCon_p->m_ConHandle & EPL_SDO_ASY_HANDLE_MASK) == EPL_SDO_ASND_HANDLE) + { // ASND +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + Ret = EplSdoAsnduSendData(pAsySdoSeqCon_p->m_ConHandle, + pEplFrame_p, // pointer to frame + uiDataSize_p); +#else + Ret = kEplSdoSeqUnsupportedProt; +#endif + } + else + { // error + Ret = kEplSdoSeqInvalidHdl; + } + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsyReceiveCb +// +// Description: callback-function for received frames from lower layer +// +// +// +// Parameters: ConHdl_p = handle of the connection +// pSdoSeqData_p = pointer to frame +// uiDataSize_p = size of frame +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsyReceiveCb ( + tEplSdoConHdl ConHdl_p, + tEplAsySdoSeq* pSdoSeqData_p, + unsigned int uiDataSize_p) +{ +tEplKernel Ret; +unsigned int uiCount = 0; +unsigned int uiFreeEntry = EPL_MAX_SDO_SEQ_CON; +tEplAsySdoSeqCon* pAsySdoSeqCon; + +#if defined(WIN32) || defined(_WIN32) + // enter critical section + EnterCriticalSection(AsySdoSequInstance_g.m_pCriticalSectionReceive); +#endif + + EPL_DBGLVL_SDO_TRACE2("Handle: 0x%x , First Databyte 0x%x\n", ConHdl_p,((BYTE*)pSdoSeqData_p)[0]); + + // search controll structure for this connection + pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[uiCount]; + while (uiCount < EPL_MAX_SDO_SEQ_CON) + { + if (pAsySdoSeqCon->m_ConHandle == ConHdl_p) + { + break; + } + else if ((pAsySdoSeqCon->m_ConHandle == 0) + && (uiFreeEntry == EPL_MAX_SDO_SEQ_CON)) + { + // free entry + uiFreeEntry = uiCount; + } + uiCount++; + pAsySdoSeqCon++; + } + + if (uiCount == EPL_MAX_SDO_SEQ_CON) + { // new connection + if (uiFreeEntry == EPL_MAX_SDO_SEQ_CON) + { + Ret = kEplSdoSeqNoFreeHandle; + goto Exit; + } + else + { + pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[uiFreeEntry]; + // save handle from lower layer + pAsySdoSeqCon->m_ConHandle = ConHdl_p; + // increment use counter + pAsySdoSeqCon->m_uiUseCount++; + uiCount = uiFreeEntry ; + } + } + + // call history ack function + Ret = EplSdoAsyAckFrameToHistory(pAsySdoSeqCon, + (AmiGetByteFromLe(&pSdoSeqData_p->m_le_bRecSeqNumCon)& EPL_SEQ_NUM_MASK)); + if (Ret != kEplSuccessful) + { + goto Exit; + } + +#if defined(WIN32) || defined(_WIN32) + // leave critical section + LeaveCriticalSection(AsySdoSequInstance_g.m_pCriticalSectionReceive); +#endif + + // call process function with pointer of frame and event kAsySdoSeqEventFrameRec + Ret = EplSdoAsySeqProcess(uiCount, + uiDataSize_p, + NULL, + pSdoSeqData_p, + kAsySdoSeqEventFrameRec); + + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsyInitHistory +// +// Description: inti function for history buffer +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoAsyInitHistory(void) +{ +tEplKernel Ret; +unsigned int uiCount; + + Ret = kEplSuccessful; + // init m_bFreeEntries in history-buffer + for(uiCount = 0; uiCount < EPL_MAX_SDO_SEQ_CON; uiCount++) + { + AsySdoSequInstance_g.m_AsySdoConnection[uiCount].m_SdoConHistory.m_bFreeEntries = EPL_SDO_HISTORY_SIZE; + } + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsyAddFrameToHistory +// +// Description: function to add a frame to the history buffer +// +// +// +// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection +// pFrame_p = pointer to frame +// uiSize_p = size of the frame +// -> without size of the ethernet header +// and the asnd header +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoAsyAddFrameToHistory(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + tEplFrame* pFrame_p, + unsigned int uiSize_p) +{ +tEplKernel Ret; +tEplAsySdoConHistory* pHistory; + + Ret = kEplSuccessful; + + // add frame to history buffer + + // check size + // $$$ d.k. EPL_SEQ_HISTORY_FRAME_SIZE includes the header size, but uiSize_p does not!!! + if(uiSize_p > EPL_SEQ_HISTROY_FRAME_SIZE) + { + Ret = kEplSdoSeqFrameSizeError; + goto Exit; + } + + // save pointer to history + pHistory = &pAsySdoSeqCon_p->m_SdoConHistory; + + + // check if a free entry is available + if(pHistory->m_bFreeEntries > 0) + { // write message in free entry + EPL_MEMCPY(&((tEplFrame*)pHistory->m_aabHistoryFrame[pHistory->m_bWrite])->m_le_bMessageType, + &pFrame_p->m_le_bMessageType, + uiSize_p + EPL_ASND_HEADER_SIZE); + // store size + pHistory->m_auiFrameSize[pHistory->m_bWrite] = uiSize_p; + + // decremend number of free bufferentries + pHistory->m_bFreeEntries--; + + // increment writeindex + pHistory->m_bWrite++; + + // check if write-index run over array-boarder + if(pHistory->m_bWrite == EPL_SDO_HISTORY_SIZE) + { + pHistory->m_bWrite = 0; + } + + } + else + { // no free entry + Ret = kEplSdoSeqNoFreeHistory; + } + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsyAckFrameToHistory +// +// Description: function to delete acknowledged frames fron history buffer +// +// +// +// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection +// bRecSeqNumber_p = receive sequence number of the received frame +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoAsyAckFrameToHistory(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + BYTE bRecSeqNumber_p) +{ +tEplKernel Ret; +tEplAsySdoConHistory* pHistory; +BYTE bAckIndex; +BYTE bCurrentSeqNum; + + Ret = kEplSuccessful; + + // get pointer to history buffer + pHistory = &pAsySdoSeqCon_p->m_SdoConHistory; + + // release all acknowledged frames from history buffer + + // check if there are entries in history + if (pHistory->m_bFreeEntries < EPL_SDO_HISTORY_SIZE) + { + bAckIndex = pHistory->m_bAck; + do + { + bCurrentSeqNum = (((tEplFrame*)pHistory->m_aabHistoryFrame[bAckIndex])->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_bSendSeqNumCon & EPL_SEQ_NUM_MASK); + if (((bRecSeqNumber_p - bCurrentSeqNum) & EPL_SEQ_NUM_MASK) + < EPL_SEQ_NUM_THRESHOLD) + { + pHistory->m_auiFrameSize[bAckIndex] = 0; + bAckIndex++; + pHistory->m_bFreeEntries++; + if (bAckIndex == EPL_SDO_HISTORY_SIZE) + { // read index run over array-boarder + bAckIndex = 0; + } + } + else + { // nothing to do anymore, + // because any further frame in history has larger sequence + // number than the acknowledge + goto Exit; + } + } + while ((((bRecSeqNumber_p - 1 - bCurrentSeqNum) & EPL_SEQ_NUM_MASK) + < EPL_SEQ_NUM_THRESHOLD) + && (pHistory->m_bWrite != bAckIndex)); + + // store local read-index to global var + pHistory->m_bAck = bAckIndex; + } + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsyReadFromHistory +// +// Description: function to one frame from history +// +// +// +// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection +// ppFrame_p = pointer to pointer to the buffer of the stored frame +// puiSize_p = OUT: size of the frame +// fInitRead = bool which indicate a start of retransmission +// -> return last not acknowledged message if TRUE +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoAsyReadFromHistory(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + tEplFrame** ppFrame_p, + unsigned int* puiSize_p, + BOOL fInitRead_p) +{ +tEplKernel Ret; +tEplAsySdoConHistory* pHistory; + + Ret = kEplSuccessful; + + // read one message from History + + // get pointer to history buffer + pHistory = &pAsySdoSeqCon_p->m_SdoConHistory; + + // check if init + if (fInitRead_p != FALSE) + { // initialize read index to the index which shall be acknowledged next + pHistory->m_bRead = pHistory->m_bAck; + } + + // check if entries are available for reading + if ((pHistory->m_bFreeEntries < EPL_SDO_HISTORY_SIZE) + && (pHistory->m_bWrite != pHistory->m_bRead)) + { +// PRINTF4("EplSdoAsyReadFromHistory(): init = %d, read = %u, write = %u, ack = %u", (int) fInitRead_p, (WORD)pHistory->m_bRead, (WORD)pHistory->m_bWrite, (WORD)pHistory->m_bAck); +// PRINTF2(", free entries = %u, next frame size = %u\n", (WORD)pHistory->m_bFreeEntries, pHistory->m_auiFrameSize[pHistory->m_bRead]); + + // return pointer to stored frame + *ppFrame_p = (tEplFrame*)pHistory->m_aabHistoryFrame[pHistory->m_bRead]; + + // save size + *puiSize_p = pHistory->m_auiFrameSize[pHistory->m_bRead]; + + pHistory->m_bRead++; + if(pHistory->m_bRead == EPL_SDO_HISTORY_SIZE) + { + pHistory->m_bRead = 0; + } + + } + else + { +// PRINTF3("EplSdoAsyReadFromHistory(): read = %u, ack = %u, free entries = %u, no frame\n", (WORD)pHistory->m_bRead, (WORD)pHistory->m_bAck, (WORD)pHistory->m_bFreeEntries); + + // no more frames to send + // return null pointer + *ppFrame_p = NULL; + + *puiSize_p = 0; + } + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsyGetFreeEntriesFromHistory +// +// Description: function returns the number of free histroy entries +// +// +// +// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection +// +// +// Returns: unsigned int = number of free entries +// +// +// State: +// +//--------------------------------------------------------------------------- +static unsigned int EplSdoAsyGetFreeEntriesFromHistory(tEplAsySdoSeqCon* pAsySdoSeqCon_p) +{ +unsigned int uiFreeEntries; + + uiFreeEntries = (unsigned int)pAsySdoSeqCon_p->m_SdoConHistory.m_bFreeEntries; + + return uiFreeEntries; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoAsySeqSetTimer +// +// Description: function sets or modify timer in timermosule +// +// +// +// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection +// ulTimeout = timeout in ms +// +// +// Returns: unsigned int = number of free entries +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoAsySeqSetTimer(tEplAsySdoSeqCon* pAsySdoSeqCon_p, + unsigned long ulTimeout) +{ +tEplKernel Ret; +tEplTimerArg TimerArg; + + TimerArg.m_EventSink = kEplEventSinkSdoAsySeq; + TimerArg.m_ulArg = (unsigned long)pAsySdoSeqCon_p; + + if(pAsySdoSeqCon_p->m_EplTimerHdl == 0) + { // create new timer + Ret = EplTimeruSetTimerMs(&pAsySdoSeqCon_p->m_EplTimerHdl, + ulTimeout, + TimerArg); + } + else + { // modify exisiting timer + Ret = EplTimeruModifyTimerMs(&pAsySdoSeqCon_p->m_EplTimerHdl, + ulTimeout, + TimerArg); + + } + + + return Ret; +} + +// EOF + diff --git a/drivers/staging/epl/EplSdoComu.c b/drivers/staging/epl/EplSdoComu.c new file mode 100644 index 0000000..ce5af66 --- /dev/null +++ b/drivers/staging/epl/EplSdoComu.c @@ -0,0 +1,3029 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for SDO Command Layer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdoComu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.14 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/26 k.t.: start of the implementation + +****************************************************************************/ + +#include "user/EplSdoComu.h" + +#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) == 0) &&\ + (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) == 0) ) + + #error 'ERROR: At least SDO Server or SDO Client should be activate!' + +#endif + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE) + + #error 'ERROR: SDO Server needs OBDu module!' + + #endif + +#endif + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#ifndef EPL_MAX_SDO_COM_CON +#define EPL_MAX_SDO_COM_CON 5 +#endif + + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +// intern events +typedef enum +{ + kEplSdoComConEventSendFirst = 0x00, // first frame to send + kEplSdoComConEventRec = 0x01, // frame received + kEplSdoComConEventConEstablished= 0x02, // connection established + kEplSdoComConEventConClosed = 0x03, // connection closed + kEplSdoComConEventAckReceived = 0x04, // acknowledge received by lower layer + // -> continue sending + kEplSdoComConEventFrameSended = 0x05, // lower has send a frame + kEplSdoComConEventInitError = 0x06, // error duringinitialisiation + // of the connection + kEplSdoComConEventTimeout = 0x07 // timeout in lower layer +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + + , + + kEplSdoComConEventInitCon = 0x08, // init connection (only client) + kEplSdoComConEventAbort = 0x09 // abort sdo transfer (only client) +#endif + + +}tEplSdoComConEvent; + +typedef enum +{ + kEplSdoComSendTypeReq = 0x00, // send a request + kEplSdoComSendTypeAckRes = 0x01, // send a resonse without data + kEplSdoComSendTypeRes = 0x02, // send response with data + kEplSdoComSendTypeAbort = 0x03 // send abort + +}tEplSdoComSendType; + +// state of the state maschine +typedef enum +{ + // General State + kEplSdoComStateIdle = 0x00, // idle state + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) + // Server States + kEplSdoComStateServerSegmTrans = 0x01, // send following frames +#endif + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + // Client States + kEplSdoComStateClientWaitInit = 0x10, // wait for init connection + // on lower layer + kEplSdoComStateClientConnected = 0x11, // connection established + kEplSdoComStateClientSegmTrans = 0x12 // send following frames +#endif + + + +} tEplSdoComState; + + +// control structure for transaction +typedef struct +{ + tEplSdoSeqConHdl m_SdoSeqConHdl; // if != 0 -> entry used + tEplSdoComState m_SdoComState; + BYTE m_bTransactionId; + unsigned int m_uiNodeId; // NodeId of the target + // -> needed to reinit connection + // after timeout + tEplSdoTransType m_SdoTransType; // Auto, Expedited, Segmented + tEplSdoServiceType m_SdoServiceType; // WriteByIndex, ReadByIndex + tEplSdoType m_SdoProtType; // protocol layer: Auto, Udp, Asnd, Pdo + BYTE* m_pData; // pointer to data + unsigned int m_uiTransSize; // number of bytes + // to transfer + unsigned int m_uiTransferredByte;// number of bytes + // already transferred + tEplSdoFinishedCb m_pfnTransferFinished;// callback function of the + // application + // -> called in the end of + // the SDO transfer + void* m_pUserArg; // user definable argument pointer + + DWORD m_dwLastAbortCode; // save the last abort code +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + // only for client + unsigned int m_uiTargetIndex; // index to access + unsigned int m_uiTargetSubIndex; // subiondex to access + + // for future use + unsigned int m_uiTimeout; // timeout for this connection + +#endif + +} tEplSdoComCon; + +// instance table +typedef struct +{ + tEplSdoComCon m_SdoComCon[EPL_MAX_SDO_COM_CON]; + +#if defined(WIN32) || defined(_WIN32) + LPCRITICAL_SECTION m_pCriticalSection; + CRITICAL_SECTION m_CriticalSection; +#endif + +}tEplSdoComInstance; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- +static tEplSdoComInstance SdoComInstance_g; +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoComReceiveCb (tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoCom* pAsySdoCom_p, + unsigned int uiDataSize_p); + + +tEplKernel PUBLIC EplSdoComConCb (tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoConState AsySdoConState_p); + +static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplSdoComConEvent SdoComConEvent_p, + tEplAsySdoCom* pAsySdoCom_p); + +static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, + tEplSdoComConEvent SdoComConEvent_p, + tEplAsySdoCom* pAsySdoCom_p); + +static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl SdoComCon_p, + tEplSdoComCon* pSdoComCon_p, + tEplSdoComConState SdoComConState_p); + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) +static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon* pSdoComCon_p, + tEplAsySdoCom* pAsySdoCom_p); + +static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon* pSdoComCon_p, + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplSdoComSendType SendType_p); + +static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon* pSdoComCon_p, + tEplAsySdoCom* pAsySdoCom_p); +#endif + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + +static tEplKernel EplSdoComClientSend(tEplSdoComCon* pSdoComCon_p); + +static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p, + tEplAsySdoCom* pAsySdoCom_p); + +static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon* pSdoComCon_p, + DWORD dwAbortCode_p); +#endif + + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <SDO Command Layer> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: SDO Command layer Modul +// +// +/***************************************************************************/ + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComInit +// +// Description: Init first instance of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoComInit(void) +{ +tEplKernel Ret; + + + Ret = EplSdoComAddInstance(); + +return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComAddInstance +// +// Description: Init additional instance of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoComAddInstance(void) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // init controll structure + EPL_MEMSET(&SdoComInstance_g, 0x00, sizeof(SdoComInstance_g)); + + // init instance of lower layer + Ret = EplSdoAsySeqAddInstance(EplSdoComReceiveCb, EplSdoComConCb); + if(Ret != kEplSuccessful) + { + goto Exit; + } + +#if defined(WIN32) || defined(_WIN32) + // create critical section for process function + SdoComInstance_g.m_pCriticalSection = &SdoComInstance_g.m_CriticalSection; + InitializeCriticalSection(SdoComInstance_g.m_pCriticalSection); +#endif + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComDelInstance +// +// Description: delete instance of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoComDelInstance(void) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + +#if defined(WIN32) || defined(_WIN32) + // delete critical section for process function + DeleteCriticalSection(SdoComInstance_g.m_pCriticalSection); +#endif + + Ret = EplSdoAsySeqDelInstance(); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + +Exit: + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComDefineCon +// +// Description: function defines a SDO connection to another node +// -> init lower layer and returns a handle for the connection. +// Two client connections to the same node via the same protocol +// are not allowed. If this function detects such a situation +// it will return kEplSdoComHandleExists and the handle of +// the existing connection in pSdoComConHdl_p. +// Using of existing server connections is possible. +// +// Parameters: pSdoComConHdl_p = pointer to the buffer of the handle +// uiTargetNodeId_p = NodeId of the targetnode +// ProtType_p = type of protocol to use for connection +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +tEplKernel PUBLIC EplSdoComDefineCon(tEplSdoComConHdl* pSdoComConHdl_p, + unsigned int uiTargetNodeId_p, + tEplSdoType ProtType_p) +{ +tEplKernel Ret; +unsigned int uiCount; +unsigned int uiFreeHdl; +tEplSdoComCon* pSdoComCon; + + // check Parameter + ASSERT(pSdoComConHdl_p != NULL); + + // check NodeId + if((uiTargetNodeId_p == EPL_C_ADR_INVALID) + ||(uiTargetNodeId_p >= EPL_C_ADR_BROADCAST)) + { + Ret = kEplInvalidNodeId; + + } + + // search free control structure + pSdoComCon = &SdoComInstance_g.m_SdoComCon[0]; + uiCount = 0; + uiFreeHdl = EPL_MAX_SDO_COM_CON; + while (uiCount < EPL_MAX_SDO_COM_CON) + { + if (pSdoComCon->m_SdoSeqConHdl == 0) + { // free entry + uiFreeHdl = uiCount; + } + else if ((pSdoComCon->m_uiNodeId == uiTargetNodeId_p) + && (pSdoComCon->m_SdoProtType == ProtType_p)) + { // existing client connection with same node ID and same protocol type + *pSdoComConHdl_p = uiCount; + Ret = kEplSdoComHandleExists; + goto Exit; + } + uiCount++; + pSdoComCon++; + } + + if (uiFreeHdl == EPL_MAX_SDO_COM_CON) + { + Ret = kEplSdoComNoFreeHandle; + goto Exit; + } + + pSdoComCon = &SdoComInstance_g.m_SdoComCon[uiFreeHdl]; + // save handle for application + *pSdoComConHdl_p = uiFreeHdl; + // save parameters + pSdoComCon->m_SdoProtType = ProtType_p; + pSdoComCon->m_uiNodeId = uiTargetNodeId_p; + + // set Transaction Id + pSdoComCon->m_bTransactionId = 0; + + // check protocol + switch(ProtType_p) + { + // udp + case kEplSdoTypeUdp: + { + // call connection int function of lower layer + Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl, + pSdoComCon->m_uiNodeId, + kEplSdoTypeUdp); + if(Ret != kEplSuccessful) + { + goto Exit; + } + break; + } + + // Asend + case kEplSdoTypeAsnd: + { + // call connection int function of lower layer + Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl, + pSdoComCon->m_uiNodeId, + kEplSdoTypeAsnd); + if(Ret != kEplSuccessful) + { + goto Exit; + } + break; + } + + // Pdo -> not supported + case kEplSdoTypePdo: + default: + { + Ret = kEplSdoComUnsupportedProt; + goto Exit; + } + }// end of switch(m_ProtType_p) + + // call process function + Ret = EplSdoComProcessIntern(uiFreeHdl, + kEplSdoComConEventInitCon, + NULL); + +Exit: + return Ret; +} +#endif +//--------------------------------------------------------------------------- +// +// Function: EplSdoComInitTransferByIndex +// +// Description: function init SDO Transfer for a defined connection +// +// +// +// Parameters: SdoComTransParam_p = Structure with parameters for connection +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +tEplKernel PUBLIC EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex* pSdoComTransParam_p) +{ +tEplKernel Ret; +tEplSdoComCon* pSdoComCon; + + // check parameter + if ((pSdoComTransParam_p->m_uiSubindex >= 0xFF) + || (pSdoComTransParam_p->m_uiIndex == 0) + || (pSdoComTransParam_p->m_uiIndex > 0xFFFF) + || (pSdoComTransParam_p->m_pData == NULL) + || (pSdoComTransParam_p->m_uiDataSize == 0)) + { + Ret = kEplSdoComInvalidParam; + goto Exit; + } + + if(pSdoComTransParam_p->m_SdoComConHdl >= EPL_MAX_SDO_COM_CON) + { + Ret = kEplSdoComInvalidHandle; + goto Exit; + } + + // get pointer to control structure of connection + pSdoComCon = &SdoComInstance_g.m_SdoComCon[pSdoComTransParam_p->m_SdoComConHdl]; + + // check if handle ok + if(pSdoComCon->m_SdoSeqConHdl == 0) + { + Ret = kEplSdoComInvalidHandle; + goto Exit; + } + + // check if command layer is idle + if ((pSdoComCon->m_uiTransferredByte + pSdoComCon->m_uiTransSize) > 0) + { // handle is not idle + Ret = kEplSdoComHandleBusy; + goto Exit; + } + + // save parameter + // callback function for end of transfer + pSdoComCon->m_pfnTransferFinished = pSdoComTransParam_p->m_pfnSdoFinishedCb; + pSdoComCon->m_pUserArg = pSdoComTransParam_p->m_pUserArg; + + // set type of SDO command + if (pSdoComTransParam_p->m_SdoAccessType == kEplSdoAccessTypeRead) + { + pSdoComCon->m_SdoServiceType = kEplSdoServiceReadByIndex; + } + else + { + pSdoComCon->m_SdoServiceType = kEplSdoServiceWriteByIndex; + + } + // save pointer to data + pSdoComCon->m_pData = pSdoComTransParam_p->m_pData; + // maximal bytes to transfer + pSdoComCon->m_uiTransSize = pSdoComTransParam_p->m_uiDataSize; + // bytes already transfered + pSdoComCon->m_uiTransferredByte = 0; + + // reset parts of control structure + pSdoComCon->m_dwLastAbortCode = 0; + pSdoComCon->m_SdoTransType = kEplSdoTransAuto; + // save timeout + //pSdoComCon->m_uiTimeout = SdoComTransParam_p.m_uiTimeout; + + // save index and subindex + pSdoComCon->m_uiTargetIndex = pSdoComTransParam_p->m_uiIndex; + pSdoComCon->m_uiTargetSubIndex = pSdoComTransParam_p->m_uiSubindex; + + // call process function + Ret = EplSdoComProcessIntern(pSdoComTransParam_p->m_SdoComConHdl, + kEplSdoComConEventSendFirst, // event to start transfer + NULL); + +Exit: + return Ret; + +} +#endif + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComUndefineCon +// +// Description: function undefine a SDO connection +// +// +// +// Parameters: SdoComConHdl_p = handle for the connection +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +tEplKernel PUBLIC EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p) +{ +tEplKernel Ret; +tEplSdoComCon* pSdoComCon; + + Ret = kEplSuccessful; + + if(SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) + { + Ret = kEplSdoComInvalidHandle; + goto Exit; + } + + // get pointer to control structure + pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p]; + + // $$$ d.k. abort a running transfer before closing the sequence layer + + if(((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) != EPL_SDO_SEQ_INVALID_HDL) + && (pSdoComCon->m_SdoSeqConHdl != 0)) + { + // close connection in lower layer + switch(pSdoComCon->m_SdoProtType) + { + case kEplSdoTypeAsnd: + case kEplSdoTypeUdp: + { + Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); + break; + } + + case kEplSdoTypePdo: + case kEplSdoTypeAuto: + default: + { + Ret = kEplSdoComUnsupportedProt; + goto Exit; + } + + }// end of switch(pSdoComCon->m_SdoProtType) + } + + + // clean controll structure + EPL_MEMSET(pSdoComCon, 0x00, sizeof(tEplSdoComCon)); +Exit: + return Ret; +} +#endif +//--------------------------------------------------------------------------- +// +// Function: EplSdoComGetState +// +// Description: function returns the state fo the connection +// +// +// +// Parameters: SdoComConHdl_p = handle for the connection +// pSdoComFinished_p = pointer to structur for sdo state +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +tEplKernel PUBLIC EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p, + tEplSdoComFinished* pSdoComFinished_p) +{ +tEplKernel Ret; +tEplSdoComCon* pSdoComCon; + + Ret = kEplSuccessful; + + if(SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) + { + Ret = kEplSdoComInvalidHandle; + goto Exit; + } + + // get pointer to control structure + pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p]; + + // check if handle ok + if(pSdoComCon->m_SdoSeqConHdl == 0) + { + Ret = kEplSdoComInvalidHandle; + goto Exit; + } + + pSdoComFinished_p->m_pUserArg = pSdoComCon->m_pUserArg; + pSdoComFinished_p->m_uiNodeId = pSdoComCon->m_uiNodeId; + pSdoComFinished_p->m_uiTargetIndex = pSdoComCon->m_uiTargetIndex; + pSdoComFinished_p->m_uiTargetSubIndex = pSdoComCon->m_uiTargetSubIndex; + pSdoComFinished_p->m_uiTransferredByte = pSdoComCon->m_uiTransferredByte; + pSdoComFinished_p->m_dwAbortCode = pSdoComCon->m_dwLastAbortCode; + pSdoComFinished_p->m_SdoComConHdl = SdoComConHdl_p; + if (pSdoComCon->m_SdoServiceType == kEplSdoServiceWriteByIndex) + { + pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeWrite; + } + else + { + pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeRead; + } + + if(pSdoComCon->m_dwLastAbortCode != 0) + { // sdo abort + pSdoComFinished_p->m_SdoComConState = kEplSdoComTransferRxAborted; + + // delete abort code + pSdoComCon->m_dwLastAbortCode = 0; + + } + else if((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK)== EPL_SDO_SEQ_INVALID_HDL) + { // check state + pSdoComFinished_p->m_SdoComConState = kEplSdoComTransferLowerLayerAbort; + } + else if(pSdoComCon->m_SdoComState == kEplSdoComStateClientWaitInit) + { + // finished + pSdoComFinished_p->m_SdoComConState = kEplSdoComTransferNotActive; + } + else if(pSdoComCon->m_uiTransSize == 0) + { // finished + pSdoComFinished_p->m_SdoComConState = kEplSdoComTransferFinished; + } + +Exit: + return Ret; + +} +#endif +//--------------------------------------------------------------------------- +// +// Function: EplSdoComSdoAbort +// +// Description: function abort a sdo transfer +// +// +// +// Parameters: SdoComConHdl_p = handle for the connection +// dwAbortCode_p = abort code +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +tEplKernel PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, + DWORD dwAbortCode_p) +{ +tEplKernel Ret; +tEplSdoComCon* pSdoComCon; + + + if(SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) + { + Ret = kEplSdoComInvalidHandle; + goto Exit; + } + + // get pointer to control structure of connection + pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p]; + + // check if handle ok + if(pSdoComCon->m_SdoSeqConHdl == 0) + { + Ret = kEplSdoComInvalidHandle; + goto Exit; + } + + // save pointer to abort code + pSdoComCon->m_pData = (BYTE*)&dwAbortCode_p; + + Ret = EplSdoComProcessIntern(SdoComConHdl_p, + kEplSdoComConEventAbort, + (tEplAsySdoCom*)NULL); + +Exit: + return Ret; +} +#endif + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComReceiveCb +// +// Description: callback function for SDO Sequence Layer +// -> indicates new data +// +// +// +// Parameters: SdoSeqConHdl_p = Handle for connection +// pAsySdoCom_p = pointer to data +// uiDataSize_p = size of data ($$$ not used yet, but it should) +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoComReceiveCb (tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoCom* pAsySdoCom_p, + unsigned int uiDataSize_p) +{ +tEplKernel Ret; + + + // search connection internally + Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p, + kEplSdoComConEventRec, + pAsySdoCom_p); + + EPL_DBGLVL_SDO_TRACE3("EplSdoComReceiveCb SdoSeqConHdl: 0x%X, First Byte of pAsySdoCom_p: 0x%02X, uiDataSize_p: 0x%04X\n", SdoSeqConHdl_p, (WORD)pAsySdoCom_p->m_le_abCommandData[0], uiDataSize_p); + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComConCb +// +// Description: callback function called by SDO Sequence Layer to inform +// command layer about state change of connection +// +// +// +// Parameters: SdoSeqConHdl_p = Handle of the connection +// AsySdoConState_p = Event of the connection +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoComConCb (tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoConState AsySdoConState_p) +{ +tEplKernel Ret; +tEplSdoComConEvent SdoComConEvent = kEplSdoComConEventSendFirst; + + Ret = kEplSuccessful; + + // check state + switch(AsySdoConState_p) + { + case kAsySdoConStateConnected: + { + EPL_DBGLVL_SDO_TRACE0("Connection established\n"); + SdoComConEvent = kEplSdoComConEventConEstablished; + // start transmission if needed + break; + } + + case kAsySdoConStateInitError: + { + EPL_DBGLVL_SDO_TRACE0("Error during initialisation\n"); + SdoComConEvent = kEplSdoComConEventInitError; + // inform app about error and close sequence layer handle + break; + } + + case kAsySdoConStateConClosed: + { + EPL_DBGLVL_SDO_TRACE0("Connection closed\n"); + SdoComConEvent = kEplSdoComConEventConClosed; + // close sequence layer handle + break; + } + + case kAsySdoConStateAckReceived: + { + EPL_DBGLVL_SDO_TRACE0("Acknowlage received\n"); + SdoComConEvent = kEplSdoComConEventAckReceived; + // continue transmission + break; + } + + case kAsySdoConStateFrameSended: + { + EPL_DBGLVL_SDO_TRACE0("One Frame sent\n"); + SdoComConEvent = kEplSdoComConEventFrameSended; + // to continue transmission + break; + + } + + case kAsySdoConStateTimeout: + { + EPL_DBGLVL_SDO_TRACE0("Timeout\n"); + SdoComConEvent = kEplSdoComConEventTimeout; + // close sequence layer handle + break; + + } + }// end of switch(AsySdoConState_p) + + Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p, + SdoComConEvent, + (tEplAsySdoCom*)NULL); + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComSearchConIntern +// +// Description: search a Sdo Sequence Layer connection handle in the +// control structure of the Command Layer +// +// Parameters: SdoSeqConHdl_p = Handle to search +// SdoComConEvent_p = event to process +// pAsySdoCom_p = pointer to received frame +// +// Returns: tEplKernel +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplSdoComConEvent SdoComConEvent_p, + tEplAsySdoCom* pAsySdoCom_p) +{ +tEplKernel Ret; +tEplSdoComCon* pSdoComCon; +tEplSdoComConHdl HdlCount; +tEplSdoComConHdl HdlFree; + + Ret = kEplSdoComNotResponsible; + + // get pointer to first element of the array + pSdoComCon = &SdoComInstance_g.m_SdoComCon[0]; + HdlCount = 0; + HdlFree = 0xFFFF; + while (HdlCount < EPL_MAX_SDO_COM_CON) + { + if (pSdoComCon->m_SdoSeqConHdl == SdoSeqConHdl_p) + { // matching command layer handle found + Ret = EplSdoComProcessIntern(HdlCount, + SdoComConEvent_p, + pAsySdoCom_p); + } + else if ((pSdoComCon->m_SdoSeqConHdl == 0) + &&(HdlFree == 0xFFFF)) + { + HdlFree = HdlCount; + } + + pSdoComCon++; + HdlCount++; + } + + if (Ret == kEplSdoComNotResponsible) + { // no responsible command layer handle found + if (HdlFree == 0xFFFF) + { // no free handle + // delete connection immediately + // 2008/04/14 m.u./d.k. This connection actually does not exist. + // pSdoComCon is invalid. + // Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); + Ret = kEplSdoComNoFreeHandle; + } + else + { // create new handle + HdlCount = HdlFree; + pSdoComCon = &SdoComInstance_g.m_SdoComCon[HdlCount]; + pSdoComCon->m_SdoSeqConHdl = SdoSeqConHdl_p; + Ret = EplSdoComProcessIntern(HdlCount, + SdoComConEvent_p, + pAsySdoCom_p); + } + } + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComProcessIntern +// +// Description: search a Sdo Sequence Layer connection handle in the +// control structer of the Command Layer +// +// +// +// Parameters: SdoComCon_p = index of control structure of connection +// SdoComConEvent_p = event to process +// pAsySdoCom_p = pointer to received frame +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, + tEplSdoComConEvent SdoComConEvent_p, + tEplAsySdoCom* pAsySdoCom_p) +{ +tEplKernel Ret; +tEplSdoComCon* pSdoComCon; +BYTE bFlag; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) +DWORD dwAbortCode; +unsigned int uiSize; +#endif + +#if defined(WIN32) || defined(_WIN32) + // enter critical section for process function + EnterCriticalSection(SdoComInstance_g.m_pCriticalSection); + EPL_DBGLVL_SDO_TRACE0("\n\tEnterCiticalSection EplSdoComProcessIntern\n\n"); +#endif + + Ret = kEplSuccessful; + + // get pointer to control structure + pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p]; + + // process state maschine + switch(pSdoComCon->m_SdoComState) + { + // idle state + case kEplSdoComStateIdle: + { + // check events + switch(SdoComConEvent_p) + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + // init con for client + case kEplSdoComConEventInitCon: + { + + // call of the init function already + // processed in EplSdoComDefineCon() + // only change state to kEplSdoComStateClientWaitInit + pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit; + break; + } +#endif + + + // int con for server + case kEplSdoComConEventRec: + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) + // check if init of an transfer and no SDO abort + if ((pAsySdoCom_p->m_le_bFlags & 0x80) == 0) + { // SDO request + if ((pAsySdoCom_p->m_le_bFlags & 0x40) == 0) + { // no SDO abort + // save tansaction id + pSdoComCon->m_bTransactionId = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId); + // check command + switch(pAsySdoCom_p->m_le_bCommandId) + { + case kEplSdoServiceNIL: + { // simply acknowlegde NIL command on sequence layer + + Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl, + 0, + (tEplFrame*)NULL); + + break; + } + + case kEplSdoServiceReadByIndex: + { // read by index + + // search entry an start transfer + EplSdoComServerInitReadByIndex(pSdoComCon, + pAsySdoCom_p); + // check next state + if(pSdoComCon->m_uiTransSize == 0) + { // ready -> stay idle + pSdoComCon->m_SdoComState = kEplSdoComStateIdle; + // reset abort code + pSdoComCon->m_dwLastAbortCode = 0; + } + else + { // segmented transfer + pSdoComCon->m_SdoComState = kEplSdoComStateServerSegmTrans; + } + + break; + } + + case kEplSdoServiceWriteByIndex: + { + + // search entry an start write + EplSdoComServerInitWriteByIndex(pSdoComCon, + pAsySdoCom_p); + // check next state + if(pSdoComCon->m_uiTransSize == 0) + { // already -> stay idle + pSdoComCon->m_SdoComState = kEplSdoComStateIdle; + // reset abort code + pSdoComCon->m_dwLastAbortCode = 0; + } + else + { // segmented transfer + pSdoComCon->m_SdoComState = kEplSdoComStateServerSegmTrans; + } + + break; + } + + default: + { + // unsupported command + // -> abort senden + dwAbortCode = EPL_SDOAC_UNKNOWN_COMMAND_SPECIFIER; + // send abort + pSdoComCon->m_pData = (BYTE*)&dwAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon, + 0, + 0, + kEplSdoComSendTypeAbort); + + } + + + }// end of switch(pAsySdoCom_p->m_le_bCommandId) + } + } + else + { // this command layer handle is not responsible + // (wrong direction or wrong transaction ID) + Ret = kEplSdoComNotResponsible; + goto Exit; + } +#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) + + break; + } + + // connection closed + case kEplSdoComConEventInitError: + case kEplSdoComConEventTimeout: + case kEplSdoComConEventConClosed: + { + Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); + // clean control structure + EPL_MEMSET(pSdoComCon, 0x00, sizeof(tEplSdoComCon)); + break; + } + + default: + // d.k. do nothing + break; + }// end of switch(SdoComConEvent_p) + break; + } + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) + //------------------------------------------------------------------------- + // SDO Server part + // segmented transfer + case kEplSdoComStateServerSegmTrans: + { + // check events + switch(SdoComConEvent_p) + { + // send next frame + case kEplSdoComConEventAckReceived: + case kEplSdoComConEventFrameSended: + { + // check if it is a read + if(pSdoComCon->m_SdoServiceType == kEplSdoServiceReadByIndex) + { + // send next frame + EplSdoComServerSendFrameIntern(pSdoComCon, + 0, + 0, + kEplSdoComSendTypeRes); + // if all send -> back to idle + if(pSdoComCon->m_uiTransSize == 0) + { // back to idle + pSdoComCon->m_SdoComState = kEplSdoComStateIdle; + // reset abort code + pSdoComCon->m_dwLastAbortCode = 0; + } + + } + break; + } + + // process next frame + case kEplSdoComConEventRec: + { + // check if the frame is a SDO response and has the right transaction ID + bFlag = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bFlags); + if (((bFlag & 0x80) != 0) && (AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId) == pSdoComCon->m_bTransactionId)) + { + // check if it is a abort + if((bFlag & 0x40) != 0) + { // SDO abort + // clear control structure + pSdoComCon->m_uiTransSize = 0; + pSdoComCon->m_uiTransferredByte = 0; + // change state + pSdoComCon->m_SdoComState = kEplSdoComStateIdle; + // reset abort code + pSdoComCon->m_dwLastAbortCode = 0; + // d.k.: do not execute anything further on this command + break; + } + + // check if it is a write + if(pSdoComCon->m_SdoServiceType == kEplSdoServiceWriteByIndex) + { + // write data to OD + uiSize = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize); + if(pSdoComCon->m_dwLastAbortCode == 0) + { + EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[0],uiSize); + } + // update counter + pSdoComCon->m_uiTransferredByte += uiSize; + pSdoComCon->m_uiTransSize -= uiSize; + + // update pointer + if(pSdoComCon->m_dwLastAbortCode == 0) + { + (/*(BYTE*)*/pSdoComCon->m_pData) += uiSize; + } + + // check end of transfer + if((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x30) + { // transfer ready + pSdoComCon->m_uiTransSize = 0; + + if(pSdoComCon->m_dwLastAbortCode == 0) + { + // send response + // send next frame + EplSdoComServerSendFrameIntern(pSdoComCon, + 0, + 0, + kEplSdoComSendTypeRes); + // if all send -> back to idle + if(pSdoComCon->m_uiTransSize == 0) + { // back to idle + pSdoComCon->m_SdoComState = kEplSdoComStateIdle; + // reset abort code + pSdoComCon->m_dwLastAbortCode = 0; + } + } + else + { // send dabort code + // send abort + pSdoComCon->m_pData = (BYTE*)&pSdoComCon->m_dwLastAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon, + 0, + 0, + kEplSdoComSendTypeAbort); + + // reset abort code + pSdoComCon->m_dwLastAbortCode = 0; + + } + } + else + { + // send acknowledge without any Command layer data + Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl, + 0, + (tEplFrame*)NULL); + } + } + } + else + { // this command layer handle is not responsible + // (wrong direction or wrong transaction ID) + Ret = kEplSdoComNotResponsible; + goto Exit; + } + break; + } + + // connection closed + case kEplSdoComConEventInitError: + case kEplSdoComConEventTimeout: + case kEplSdoComConEventConClosed: + { + Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); + // clean control structure + EPL_MEMSET(pSdoComCon, 0x00, sizeof(tEplSdoComCon)); + break; + } + + default: + // d.k. do nothing + break; + }// end of switch(SdoComConEvent_p) + + break; + } +#endif // endif of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + //------------------------------------------------------------------------- + // SDO Client part + // wait for finish of establishing connection + case kEplSdoComStateClientWaitInit: + { + + // if connection handle is invalid reinit connection + // d.k.: this will be done only on new events (i.e. InitTransfer) + if((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) == EPL_SDO_SEQ_INVALID_HDL) + { + // check kind of connection to reinit + // check protocol + switch(pSdoComCon->m_SdoProtType) + { + // udp + case kEplSdoTypeUdp: + { + // call connection int function of lower layer + Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl, + pSdoComCon->m_uiNodeId, + kEplSdoTypeUdp); + if(Ret != kEplSuccessful) + { + goto Exit; + } + break; + } + + // Asend -> not supported + case kEplSdoTypeAsnd: + { + // call connection int function of lower layer + Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl, + pSdoComCon->m_uiNodeId, + kEplSdoTypeAsnd); + if(Ret != kEplSuccessful) + { + goto Exit; + } + break; + } + + // Pdo -> not supported + case kEplSdoTypePdo: + default: + { + Ret = kEplSdoComUnsupportedProt; + goto Exit; + } + }// end of switch(m_ProtType_p) + // d.k.: reset transaction ID, because new sequence layer connection was initialized + // $$$ d.k. is this really necessary? + //pSdoComCon->m_bTransactionId = 0; + } + + // check events + switch(SdoComConEvent_p) + { + // connection established + case kEplSdoComConEventConEstablished: + { + //send first frame if needed + if((pSdoComCon->m_uiTransSize > 0) + &&(pSdoComCon->m_uiTargetIndex != 0)) + { // start SDO transfer + Ret = EplSdoComClientSend(pSdoComCon); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // check if segemted transfer + if(pSdoComCon->m_SdoTransType == kEplSdoTransSegmented) + { + pSdoComCon->m_SdoComState = kEplSdoComStateClientSegmTrans; + goto Exit; + } + } + // goto state kEplSdoComStateClientConnected + pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected; + goto Exit; + } + + case kEplSdoComConEventSendFirst: + { + // infos for transfer already saved by function EplSdoComInitTransferByIndex + break; + } + + case kEplSdoComConEventConClosed: + case kEplSdoComConEventInitError: + case kEplSdoComConEventTimeout: + { + // close sequence layer handle + Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); + pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL; + // call callback function + if (SdoComConEvent_p == kEplSdoComConEventTimeout) + { + pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_TIME_OUT; + } + else + { + pSdoComCon->m_dwLastAbortCode = 0; + } + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferLowerLayerAbort); + // d.k.: do not clean control structure + break; + } + + default: + // d.k. do nothing + break; + + } // end of switch(SdoComConEvent_p) + break; + } + + // connected + case kEplSdoComStateClientConnected: + { + // check events + switch(SdoComConEvent_p) + { + // send a frame + case kEplSdoComConEventSendFirst: + case kEplSdoComConEventAckReceived: + case kEplSdoComConEventFrameSended: + { + Ret = EplSdoComClientSend(pSdoComCon); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // check if read transfer finished + if((pSdoComCon->m_uiTransSize == 0) + && (pSdoComCon->m_uiTransferredByte != 0) + && (pSdoComCon->m_SdoServiceType == kEplSdoServiceReadByIndex)) + { + // inc transaction id + pSdoComCon->m_bTransactionId++; + // call callback of application + pSdoComCon->m_dwLastAbortCode = 0; + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished); + + goto Exit; + } + + // check if segemted transfer + if(pSdoComCon->m_SdoTransType == kEplSdoTransSegmented) + { + pSdoComCon->m_SdoComState = kEplSdoComStateClientSegmTrans; + goto Exit; + } + break; + } + + // frame received + case kEplSdoComConEventRec: + { + // check if the frame is a SDO response and has the right transaction ID + bFlag = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bFlags); + if (((bFlag & 0x80) != 0) && (AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId) == pSdoComCon->m_bTransactionId)) + { + // check if abort or not + if((bFlag & 0x40) != 0) + { + // send acknowledge without any Command layer data + Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl, + 0, + (tEplFrame*)NULL); + // inc transaction id + pSdoComCon->m_bTransactionId++; + // save abort code + pSdoComCon->m_dwLastAbortCode = AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]); + // call callback of application + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferRxAborted); + + goto Exit; + } + else + { // normal frame received + // check frame + Ret = EplSdoComClientProcessFrame(SdoComCon_p, pAsySdoCom_p); + + // check if transfer ready + if(pSdoComCon->m_uiTransSize == 0) + { + // send acknowledge without any Command layer data + Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl, + 0, + (tEplFrame*)NULL); + // inc transaction id + pSdoComCon->m_bTransactionId++; + // call callback of application + pSdoComCon->m_dwLastAbortCode = 0; + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished); + + goto Exit; + } + + } + } + else + { // this command layer handle is not responsible + // (wrong direction or wrong transaction ID) + Ret = kEplSdoComNotResponsible; + goto Exit; + } + break; + } + + // connection closed event go back to kEplSdoComStateClientWaitInit + case kEplSdoComConEventConClosed: + { // connection closed by communication partner + // close sequence layer handle + Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); + // set handle to invalid and enter kEplSdoComStateClientWaitInit + pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL; + // change state + pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit; + + // call callback of application + pSdoComCon->m_dwLastAbortCode = 0; + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferLowerLayerAbort); + + goto Exit; + + break; + } + + // abort to send from higher layer + case kEplSdoComConEventAbort: + { + EplSdoComClientSendAbort(pSdoComCon,*((DWORD*)pSdoComCon->m_pData)); + + // inc transaction id + pSdoComCon->m_bTransactionId++; + // call callback of application + pSdoComCon->m_dwLastAbortCode = *((DWORD*)pSdoComCon->m_pData); + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferTxAborted); + + break; + } + + case kEplSdoComConEventInitError: + case kEplSdoComConEventTimeout: + { + // close sequence layer handle + Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); + pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL; + // change state + pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit; + // call callback of application + pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_TIME_OUT; + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferLowerLayerAbort); + + } + + default: + // d.k. do nothing + break; + + } // end of switch(SdoComConEvent_p) + + break; + } + + // process segmented transfer + case kEplSdoComStateClientSegmTrans: + { + // check events + switch(SdoComConEvent_p) + { + // sned a frame + case kEplSdoComConEventSendFirst: + case kEplSdoComConEventAckReceived: + case kEplSdoComConEventFrameSended: + { + Ret = EplSdoComClientSend(pSdoComCon); + if(Ret != kEplSuccessful) + { + goto Exit; + } + + // check if read transfer finished + if((pSdoComCon->m_uiTransSize == 0) + && (pSdoComCon->m_SdoServiceType == kEplSdoServiceReadByIndex)) + { + // inc transaction id + pSdoComCon->m_bTransactionId++; + // change state + pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected; + // call callback of application + pSdoComCon->m_dwLastAbortCode = 0; + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished); + + goto Exit; + } + + break; + } + + // frame received + case kEplSdoComConEventRec: + { + // check if the frame is a response + bFlag = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bFlags); + if (((bFlag & 0x80) != 0) && (AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId) == pSdoComCon->m_bTransactionId)) + { + // check if abort or not + if((bFlag & 0x40) != 0) + { + // send acknowledge without any Command layer data + Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl, + 0, + (tEplFrame*)NULL); + // inc transaction id + pSdoComCon->m_bTransactionId++; + // change state + pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected; + // save abort code + pSdoComCon->m_dwLastAbortCode = AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]); + // call callback of application + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferRxAborted); + + goto Exit; + } + else + { // normal frame received + // check frame + Ret = EplSdoComClientProcessFrame(SdoComCon_p, pAsySdoCom_p); + + // check if transfer ready + if(pSdoComCon->m_uiTransSize == 0) + { + // send acknowledge without any Command layer data + Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl, + 0, + (tEplFrame*)NULL); + // inc transaction id + pSdoComCon->m_bTransactionId++; + // change state + pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected; + // call callback of application + pSdoComCon->m_dwLastAbortCode = 0; + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished); + + } + + } + } + break; + } + + // connection closed event go back to kEplSdoComStateClientWaitInit + case kEplSdoComConEventConClosed: + { // connection closed by communication partner + // close sequence layer handle + Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); + // set handle to invalid and enter kEplSdoComStateClientWaitInit + pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL; + // change state + pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit; + // inc transaction id + pSdoComCon->m_bTransactionId++; + // call callback of application + pSdoComCon->m_dwLastAbortCode = 0; + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished); + + break; + } + + // abort to send from higher layer + case kEplSdoComConEventAbort: + { + EplSdoComClientSendAbort(pSdoComCon,*((DWORD*)pSdoComCon->m_pData)); + + // inc transaction id + pSdoComCon->m_bTransactionId++; + // change state + pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected; + // call callback of application + pSdoComCon->m_dwLastAbortCode = *((DWORD*)pSdoComCon->m_pData); + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferTxAborted); + + break; + } + + case kEplSdoComConEventInitError: + case kEplSdoComConEventTimeout: + { + // close sequence layer handle + Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); + pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL; + // change state + pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit; + // call callback of application + pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_TIME_OUT; + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferLowerLayerAbort); + + } + + default: + // d.k. do nothing + break; + + } // end of switch(SdoComConEvent_p) + + break; + } +#endif // endo of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + + }// end of switch(pSdoComCon->m_SdoComState) + + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +Exit: +#endif + +#if defined(WIN32) || defined(_WIN32) + // leave critical section for process function + EPL_DBGLVL_SDO_TRACE0("\n\tLeaveCriticalSection EplSdoComProcessIntern\n\n"); + LeaveCriticalSection(SdoComInstance_g.m_pCriticalSection); + +#endif + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComServerInitReadByIndex +// +// Description: function start the processing of an read by index command +// +// +// +// Parameters: pSdoComCon_p = pointer to control structure of connection +// pAsySdoCom_p = pointer to received frame +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) +static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon* pSdoComCon_p, + tEplAsySdoCom* pAsySdoCom_p) +{ +tEplKernel Ret; +unsigned int uiIndex; +unsigned int uiSubindex; +tEplObdSize EntrySize; +tEplObdAccess AccessType; +DWORD dwAbortCode; + + dwAbortCode = 0; + + // a init of a read could not be a segmented transfer + // -> no variable part of header + + // get index and subindex + uiIndex = AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]); + uiSubindex = AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]); + + // check accesstype of entry + // existens of entry +//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType); +/*#else + Ret = kEplObdSubindexNotExist; + AccessType = 0; +#endif*/ + if(Ret == kEplObdSubindexNotExist) + { // subentry doesn't exist + dwAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST; + // send abort + pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort); + goto Exit; + } + else if(Ret != kEplSuccessful) + { // entry doesn't exist + dwAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST; + // send abort + pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort); + goto Exit; + } + + // compare accesstype must be read or const + if(((AccessType & kEplObdAccRead) == 0) + && ((AccessType & kEplObdAccConst) == 0)) + { + + if((AccessType & kEplObdAccWrite) != 0) + { + // entry read a write only object + dwAbortCode = EPL_SDOAC_READ_TO_WRITE_ONLY_OBJ; + } + else + { + dwAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS; + } + // send abort + pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort); + goto Exit; + } + + // save service + pSdoComCon_p->m_SdoServiceType = kEplSdoServiceReadByIndex; + + // get size of object to see iof segmented or expedited transfer +//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + EntrySize = EplObduGetDataSize(uiIndex, uiSubindex); +/*#else + EntrySize = 0; +#endif*/ + if(EntrySize > EPL_SDO_MAX_PAYLOAD) + { // segmented transfer + pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented; + // get pointer to object-entry data +//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + pSdoComCon_p->m_pData = EplObduGetObjectDataPtr(uiIndex, uiSubindex); +//#endif + } + else + { // expedited transfer + pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited; + } + + pSdoComCon_p->m_uiTransSize = EntrySize; + pSdoComCon_p->m_uiTransferredByte = 0; + + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeRes); + if(Ret != kEplSuccessful) + { + // error -> abort + dwAbortCode = EPL_SDOAC_GENERAL_ERROR; + // send abort + pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort); + goto Exit; + } + +Exit: + return Ret; +} +#endif + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComServerSendFrameIntern(); +// +// Description: function creats and send a frame for server +// +// +// +// Parameters: pSdoComCon_p = pointer to control structure of connection +// uiIndex_p = index to send if expedited transfer else 0 +// uiSubIndex_p = subindex to send if expedited transfer else 0 +// SendType_p = to of frame to send +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) +static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon* pSdoComCon_p, + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplSdoComSendType SendType_p) +{ +tEplKernel Ret; +BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE]; +tEplFrame* pFrame; +tEplAsySdoCom* pCommandFrame; +unsigned int uiSizeOfFrame; +BYTE bFlag; + + Ret = kEplSuccessful; + + pFrame = (tEplFrame*)&abFrame[0]; + + EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame)); + + // build generic part of frame + // get pointer to command layerpart of frame + pCommandFrame = &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_abSdoSeqPayload; + AmiSetByteToLe(&pCommandFrame->m_le_bCommandId, pSdoComCon_p->m_SdoServiceType); + AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId, pSdoComCon_p->m_bTransactionId); + + // set size to header size + uiSizeOfFrame = 8; + + // check SendType + switch(SendType_p) + { + // requestframe to send + case kEplSdoComSendTypeReq: + { + // nothing to do for server + //-> error + Ret = kEplSdoComInvalidSendType; + break; + } + + // response without data to send + case kEplSdoComSendTypeAckRes: + { + // set response flag + AmiSetByteToLe(&pCommandFrame->m_le_bFlags, 0x80); + + // send frame + Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, + uiSizeOfFrame, + pFrame); + + break; + } + + // responsframe to send + case kEplSdoComSendTypeRes: + { + // set response flag + bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags); + bFlag |= 0x80; + AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag); + + // check type of resonse + if(pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited) + { // Expedited transfer + // copy data in frame +//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + Ret = EplObduReadEntryToLe(uiIndex_p, + uiSubIndex_p, + &pCommandFrame->m_le_abCommandData[0], + (tEplObdSize*)&pSdoComCon_p->m_uiTransSize); + if(Ret != kEplSuccessful) + { + goto Exit; + } +//#endif + + // set size of frame + AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, (WORD) pSdoComCon_p->m_uiTransSize); + + // correct byte-counter + uiSizeOfFrame += pSdoComCon_p->m_uiTransSize; + pSdoComCon_p->m_uiTransferredByte += pSdoComCon_p->m_uiTransSize; + pSdoComCon_p->m_uiTransSize = 0; + + + // send frame + uiSizeOfFrame += pSdoComCon_p->m_uiTransSize; + Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, + uiSizeOfFrame, + pFrame); + } + else if(pSdoComCon_p->m_SdoTransType == kEplSdoTransSegmented) + { // segmented transfer + // distinguish between init, segment and complete + if(pSdoComCon_p->m_uiTransferredByte == 0) + { // init + // set init flag + bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags); + bFlag |= 0x10; + AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag); + // init variable header + AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0],pSdoComCon_p->m_uiTransSize); + // copy data in frame + EPL_MEMCPY(&pCommandFrame->m_le_abCommandData[4],pSdoComCon_p->m_pData, (EPL_SDO_MAX_PAYLOAD-4)); + + // correct byte-counter + pSdoComCon_p->m_uiTransSize -= (EPL_SDO_MAX_PAYLOAD-4); + pSdoComCon_p->m_uiTransferredByte += (EPL_SDO_MAX_PAYLOAD-4); + // move data pointer + pSdoComCon_p->m_pData +=(EPL_SDO_MAX_PAYLOAD-4); + + // set segment size + AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize,(EPL_SDO_MAX_PAYLOAD-4)); + + // send frame + uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD; + Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, + uiSizeOfFrame, + pFrame); + + } + else if((pSdoComCon_p->m_uiTransferredByte > 0) + &&(pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD)) + { // segment + // set segment flag + bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags); + bFlag |= 0x20; + AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag); + + // copy data in frame + EPL_MEMCPY(&pCommandFrame->m_le_abCommandData[0],pSdoComCon_p->m_pData, EPL_SDO_MAX_PAYLOAD); + + // correct byte-counter + pSdoComCon_p->m_uiTransSize -= EPL_SDO_MAX_PAYLOAD; + pSdoComCon_p->m_uiTransferredByte += EPL_SDO_MAX_PAYLOAD; + // move data pointer + pSdoComCon_p->m_pData +=EPL_SDO_MAX_PAYLOAD; + + // set segment size + AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize,EPL_SDO_MAX_PAYLOAD); + + // send frame + uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD; + Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, + uiSizeOfFrame, + pFrame); + } + else + { + if((pSdoComCon_p->m_uiTransSize == 0) + && (pSdoComCon_p->m_SdoServiceType != kEplSdoServiceWriteByIndex)) + { + goto Exit; + } + // complete + // set segment complete flag + bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags); + bFlag |= 0x30; + AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag); + + // copy data in frame + EPL_MEMCPY(&pCommandFrame->m_le_abCommandData[0],pSdoComCon_p->m_pData, pSdoComCon_p->m_uiTransSize); + + // correct byte-counter + pSdoComCon_p->m_uiTransferredByte += pSdoComCon_p->m_uiTransSize; + + + // move data pointer + pSdoComCon_p->m_pData +=pSdoComCon_p->m_uiTransSize; + + // set segment size + AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, (WORD) pSdoComCon_p->m_uiTransSize); + + // send frame + uiSizeOfFrame += pSdoComCon_p->m_uiTransSize; + pSdoComCon_p->m_uiTransSize = 0; + Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, + uiSizeOfFrame, + pFrame); + } + + } + break; + } + // abort to send + case kEplSdoComSendTypeAbort: + { + // set response and abort flag + bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags); + bFlag |= 0xC0; + AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag); + + // copy abortcode to frame + AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], *((DWORD*)pSdoComCon_p->m_pData)); + + // set size of segment + AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, sizeof(DWORD)); + + // update counter + pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD); + pSdoComCon_p->m_uiTransSize = 0; + + // calc framesize + uiSizeOfFrame += sizeof(DWORD); + Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, + uiSizeOfFrame, + pFrame); + break; + } + } // end of switch(SendType_p) + +Exit: + return Ret; +} +#endif +//--------------------------------------------------------------------------- +// +// Function: EplSdoComServerInitWriteByIndex +// +// Description: function start the processing of an write by index command +// +// +// +// Parameters: pSdoComCon_p = pointer to control structure of connection +// pAsySdoCom_p = pointer to received frame +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) +static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon* pSdoComCon_p, + tEplAsySdoCom* pAsySdoCom_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiIndex; +unsigned int uiSubindex; +unsigned int uiBytesToTransfer; +tEplObdSize EntrySize; +tEplObdAccess AccessType; +DWORD dwAbortCode; +BYTE* pbSrcData; + + dwAbortCode = 0; + + // a init of a write + // -> variable part of header possible + + // check if expedited or segmented transfer + if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x10) + { // initiate segmented transfer + pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented; + // get index and subindex + uiIndex = AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[4]); + uiSubindex = AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[6]); + // get source-pointer for copy + pbSrcData = &pAsySdoCom_p->m_le_abCommandData[8]; + // save size + pSdoComCon_p->m_uiTransSize = AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]); + + } + else if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x00) + { // expedited transfer + pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited; + // get index and subindex + uiIndex = AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]); + uiSubindex = AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]); + // get source-pointer for copy + pbSrcData = &pAsySdoCom_p->m_le_abCommandData[4]; + // save size + pSdoComCon_p->m_uiTransSize = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize); + // subtract header + pSdoComCon_p->m_uiTransSize -= 4; + + } + else + { + // just ignore any other transfer type + goto Exit; + } + + // check accesstype of entry + // existens of entry +//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType); +/*#else + Ret = kEplObdSubindexNotExist; + AccessType = 0; +#endif*/ + if (Ret == kEplObdSubindexNotExist) + { // subentry doesn't exist + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST; + // send abort + // d.k. This is wrong: k.t. not needed send abort on end of write + /*pSdoComCon_p->m_pData = (BYTE*)pSdoComCon_p->m_dwLastAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort);*/ + goto Abort; + } + else if(Ret != kEplSuccessful) + { // entry doesn't exist + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST; + // send abort + // d.k. This is wrong: k.t. not needed send abort on end of write + /* + pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort);*/ + goto Abort; + } + + // compare accesstype must be read + if((AccessType & kEplObdAccWrite) == 0) + { + + if((AccessType & kEplObdAccRead) != 0) + { + // entry write a read only object + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_WRITE_TO_READ_ONLY_OBJ; + } + else + { + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS; + } + // send abort + // d.k. This is wrong: k.t. not needed send abort on end of write + /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort);*/ + goto Abort; + } + + // save service + pSdoComCon_p->m_SdoServiceType = kEplSdoServiceWriteByIndex; + + pSdoComCon_p->m_uiTransferredByte = 0; + + // write data to OD + if(pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited) + { // expedited transfer + // size checking is done by EplObduWriteEntryFromLe() + +//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + Ret = EplObduWriteEntryFromLe(uiIndex, + uiSubindex, + pbSrcData, + pSdoComCon_p->m_uiTransSize); + switch (Ret) + { + case kEplSuccessful: + { + break; + } + + case kEplObdAccessViolation: + { + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS; + // send abort + goto Abort; + } + + case kEplObdValueLengthError: + { + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_DATA_TYPE_LENGTH_NOT_MATCH; + // send abort + goto Abort; + } + + case kEplObdValueTooHigh: + { + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_VALUE_RANGE_TOO_HIGH; + // send abort + goto Abort; + } + + case kEplObdValueTooLow: + { + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_VALUE_RANGE_TOO_LOW; + // send abort + goto Abort; + } + + default: + { + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR; + // send abort + goto Abort; + } + } +//#endif + // send command acknowledge + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + 0, + 0, + kEplSdoComSendTypeAckRes); + + pSdoComCon_p->m_uiTransSize = 0; + goto Exit; + } + else + { + // get size of the object to check if it fits + // because we directly write to the destination memory + // d.k. no one calls the user OD callback function + + //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + EntrySize = EplObduGetDataSize(uiIndex, uiSubindex); + /*#else + EntrySize = 0; + #endif*/ + if(EntrySize < pSdoComCon_p->m_uiTransSize) + { // parameter too big + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH; + // send abort + // d.k. This is wrong: k.t. not needed send abort on end of write + /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort);*/ + goto Abort; + } + + uiBytesToTransfer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize); + // eleminate header (Command header (8) + variable part (4) + Command header (4)) + uiBytesToTransfer -= 16; + // get pointer to object entry +//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + pSdoComCon_p->m_pData = EplObduGetObjectDataPtr(uiIndex, + uiSubindex); +//#endif + if(pSdoComCon_p->m_pData == NULL) + { + pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR; + // send abort + // d.k. This is wrong: k.t. not needed send abort on end of write +/* pSdoComCon_p->m_pData = (BYTE*)&pSdoComCon_p->m_dwLastAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort);*/ + goto Abort; + } + + // copy data + EPL_MEMCPY(pSdoComCon_p->m_pData, pbSrcData, uiBytesToTransfer); + + // update internal counter + pSdoComCon_p->m_uiTransferredByte = uiBytesToTransfer; + pSdoComCon_p->m_uiTransSize -= uiBytesToTransfer; + + // update target pointer + (/*(BYTE*)*/pSdoComCon_p->m_pData) += uiBytesToTransfer; + + // send acknowledge without any Command layer data + Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, + 0, + (tEplFrame*)NULL); + goto Exit; + } + +Abort: + if(pSdoComCon_p->m_dwLastAbortCode != 0) + { + // send abort + pSdoComCon_p->m_pData = (BYTE*)&pSdoComCon_p->m_dwLastAbortCode; + Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, + uiIndex, + uiSubindex, + kEplSdoComSendTypeAbort); + + // reset abort code + pSdoComCon_p->m_dwLastAbortCode = 0; + pSdoComCon_p->m_uiTransSize = 0; + goto Exit; + } + +Exit: + return Ret; +} +#endif + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComClientSend +// +// Description: function starts an sdo transfer an send all further frames +// +// +// +// Parameters: pSdoComCon_p = pointer to control structure of connection +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +static tEplKernel EplSdoComClientSend(tEplSdoComCon* pSdoComCon_p) +{ +tEplKernel Ret; +BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE]; +tEplFrame* pFrame; +tEplAsySdoCom* pCommandFrame; +unsigned int uiSizeOfFrame; +BYTE bFlags; +BYTE* pbPayload; + + Ret = kEplSuccessful; + + pFrame = (tEplFrame*)&abFrame[0]; + + EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame)); + + // build generic part of frame + // get pointer to command layerpart of frame + pCommandFrame = &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_abSdoSeqPayload; + AmiSetByteToLe( &pCommandFrame->m_le_bCommandId, pSdoComCon_p->m_SdoServiceType); + AmiSetByteToLe( &pCommandFrame->m_le_bTransactionId, pSdoComCon_p->m_bTransactionId); + + // set size constant part of header + uiSizeOfFrame = 8; + + // check if first frame to send -> command header needed + if (pSdoComCon_p->m_uiTransSize > 0) + { + if (pSdoComCon_p->m_uiTransferredByte == 0) + { // start SDO transfer + // check if segmented or expedited transfer + // only for write commands + switch(pSdoComCon_p->m_SdoServiceType) + { + case kEplSdoServiceReadByIndex: + { // first frame of read access always expedited + pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited; + pbPayload = &pCommandFrame->m_le_abCommandData[0]; + // fill rest of header + AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, 4); + + // create command header + AmiSetWordToLe(pbPayload, (WORD)pSdoComCon_p->m_uiTargetIndex); + pbPayload += 2; + AmiSetByteToLe(pbPayload, (BYTE)pSdoComCon_p->m_uiTargetSubIndex); + // calc size + uiSizeOfFrame += 4; + + // set pSdoComCon_p->m_uiTransferredByte to one + pSdoComCon_p->m_uiTransferredByte = 1; + break; + } + + case kEplSdoServiceWriteByIndex: + { + if(pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD ) + { // segmented transfer + // -> variable part of header needed + // save that transfer is segmented + pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented; + // fill variable part of header + AmiSetDwordToLe( &pCommandFrame->m_le_abCommandData[0], pSdoComCon_p->m_uiTransSize); + // set pointer to real payload + pbPayload = &pCommandFrame->m_le_abCommandData[4]; + // fill rest of header + AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, EPL_SDO_MAX_PAYLOAD); + bFlags = 0x10; + AmiSetByteToLe( &pCommandFrame->m_le_bFlags, bFlags); + // create command header + AmiSetWordToLe(pbPayload, (WORD) pSdoComCon_p->m_uiTargetIndex); + pbPayload += 2; + AmiSetByteToLe(pbPayload, (BYTE)pSdoComCon_p->m_uiTargetSubIndex); + // on byte for reserved + pbPayload += 2; + // calc size + uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD; + + // copy payload + EPL_MEMCPY( pbPayload,pSdoComCon_p->m_pData, (EPL_SDO_MAX_PAYLOAD - 8)); + pSdoComCon_p->m_pData += (EPL_SDO_MAX_PAYLOAD - 8); + // correct intern counter + pSdoComCon_p->m_uiTransSize -= (EPL_SDO_MAX_PAYLOAD - 8); + pSdoComCon_p->m_uiTransferredByte = (EPL_SDO_MAX_PAYLOAD - 8); + + } + else + { // expedited trandsfer + // save that transfer is expedited + pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited; + pbPayload = &pCommandFrame->m_le_abCommandData[0]; + + // create command header + AmiSetWordToLe(pbPayload, (WORD) pSdoComCon_p->m_uiTargetIndex); + pbPayload += 2; + AmiSetByteToLe(pbPayload, (BYTE)pSdoComCon_p->m_uiTargetSubIndex); + // + 2 -> one byte for subindex and one byte reserved + pbPayload += 2; + // copy data + EPL_MEMCPY( pbPayload,pSdoComCon_p->m_pData, pSdoComCon_p->m_uiTransSize); + // calc size + uiSizeOfFrame += (4 + pSdoComCon_p->m_uiTransSize); + // fill rest of header + AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, (WORD) (4 + pSdoComCon_p->m_uiTransSize)); + + pSdoComCon_p->m_uiTransferredByte = pSdoComCon_p->m_uiTransSize; + pSdoComCon_p->m_uiTransSize = 0; + } + break; + } + + case kEplSdoServiceNIL: + default: + // invalid service requested + Ret = kEplSdoComInvalidServiceType; + goto Exit; + } // end of switch(pSdoComCon_p->m_SdoServiceType) + } + else // (pSdoComCon_p->m_uiTransferredByte > 0) + { // continue SDO transfer + switch(pSdoComCon_p->m_SdoServiceType) + { + // for expedited read is nothing to do + // -> server sends data + + case kEplSdoServiceWriteByIndex: + { // send next frame + if(pSdoComCon_p->m_SdoTransType == kEplSdoTransSegmented) + { + if(pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD) + { // next segment + pbPayload = &pCommandFrame->m_le_abCommandData[0]; + // fill rest of header + AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, EPL_SDO_MAX_PAYLOAD); + bFlags = 0x20; + AmiSetByteToLe( &pCommandFrame->m_le_bFlags, bFlags); + // copy data + EPL_MEMCPY( pbPayload,pSdoComCon_p->m_pData, EPL_SDO_MAX_PAYLOAD); + pSdoComCon_p->m_pData += EPL_SDO_MAX_PAYLOAD; + // correct intern counter + pSdoComCon_p->m_uiTransSize -= EPL_SDO_MAX_PAYLOAD; + pSdoComCon_p->m_uiTransferredByte = EPL_SDO_MAX_PAYLOAD; + // calc size + uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD; + + + } + else + { // end of transfer + pbPayload = &pCommandFrame->m_le_abCommandData[0]; + // fill rest of header + AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, (WORD) pSdoComCon_p->m_uiTransSize); + bFlags = 0x30; + AmiSetByteToLe( &pCommandFrame->m_le_bFlags, bFlags); + // copy data + EPL_MEMCPY( pbPayload,pSdoComCon_p->m_pData, pSdoComCon_p->m_uiTransSize); + pSdoComCon_p->m_pData += pSdoComCon_p->m_uiTransSize; + // calc size + uiSizeOfFrame += pSdoComCon_p->m_uiTransSize; + // correct intern counter + pSdoComCon_p->m_uiTransSize = 0; + pSdoComCon_p->m_uiTransferredByte = pSdoComCon_p->m_uiTransSize; + + } + } + else + { + goto Exit; + } + break; + } + default: + { + goto Exit; + } + } // end of switch(pSdoComCon_p->m_SdoServiceType) + } + } + else + { + goto Exit; + } + + + // call send function of lower layer + switch(pSdoComCon_p->m_SdoProtType) + { + case kEplSdoTypeAsnd: + case kEplSdoTypeUdp: + { + Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, + uiSizeOfFrame, + pFrame); + break; + } + + default: + { + Ret = kEplSdoComUnsupportedProt; + } + } // end of switch(pSdoComCon_p->m_SdoProtType) + + +Exit: + return Ret; + +} +#endif +//--------------------------------------------------------------------------- +// +// Function: EplSdoComClientProcessFrame +// +// Description: function process a received frame +// +// +// +// Parameters: SdoComCon_p = connection handle +// pAsySdoCom_p = pointer to frame to process +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p, + tEplAsySdoCom* pAsySdoCom_p) +{ +tEplKernel Ret; +BYTE bBuffer; +unsigned int uiBuffer; +unsigned int uiDataSize; +unsigned long ulBuffer; +tEplSdoComCon* pSdoComCon; + + + Ret = kEplSuccessful; + + // get pointer to control structure + pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p]; + + // check if transaction Id fit + bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId); + if(pSdoComCon->m_bTransactionId != bBuffer) + { + // incorrect transaction id + + // if running transfer + if((pSdoComCon->m_uiTransferredByte != 0) + && (pSdoComCon->m_uiTransSize !=0)) + { + pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR; + // -> send abort + EplSdoComClientSendAbort(pSdoComCon, pSdoComCon->m_dwLastAbortCode); + // call callback of application + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferTxAborted); + } + + } + else + { // check if correct command + bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bCommandId); + if(pSdoComCon->m_SdoServiceType != bBuffer) + { + // incorrect command + // if running transfer + if((pSdoComCon->m_uiTransferredByte != 0) + && (pSdoComCon->m_uiTransSize !=0)) + { + pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR; + // -> send abort + EplSdoComClientSendAbort(pSdoComCon, pSdoComCon->m_dwLastAbortCode); + // call callback of application + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferTxAborted); + } + + } + else + { // switch on command + switch(pSdoComCon->m_SdoServiceType) + { + case kEplSdoServiceWriteByIndex: + { // check if confirmation from server + // nothing more to do + break; + } + + case kEplSdoServiceReadByIndex: + { // check if it is an segmented or an expedited transfer + bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bFlags); + // mask uninteressting bits + bBuffer &= 0x30; + switch(bBuffer) + { + // expedited transfer + case 0x00: + { + // check size of buffer + uiBuffer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize); + if(uiBuffer > pSdoComCon->m_uiTransSize) + { // buffer provided by the application is to small + // copy only a part + uiDataSize = pSdoComCon->m_uiTransSize; + } + else + { // buffer fits + uiDataSize = uiBuffer; + } + + // copy data + EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[0], uiDataSize); + + // correct counter + pSdoComCon->m_uiTransSize = 0; + pSdoComCon->m_uiTransferredByte = uiDataSize; + break; + } + + // start of a segmented transfer + case 0x10: + { // get total size of transfer + ulBuffer = AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]); + if(ulBuffer <= pSdoComCon->m_uiTransSize) + { // buffer fit + pSdoComCon->m_uiTransSize = (unsigned int)ulBuffer; + } + else + { // buffer to small + // send abort + pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH; + // -> send abort + EplSdoComClientSendAbort(pSdoComCon, pSdoComCon->m_dwLastAbortCode); + // call callback of application + Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferRxAborted); + goto Exit; + } + + // get segment size + // check size of buffer + uiBuffer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize); + // subtract size of vaiable header from datasize + uiBuffer -= 4; + // copy data + EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[4], uiBuffer); + + // correct counter an pointer + pSdoComCon->m_pData += uiBuffer; + pSdoComCon->m_uiTransferredByte += uiBuffer; + pSdoComCon->m_uiTransSize -= uiBuffer; + + break; + } + + // segment + case 0x20: + { + // get segment size + // check size of buffer + uiBuffer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize); + // check if data to copy fit to buffer + if(uiBuffer >= pSdoComCon->m_uiTransSize) + { // to much data + uiBuffer = (pSdoComCon->m_uiTransSize - 1); + } + // copy data + EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[0], uiBuffer); + + // correct counter an pointer + pSdoComCon->m_pData += uiBuffer; + pSdoComCon->m_uiTransferredByte += uiBuffer; + pSdoComCon->m_uiTransSize -= uiBuffer; + break; + } + + // last segment + case 0x30: + { + // get segment size + // check size of buffer + uiBuffer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize); + // check if data to copy fit to buffer + if(uiBuffer > pSdoComCon->m_uiTransSize) + { // to much data + uiBuffer = (pSdoComCon->m_uiTransSize - 1); + } + // copy data + EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[0], uiBuffer); + + // correct counter an pointer + pSdoComCon->m_pData += uiBuffer; + pSdoComCon->m_uiTransferredByte += uiBuffer; + pSdoComCon->m_uiTransSize = 0; + + break; + } + }// end of switch(bBuffer & 0x30) + + break; + } + + case kEplSdoServiceNIL: + default: + // invalid service requested + // $$$ d.k. What should we do? + break; + }// end of switch(pSdoComCon->m_SdoServiceType) + } + } + +Exit: + return Ret; +} +#endif + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComClientSendAbort +// +// Description: function send a abort message +// +// +// +// Parameters: pSdoComCon_p = pointer to control structure of connection +// dwAbortCode_p = Sdo abort code +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) +static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon* pSdoComCon_p, + DWORD dwAbortCode_p) +{ +tEplKernel Ret; +BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE]; +tEplFrame* pFrame; +tEplAsySdoCom* pCommandFrame; +unsigned int uiSizeOfFrame; + + Ret = kEplSuccessful; + + pFrame = (tEplFrame*)&abFrame[0]; + + EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame)); + + // build generic part of frame + // get pointer to command layerpart of frame + pCommandFrame = &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_abSdoSeqPayload; + AmiSetByteToLe( &pCommandFrame->m_le_bCommandId, pSdoComCon_p->m_SdoServiceType); + AmiSetByteToLe( &pCommandFrame->m_le_bTransactionId, pSdoComCon_p->m_bTransactionId); + + uiSizeOfFrame = 8; + + // set response and abort flag + pCommandFrame->m_le_bFlags |= 0x40; + + // copy abortcode to frame + AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], dwAbortCode_p); + + // set size of segment + AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, sizeof(DWORD)); + + // update counter + pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD); + pSdoComCon_p->m_uiTransSize = 0; + + // calc framesize + uiSizeOfFrame += sizeof(DWORD); + + // save abort code + pSdoComCon_p->m_dwLastAbortCode = dwAbortCode_p; + + // call send function of lower layer + switch(pSdoComCon_p->m_SdoProtType) + { + case kEplSdoTypeAsnd: + case kEplSdoTypeUdp: + { + Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, + uiSizeOfFrame, + pFrame); + break; + } + + default: + { + Ret = kEplSdoComUnsupportedProt; + } + } // end of switch(pSdoComCon_p->m_SdoProtType) + + + return Ret; +} +#endif + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComTransferFinished +// +// Description: calls callback function of application if available +// and clears entry in control structure +// +// Parameters: pSdoComCon_p = pointer to control structure of connection +// SdoComConState_p = state of SDO transfer +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl SdoComCon_p, + tEplSdoComCon* pSdoComCon_p, + tEplSdoComConState SdoComConState_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + if(pSdoComCon_p->m_pfnTransferFinished != NULL) + { + tEplSdoFinishedCb pfnTransferFinished; + tEplSdoComFinished SdoComFinished; + + SdoComFinished.m_pUserArg = pSdoComCon_p->m_pUserArg; + SdoComFinished.m_uiNodeId = pSdoComCon_p->m_uiNodeId; + SdoComFinished.m_uiTargetIndex = pSdoComCon_p->m_uiTargetIndex; + SdoComFinished.m_uiTargetSubIndex = pSdoComCon_p->m_uiTargetSubIndex; + SdoComFinished.m_uiTransferredByte = pSdoComCon_p->m_uiTransferredByte; + SdoComFinished.m_dwAbortCode = pSdoComCon_p->m_dwLastAbortCode; + SdoComFinished.m_SdoComConHdl = SdoComCon_p; + SdoComFinished.m_SdoComConState = SdoComConState_p; + if (pSdoComCon_p->m_SdoServiceType == kEplSdoServiceWriteByIndex) + { + SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeWrite; + } + else + { + SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeRead; + } + + // reset transfer state so this handle is not busy anymore + pSdoComCon_p->m_uiTransferredByte = 0; + pSdoComCon_p->m_uiTransSize = 0; + + pfnTransferFinished = pSdoComCon_p->m_pfnTransferFinished; + // delete function pointer to inform application only once for each transfer + pSdoComCon_p->m_pfnTransferFinished = NULL; + + // call application's callback function + pfnTransferFinished(&SdoComFinished); + + } + + return Ret; +} + +// EOF + diff --git a/drivers/staging/epl/EplSdoUdpu.c b/drivers/staging/epl/EplSdoUdpu.c new file mode 100644 index 0000000..b761cf3 --- /dev/null +++ b/drivers/staging/epl/EplSdoUdpu.c @@ -0,0 +1,821 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for SDO/UDP-Protocolabstractionlayer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdoUdpu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/26 k.t.: start of the implementation + +****************************************************************************/ + + +#include "user/EplSdoUdpu.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + +#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) +#include "SocketLinuxKernel.h" +#include <linux/completion.h> +#include <linux/sched.h> +#endif + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#ifndef EPL_SDO_MAX_CONNECTION_UDP +#define EPL_SDO_MAX_CONNECTION_UDP 5 +#endif + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ + unsigned long m_ulIpAddr; // in network byte order + unsigned int m_uiPort; // in network byte order + +} tEplSdoUdpCon; + +// instance table +typedef struct +{ + tEplSdoUdpCon m_aSdoAbsUdpConnection[EPL_SDO_MAX_CONNECTION_UDP]; + tEplSequLayerReceiveCb m_fpSdoAsySeqCb; + SOCKET m_UdpSocket; + +#if (TARGET_SYSTEM == _WIN32_) + HANDLE m_ThreadHandle; + LPCRITICAL_SECTION m_pCriticalSection; + CRITICAL_SECTION m_CriticalSection; + +#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + struct completion m_CompletionUdpThread; + int m_ThreadHandle; + int m_iTerminateThread; +#endif + +} tEplSdoUdpInstance; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +static tEplSdoUdpInstance SdoUdpInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +#if (TARGET_SYSTEM == _WIN32_) +static DWORD PUBLIC EplSdoUdpThread(LPVOID lpParameter); + +#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) +static int EplSdoUdpThread(void * pArg_p); +#endif + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <EPL-SDO-UDP-Layer> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: Protocolabstraction layer for UDP +// +// +/***************************************************************************/ + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplSdoUdpuInit +// +// Description: init first instance of the module +// +// +// +// Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer +// callback-function +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p) +{ +tEplKernel Ret; + + + Ret = EplSdoUdpuAddInstance(fpReceiveCb_p); + +return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoUdpuAddInstance +// +// Description: init additional instance of the module +// înit socket and start Listen-Thread +// +// +// +// Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer +// callback-function +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p) +{ +tEplKernel Ret; + +#if (TARGET_SYSTEM == _WIN32_) +int iError; +WSADATA Wsa; + +#endif + + // set instance variables to 0 + EPL_MEMSET(&SdoUdpInstance_g, 0x00, sizeof(SdoUdpInstance_g)); + + Ret = kEplSuccessful; + + // save pointer to callback-function + if (fpReceiveCb_p != NULL) + { + SdoUdpInstance_g.m_fpSdoAsySeqCb = fpReceiveCb_p; + } + else + { + Ret = kEplSdoUdpMissCb; + goto Exit; + } + +#if (TARGET_SYSTEM == _WIN32_) + // start winsock2 for win32 + // windows specific start of socket + iError = WSAStartup(MAKEWORD(2,0),&Wsa); + if (iError != 0) + { + Ret = kEplSdoUdpNoSocket; + goto Exit; + } + + // create critical section for acccess of instnace variables + SdoUdpInstance_g.m_pCriticalSection = &SdoUdpInstance_g.m_CriticalSection; + InitializeCriticalSection(SdoUdpInstance_g.m_pCriticalSection); + +#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + init_completion(&SdoUdpInstance_g.m_CompletionUdpThread); + SdoUdpInstance_g.m_iTerminateThread = 0; +#endif + + SdoUdpInstance_g.m_ThreadHandle = 0; + SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET; + + Ret = EplSdoUdpuConfig(INADDR_ANY, 0); + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoUdpuDelInstance +// +// Description: del instance of the module +// del socket and del Listen-Thread +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoUdpuDelInstance() +{ +tEplKernel Ret; + +#if (TARGET_SYSTEM == _WIN32_) +BOOL fTermError; +#endif + + Ret = kEplSuccessful; + + if (SdoUdpInstance_g.m_ThreadHandle != 0) + { // listen thread was started + // close thread +#if (TARGET_SYSTEM == _WIN32_) + fTermError = TerminateThread(SdoUdpInstance_g.m_ThreadHandle, 0); + if(fTermError == FALSE) + { + Ret = kEplSdoUdpThreadError; + goto Exit; + } + +#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + SdoUdpInstance_g.m_iTerminateThread = 1; + /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */ + send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1); + wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread); +#endif + + SdoUdpInstance_g.m_ThreadHandle = 0; + } + + if (SdoUdpInstance_g.m_UdpSocket != INVALID_SOCKET) + { + // close socket + closesocket(SdoUdpInstance_g.m_UdpSocket); + SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET; + } + +#if (TARGET_SYSTEM == _WIN32_) + // delete critical section + DeleteCriticalSection(SdoUdpInstance_g.m_pCriticalSection); +#endif + +#if (TARGET_SYSTEM == _WIN32_) + // for win 32 + WSACleanup(); +#endif + +#if (TARGET_SYSTEM == _WIN32_) +Exit: +#endif + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoUdpuConfig +// +// Description: reconfigurate socket with new IP-Address +// -> needed for NMT ResetConfiguration +// +// Parameters: ulIpAddr_p = IpAddress in platform byte order +// uiPort_p = port number in platform byte order +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p, unsigned int uiPort_p) +{ +tEplKernel Ret; +struct sockaddr_in Addr; +int iError; + +#if (TARGET_SYSTEM == _WIN32_) +BOOL fTermError; +unsigned long ulThreadId; +#endif + + Ret = kEplSuccessful; + + if (uiPort_p == 0) + { // set UDP port to default port number + uiPort_p = EPL_C_SDO_EPL_PORT; + } + else if (uiPort_p > 65535) + { + Ret = kEplSdoUdpSocketError; + goto Exit; + } + + if (SdoUdpInstance_g.m_ThreadHandle != 0) + { // listen thread was started + + // close old thread +#if (TARGET_SYSTEM == _WIN32_) + fTermError = TerminateThread(SdoUdpInstance_g.m_ThreadHandle, 0); + if(fTermError == FALSE) + { + Ret = kEplSdoUdpThreadError; + goto Exit; + } + +#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + SdoUdpInstance_g.m_iTerminateThread = 1; + /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */ + send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1); + wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread); + SdoUdpInstance_g.m_iTerminateThread = 0; +#endif + + SdoUdpInstance_g.m_ThreadHandle = 0; + } + + if (SdoUdpInstance_g.m_UdpSocket != INVALID_SOCKET) + { + // close socket + iError = closesocket(SdoUdpInstance_g.m_UdpSocket); + SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET; + if(iError != 0) + { + Ret = kEplSdoUdpSocketError; + goto Exit; + } + } + + // create Socket + SdoUdpInstance_g.m_UdpSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (SdoUdpInstance_g.m_UdpSocket == INVALID_SOCKET) + { + Ret = kEplSdoUdpNoSocket; + EPL_DBGLVL_SDO_TRACE0("EplSdoUdpuConfig: socket() failed\n"); + goto Exit; + } + + // bind socket + Addr.sin_family = AF_INET; + Addr.sin_port = htons((unsigned short) uiPort_p); + Addr.sin_addr.s_addr = htonl(ulIpAddr_p); + iError = bind(SdoUdpInstance_g.m_UdpSocket, (struct sockaddr*)&Addr, sizeof (Addr)); + if (iError < 0) + { + //iError = WSAGetLastError(); + EPL_DBGLVL_SDO_TRACE1("EplSdoUdpuConfig: bind() finished with %i\n", iError); + Ret = kEplSdoUdpNoSocket; + goto Exit; + } + + // create Listen-Thread +#if (TARGET_SYSTEM == _WIN32_) + // for win32 + + // create thread + SdoUdpInstance_g.m_ThreadHandle = CreateThread(NULL, + 0, + EplSdoUdpThread, + &SdoUdpInstance_g, + 0, + &ulThreadId); + if(SdoUdpInstance_g.m_ThreadHandle == NULL) + { + Ret = kEplSdoUdpThreadError; + goto Exit; + } + +#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + + SdoUdpInstance_g.m_ThreadHandle = kernel_thread(EplSdoUdpThread, &SdoUdpInstance_g, CLONE_KERNEL); + if(SdoUdpInstance_g.m_ThreadHandle == 0) + { + Ret = kEplSdoUdpThreadError; + goto Exit; + } +#endif + + +Exit: + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoUdpuInitCon +// +// Description: init a new connect +// +// +// +// Parameters: pSdoConHandle_p = pointer for the new connection handle +// uiTargetNodeId_p = NodeId of the target node +// +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoUdpuInitCon(tEplSdoConHdl* pSdoConHandle_p, + unsigned int uiTargetNodeId_p) +{ +tEplKernel Ret; +unsigned int uiCount; +unsigned int uiFreeCon; +tEplSdoUdpCon* pSdoUdpCon; + + Ret = kEplSuccessful; + + // get free entry in control structure + uiCount = 0; + uiFreeCon = EPL_SDO_MAX_CONNECTION_UDP; + pSdoUdpCon = &SdoUdpInstance_g.m_aSdoAbsUdpConnection[0]; + while (uiCount < EPL_SDO_MAX_CONNECTION_UDP) + { + if ((pSdoUdpCon->m_ulIpAddr & htonl(0xFF)) == htonl(uiTargetNodeId_p)) + { // existing connection to target node found + // set handle + *pSdoConHandle_p = (uiCount | EPL_SDO_UDP_HANDLE); + + goto Exit; + } + else if ((pSdoUdpCon->m_ulIpAddr == 0) + && (pSdoUdpCon->m_uiPort == 0)) + { + uiFreeCon = uiCount; + } + uiCount++; + pSdoUdpCon++; + } + + if (uiFreeCon == EPL_SDO_MAX_CONNECTION_UDP) + { + // error no free handle + Ret = kEplSdoUdpNoFreeHandle; + } + else + { + pSdoUdpCon = &SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiFreeCon]; + // save infos for connection + pSdoUdpCon->m_uiPort = htons(EPL_C_SDO_EPL_PORT); + pSdoUdpCon->m_ulIpAddr = htonl(0xC0A86400 | uiTargetNodeId_p); // 192.168.100.uiTargetNodeId_p + + // set handle + *pSdoConHandle_p = (uiFreeCon | EPL_SDO_UDP_HANDLE); + + } + +Exit: + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoUdpuSendData +// +// Description: send data using exisiting connection +// +// +// +// Parameters: SdoConHandle_p = connection handle +// pSrcData_p = pointer to data +// dwDataSize_p = number of databyte +// -> without asend-header!!! +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p, + tEplFrame * pSrcData_p, + DWORD dwDataSize_p) +{ +tEplKernel Ret; +int iError; +unsigned int uiArray; +struct sockaddr_in Addr; + + Ret = kEplSuccessful; + + uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK); + if(uiArray >= EPL_SDO_MAX_CONNECTION_UDP) + { + Ret = kEplSdoUdpInvalidHdl; + goto Exit; + } + //set message type + AmiSetByteToLe(&pSrcData_p->m_le_bMessageType, 0x06); // SDO + // target node id (for Udp = 0) + AmiSetByteToLe(&pSrcData_p->m_le_bDstNodeId, 0x00); + // set source-nodeid (for Udp = 0) + AmiSetByteToLe(&pSrcData_p->m_le_bSrcNodeId, 0x00); + + // calc size + dwDataSize_p += EPL_ASND_HEADER_SIZE; + + // call sendto + Addr.sin_family = AF_INET; +#if (TARGET_SYSTEM == _WIN32_) + // enter critical section for process function + EnterCriticalSection(SdoUdpInstance_g.m_pCriticalSection); +#endif + + Addr.sin_port = (unsigned short) SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_uiPort; + Addr.sin_addr.s_addr = SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_ulIpAddr; + +#if (TARGET_SYSTEM == _WIN32_) + // leave critical section for process function + LeaveCriticalSection(SdoUdpInstance_g.m_pCriticalSection); +#endif + + iError = sendto (SdoUdpInstance_g.m_UdpSocket, // sockethandle + (const char*) &pSrcData_p->m_le_bMessageType, // data to send + dwDataSize_p, // number of bytes to send + 0, // flags + (struct sockaddr*)&Addr, // target + sizeof(struct sockaddr_in)); // sizeof targetadress + if(iError < 0) + { + EPL_DBGLVL_SDO_TRACE1("EplSdoUdpuSendData: sendto() finished with %i\n", iError); + Ret = kEplSdoUdpSendError; + goto Exit; + } + +Exit: + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplSdoUdpuDelCon +// +// Description: delete connection from intern structure +// +// +// +// Parameters: SdoConHandle_p = connection handle +// +// Returns: tEplKernel = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p) +{ +tEplKernel Ret; +unsigned int uiArray; + + + uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK); + + if(uiArray >= EPL_SDO_MAX_CONNECTION_UDP) + { + Ret = kEplSdoUdpInvalidHdl; + goto Exit; + } + else + { + Ret = kEplSuccessful; + } + + + // delete connection + SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_ulIpAddr = 0; + SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_uiPort = 0; + +Exit: + return Ret; +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplSdoUdpThread +// +// Description: thread check socket for new data +// +// +// +// Parameters: lpParameter = pointer to parameter type tEplSdoUdpThreadPara +// +// +// Returns: DWORD = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +#if (TARGET_SYSTEM == _WIN32_) +static DWORD PUBLIC EplSdoUdpThread(LPVOID lpParameter) +#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) +static int EplSdoUdpThread(void * pArg_p) +#endif +{ + +tEplSdoUdpInstance* pInstance; +struct sockaddr_in RemoteAddr; +int iError; +int iCount; +int iFreeEntry; +BYTE abBuffer[EPL_MAX_SDO_REC_FRAME_SIZE]; +unsigned int uiSize; +tEplSdoConHdl SdoConHdl; + +#if (TARGET_SYSTEM == _WIN32_) + pInstance = (tEplSdoUdpInstance*)lpParameter; + + for (;;) + +#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + pInstance = (tEplSdoUdpInstance*)pArg_p; + daemonize("EplSdoUdpThread"); + allow_signal( SIGTERM ); + + for (;pInstance->m_iTerminateThread == 0;) +#endif + + { + // wait for data + uiSize = sizeof(struct sockaddr); + iError = recvfrom(pInstance->m_UdpSocket, // Socket + (char *)&abBuffer[0], // buffer for data + sizeof(abBuffer), // size of the buffer + 0, // flags + (struct sockaddr*)&RemoteAddr, + (int*)&uiSize); +#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + if (iError == -ERESTARTSYS) + { + break; + } +#endif + if (iError > 0) + { + // get handle for higher layer + iCount = 0; + iFreeEntry = 0xFFFF; +#if (TARGET_SYSTEM == _WIN32_) + // enter critical section for process function + EnterCriticalSection(SdoUdpInstance_g.m_pCriticalSection); +#endif + while (iCount < EPL_SDO_MAX_CONNECTION_UDP) + { + // check if this connection is already known + if((pInstance->m_aSdoAbsUdpConnection[iCount].m_ulIpAddr == RemoteAddr.sin_addr.s_addr) + && (pInstance->m_aSdoAbsUdpConnection[iCount].m_uiPort == RemoteAddr.sin_port)) + { + break; + } + + if((pInstance->m_aSdoAbsUdpConnection[iCount].m_ulIpAddr == 0) + && (pInstance->m_aSdoAbsUdpConnection[iCount].m_uiPort == 0) + && (iFreeEntry == 0xFFFF)) + + { + iFreeEntry = iCount; + } + + iCount++; + } + + if (iCount == EPL_SDO_MAX_CONNECTION_UDP) + { + // connection unknown + // see if there is a free handle + if (iFreeEntry != 0xFFFF) + { + // save adress infos + pInstance->m_aSdoAbsUdpConnection[iFreeEntry].m_ulIpAddr = + RemoteAddr.sin_addr.s_addr; + pInstance->m_aSdoAbsUdpConnection[iFreeEntry].m_uiPort = + RemoteAddr.sin_port; +#if (TARGET_SYSTEM == _WIN32_) + // leave critical section for process function + LeaveCriticalSection(SdoUdpInstance_g.m_pCriticalSection); +#endif + // call callback + SdoConHdl = iFreeEntry; + SdoConHdl |= EPL_SDO_UDP_HANDLE; + // offset 4 -> start of SDO Sequence header + pInstance->m_fpSdoAsySeqCb(SdoConHdl, (tEplAsySdoSeq*)&abBuffer[4], (iError - 4)); + } + else + { + EPL_DBGLVL_SDO_TRACE0("Error in EplSdoUdpThread() no free handle\n"); +#if (TARGET_SYSTEM == _WIN32_) + // leave critical section for process function + LeaveCriticalSection(SdoUdpInstance_g.m_pCriticalSection); +#endif + } + + } + else + { + // known connection + // call callback with correct handle + SdoConHdl = iCount; + SdoConHdl |= EPL_SDO_UDP_HANDLE; +#if (TARGET_SYSTEM == _WIN32_) + // leave critical section for process function + LeaveCriticalSection(SdoUdpInstance_g.m_pCriticalSection); +#endif + // offset 4 -> start of SDO Sequence header + pInstance->m_fpSdoAsySeqCb(SdoConHdl, (tEplAsySdoSeq*)&abBuffer[4], (iError - 4)); + } + } // end of if(iError!=SOCKET_ERROR) + }// end of for(;;) + +#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + complete_and_exit(&SdoUdpInstance_g.m_CompletionUdpThread, 0); +#endif + + return 0; +} + +#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + +// EOF + diff --git a/drivers/staging/epl/EplStatusu.c b/drivers/staging/epl/EplStatusu.c new file mode 100644 index 0000000..2c81636 --- /dev/null +++ b/drivers/staging/epl/EplStatusu.c @@ -0,0 +1,387 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for Statusu-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplStatusu.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/11/15 d.k.: start of the implementation + +****************************************************************************/ + +#include "user/EplStatusu.h" +#include "user/EplDlluCal.h" + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <xxxxx> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: +// +// +/***************************************************************************/ + + +//=========================================================================// +// // +// P R I V A T E D E F I N I T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +typedef struct +{ + tEplStatusuCbResponse m_apfnCbResponse[254]; + +} tEplStatusuInstance; + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +static tEplStatusuInstance EplStatusuInstance_g; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static tEplKernel PUBLIC EplStatusuCbStatusResponse(tEplFrameInfo * pFrameInfo_p); + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplStatusuInit +// +// Description: init first instance of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplStatusuInit() +{ +tEplKernel Ret; + + Ret = EplStatusuAddInstance(); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplStatusuAddInstance +// +// Description: init other instances of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplStatusuAddInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // reset instance structure + EPL_MEMSET(&EplStatusuInstance_g, 0, sizeof (EplStatusuInstance_g)); + + // register StatusResponse callback function + Ret = EplDlluCalRegAsndService(kEplDllAsndStatusResponse, EplStatusuCbStatusResponse, kEplDllAsndFilterAny); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplStatusuDelInstance +// +// Description: delete instance +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplStatusuDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // deregister StatusResponse callback function + Ret = EplDlluCalRegAsndService(kEplDllAsndStatusResponse, NULL, kEplDllAsndFilterNone); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplStatusuReset +// +// Description: resets this instance +// +// Parameters: +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- + +EPLDLLEXPORT tEplKernel PUBLIC EplStatusuReset() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // reset instance structure + EPL_MEMSET(&EplStatusuInstance_g, 0, sizeof (EplStatusuInstance_g)); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplStatusuRequestStatusResponse +// +// Description: returns the StatusResponse for the specified node. +// +// Parameters: uiNodeId_p = IN: node ID +// pfnCbResponse_p = IN: function pointer to callback function +// which will be called if StatusResponse is received +// +// Return: tEplKernel = error code +// +// State: not tested +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplStatusuRequestStatusResponse( + unsigned int uiNodeId_p, + tEplStatusuCbResponse pfnCbResponse_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // decrement node ID, because array is zero based + uiNodeId_p--; + if (uiNodeId_p < tabentries (EplStatusuInstance_g.m_apfnCbResponse)) + { +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + if (EplStatusuInstance_g.m_apfnCbResponse[uiNodeId_p] != NULL) + { // request already issued (maybe by someone else) + Ret = kEplInvalidOperation; + } + else + { + EplStatusuInstance_g.m_apfnCbResponse[uiNodeId_p] = pfnCbResponse_p; + Ret = EplDlluCalIssueRequest(kEplDllReqServiceStatus, (uiNodeId_p + 1), 0xFF); + } +#else + Ret = kEplInvalidOperation; +#endif + } + else + { // invalid node ID specified + Ret = kEplInvalidNodeId; + } + + return Ret; + +} + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplStatusuCbStatusResponse +// +// Description: callback funktion for StatusResponse +// +// +// +// Parameters: pFrameInfo_p = Frame with the StatusResponse +// +// +// Returns: tEplKernel = error code +// +// +// State: +// +//--------------------------------------------------------------------------- +static tEplKernel PUBLIC EplStatusuCbStatusResponse(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiNodeId; +unsigned int uiIndex; +tEplStatusuCbResponse pfnCbResponse; + + uiNodeId = AmiGetByteFromLe(&pFrameInfo_p->m_pFrame->m_le_bSrcNodeId); + + uiIndex = uiNodeId - 1; + + if (uiIndex < tabentries (EplStatusuInstance_g.m_apfnCbResponse)) + { + // memorize pointer to callback function + pfnCbResponse = EplStatusuInstance_g.m_apfnCbResponse[uiIndex]; + if (pfnCbResponse == NULL) + { // response was not requested + goto Exit; + } + // reset callback function pointer so that caller may issue next request + EplStatusuInstance_g.m_apfnCbResponse[uiIndex] = NULL; + + if (pFrameInfo_p->m_uiFrameSize < EPL_C_DLL_MINSIZE_STATUSRES) + { // StatusResponse not received or it has invalid size + Ret = pfnCbResponse(uiNodeId, NULL); + } + else + { // StatusResponse received + Ret = pfnCbResponse(uiNodeId, &pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.m_StatusResponse); + } + } + +Exit: + return Ret; +} + +// EOF + diff --git a/drivers/staging/epl/EplTarget.h b/drivers/staging/epl/EplTarget.h new file mode 100644 index 0000000..0d1fe8a --- /dev/null +++ b/drivers/staging/epl/EplTarget.h @@ -0,0 +1,240 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for target api function + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplTarget.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2005/12/05 -as: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPLTARGET_H_ +#define _EPLTARGET_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- +// ========================================================================= +// macros for memory access (depends on target system) +// ========================================================================= + +// NOTE: +// The following macros are used to combine standard library definitions. Some +// applications needs to use one common library function (e.g. memcpy()). So +// you can set (or change) it here. + +#if (TARGET_SYSTEM == _WIN32_) + + #define _WIN32_WINDOWS 0x0401 + #define _WIN32_WINNT 0x0400 + + #include <stdlib.h> + #include <stdio.h> + + //29.11.2004 f.j. sonst ist memcpy und memset unbekannt + #include <string.h> + + #define EPL_MEMCPY(dst,src,siz) memcpy((void*)(dst),(const void*)(src),(size_t)(siz)); + #define EPL_MEMSET(dst,val,siz) memset((void*)(dst),(int)(val),(size_t)(siz)); + + // f.j.: die Funktionen für <MemAlloc> und <MemFree> sind in WinMem.c definiert + //definition der Prototypen + void FAR* MemAlloc (DWORD dwMemSize_p); + void MemFree (void FAR* pMem_p); + + #define EPL_MALLOC(siz) malloc((size_t)(siz)) + #define EPL_FREE(ptr) free((void *)ptr) + + #ifndef PRINTF0 + void trace (const char* fmt, ...); + #define PRINTF TRACE + #define PRINTF0(arg) TRACE0(arg) + #define PRINTF1(arg,p1) TRACE1(arg,p1) + #define PRINTF2(arg,p1,p2) TRACE2(arg,p1,p2) + #define PRINTF3(arg,p1,p2,p3) TRACE3(arg,p1,p2,p3) + #define PRINTF4(arg,p1,p2,p3,p4) TRACE4(arg,p1,p2,p3,p4) + //#define PRINTF printf + //#define PRINTF0(arg) PRINTF(arg) + //#define PRINTF1(arg,p1) PRINTF(arg,p1) + //#define PRINTF2(arg,p1,p2) PRINTF(arg,p1,p2) + //#define PRINTF3(arg,p1,p2,p3) PRINTF(arg,p1,p2,p3) + //#define PRINTF4(arg,p1,p2,p3,p4) PRINTF(arg,p1,p2,p3,p4) + #endif + + #ifdef ASSERTMSG + #undef ASSERTMSG + #endif + + #define ASSERTMSG(expr,string) if (!(expr)) { \ + MessageBox (NULL, string, "Assertion failed", MB_OK | MB_ICONERROR); \ + exit (-1);} + + + +#elif (TARGET_SYSTEM == _NO_OS_) + + #include <stdlib.h> + #include <stdio.h> + + //29.11.2004 f.j. sonst ist memcpy und memset unbekannt +// #include <string.h> + + #define EPL_MEMCPY(dst,src,siz) memcpy((void*)(dst),(const void*)(src),(size_t)(siz)); + #define EPL_MEMSET(dst,val,siz) memset((void*)(dst),(int)(val),(size_t)(siz)); + + #define EPL_MALLOC(siz) malloc((size_t)(siz)) + #define EPL_FREE(ptr) free((void *)ptr) + + #ifndef PRINTF0 + #define PRINTF TRACE + #define PRINTF0(arg) TRACE0(arg) + #define PRINTF1(arg,p1) TRACE1(arg,p1) + #define PRINTF2(arg,p1,p2) TRACE2(arg,p1,p2) + #define PRINTF3(arg,p1,p2,p3) TRACE3(arg,p1,p2,p3) + #define PRINTF4(arg,p1,p2,p3,p4) TRACE4(arg,p1,p2,p3,p4) + //#define PRINTF printf + //#define PRINTF0(arg) PRINTF(arg) + //#define PRINTF1(arg,p1) PRINTF(arg,p1) + //#define PRINTF2(arg,p1,p2) PRINTF(arg,p1,p2) + //#define PRINTF3(arg,p1,p2,p3) PRINTF(arg,p1,p2,p3) + //#define PRINTF4(arg,p1,p2,p3,p4) PRINTF(arg,p1,p2,p3,p4) + #endif + + +#elif (TARGET_SYSTEM == _LINUX_) + + #ifndef __KERNEL__ + #include <stdlib.h> + #include <stdio.h> + #else +// #include <linux/config.h> + #include <linux/module.h> + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/errno.h> + #include <linux/major.h> + #include <linux/version.h> + #endif + + //29.11.2004 f.j. sonst ist memcpy und memset unbekannt +// #include <string.h> + + #define EPL_MEMCPY(dst,src,siz) memcpy((void*)(dst),(const void*)(src),(size_t)(siz)); + #define EPL_MEMSET(dst,val,siz) memset((void*)(dst),(int)(val),(size_t)(siz)); + + #ifndef __KERNEL__ + #define EPL_MALLOC(siz) malloc((size_t)(siz)) + #define EPL_FREE(ptr) free((void *)ptr) + #else + #define EPL_MALLOC(siz) kmalloc((size_t)(siz), GFP_KERNEL) + #define EPL_FREE(ptr) kfree((void *)ptr) + #endif + + #ifndef PRINTF0 + #define PRINTF TRACE + #define PRINTF0(arg) TRACE0(arg) + #define PRINTF1(arg,p1) TRACE1(arg,p1) + #define PRINTF2(arg,p1,p2) TRACE2(arg,p1,p2) + #define PRINTF3(arg,p1,p2,p3) TRACE3(arg,p1,p2,p3) + #define PRINTF4(arg,p1,p2,p3,p4) TRACE4(arg,p1,p2,p3,p4) + //#define PRINTF printf + //#define PRINTF0(arg) PRINTF(arg) + //#define PRINTF1(arg,p1) PRINTF(arg,p1) + //#define PRINTF2(arg,p1,p2) PRINTF(arg,p1,p2) + //#define PRINTF3(arg,p1,p2,p3) PRINTF(arg,p1,p2,p3) + //#define PRINTF4(arg,p1,p2,p3,p4) PRINTF(arg,p1,p2,p3,p4) + #endif + + +#endif + +#define EPL_TGT_INTMASK_ETH 0x0001 // ethernet interrupt +#define EPL_TGT_INTMASK_DMA 0x0002 // DMA interrupt + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +// currently no Timer functions are needed by EPL stack +// so they are not implemented yet +//void PUBLIC TgtTimerInit(void); +//DWORD PUBLIC TgtGetTickCount(void); +//void PUBLIC TgtGetNetTime(tEplNetTime * pNetTime_p); + +// functions for ethernet driver +tEplKernel PUBLIC TgtInitEthIsr(void); +void PUBLIC TgtFreeEthIsr(void); +void PUBLIC TgtEnableGlobalInterrupt(BYTE fEnable_p); +void PUBLIC TgtEnableEthInterrupt0(BYTE fEnable_p, unsigned int uiInterruptMask_p); +void PUBLIC TgtEnableEthInterrupt1(BYTE fEnable_p, unsigned int uiInterruptMask_p); + +#endif // #ifndef _EPLTARGET_H_ + + diff --git a/drivers/staging/epl/EplTimer.h b/drivers/staging/epl/EplTimer.h new file mode 100644 index 0000000..6dbb53b --- /dev/null +++ b/drivers/staging/epl/EplTimer.h @@ -0,0 +1,125 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for Epl Timer-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplTimer.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/06 k.t.: start of the implementation + + +****************************************************************************/ + +#include "EplInc.h" +#include "EplEvent.h" + +#ifndef _EPLTIMER_H_ +#define _EPLTIMER_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +// type for timer handle +typedef unsigned long tEplTimerHdl; + +typedef struct +{ + tEplEventSink m_EventSink; + unsigned long m_ulArg; // d.k.: converted to unsigned long because + // it is never accessed as a pointer by the + // timer module and the data the + // pointer points to is not saved in any way. + // It is just a value. The user is responsible + // to store the data statically and convert + // the pointer between address spaces. + +} tEplTimerArg; + +typedef struct +{ + tEplTimerHdl m_TimerHdl; + unsigned long m_ulArg; // d.k.: converted to unsigned long because + // it is never accessed as a pointer by the + // timer module and the data the + // pointer points to is not saved in any way. + // It is just a value. + +} tEplTimerEventArg; + +typedef tEplKernel (PUBLIC * tEplTimerkCallback) ( + tEplTimerEventArg* pEventArg_p); + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPLTIMER_H_ + + diff --git a/drivers/staging/epl/EplTimeruLinuxKernel.c b/drivers/staging/epl/EplTimeruLinuxKernel.c new file mode 100644 index 0000000..41dfb61 --- /dev/null +++ b/drivers/staging/epl/EplTimeruLinuxKernel.c @@ -0,0 +1,472 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for EPL User Timermodule for Linux kernel module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplTimeruLinuxKernel.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + KEIL uVision 2 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/09/12 d.k.: start of the implementation + +****************************************************************************/ + +#include "user/EplTimeru.h" +#include <linux/timer.h> + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- +typedef struct +{ + struct timer_list m_Timer; + tEplTimerArg TimerArgument; + +} tEplTimeruData; + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- +static void PUBLIC EplTimeruCbMs(unsigned long ulParameter_p); + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <Epl Userspace-Timermodule for Linux Kernel> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: Epl Userspace-Timermodule for Linux Kernel +// +// +/***************************************************************************/ + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruInit +// +// Description: function inits first instance +// +// Parameters: void +// +// Returns: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimeruInit() +{ +tEplKernel Ret; + + Ret = EplTimeruAddInstance(); + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruAddInstance +// +// Description: function inits additional instance +// +// Parameters: void +// +// Returns: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimeruAddInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruDelInstance +// +// Description: function deletes instance +// -> under Linux nothing to do +// -> no instance table needed +// +// Parameters: void +// +// Returns: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimeruDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruSetTimerMs +// +// Description: function creates a timer and returns the corresponding handle +// +// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle +// ulTime_p = time for timer in ms +// Argument_p = argument for timer +// +// Returns: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplTimeruData* pData; + + // check pointer to handle + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + pData = (tEplTimeruData*) EPL_MALLOC(sizeof (tEplTimeruData)); + if (pData == NULL) + { + Ret = kEplNoResource; + goto Exit; + } + + init_timer(&pData->m_Timer); + pData->m_Timer.function = EplTimeruCbMs; + pData->m_Timer.data = (unsigned long) pData; + pData->m_Timer.expires = jiffies + ulTime_p * HZ / 1000; + + EPL_MEMCPY(&pData->TimerArgument, &Argument_p, sizeof(tEplTimerArg)); + + add_timer(&pData->m_Timer); + + *pTimerHdl_p = (tEplTimerHdl) pData; + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruModifyTimerMs +// +// Description: function changes a timer and returns the corresponding handle +// +// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle +// ulTime_p = time for timer in ms +// Argument_p = argument for timer +// +// Returns: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplTimeruData* pData; + + // check pointer to handle + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + // check handle itself, i.e. was the handle initialized before + if (*pTimerHdl_p == 0) + { + Ret = EplTimeruSetTimerMs(pTimerHdl_p, ulTime_p, Argument_p); + goto Exit; + } + pData = (tEplTimeruData*) *pTimerHdl_p; + if ((tEplTimeruData*)pData->m_Timer.data != pData) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + mod_timer(&pData->m_Timer, (jiffies + ulTime_p * HZ / 1000)); + + // copy the TimerArg after the timer is restarted, + // so that a timer occured immediately before mod_timer + // won't use the new TimerArg and + // therefore the old timer cannot be distinguished from the new one. + // But if the new timer is too fast, it may get lost. + EPL_MEMCPY(&pData->TimerArgument, &Argument_p, sizeof(tEplTimerArg)); + + // check if timer is really running + if (timer_pending(&pData->m_Timer) == 0) + { // timer is not running + // retry starting it + add_timer(&pData->m_Timer); + } + + // set handle to pointer of tEplTimeruData +// *pTimerHdl_p = (tEplTimerHdl) pData; + +Exit: + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruDeleteTimer +// +// Description: function deletes a timer +// +// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle +// +// Returns: tEplKernel = errorcode +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl* pTimerHdl_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplTimeruData* pData; + + // check pointer to handle + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + // check handle itself, i.e. was the handle initialized before + if (*pTimerHdl_p == 0) + { + Ret = kEplSuccessful; + goto Exit; + } + pData = (tEplTimeruData*) *pTimerHdl_p; + if ((tEplTimeruData*)pData->m_Timer.data != pData) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + +/* if (del_timer(&pData->m_Timer) == 1) + { + kfree(pData); + } +*/ + // try to delete the timer + del_timer(&pData->m_Timer); + // free memory in any case + kfree(pData); + + // uninitialize handle + *pTimerHdl_p = 0; + +Exit: + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruIsTimerActive +// +// Description: checks if the timer referenced by the handle is currently +// active. +// +// Parameters: TimerHdl_p = handle of the timer to check +// +// Returns: BOOL = TRUE, if active; +// FALSE, otherwise +// +// State: +// +//--------------------------------------------------------------------------- + +BOOL PUBLIC EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p) +{ +BOOL fActive = FALSE; +tEplTimeruData* pData; + + // check handle itself, i.e. was the handle initialized before + if (TimerHdl_p == 0) + { // timer was not created yet, so it is not active + goto Exit; + } + pData = (tEplTimeruData*) TimerHdl_p; + if ((tEplTimeruData*)pData->m_Timer.data != pData) + { // invalid timer + goto Exit; + } + + // check if timer is running + if (timer_pending(&pData->m_Timer) == 0) + { // timer is not running + goto Exit; + } + + fActive = TRUE; + +Exit: + return fActive; +} + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruCbMs +// +// Description: function to process timer +// +// +// +// Parameters: lpParameter = pointer to structur of type tEplTimeruData +// +// +// Returns: (none) +// +// +// State: +// +//--------------------------------------------------------------------------- +static void PUBLIC EplTimeruCbMs(unsigned long ulParameter_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplTimeruData* pData; +tEplEvent EplEvent; +tEplTimerEventArg TimerEventArg; + + pData = (tEplTimeruData*) ulParameter_p; + + // call event function + TimerEventArg.m_TimerHdl = (tEplTimerHdl)pData; + TimerEventArg.m_ulArg = pData->TimerArgument.m_ulArg; + + EplEvent.m_EventSink = pData->TimerArgument.m_EventSink; + EplEvent.m_EventType = kEplEventTypeTimer; + EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(tEplNetTime)); + EplEvent.m_pArg = &TimerEventArg; + EplEvent.m_uiSize = sizeof(TimerEventArg); + + Ret = EplEventuPost(&EplEvent); + + // d.k. do not free memory, user has to call EplTimeruDeleteTimer() + //kfree(pData); + +} + + +// EOF + diff --git a/drivers/staging/epl/EplTimeruNull.c b/drivers/staging/epl/EplTimeruNull.c new file mode 100644 index 0000000..ce9af38 --- /dev/null +++ b/drivers/staging/epl/EplTimeruNull.c @@ -0,0 +1,323 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for Epl Userspace-Timermodule NULL-Implementation + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplTimeruNull.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + KEIL uVision 2 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/06 k.t.: start of the implementation + +****************************************************************************/ + +#include "user/EplTimeru.h" + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <Epl Userspace-Timermodule NULL-Implementation> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: Epl Userspace-Timermodule NULL-Implementation +// +// +/***************************************************************************/ + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruInit +// +// Description: function init first instance +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruInit() +{ +tEplKernel Ret; + + Ret = EplTimeruAddInstance(); + +return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruAddInstance +// +// Description: function init additional instance +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruAddInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + +return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruDelInstance +// +// Description: function delte instance +// -> under Win32 nothing to do +// -> no instnace table needed +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruSetTimerMs +// +// Description: function create a timer and return a handle to the pointer +// +// +// +// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle +// ulTime_p = time for timer in ms +// Argument_p = argument for timer +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p) +{ +tEplKernel Ret; + + + Ret = kEplSuccessful; + + // check handle + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + +Exit: + return Ret; +} + + + //--------------------------------------------------------------------------- +// +// Function: EplTimeruModifyTimerMs +// +// Description: function change a timer and return a handle to the pointer +// +// +// +// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle +// ulTime_p = time for timer in ms +// Argument_p = argument for timer +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // check parameter + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + +Exit: + return Ret; +} + + //--------------------------------------------------------------------------- +// +// Function: EplTimeruDeleteTimer +// +// Description: function delte a timer +// +// +// +// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl* pTimerHdl_p) +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + // check parameter + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + // set handle invalide + *pTimerHdl_p = 0; + + +Exit: + return Ret; + +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + + + +// EOF + diff --git a/drivers/staging/epl/EplTimeruWin32.c b/drivers/staging/epl/EplTimeruWin32.c new file mode 100644 index 0000000..b5d845c --- /dev/null +++ b/drivers/staging/epl/EplTimeruWin32.c @@ -0,0 +1,551 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: source file for Epl Userspace-Timermodule for Win32 + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplTimeruWin32.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/06 k.t.: start of the implementation + +****************************************************************************/ + +#include "user/EplTimeru.h" + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- +typedef struct +{ + tEplTimerArg TimerArgument; + HANDLE DelteHandle; + unsigned long ulTimeout; + +}tEplTimeruThread; + +typedef struct +{ + LPCRITICAL_SECTION m_pCriticalSection; + CRITICAL_SECTION m_CriticalSection; +}tEplTimeruInstance; +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- +static tEplTimeruInstance EplTimeruInstance_g; +static tEplTimeruThread ThreadData_l; +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- +DWORD PUBLIC EplSdoTimeruThreadms(LPVOID lpParameter); + +/***************************************************************************/ +/* */ +/* */ +/* C L A S S <Epl Userspace-Timermodule for Win32> */ +/* */ +/* */ +/***************************************************************************/ +// +// Description: Epl Userspace-Timermodule for Win32 +// +// +/***************************************************************************/ + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruInit +// +// Description: function init first instance +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruInit() +{ +tEplKernel Ret; + + Ret = EplTimeruAddInstance(); + +return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruAddInstance +// +// Description: function init additional instance +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruAddInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + + // create critical section + EplTimeruInstance_g.m_pCriticalSection = &EplTimeruInstance_g.m_CriticalSection; + InitializeCriticalSection(EplTimeruInstance_g.m_pCriticalSection); + + + +return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruDelInstance +// +// Description: function delte instance +// -> under Win32 nothing to do +// -> no instnace table needed +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruDelInstance() +{ +tEplKernel Ret; + + Ret = kEplSuccessful; + + return Ret; +} + +//--------------------------------------------------------------------------- +// +// Function: EplTimeruSetTimerMs +// +// Description: function create a timer and return a handle to the pointer +// +// +// +// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle +// ulTime_p = time for timer in ms +// Argument_p = argument for timer +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p) +{ +tEplKernel Ret; +HANDLE DeleteHandle; +HANDLE ThreadHandle; +DWORD ThreadId; + + + Ret = kEplSuccessful; + + // check handle + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + // enter critical section + EnterCriticalSection(EplTimeruInstance_g.m_pCriticalSection); + + // first create event to delete timer + DeleteHandle = CreateEvent(NULL,FALSE,FALSE, NULL); + if(DeleteHandle == NULL) + { + Ret = kEplTimerNoTimerCreated; + goto Exit; + } + + // set handle for caller + *pTimerHdl_p = (tEplTimerHdl)DeleteHandle; + + + + + // fill data for thread + ThreadData_l.DelteHandle = DeleteHandle; + EPL_MEMCPY(&ThreadData_l.TimerArgument, &Argument_p, sizeof(tEplTimerArg)); + ThreadData_l.ulTimeout = ulTime_p; + + // create thread to create waitable timer and wait for timer + ThreadHandle = CreateThread(NULL, + 0, + EplSdoTimeruThreadms, + &ThreadData_l, + 0, + &ThreadId); + if(ThreadHandle == NULL) + { + // leave critical section + LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection); + + // delte handle + CloseHandle(DeleteHandle); + + Ret = kEplTimerNoTimerCreated; + goto Exit; + } + +Exit: + return Ret; +} + + + //--------------------------------------------------------------------------- +// +// Function: EplTimeruModifyTimerMs +// +// Description: function change a timer and return a handle to the pointer +// +// +// +// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle +// ulTime_p = time for timer in ms +// Argument_p = argument for timer +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p) +{ +tEplKernel Ret; +HANDLE DeleteHandle; +HANDLE ThreadHandle; +DWORD ThreadId; + + Ret = kEplSuccessful; + + // check parameter + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + DeleteHandle = (HANDLE)(*pTimerHdl_p); + + // set event to end timer task for this timer + SetEvent(DeleteHandle); + + // create new timer + // first create event to delete timer + DeleteHandle = CreateEvent(NULL,FALSE,FALSE, NULL); + if(DeleteHandle == NULL) + { + Ret = kEplTimerNoTimerCreated; + goto Exit; + } + + // set handle for caller + *pTimerHdl_p = (tEplTimerHdl)DeleteHandle; + + // enter critical section + EnterCriticalSection(EplTimeruInstance_g.m_pCriticalSection); + + // fill data for thread + ThreadData_l.DelteHandle = DeleteHandle; + EPL_MEMCPY(&ThreadData_l.TimerArgument, &Argument_p, sizeof(tEplTimerArg)); + ThreadData_l.ulTimeout = ulTime_p; + + // create thread to create waitable timer and wait for timer + ThreadHandle = CreateThread(NULL, + 0, + EplSdoTimeruThreadms, + &ThreadData_l, + 0, + &ThreadId); + if(ThreadHandle == NULL) + { + // leave critical section + LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection); + + // delte handle + + Ret = kEplTimerNoTimerCreated; + goto Exit; + } + +Exit: + return Ret; +} + + //--------------------------------------------------------------------------- +// +// Function: EplTimeruDeleteTimer +// +// Description: function delte a timer +// +// +// +// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl* pTimerHdl_p) +{ +tEplKernel Ret; +HANDLE DeleteHandle; + + Ret = kEplSuccessful; + + // check parameter + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + DeleteHandle = (HANDLE)(*pTimerHdl_p); + + // set event to end timer task for this timer + SetEvent(DeleteHandle); + + // set handle invalide + *pTimerHdl_p = 0; + + +Exit: + return Ret; + +} + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: EplSdoTimeruThreadms +// +// Description: function to process timer as thread +// +// +// +// Parameters: lpParameter = pointer to structur of type tEplTimeruThread +// +// +// Returns: DWORD = Errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +DWORD PUBLIC EplSdoTimeruThreadms(LPVOID lpParameter) +{ +tEplKernel Ret; +tEplTimeruThread* pThreadData; +HANDLE aHandles[2]; +BOOL fReturn; +LARGE_INTEGER TimeoutTime; +unsigned long ulEvent; +tEplEvent EplEvent; +tEplTimeruThread ThreadData; +tEplTimerEventArg TimerEventArg; + + Ret = kEplSuccessful; + + // get pointer to data + pThreadData = (tEplTimeruThread*)lpParameter; + // copy thread data + EPL_MEMCPY(&ThreadData, pThreadData, sizeof(ThreadData)); + pThreadData = &ThreadData; + + // leave critical section + LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection); + + // create waitable timer + aHandles[1] = CreateWaitableTimer(NULL,FALSE,NULL); + if(aHandles[1] == NULL) + { + Ret = kEplTimerNoTimerCreated; + goto Exit; + } + + // set timer + // set timeout interval -> needed to be negativ + // -> because relative timeout + // -> multiply by 10000 for 100 ns timebase of function + TimeoutTime.QuadPart = (((long long)pThreadData->ulTimeout) * -10000); + fReturn = SetWaitableTimer(aHandles[1], + &TimeoutTime, + 0, + NULL, + NULL, + FALSE); + if(fReturn == 0) + { + Ret = kEplTimerNoTimerCreated; + goto Exit; + } + + // save delte event handle in handle array + aHandles[0] = pThreadData->DelteHandle; + + // wait for one of the events + ulEvent = WaitForMultipleObjects( 2, + &aHandles[0], + FALSE, + INFINITE); + if(ulEvent == WAIT_OBJECT_0) + { // delte event + + // close handels + CloseHandle(aHandles[1]); + // terminate thread + goto Exit; + } + else if(ulEvent == (WAIT_OBJECT_0 + 1)) + { // timer event + // call event function + TimerEventArg.m_TimerHdl = (tEplTimerHdl)pThreadData->DelteHandle; + TimerEventArg.m_ulArg = pThreadData->TimerArgument.m_ulArg; + + EplEvent.m_EventSink = pThreadData->TimerArgument.m_EventSink; + EplEvent.m_EventType = kEplEventTypeTimer; + EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(tEplNetTime)); + EplEvent.m_pArg = &TimerEventArg; + EplEvent.m_uiSize = sizeof(TimerEventArg); + + Ret = EplEventuPost(&EplEvent); + + // close handels + CloseHandle(aHandles[1]); + // terminate thread + goto Exit; + + } + else + { // error + ulEvent = GetLastError(); + TRACE1("Error in WaitForMultipleObjects Errorcode: 0x%x\n",ulEvent); + // terminate thread + goto Exit; + } + +Exit: + return Ret; +} + + +// EOF + diff --git a/drivers/staging/epl/EplVersion.h b/drivers/staging/epl/EplVersion.h new file mode 100644 index 0000000..4f47761 --- /dev/null +++ b/drivers/staging/epl/EplVersion.h @@ -0,0 +1,100 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: This file defines the EPL version for the stack, as string + and for object 0x1018 within object dictionary. + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplVersion.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + all + + ------------------------------------------------------------------------- + + Revision History: + +****************************************************************************/ + +#ifndef _EPL_VERSION_H_ +#define _EPL_VERSION_H_ + + +// NOTE: +// All version macros should contain the same version number. But do not use +// defines instead of the numbers. Because the macro EPL_STRING_VERSION() can not +// convert a define to a string. +// +// Format: maj.min.build +// maj = major version +// min = minor version (will be set to 0 if major version will be incremented) +// build = current build (will be set to 0 if minor version will be incremented) +// +#define DEFINED_STACK_VERSION EPL_STACK_VERSION (1, 3, 0) +#define DEFINED_OBJ1018_VERSION EPL_OBJ1018_VERSION (1, 3, 0) +#define DEFINED_STRING_VERSION EPL_STRING_VERSION (1, 3, 0) + + +// ----------------------------------------------------------------------------- +#define EPL_PRODUCT_NAME "EPL V2" +#define EPL_PRODUCT_VERSION DEFINED_STRING_VERSION +#define EPL_PRODUCT_MANUFACTURER "SYS TEC electronic GmbH" + + #define EPL_PRODUCT_KEY "SO-1083" + #define EPL_PRODUCT_DESCRIPTION "openPOWERLINK Protocol Stack Source" + +#endif // _EPL_VERSION_H_ + +// Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler +// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder). diff --git a/drivers/staging/epl/Kconfig b/drivers/staging/epl/Kconfig new file mode 100644 index 0000000..9f939d5 --- /dev/null +++ b/drivers/staging/epl/Kconfig @@ -0,0 +1,6 @@ +config EPL + tristate "openPOWERLINK protocol stack" + depends on NET && HIGH_RES_TIMERS && X86 + default N + ---help--- + Enable support for the openPOWERLINK network protocol stack. diff --git a/drivers/staging/epl/Makefile b/drivers/staging/epl/Makefile new file mode 100644 index 0000000..a2c8241 --- /dev/null +++ b/drivers/staging/epl/Makefile @@ -0,0 +1,41 @@ +obj-$(CONFIG_EPL) += epl.o + +epl-objs := \ + EplApiGeneric.o \ + EplApiLinuxKernel.o \ + EplApiProcessImage.o \ + EplDllk.o \ + EplDllkCal.o \ + EplDlluCal.o \ + EplErrorHandlerk.o \ + EplEventk.o \ + EplEventu.o \ + EplIdentu.o \ + EplNmtCnu.o \ + EplNmtk.o \ + EplNmtkCal.o \ + EplNmtMnu.o \ + EplNmtu.o \ + EplNmtuCal.o \ + EplObd.o \ + EplObdkCal.o \ + EplObdu.o \ + EplObduCal.o \ + EplPdok.o \ + EplPdokCal.o \ + EplPdou.o \ + EplSdoAsndu.o \ + EplSdoAsySequ.o \ + EplSdoComu.o \ + EplSdoUdpu.o \ + EplStatusu.o \ + EplTimeruLinuxKernel.o \ + amix86.o \ + SharedBuff.o \ + ShbIpc-LinuxKernel.o \ + TimerHighReskX86.o \ + VirtualEthernetLinux.o \ + SocketLinuxKernel.o \ + proc_fs.o \ + demo_main.o \ + Edrv8139.o \ diff --git a/drivers/staging/epl/SharedBuff.c b/drivers/staging/epl/SharedBuff.c new file mode 100644 index 0000000..1833d71 --- /dev/null +++ b/drivers/staging/epl/SharedBuff.c @@ -0,0 +1,2041 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: Project independend shared buffer (linear + circular) + + Description: Implementation of platform independend part for the + shared buffer + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + 2006/06/27 -rs: V 1.00 (initial version) + +****************************************************************************/ + +#if defined(WIN32) || defined(_WIN32) + + #ifdef UNDER_RTSS + // RTX header + #include <windows.h> + #include <process.h> + #include <rtapi.h> + + #elif __BORLANDC__ + // borland C header + #include <windows.h> + #include <process.h> + + #elif WINCE + #include <windows.h> + + #else + // MSVC needs to include windows.h at first + // the following defines ar necessary for function prototypes for waitable timers + #define _WIN32_WINDOWS 0x0401 + #define _WIN32_WINNT 0x0400 + #include <windows.h> + #include <process.h> + #endif + +#endif + +#include "global.h" +#include "SharedBuff.h" +#include "ShbIpc.h" + +// d.k. Linux kernel modules needs other header files for memcpy() +#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) + #include <linux/string.h> +#else + #include <stdio.h> + #include <stdlib.h> + #include <string.h> +#endif + + + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// Configuration +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Constant definitions +//--------------------------------------------------------------------------- + +#define SBC_MAGIC_ID 0x53424323 // magic ID ("SBC#") +#define SBL_MAGIC_ID 0x53424C23 // magic ID ("SBL#") + + + +//--------------------------------------------------------------------------- +// Local types +//--------------------------------------------------------------------------- + +// structure to administrate circular shared buffer head +typedef struct +{ + unsigned long m_ShbCirMagicID; // magic ID ("SBC#") + unsigned long m_ulBufferTotalSize; // over-all size of complete buffer + unsigned long m_ulBufferDataSize; // size of complete data area + unsigned long m_ulWrIndex; // current write index (set bevore write) + unsigned long m_ulRdIndex; // current read index (set after read) + unsigned long m_ulNumOfWriteJobs; // number of currently (parallel running) write operations + unsigned long m_ulDataInUse; // currently used buffer size (incl. uncompleted write operations) + unsigned long m_ulDataApended; // buffer size of complete new written but not yet readable data (in case of m_ulNumOfWriteJobs>1) + unsigned long m_ulBlocksApended; // number of complete new written but not yet readable data blocks (in case of m_ulNumOfWriteJobs>1) + unsigned long m_ulDataReadable; // buffer size with readable (complete written) data + unsigned long m_ulBlocksReadable; // number of readable (complete written) data blocks + tShbCirSigHndlrNewData m_pfnSigHndlrNewData;// application handler to signal new data + unsigned int m_fBufferLocked; // TRUE if buffer is locked (because of pending reset request) + tShbCirSigHndlrReset m_pfnSigHndlrReset; // application handler to signal buffer reset is done + unsigned char m_Data; // start of data area (the real data size is unknown at this time) + +} tShbCirBuff; + + +// structure to administrate linear shared buffer head +typedef struct +{ + unsigned int m_ShbLinMagicID; // magic ID ("SBL#") + unsigned long m_ulBufferTotalSize; // over-all size of complete buffer + unsigned long m_ulBufferDataSize; // size of complete data area + unsigned char m_Data; // start of data area (the real data size is unknown at this time) + +} tShbLinBuff; + + +// type to save size of a single data block inside the circular shared buffer +typedef struct +{ + unsigned int m_uiFullBlockSize : 28; // a single block must not exceed a length of 256MByte :-) + unsigned int m_uiAlignFillBytes : 4; + +} tShbCirBlockSize; + +#define SBC_BLOCK_ALIGNMENT 4 // alignment must *not* be lower than sizeof(tShbCirBlockSize)! +#define SBC_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-) + +#define SBL_BLOCK_ALIGNMENT 4 +#define SBL_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-) + + + +//--------------------------------------------------------------------------- +// Global variables +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Local variables +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Prototypes of internal functions +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Get pointer to Circular Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbCirBuff* ShbCirGetBuffer ( + tShbInstance pShbInstance_p) +{ + +tShbCirBuff* pShbCirBuff; + + + pShbCirBuff = (tShbCirBuff*) ShbIpcGetShMemPtr (pShbInstance_p); + ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID); + + return (pShbCirBuff); + +} + + + +//--------------------------------------------------------------------------- +// Get pointer to Linear Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbLinBuff* ShbLinGetBuffer ( + tShbInstance pShbInstance_p) +{ + +tShbLinBuff* pShbLinBuff; + + + pShbLinBuff = (tShbLinBuff*) ShbIpcGetShMemPtr (pShbInstance_p); + ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID); + + return (pShbLinBuff); + +} + + + +// not inlined internal functions +int ShbCirSignalHandlerNewData (tShbInstance pShbInstance_p); +void ShbCirSignalHandlerReset (tShbInstance pShbInstance_p, unsigned int fTimeOut_p); + +#endif + + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +#if !defined(INLINE_ENABLED) +// not inlined external functions + +//--------------------------------------------------------------------------- +// Initialize Shared Buffer Module +//--------------------------------------------------------------------------- + +tShbError ShbInit (void) +{ + +tShbError ShbError; + + + ShbError = ShbIpcInit(); + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Deinitialize Shared Buffer Module +//--------------------------------------------------------------------------- + +tShbError ShbExit (void) +{ + +tShbError ShbError; + + + ShbError = ShbIpcExit(); + + return (ShbError); + +} + + + + + +//-------------------------------------------------------------------------// +// // +// C i r c u l a r S h a r e d B u f f e r // +// // +//-------------------------------------------------------------------------// + +//--------------------------------------------------------------------------- +// Allocate Circular Shared Buffer +//--------------------------------------------------------------------------- + +tShbError ShbCirAllocBuffer ( + unsigned long ulBufferSize_p, + const char* pszBufferID_p, + tShbInstance* ppShbInstance_p, + unsigned int* pfShbNewCreated_p) +{ + +tShbInstance pShbInstance; +tShbCirBuff* pShbCirBuff; +unsigned int fShbNewCreated; +unsigned long ulBufferDataSize; +unsigned long ulBufferTotalSize; +tShbError ShbError; + + + // check arguments + if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) + { + return (kShbInvalidArg); + } + + + // calculate length of memory to allocate + ulBufferDataSize = (ulBufferSize_p + (SBC_BLOCK_ALIGNMENT-1)) & ~(SBC_BLOCK_ALIGNMENT-1); + ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff); + + // allocate a new or open an existing shared buffer + ShbError = ShbIpcAllocBuffer (ulBufferTotalSize, pszBufferID_p, + &pShbInstance, &fShbNewCreated); + if (ShbError != kShbOk) + { + goto Exit; + } + + if (pShbInstance == NULL) + { + ShbError = kShbOutOfMem; + goto Exit; + } + + + // get pointer to shared buffer + pShbCirBuff = (tShbCirBuff*) ShbIpcGetShMemPtr (pShbInstance); + + // if the shared buffer was new created, than this process has + // to initialize it, otherwise the buffer is already in use + // and *must not* be reseted + if ( fShbNewCreated ) + { + #ifndef NDEBUG + { + memset (pShbCirBuff, 0xCC, ulBufferTotalSize); + } + #endif + + + pShbCirBuff->m_ShbCirMagicID = SBC_MAGIC_ID; + pShbCirBuff->m_ulBufferTotalSize = ulBufferTotalSize; + pShbCirBuff->m_ulBufferDataSize = ulBufferDataSize; + pShbCirBuff->m_ulWrIndex = 0; + pShbCirBuff->m_ulRdIndex = 0; + pShbCirBuff->m_ulNumOfWriteJobs = 0; + pShbCirBuff->m_ulDataInUse = 0; + pShbCirBuff->m_ulDataApended = 0; + pShbCirBuff->m_ulBlocksApended = 0; + pShbCirBuff->m_ulDataReadable = 0; + pShbCirBuff->m_ulBlocksReadable = 0; + pShbCirBuff->m_pfnSigHndlrNewData = NULL; + pShbCirBuff->m_fBufferLocked = FALSE; + pShbCirBuff->m_pfnSigHndlrReset = NULL; + } + else + { + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + } + + +Exit: + + *ppShbInstance_p = pShbInstance; + *pfShbNewCreated_p = fShbNewCreated; + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Release Circular Shared Buffer +//--------------------------------------------------------------------------- + +tShbError ShbCirReleaseBuffer ( + tShbInstance pShbInstance_p) +{ + +tShbError ShbError; + + + // check arguments + if (pShbInstance_p == NULL) + { + ShbError = kShbOk; + goto Exit; + } + + + ShbError = ShbIpcReleaseBuffer (pShbInstance_p); + + +Exit: + + return (ShbError); + +} + + +#endif // !defined(INLINE_ENABLED) + +#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// Reset Circular Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbCirResetBuffer ( + tShbInstance pShbInstance_p, + unsigned long ulTimeOut_p, + tShbCirSigHndlrReset pfnSignalHandlerReset_p) +{ + +tShbCirBuff* pShbCirBuff; +unsigned long ulNumOfWriteJobs = 0; // d.k. GCC complains about uninitialized variable otherwise +tShbError ShbError; + + + // check arguments + if (pShbInstance_p == NULL) + { + ShbError = kShbInvalidArg; + goto Exit; + } + + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + ShbError = kShbOk; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + // start reset job by setting request request in buffer header + ShbIpcEnterAtomicSection (pShbInstance_p); + { + if ( !pShbCirBuff->m_fBufferLocked ) + { + ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs; + + pShbCirBuff->m_fBufferLocked = TRUE; + pShbCirBuff->m_pfnSigHndlrReset = pfnSignalHandlerReset_p; + } + else + { + ShbError = kShbAlreadyReseting; + } + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + if (ShbError != kShbOk) + { + goto Exit; + } + + + // if there is currently no running write operation then reset buffer + // immediately, otherwise wait until the last write job is ready by + // starting a signal process + if (ulNumOfWriteJobs == 0) + { + // there is currently no running write operation + // -> reset buffer immediately + ShbCirSignalHandlerReset (pShbInstance_p, FALSE); + ShbError = kShbOk; + } + else + { + // there is currently at least one running write operation + // -> starting signal process to wait until the last write job is ready + ShbError = ShbIpcStartSignalingJobReady (pShbInstance_p, ulTimeOut_p, ShbCirSignalHandlerReset); + } + + +Exit: + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Write data block to Circular Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbCirWriteDataBlock ( + tShbInstance pShbInstance_p, + const void* pSrcDataBlock_p, + unsigned long ulDataBlockSize_p) +{ + +tShbCirBuff* pShbCirBuff; +tShbCirBlockSize ShbCirBlockSize; +unsigned int uiFullBlockSize; +unsigned int uiAlignFillBytes; +unsigned char* pShbCirDataPtr; +unsigned char* pScrDataPtr; +unsigned long ulDataSize; +unsigned long ulChunkSize; +unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise +unsigned int fSignalNewData; +unsigned int fSignalReset; +tShbError ShbError; +tShbError ShbError2; +int fRes; + + + // check arguments + if (pShbInstance_p == NULL) + { + ShbError = kShbInvalidArg; + goto Exit; + } + + if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) + { + // nothing to do here + ShbError = kShbOk; + goto Exit; + } + + if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE) + { + ShbError = kShbExceedDataSizeLimit; + goto Exit; + } + + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + pScrDataPtr = (unsigned char*)pSrcDataBlock_p; + fSignalNewData = FALSE; + fSignalReset = FALSE; + ShbError = kShbOk; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + // calculate data block size in circular buffer + ulDataSize = (ulDataBlockSize_p + (SBC_BLOCK_ALIGNMENT-1)) & ~(SBC_BLOCK_ALIGNMENT-1); + uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header + uiAlignFillBytes = ulDataSize - ulDataBlockSize_p; + + ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize; + ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes; + + + // reserve the needed memory for the write operation to do now + // and make necessary adjustments in the circular buffer header + ShbIpcEnterAtomicSection (pShbInstance_p); + { + // check if there is sufficient memory available to store + // the new data + fRes = uiFullBlockSize <= (pShbCirBuff->m_ulBufferDataSize - pShbCirBuff->m_ulDataInUse); + if ( fRes ) + { + // set write pointer for the write operation to do now + // to the current write pointer of the circular buffer + ulWrIndex = pShbCirBuff->m_ulWrIndex; + + // reserve the needed memory for the write operation to do now + pShbCirBuff->m_ulDataInUse += uiFullBlockSize; + + // set new write pointer behind the reserved memory + // for the write operation to do now + pShbCirBuff->m_ulWrIndex += uiFullBlockSize; + pShbCirBuff->m_ulWrIndex %= pShbCirBuff->m_ulBufferDataSize; + + // increment number of currently (parallel running) + // write operations + pShbCirBuff->m_ulNumOfWriteJobs++; + } + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + if ( !fRes ) + { + ShbError = kShbBufferFull; + goto Exit; + } + + + // copy the data to the circular buffer + // (the copy process itself will be done outside of any + // critical/locked section) + pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area + + // write real size of current block (incl. alignment fill bytes) + *(tShbCirBlockSize*)(pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize; + ulWrIndex += sizeof(tShbCirBlockSize); + ulWrIndex %= pShbCirBuff->m_ulBufferDataSize; + + if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize) + { + // linear write operation + memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulDataBlockSize_p); + } + else + { + // wrap-around write operation + ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex; + memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulChunkSize); + memcpy (pShbCirDataPtr, pScrDataPtr + ulChunkSize, ulDataBlockSize_p - ulChunkSize); + } + + + // adjust header information for circular buffer with properties + // of the wiritten data block + ShbIpcEnterAtomicSection (pShbInstance_p); + { + pShbCirBuff->m_ulDataApended += uiFullBlockSize; + pShbCirBuff->m_ulBlocksApended ++; + + // decrement number of currently (parallel running) write operations + if ( !--pShbCirBuff->m_ulNumOfWriteJobs ) + { + // if there is no other write process running then + // set new size of readable (complete written) data and + // adjust number of readable blocks + pShbCirBuff->m_ulDataReadable += pShbCirBuff->m_ulDataApended; + pShbCirBuff->m_ulBlocksReadable += pShbCirBuff->m_ulBlocksApended; + + pShbCirBuff->m_ulDataApended = 0; + pShbCirBuff->m_ulBlocksApended = 0; + + fSignalNewData = TRUE; + fSignalReset = pShbCirBuff->m_fBufferLocked; + } + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + // signal new data event to a potentially reading application + if ( fSignalNewData ) + { + ShbError2 = ShbIpcSignalNewData (pShbInstance_p); + if (ShbError == kShbOk) + { + ShbError = ShbError2; + } + } + + // signal that the last write job has been finished to allow + // a waiting application to reset the buffer now + if ( fSignalReset ) + { + ShbError2 = ShbIpcSignalJobReady (pShbInstance_p); + if (ShbError == kShbOk) + { + ShbError = ShbError2; + } + } + + +Exit: + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Allocate block within the Circular Shared Buffer for chunk writing +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbCirAllocDataBlock ( + tShbInstance pShbInstance_p, + tShbCirChunk* pShbCirChunk_p, + unsigned long ulDataBufferSize_p) +{ + +tShbCirBuff* pShbCirBuff; +tShbCirBlockSize ShbCirBlockSize; +unsigned int uiFullBlockSize; +unsigned int uiAlignFillBytes; +unsigned char* pShbCirDataPtr; +unsigned long ulDataSize; +unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise +tShbError ShbError; +int fRes; + + + // check arguments + if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)) + { + ShbError = kShbInvalidArg; + goto Exit; + } + + if (ulDataBufferSize_p == 0) + { + ShbError = kShbInvalidArg; + goto Exit; + } + + if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE) + { + ShbError = kShbExceedDataSizeLimit; + goto Exit; + } + + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + ShbError = kShbOk; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + // calculate data block size in circular buffer + ulDataSize = (ulDataBufferSize_p + (SBC_BLOCK_ALIGNMENT-1)) & ~(SBC_BLOCK_ALIGNMENT-1); + uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header + uiAlignFillBytes = ulDataSize - ulDataBufferSize_p; + + ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize; + ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes; + + + // reserve the needed memory for the write operation to do now + // and make necessary adjustments in the circular buffer header + ShbIpcEnterAtomicSection (pShbInstance_p); + { + // check if there is sufficient memory available to store + // the new data + fRes = (uiFullBlockSize <= (pShbCirBuff->m_ulBufferDataSize - pShbCirBuff->m_ulDataInUse)); + if ( fRes ) + { + // set write pointer for the write operation to do now + // to the current write pointer of the circular buffer + ulWrIndex = pShbCirBuff->m_ulWrIndex; + + // reserve the needed memory for the write operation to do now + pShbCirBuff->m_ulDataInUse += uiFullBlockSize; + + // set new write pointer behind the reserved memory + // for the write operation to do now + pShbCirBuff->m_ulWrIndex += uiFullBlockSize; + pShbCirBuff->m_ulWrIndex %= pShbCirBuff->m_ulBufferDataSize; + + // increment number of currently (parallel running) + // write operations + pShbCirBuff->m_ulNumOfWriteJobs++; + } + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + if ( !fRes ) + { + ShbError = kShbBufferFull; + goto Exit; + } + + + // setup header information for allocated buffer + pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area + + // write real size of current block (incl. alignment fill bytes) + *(tShbCirBlockSize*)(pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize; + ulWrIndex += sizeof(tShbCirBlockSize); + ulWrIndex %= pShbCirBuff->m_ulBufferDataSize; + + // setup chunk descriptor + pShbCirChunk_p->m_uiFullBlockSize = uiFullBlockSize; + pShbCirChunk_p->m_ulAvailableSize = ulDataBufferSize_p; + pShbCirChunk_p->m_ulWrIndex = ulWrIndex; + pShbCirChunk_p->m_fBufferCompleted = FALSE; + + +Exit: + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Write data chunk into an allocated buffer of the Circular Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbCirWriteDataChunk ( + tShbInstance pShbInstance_p, + tShbCirChunk* pShbCirChunk_p, + const void* pSrcDataChunk_p, + unsigned long ulDataChunkSize_p, + unsigned int* pfBufferCompleted_p) +{ + +tShbCirBuff* pShbCirBuff; +unsigned char* pShbCirDataPtr; +unsigned char* pScrDataPtr; +unsigned long ulSubChunkSize; +unsigned long ulWrIndex; +unsigned int fBufferCompleted; +unsigned int fSignalNewData; +unsigned int fSignalReset; +tShbError ShbError; +tShbError ShbError2; + + + // check arguments + if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL) || (pfBufferCompleted_p == NULL)) + { + ShbError = kShbInvalidArg; + goto Exit; + } + + if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0)) + { + // nothing to do here + ShbError = kShbOk; + goto Exit; + } + + if ( pShbCirChunk_p->m_fBufferCompleted ) + { + ShbError = kShbBufferAlreadyCompleted; + goto Exit; + } + + if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize) + { + ShbError = kShbExceedDataSizeLimit; + goto Exit; + } + + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + pScrDataPtr = (unsigned char*)pSrcDataChunk_p; + fSignalNewData = FALSE; + fSignalReset = FALSE; + ShbError = kShbOk; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + ulWrIndex = pShbCirChunk_p->m_ulWrIndex; + + + // copy the data to the circular buffer + // (the copy process itself will be done outside of any + // critical/locked section) + pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area + + + if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize) + { + // linear write operation + memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulDataChunkSize_p); + } + else + { + // wrap-around write operation + ulSubChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex; + memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulSubChunkSize); + memcpy (pShbCirDataPtr, pScrDataPtr + ulSubChunkSize, ulDataChunkSize_p - ulSubChunkSize); + } + + + // adjust chunk descriptor + ulWrIndex += ulDataChunkSize_p; + ulWrIndex %= pShbCirBuff->m_ulBufferDataSize; + + pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p; + pShbCirChunk_p->m_ulWrIndex = ulWrIndex; + + fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0); + pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted; + + + // if the complete allocated buffer is filled with data then + // adjust header information for circular buffer with properties + // of the wiritten data block + if ( fBufferCompleted ) + { + ShbIpcEnterAtomicSection (pShbInstance_p); + { + pShbCirBuff->m_ulDataApended += pShbCirChunk_p->m_uiFullBlockSize; + pShbCirBuff->m_ulBlocksApended ++; + + // decrement number of currently (parallel running) write operations + if ( !--pShbCirBuff->m_ulNumOfWriteJobs ) + { + // if there is no other write process running then + // set new size of readable (complete written) data and + // adjust number of readable blocks + pShbCirBuff->m_ulDataReadable += pShbCirBuff->m_ulDataApended; + pShbCirBuff->m_ulBlocksReadable += pShbCirBuff->m_ulBlocksApended; + + pShbCirBuff->m_ulDataApended = 0; + pShbCirBuff->m_ulBlocksApended = 0; + + fSignalNewData = TRUE; + fSignalReset = pShbCirBuff->m_fBufferLocked; + } + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + } + + + // signal new data event to a potentially reading application + if ( fSignalNewData ) + { + ShbError2 = ShbIpcSignalNewData (pShbInstance_p); + if (ShbError == kShbOk) + { + ShbError = ShbError2; + } + } + + // signal that the last write job has been finished to allow + // a waiting application to reset the buffer now + if ( fSignalReset ) + { + ShbError2 = ShbIpcSignalJobReady (pShbInstance_p); + if (ShbError == kShbOk) + { + ShbError = ShbError2; + } + } + + + *pfBufferCompleted_p = fBufferCompleted; + + +Exit: + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Read data block from Circular Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbCirReadDataBlock ( + tShbInstance pShbInstance_p, + void* pDstDataBlock_p, + unsigned long ulRdBuffSize_p, + unsigned long* pulDataBlockSize_p) +{ + +tShbCirBuff* pShbCirBuff; +tShbCirBlockSize ShbCirBlockSize; +unsigned long ulDataReadable; +unsigned char* pShbCirDataPtr; +unsigned char* pDstDataPtr; +unsigned long ulDataSize = 0; // d.k. GCC complains about uninitialized variable otherwise +unsigned long ulChunkSize; +unsigned long ulRdIndex; +tShbError ShbError; + + + // check arguments + if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) + { + return (kShbInvalidArg); + } + + if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0)) + { + // nothing to do here + ShbError = kShbOk; + goto Exit; + } + + + ShbError = kShbOk; + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + pDstDataPtr = (unsigned char*)pDstDataBlock_p; + ulDataSize = 0; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + // get total number of readable bytes for the whole circular buffer + ShbIpcEnterAtomicSection (pShbInstance_p); + { + ulDataReadable = pShbCirBuff->m_ulDataReadable; + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + // if there are readable data available, then there must be at least + // one complete readable data block + if (ulDataReadable > 0) + { + // get pointer to start of data area and current read index + pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area + ulRdIndex = pShbCirBuff->m_ulRdIndex; + + // get real size of current block (incl. alignment fill bytes) + ShbCirBlockSize = *(tShbCirBlockSize*)(pShbCirDataPtr + ulRdIndex); + ulRdIndex += sizeof(tShbCirBlockSize); + ulRdIndex %= pShbCirBuff->m_ulBufferDataSize; + + // get size of user data inside the current block + ulDataSize = ShbCirBlockSize.m_uiFullBlockSize - ShbCirBlockSize.m_uiAlignFillBytes; + ulDataSize -= sizeof(tShbCirBlockSize); + } + + + // ulDataSize = MIN(ulDataSize, ulRdBuffSize_p); + if (ulDataSize > ulRdBuffSize_p) + { + ulDataSize = ulRdBuffSize_p; + ShbError = kShbDataTruncated; + } + + if (ulDataSize == 0) + { + // nothing to do here + ShbError = kShbNoReadableData; + goto Exit; + } + + + // copy the data from the circular buffer + // (the copy process itself will be done outside of any + // critical/locked section) + if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) + { + // linear read operation + memcpy (pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulDataSize); + } + else + { + // wrap-around read operation + ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex; + memcpy (pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulChunkSize); + memcpy (pDstDataPtr + ulChunkSize, pShbCirDataPtr, ulDataSize - ulChunkSize); + } + + + #ifndef NDEBUG + { + tShbCirBlockSize ClrShbCirBlockSize; + + if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) + { + // linear buffer + memset (pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize); + } + else + { + // wrap-around read operation + ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex; + memset (pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize); + memset (pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize); + } + + ClrShbCirBlockSize.m_uiFullBlockSize = /*(unsigned int)*/ -1; // -1 = xFFFFFFF + ClrShbCirBlockSize.m_uiAlignFillBytes = /*(unsigned int)*/ -1; // -1 = Fxxxxxxx + *(tShbCirBlockSize*)(pShbCirDataPtr + pShbCirBuff->m_ulRdIndex) = ClrShbCirBlockSize; + } + #endif // #ifndef NDEBUG + + + // set new size of readable data, data in use, new read index + // and adjust number of readable blocks + ShbIpcEnterAtomicSection (pShbInstance_p); + { + pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize; + pShbCirBuff->m_ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize; + pShbCirBuff->m_ulBlocksReadable --; + + //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + if ((pShbCirBuff->m_ulDataInUse == 0) && (pShbCirBuff->m_ulDataReadable == 0)) + { + ASSERT(pShbCirBuff->m_ulBlocksReadable == 0); + + pShbCirBuff->m_ulWrIndex = 0; + pShbCirBuff->m_ulRdIndex = 0; + } + else + //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + { + pShbCirBuff->m_ulRdIndex += ShbCirBlockSize.m_uiFullBlockSize; + pShbCirBuff->m_ulRdIndex %= pShbCirBuff->m_ulBufferDataSize; + } + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + +Exit: + + *pulDataBlockSize_p = ulDataSize; + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Get data size of next readable block from Circular Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbCirGetReadDataSize ( + tShbInstance pShbInstance_p, + unsigned long* pulDataBlockSize_p) +{ + +tShbCirBuff* pShbCirBuff; +unsigned long ulDataReadable; +unsigned char* pShbCirDataPtr; +tShbCirBlockSize ShbCirBlockSize; +unsigned long ulDataSize; +tShbError ShbError; + + + // check arguments + if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) + { + return (kShbInvalidArg); + } + + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + ulDataSize = 0; + ShbError = kShbOk; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + // get total number of readable bytes for the whole circular buffer + ShbIpcEnterAtomicSection (pShbInstance_p); + { + ulDataReadable = pShbCirBuff->m_ulDataReadable; + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + // if there are readable data available, then there must be at least + // one complete readable data block + if (ulDataReadable > 0) + { + pShbCirDataPtr = &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex; + + // get real size of current block (incl. alignment fill bytes) + ShbCirBlockSize = *(tShbCirBlockSize*)pShbCirDataPtr; + + // get size of user data inside the current block + ulDataSize = ShbCirBlockSize.m_uiFullBlockSize - ShbCirBlockSize.m_uiAlignFillBytes; + ulDataSize -= sizeof(tShbCirBlockSize); + } + + +Exit: + + *pulDataBlockSize_p = ulDataSize; + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Get number of readable blocks from Circular Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbCirGetReadBlockCount ( + tShbInstance pShbInstance_p, + unsigned long* pulDataBlockCount_p) +{ + +tShbCirBuff* pShbCirBuff; +unsigned long ulBlockCount; +tShbError ShbError; + + + // check arguments + if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL)) + { + ShbError = kShbInvalidArg; + goto Exit; + } + + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + ulBlockCount = 0; + ShbError = kShbOk; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + ShbIpcEnterAtomicSection (pShbInstance_p); + { + ulBlockCount = pShbCirBuff->m_ulBlocksReadable; + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + *pulDataBlockCount_p = ulBlockCount; + + +Exit: + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Set application handler to signal new data for Circular Shared Buffer +// d.k.: new parameter priority as enum +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbCirSetSignalHandlerNewData ( + tShbInstance pShbInstance_p, + tShbCirSigHndlrNewData pfnSignalHandlerNewData_p, + tShbPriority ShbPriority_p) +{ + +tShbCirBuff* pShbCirBuff; +tShbError ShbError; + + + // check arguments + if (pShbInstance_p == NULL) + { + ShbError = kShbInvalidArg; + goto Exit; + } + + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + ShbError = kShbOk; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + if (pfnSignalHandlerNewData_p != NULL) + { + // set a new signal handler + if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) + { + ShbError = kShbAlreadySignaling; + goto Exit; + } + + pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p; + ShbError = ShbIpcStartSignalingNewData (pShbInstance_p, ShbCirSignalHandlerNewData, ShbPriority_p); + } + else + { + // remove existing signal handler + ShbError = ShbIpcStopSignalingNewData (pShbInstance_p); + if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) + { + pShbCirBuff->m_pfnSigHndlrNewData (pShbInstance_p, 0); + } + pShbCirBuff->m_pfnSigHndlrNewData = NULL; + } + + +Exit: + + return (ShbError); + +} + +#endif + +#if !defined(INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// DEBUG: Trace Circular Shared Buffer +//--------------------------------------------------------------------------- + +#ifndef NDEBUG +tShbError ShbCirTraceBuffer ( + tShbInstance pShbInstance_p) +{ + +tShbCirBuff* pShbCirBuff; +char szMagigID[sizeof(SBC_MAGIC_ID)+1]; +tShbCirBlockSize ShbCirBlockSize; +unsigned long ulDataReadable; +unsigned char* pShbCirDataPtr; +unsigned long ulBlockIndex; +unsigned int nBlockCount; +unsigned long ulDataSize; +unsigned long ulChunkSize; +unsigned long ulRdIndex; +tShbError ShbError; + + + TRACE0("\n\n##### Circular Shared Buffer #####\n"); + + // check arguments + if (pShbInstance_p == NULL) + { + TRACE1("\nERROR: invalid buffer address (0x%08lX)\n", (unsigned long)pShbInstance_p); + ShbError = kShbInvalidArg; + goto Exit; + } + + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + ShbError = kShbOk; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + *(unsigned long*) &szMagigID[0] = pShbCirBuff->m_ShbCirMagicID; + szMagigID[sizeof(SBC_MAGIC_ID)] = '\0'; + + + ShbIpcEnterAtomicSection (pShbInstance_p); + { + TRACE1("\nBuffer Address: 0x%08lX\n", (unsigned long)pShbCirBuff); + + TRACE0("\nHeader Info:"); + TRACE2("\nMagigID: '%s' (%08lX)", szMagigID, pShbCirBuff->m_ShbCirMagicID); + TRACE1("\nBufferTotalSize: %4lu [Bytes]", pShbCirBuff->m_ulBufferTotalSize); + TRACE1("\nBufferDataSize: %4lu [Bytes]", pShbCirBuff->m_ulBufferDataSize); + TRACE1("\nWrIndex: %4lu", pShbCirBuff->m_ulWrIndex); + TRACE1("\nRdIndex: %4lu", pShbCirBuff->m_ulRdIndex); + TRACE1("\nNumOfWriteJobs: %4lu", pShbCirBuff->m_ulNumOfWriteJobs); + TRACE1("\nDataInUse: %4lu [Bytes]", pShbCirBuff->m_ulDataInUse); + TRACE1("\nDataApended: %4lu [Bytes]", pShbCirBuff->m_ulDataApended); + TRACE1("\nBlocksApended: %4lu", pShbCirBuff->m_ulBlocksApended); + TRACE1("\nDataReadable: %4lu [Bytes]", pShbCirBuff->m_ulDataReadable); + TRACE1("\nBlocksReadable: %4lu", pShbCirBuff->m_ulBlocksReadable); + TRACE1("\nSigHndlrNewData: %08lX", (unsigned long)pShbCirBuff->m_pfnSigHndlrNewData); + TRACE1("\nBufferLocked: %d", pShbCirBuff->m_fBufferLocked); + TRACE1("\nSigHndlrReset: %08lX", (unsigned long)pShbCirBuff->m_pfnSigHndlrReset); + + ShbTraceDump (&pShbCirBuff->m_Data, pShbCirBuff->m_ulBufferDataSize, + 0x00000000L, "\nData Area:"); + + + ulDataReadable = pShbCirBuff->m_ulDataReadable; + nBlockCount = 1; + ulBlockIndex = pShbCirBuff->m_ulRdIndex; + + while (ulDataReadable > 0) + { + TRACE1("\n\n--- Block #%u ---", nBlockCount); + + // get pointer to start of data area and current read index + pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area + ulRdIndex = ulBlockIndex; + + // get real size of current block (incl. alignment fill bytes) + ShbCirBlockSize = *(tShbCirBlockSize*)(pShbCirDataPtr + ulRdIndex); + ulRdIndex += sizeof(tShbCirBlockSize); + ulRdIndex %= pShbCirBuff->m_ulBufferDataSize; + + // get size of user data inside the current block + ulDataSize = ShbCirBlockSize.m_uiFullBlockSize - ShbCirBlockSize.m_uiAlignFillBytes; + ulDataSize -= sizeof(tShbCirBlockSize); + + TRACE1("\nFull Data Size: %4u [Bytes] (incl. header and alignment fill bytes)", ShbCirBlockSize.m_uiFullBlockSize); + TRACE1("\nUser Data Size: %4lu [Bytes]", ulDataSize); + TRACE1("\nAlignment Fill Bytes: %4u [Bytes]", ShbCirBlockSize.m_uiAlignFillBytes); + + + if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) + { + // linear data buffer + ShbTraceDump (pShbCirDataPtr + ulRdIndex, ulDataSize, 0x00000000L, NULL); + } + else + { + // wrap-around data buffer + ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex; + ShbTraceDump (pShbCirDataPtr + ulRdIndex, ulChunkSize, 0x00000000L, NULL); + ShbTraceDump (pShbCirDataPtr, ulDataSize - ulChunkSize, ulChunkSize, NULL); + } + + nBlockCount++; + + ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize; + ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize; + + ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize; + } + + ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount-1); + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + +Exit: + + return (ShbError); + +} +#endif + + + + + +//-------------------------------------------------------------------------// +// // +// L i n e a r S h a r e d B u f f e r // +// // +//-------------------------------------------------------------------------// + +//--------------------------------------------------------------------------- +// Allocate Linear Shared Buffer +//--------------------------------------------------------------------------- + +tShbError ShbLinAllocBuffer ( + unsigned long ulBufferSize_p, + const char* pszBufferID_p, + tShbInstance* ppShbInstance_p, + unsigned int* pfShbNewCreated_p) +{ + +tShbInstance pShbInstance; +tShbLinBuff* pShbLinBuff; +unsigned int fShbNewCreated; +unsigned long ulBufferDataSize; +unsigned long ulBufferTotalSize; +tShbError ShbError; + + + // check arguments + if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) + { + return (kShbInvalidArg); + } + + + // calculate length of memory to allocate + ulBufferDataSize = (ulBufferSize_p + (SBL_BLOCK_ALIGNMENT-1)) & ~(SBL_BLOCK_ALIGNMENT-1); + ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff); + + // allocate a new or open an existing shared buffer + ShbError = ShbIpcAllocBuffer (ulBufferTotalSize, pszBufferID_p, + &pShbInstance, &fShbNewCreated); + if (ShbError != kShbOk) + { + goto Exit; + } + + if (pShbInstance == NULL) + { + ShbError = kShbOutOfMem; + goto Exit; + } + + + // get pointer to shared buffer + pShbLinBuff = (tShbLinBuff*) ShbIpcGetShMemPtr (pShbInstance); + + // if the shared buffer was new created, than this process has + // to initialize it, otherwise the buffer is already in use + // and *must not* be reseted + if ( fShbNewCreated ) + { + #ifndef NDEBUG + { + memset (pShbLinBuff, 0xCC, ulBufferTotalSize); + } + #endif + + + pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID; + pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize; + pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize; + } + else + { + if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + } + + +Exit: + + *ppShbInstance_p = pShbInstance; + *pfShbNewCreated_p = fShbNewCreated; + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Release Linear Shared Buffer +//--------------------------------------------------------------------------- + +tShbError ShbLinReleaseBuffer ( + tShbInstance pShbInstance_p) +{ + +tShbError ShbError; + + + // check arguments + if (pShbInstance_p == NULL) + { + ShbError = kShbOk; + goto Exit; + } + + + ShbError = ShbIpcReleaseBuffer (pShbInstance_p); + + +Exit: + + return (ShbError); + +} + + +#endif // !defined(INLINE_ENABLED) + +#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// Write data block to Linear Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbLinWriteDataBlock ( + tShbInstance pShbInstance_p, + unsigned long ulDstBufferOffs_p, + const void* pSrcDataBlock_p, + unsigned long ulDataBlockSize_p) +{ + +tShbLinBuff* pShbLinBuff; +unsigned char* pShbLinDataPtr; +unsigned char* pScrDataPtr; +unsigned long ulBufferDataSize; +tShbError ShbError; + + + // check arguments + if (pShbInstance_p == NULL) + { + ShbError = kShbInvalidArg; + goto Exit; + } + + if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) + { + // nothing to do here + ShbError = kShbOk; + goto Exit; + } + + if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) + { + ShbError = kShbExceedDataSizeLimit; + goto Exit; + } + + + pShbLinBuff = ShbLinGetBuffer (pShbInstance_p); + pScrDataPtr = (unsigned char*)pSrcDataBlock_p; + ShbError = kShbOk; + + if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + // check if offeset and size for the write operation matches with + // the size of the shared buffer + ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize; + if ( (ulDstBufferOffs_p > ulBufferDataSize) || + (ulDataBlockSize_p > ulBufferDataSize) || + ((ulDstBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize) ) + { + ShbError = kShbDataOutsideBufferArea; + goto Exit; + } + + + // copy the data to the linear buffer + // (the copy process will be done inside of any critical/locked section) + pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area + pShbLinDataPtr += ulDstBufferOffs_p; + + ShbIpcEnterAtomicSection (pShbInstance_p); + { + memcpy (pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p); + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + +Exit: + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Read data block from Linear Shared Buffer +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbLinReadDataBlock ( + tShbInstance pShbInstance_p, + void* pDstDataBlock_p, + unsigned long ulSrcBufferOffs_p, + unsigned long ulDataBlockSize_p) +{ + +tShbLinBuff* pShbLinBuff; +unsigned char* pShbLinDataPtr; +unsigned char* pDstDataPtr; +unsigned long ulBufferDataSize; +tShbError ShbError; + + + // check arguments + if (pShbInstance_p == NULL) + { + ShbError = kShbInvalidArg; + goto Exit; + } + + if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) + { + // nothing to do here + ShbError = kShbOk; + goto Exit; + } + + if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) + { + ShbError = kShbExceedDataSizeLimit; + goto Exit; + } + + + pShbLinBuff = ShbLinGetBuffer (pShbInstance_p); + pDstDataPtr = (unsigned char*)pDstDataBlock_p; + ShbError = kShbOk; + + if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + // check if offeset and size for the read operation matches with + // the size of the shared buffer + ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize; + if ( (ulSrcBufferOffs_p > ulBufferDataSize) || + (ulDataBlockSize_p > ulBufferDataSize) || + ((ulSrcBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize) ) + { + ShbError = kShbDataOutsideBufferArea; + goto Exit; + } + + + // copy the data to the linear buffer + // (the copy process will be done inside of any critical/locked section) + pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area + pShbLinDataPtr += ulSrcBufferOffs_p; + + ShbIpcEnterAtomicSection (pShbInstance_p); + { + memcpy (pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p); + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + +Exit: + + return (ShbError); + +} + +#endif + + +#if !defined(INLINE_ENABLED) + + +//--------------------------------------------------------------------------- +// DEBUG: Trace Linear Shared Buffer +//--------------------------------------------------------------------------- + +#ifndef NDEBUG +tShbError ShbLinTraceBuffer ( + tShbInstance pShbInstance_p) +{ + +tShbLinBuff* pShbLinBuff; +char szMagigID[sizeof(SBL_MAGIC_ID)+1]; +tShbError ShbError; + + + TRACE0("\n\n##### Linear Shared Buffer #####\n"); + + // check arguments + if (pShbInstance_p == NULL) + { + TRACE1("\nERROR: invalid buffer address (0x%08lX)\n", (unsigned long)pShbInstance_p); + ShbError = kShbInvalidArg; + goto Exit; + } + + + pShbLinBuff = ShbLinGetBuffer (pShbInstance_p); + ShbError = kShbOk; + + if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) + { + ShbError = kShbInvalidBufferType; + goto Exit; + } + + + *(unsigned int*) &szMagigID[0] = pShbLinBuff->m_ShbLinMagicID; + szMagigID[sizeof(SBL_MAGIC_ID)] = '\0'; + + + ShbIpcEnterAtomicSection (pShbInstance_p); + { + TRACE1("\nBuffer Address: 0x%08lX\n", (unsigned long)pShbLinBuff); + + TRACE0("\nHeader Info:"); + TRACE2("\nMagigID: '%s' (%08X)", szMagigID, pShbLinBuff->m_ShbLinMagicID); + TRACE1("\nBufferTotalSize: %4lu [Bytes]", pShbLinBuff->m_ulBufferTotalSize); + TRACE1("\nBufferDataSize: %4lu [Bytes]", pShbLinBuff->m_ulBufferDataSize); + + ShbTraceDump (&pShbLinBuff->m_Data, pShbLinBuff->m_ulBufferDataSize, + 0x00000000L, "\nData Area:"); + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + +Exit: + + return (ShbError); + +} +#endif + + + + + +//--------------------------------------------------------------------------- +// Dump buffer contents +//--------------------------------------------------------------------------- + +#ifndef NDEBUG +tShbError ShbTraceDump ( + const unsigned char* pabStartAddr_p, + unsigned long ulDataSize_p, + unsigned long ulAddrOffset_p, + const char* pszInfoText_p) +{ + +const unsigned char* pabBuffData; +unsigned long ulBuffSize; +unsigned char bData; +int nRow; +int nCol; + + + // get pointer to buffer and length of buffer + pabBuffData = pabStartAddr_p; + ulBuffSize = ulDataSize_p; + + + if (pszInfoText_p != NULL) + { + TRACE0(pszInfoText_p); + } + + // dump buffer contents + for (nRow=0; ; nRow++) + { + TRACE1("\n%08lX: ", (unsigned long)(nRow*0x10) + ulAddrOffset_p); + + for (nCol=0; nCol<16; nCol++) + { + if ((unsigned long)nCol < ulBuffSize) + { + TRACE1("%02X ", (unsigned int)*(pabBuffData+nCol)); + } + else + { + TRACE0(" "); + } + } + + TRACE0(" "); + + for (nCol=0; nCol<16; nCol++) + { + bData = *pabBuffData++; + if ((unsigned long)nCol < ulBuffSize) + { + if ((bData >= 0x20) && (bData < 0x7F)) + { + TRACE1("%c", bData); + } + else + { + TRACE0("."); + } + } + else + { + TRACE0(" "); + } + } + + if (ulBuffSize > 16) + { + ulBuffSize -= 16; + } + else + { + break; + } + } + + + return (kShbOk); + +} +#endif // #ifndef NDEBUG + + + + + + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// Handler to signal new data event for Circular Shared Buffer +//--------------------------------------------------------------------------- + +int ShbCirSignalHandlerNewData ( + tShbInstance pShbInstance_p) +{ + +tShbCirBuff* pShbCirBuff; +unsigned long ulDataSize; +unsigned long ulBlockCount; +tShbError ShbError; + + + // check arguments + if (pShbInstance_p == NULL) + { + return FALSE; + } + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + ShbError = kShbOk; + + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + return FALSE; + } + + + // call application handler + if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) + { +/* do + {*/ + ShbError = ShbCirGetReadDataSize (pShbInstance_p, &ulDataSize); + if ((ulDataSize > 0) && (ShbError == kShbOk)) + { + pShbCirBuff->m_pfnSigHndlrNewData (pShbInstance_p, ulDataSize); + } + + ShbError = ShbCirGetReadBlockCount (pShbInstance_p, &ulBlockCount); +/* } + while ((ulBlockCount > 0) && (ShbError == kShbOk));*/ + } + + // Return TRUE if there are pending blocks. + // In that case ShbIpc tries to call this function again immediately if there + // is no other filled shared buffer with higher priority. + return ((ulBlockCount > 0) && (ShbError == kShbOk)); + +} + + + +//--------------------------------------------------------------------------- +// Handler to reset Circular Shared Buffer +//--------------------------------------------------------------------------- + +void ShbCirSignalHandlerReset ( + tShbInstance pShbInstance_p, + unsigned int fTimeOut_p) +{ + +tShbCirBuff* pShbCirBuff; + + + // check arguments + if (pShbInstance_p == NULL) + { + return; + } + + pShbCirBuff = ShbCirGetBuffer (pShbInstance_p); + if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) + { + return; + } + + + // reset buffer header + if ( !fTimeOut_p ) + { + ShbIpcEnterAtomicSection (pShbInstance_p); + { + pShbCirBuff->m_ulWrIndex = 0; + pShbCirBuff->m_ulRdIndex = 0; + pShbCirBuff->m_ulNumOfWriteJobs = 0; + pShbCirBuff->m_ulDataInUse = 0; + pShbCirBuff->m_ulDataApended = 0; + pShbCirBuff->m_ulBlocksApended = 0; + pShbCirBuff->m_ulDataReadable = 0; + pShbCirBuff->m_ulBlocksReadable = 0; + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + #ifndef NDEBUG + { + memset (&pShbCirBuff->m_Data, 0xCC, pShbCirBuff->m_ulBufferDataSize); + } + #endif + } + + + // call application handler + if (pShbCirBuff->m_pfnSigHndlrReset != NULL) + { + pShbCirBuff->m_pfnSigHndlrReset (pShbInstance_p, fTimeOut_p); + } + + + // unlock buffer + ShbIpcEnterAtomicSection (pShbInstance_p); + { + pShbCirBuff->m_fBufferLocked = FALSE; + pShbCirBuff->m_pfnSigHndlrReset = NULL; + } + ShbIpcLeaveAtomicSection (pShbInstance_p); + + + return; + +} + +#endif + + +// EOF + diff --git a/drivers/staging/epl/SharedBuff.h b/drivers/staging/epl/SharedBuff.h new file mode 100644 index 0000000..9b5d2868 --- /dev/null +++ b/drivers/staging/epl/SharedBuff.h @@ -0,0 +1,183 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: Project independend shared buffer (linear + circular) + + Description: Declaration of platform independend part for the + shared buffer + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + 2006/06/27 -rs: V 1.00 (initial version) + +****************************************************************************/ + +#ifndef _SHAREDBUFF_H_ +#define _SHAREDBUFF_H_ + + + +//--------------------------------------------------------------------------- +// Type definitions +//--------------------------------------------------------------------------- + +typedef enum +{ + kShbOk = 0, + kShbNoReadableData = 1, + kShbDataTruncated = 2, + kShbBufferFull = 3, + kShbDataOutsideBufferArea = 4, + kShbBufferAlreadyCompleted = 5, + kShbMemUsedByOtherProcs = 6, + kShbOpenMismatch = 7, + kShbInvalidBufferType = 8, + kShbInvalidArg = 9, + kShbBufferInvalid = 10, + kShbOutOfMem = 11, + kShbAlreadyReseting = 12, + kShbAlreadySignaling = 13, + kShbExceedDataSizeLimit = 14, + +} tShbError; + + +// 2006/08/24 d.k.: Priority for threads (new data, job signaling) +typedef enum +{ + kShbPriorityLow = 0, + kShbPriorityNormal = 1, + kshbPriorityHigh = 2 + +} tShbPriority; + + +typedef struct +{ + unsigned int m_uiFullBlockSize; // real size of allocated block (incl. alignment fill bytes) + unsigned long m_ulAvailableSize; // still available size for data + unsigned long m_ulWrIndex; // current write index + unsigned int m_fBufferCompleted; // TRUE if allocated block is complete filled with data + +} tShbCirChunk; + + +typedef void* tShbInstance; + + +typedef void (*tShbCirSigHndlrNewData) (tShbInstance pShbInstance_p, unsigned long ulDataBlockSize_p); +typedef void (*tShbCirSigHndlrReset) (tShbInstance pShbInstance_p, unsigned int fTimeOut_p); + + + +//--------------------------------------------------------------------------- +// Prototypes +//--------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +/*#if defined(INLINE_FUNCTION_DEF) + #undef INLINE_FUNCTION + #define INLINE_FUNCTION INLINE_FUNCTION_DEF + #define INLINE_ENABLED TRUE + #define SHAREDBUFF_INLINED + #include "SharedBuff.c" +#endif +*/ + +tShbError ShbInit (void); +tShbError ShbExit (void); + +// Circular Shared Buffer +tShbError ShbCirAllocBuffer (unsigned long ulBufferSize_p, const char* pszBufferID_p, tShbInstance* ppShbInstance_p, unsigned int* pfShbNewCreated_p); +tShbError ShbCirReleaseBuffer (tShbInstance pShbInstance_p); + +#if !defined(INLINE_ENABLED) + +tShbError ShbCirResetBuffer (tShbInstance pShbInstance_p, unsigned long ulTimeOut_p, tShbCirSigHndlrReset pfnSignalHandlerReset_p); +tShbError ShbCirWriteDataBlock (tShbInstance pShbInstance_p, const void* pSrcDataBlock_p, unsigned long ulDataBlockSize_p); +tShbError ShbCirAllocDataBlock (tShbInstance pShbInstance_p, tShbCirChunk* pShbCirChunk_p, unsigned long ulDataBufferSize_p); +tShbError ShbCirWriteDataChunk (tShbInstance pShbInstance_p, tShbCirChunk* pShbCirChunk_p, const void* pSrcDataChunk_p, unsigned long ulDataChunkSize_p, unsigned int* pfBufferCompleted_p); +tShbError ShbCirReadDataBlock (tShbInstance pShbInstance_p, void* pDstDataBlock_p, unsigned long ulRdBuffSize_p, unsigned long* pulDataBlockSize_p); +tShbError ShbCirGetReadDataSize (tShbInstance pShbInstance_p, unsigned long* pulDataBlockSize_p); +tShbError ShbCirGetReadBlockCount (tShbInstance pShbInstance_p, unsigned long* pulDataBlockCount_p); +tShbError ShbCirSetSignalHandlerNewData (tShbInstance pShbInstance_p, tShbCirSigHndlrNewData pfnShbSignalHandlerNewData_p, tShbPriority ShbPriority_p); + +#endif + +// Linear Shared Buffer +tShbError ShbLinAllocBuffer (unsigned long ulBufferSize_p, const char* pszBufferID_p, tShbInstance* ppShbInstance_p, unsigned int* pfShbNewCreated_p); +tShbError ShbLinReleaseBuffer (tShbInstance pShbInstance_p); + +#if !defined(INLINE_ENABLED) + +tShbError ShbLinWriteDataBlock (tShbInstance pShbInstance_p, unsigned long ulDstBufferOffs_p, const void* pSrcDataBlock_p, unsigned long ulDataBlockSize_p); +tShbError ShbLinReadDataBlock (tShbInstance pShbInstance_p, void* pDstDataBlock_p, unsigned long ulSrcBufferOffs_p, unsigned long ulDataBlockSize_p); + +#endif + +#ifndef NDEBUG + tShbError ShbCirTraceBuffer (tShbInstance pShbInstance_p); + tShbError ShbLinTraceBuffer (tShbInstance pShbInstance_p); + tShbError ShbTraceDump (const unsigned char* pabStartAddr_p, unsigned long ulDataSize_p, unsigned long ulAddrOffset_p, const char* pszInfoText_p); +#else + #define ShbCirTraceBuffer(p0) + #define ShbLinTraceBuffer(p0) + #define ShbTraceDump(p0, p1, p2, p3) +#endif + +#undef INLINE_ENABLED // disable actual inlining of functions +#undef INLINE_FUNCTION +#define INLINE_FUNCTION // define INLINE_FUNCTION to nothing + +#ifdef __cplusplus +} +#endif + + +#endif // #ifndef _SHAREDBUFF_H_ + diff --git a/drivers/staging/epl/ShbIpc-LinuxKernel.c b/drivers/staging/epl/ShbIpc-LinuxKernel.c new file mode 100644 index 0000000..50a2f2d --- /dev/null +++ b/drivers/staging/epl/ShbIpc-LinuxKernel.c @@ -0,0 +1,1031 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: Project independend shared buffer (linear + circular) + + Description: Implementation of platform specific part for the + shared buffer + (Implementation for Linux KernelSpace) + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + 2006/06/28 -rs: V 1.00 (initial version) + +****************************************************************************/ + + +#include "global.h" +#include "SharedBuff.h" +#include "ShbIpc.h" +#include "ShbLinuxKernel.h" +#include "Debug.h" + +#include <linux/string.h> +#include <linux/module.h> +#include <asm/processor.h> +//#include <linux/vmalloc.h> +#include <linux/sched.h> +#include <linux/param.h> +#include <linux/spinlock.h> +#include <linux/wait.h> +#include <linux/completion.h> + + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// Configuration +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Constant definitions +//--------------------------------------------------------------------------- + +#define MAX_LEN_BUFFER_ID 256 + +#define TIMEOUT_ENTER_ATOMIC 1000 // (ms) for debgging: INFINITE +#define TIMEOUT_TERM_THREAD 1000 +#define INFINITE 3600 + +#define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+") +#define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*") + +#define INVALID_ID -1 + +#define TABLE_SIZE 10 + + +//--------------------------------------------------------------------------- +// Local types +//--------------------------------------------------------------------------- + +// This structure is the common header for the shared memory region used +// by all processes attached this shared memory. It includes common +// information to administrate/manage the shared buffer from a couple of +// separated processes (e.g. the refernce counter). This structure is +// located at the start of the shared memory region itself and exists +// consequently only one times per shared memory instance. +typedef struct +{ + + unsigned long m_ulShMemSize; + unsigned long m_ulRefCount; + int m_iBufferId; +// int m_iUserSpaceMem; //0 for userspace mem !=0 kernelspace mem + spinlock_t m_SpinlockBuffAccess; + BOOL m_fNewData; + BOOL m_fJobReady; + wait_queue_head_t m_WaitQueueNewData; + wait_queue_head_t m_WaitQueueJobReady; + + #ifndef NDEBUG + unsigned long m_ulOwnerProcID; + #endif + +} tShbMemHeader; + + + +// This structure is the "external entry point" from a separate process +// to get access to a shared buffer. This structure includes all platform +// resp. target specific information to administrate/manage the shared +// buffer from a separate process. Every process attached to the shared +// buffer has its own runtime instance of this structure with its individual +// runtime data (e.g. the scope of an event handle is limitted to the +// owner process only). The structure member <m_pShbMemHeader> points +// to the (process specific) start address of the shared memory region +// itself. +typedef struct +{ + unsigned long m_SbiMagicID; // magic ID ("SBI+") +// void* m_pSharedMem; + int m_tThreadNewDataId; + long m_lThreadNewDataNice; // nice value of the new data thread + int m_tThreadJobReadyId; + unsigned long m_ulFlagsBuffAccess; // d.k. moved from tShbMemHeader, because each + // process needs to store the interrupt flags separately + tSigHndlrNewData m_pfnSigHndlrNewData; + unsigned long m_ulTimeOutJobReady; + tSigHndlrJobReady m_pfnSigHndlrJobReady; + tShbMemHeader* m_pShbMemHeader; + int m_iThreadTermFlag; + struct completion m_CompletionNewData; +/* + struct semaphore *m_pSemBuffAccess; + struct semaphore *m_pSemNewData; + struct semaphore *m_pSemStopSignalingNewData; + struct semaphore *m_pSemJobReady; +*/ + #ifndef NDEBUG + unsigned long m_ulThreadIDNewData; + unsigned long m_ulThreadIDJobReady; + #endif +} tShbMemInst; + + +//--------------------------------------------------------------------------- +// Prototypes of internal functions +//--------------------------------------------------------------------------- + +//tShbMemInst* ShbIpcGetShbMemInst (tShbInstance pShbInstance_p); +//tShbMemHeader* ShbIpcGetShbMemHeader (tShbMemInst* pShbMemInst_p); + +//--------------------------------------------------------------------------- +// Get pointer to process local information structure +//--------------------------------------------------------------------------- + +static inline tShbMemInst* ShbIpcGetShbMemInst ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; + + + pShbMemInst = (tShbMemInst*)pShbInstance_p; + + + return (pShbMemInst); + +} + + + +//--------------------------------------------------------------------------- +// Get pointer to shared memory header +//--------------------------------------------------------------------------- + +static inline tShbMemHeader* ShbIpcGetShbMemHeader ( + tShbMemInst* pShbMemInst_p) +{ + +tShbMemHeader* pShbMemHeader; + + + pShbMemHeader = pShbMemInst_p->m_pShbMemHeader; + + return (pShbMemHeader); + +} + +// Get pointer to process local information structure +//#define ShbIpcGetShbMemInst(pShbInstance_p) ((tShbMemInst*)pShbInstance_p) + +// Get pointer to shared memory header +//#define ShbIpcGetShbMemHeader(pShbMemInst_p) (pShbMemInst_p->m_pShbMemHeader) + +// not inlined internal functions +int ShbIpcThreadSignalNewData (void* pvThreadParam_p); +int ShbIpcThreadSignalJobReady (void* pvThreadParam_p); +#endif + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +#if !defined(SHBIPC_INLINE_ENABLED) +struct sShbMemTable *psMemTableElementFirst_g; + +static void* ShbIpcAllocPrivateMem (unsigned long ulMemSize_p); +static int ShbIpcFindListElement (int iBufferId, struct sShbMemTable **ppsReturnMemTableElement); +static void ShbIpcAppendListElement (struct sShbMemTable *sNewMemTableElement); +static void ShbIpcDeleteListElement (int iBufferId); +static void ShbIpcCrc32GenTable (unsigned long aulCrcTable[256]); +static unsigned long ShbIpcCrc32GetCrc (const char *pcString, unsigned long aulCrcTable[256]); + +#endif + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +#if !defined(SHBIPC_INLINE_ENABLED) +// not inlined external functions + +//--------------------------------------------------------------------------- +// Initialize IPC for Shared Buffer Module +//--------------------------------------------------------------------------- + +tShbError ShbIpcInit (void) +{ + psMemTableElementFirst_g = NULL; + return (kShbOk); + +} + + + +//--------------------------------------------------------------------------- +// Deinitialize IPC for Shared Buffer Module +//--------------------------------------------------------------------------- + +tShbError ShbIpcExit (void) +{ + + return (kShbOk); + +} + + + +//--------------------------------------------------------------------------- +// Allocate Shared Buffer +//--------------------------------------------------------------------------- + +tShbError ShbIpcAllocBuffer ( + unsigned long ulBufferSize_p, + const char* pszBufferID_p, + tShbInstance* ppShbInstance_p, + unsigned int* pfShbNewCreated_p) +{ +tShbError ShbError; +int iBufferId=0; +unsigned long ulCrc32=0; +unsigned int uiFirstProcess=0; +unsigned long ulShMemSize; +tShbMemHeader* pShbMemHeader; +tShbMemInst* pShbMemInst=NULL; +tShbInstance pShbInstance; +unsigned int fShMemNewCreated=FALSE; +void *pSharedMem=NULL; +unsigned long aulCrcTable[256]; +struct sShbMemTable *psMemTableElement; + + + DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n"); + ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader); + + //create Buffer ID + ShbIpcCrc32GenTable(aulCrcTable); + ulCrc32=ShbIpcCrc32GetCrc(pszBufferID_p,aulCrcTable); + iBufferId=ulCrc32; + DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferSize:%d sizeof(tShb..):%d\n",ulBufferSize_p,sizeof(tShbMemHeader)); + DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferId:%d MemSize:%d\n",iBufferId,ulShMemSize); + //--------------------------------------------------------------- + // (1) open an existing or create a new shared memory + //--------------------------------------------------------------- + //test if buffer already exists + if (ShbIpcFindListElement(iBufferId, &psMemTableElement) == 0) + { + //Buffer already exists + fShMemNewCreated=FALSE; + pSharedMem = psMemTableElement->m_pBuffer; + DEBUG_LVL_29_TRACE1("ShbIpcAllocBuffer attach Buffer at:%p Id:%d\n",pSharedMem); + uiFirstProcess=1; + } + else + { + //create new Buffer + fShMemNewCreated = TRUE; + uiFirstProcess=0; + pSharedMem = kmalloc(ulShMemSize,GFP_KERNEL); + DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer Create New Buffer at:%p Id:%d\n",pSharedMem,iBufferId); + if (pSharedMem == NULL) + { + //unable to create mem + ShbError = kShbOutOfMem; + goto Exit; + } + DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer create semas\n"); + // append Element to Mem Table + psMemTableElement = kmalloc(sizeof(struct sShbMemTable),GFP_KERNEL); + psMemTableElement->m_iBufferId = iBufferId; + psMemTableElement->m_pBuffer = pSharedMem; + psMemTableElement->m_psNextMemTableElement = NULL; + ShbIpcAppendListElement (psMemTableElement); + } + + DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer update header\n"); + //update header + pShbMemHeader = (tShbMemHeader*)pSharedMem; + DEBUG_LVL_29_TRACE1("ShbIpcAllocBuffer 0 pShbMemHeader->m_ulShMemSize: %d\n",pShbMemHeader->m_ulShMemSize); + // allocate a memory block from process specific mempool to save + // process local information to administrate/manage the shared buffer + DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer alloc private mem\n"); + pShbMemInst = (tShbMemInst*) ShbIpcAllocPrivateMem (sizeof(tShbMemInst)); + if (pShbMemInst == NULL) + { + ShbError = kShbOutOfMem; + goto Exit; + } + + // reset complete header to default values + //pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID; +// pShbMemInst->m_pSharedMem = pSharedMem; + pShbMemInst->m_tThreadNewDataId = INVALID_ID; + pShbMemInst->m_tThreadJobReadyId = INVALID_ID; + pShbMemInst->m_pfnSigHndlrNewData = NULL; + pShbMemInst->m_ulTimeOutJobReady = 0; + pShbMemInst->m_pfnSigHndlrJobReady = NULL; + pShbMemInst->m_pShbMemHeader = pShbMemHeader; + pShbMemInst->m_iThreadTermFlag = 0; + + // initialize completion etc. + init_completion(&pShbMemInst->m_CompletionNewData); + + ShbError = kShbOk; + if ( fShMemNewCreated ) + { + // this process was the first who wanted to use the shared memory, + // so a new shared memory was created + // -> setup new header information inside the shared memory region + // itself + pShbMemHeader->m_ulShMemSize = ulShMemSize; + pShbMemHeader->m_ulRefCount = 1; + pShbMemHeader->m_iBufferId=iBufferId; + // initialize spinlock + spin_lock_init(&pShbMemHeader->m_SpinlockBuffAccess); + // initialize wait queues + init_waitqueue_head(&pShbMemHeader->m_WaitQueueNewData); + init_waitqueue_head(&pShbMemHeader->m_WaitQueueJobReady); + } + else + { + // any other process has created the shared memory and this + // process only has to attach to it + // -> check and update existing header information inside the + // shared memory region itself + if (pShbMemHeader->m_ulShMemSize != ulShMemSize) + { + ShbError = kShbOpenMismatch; + goto Exit; + } + pShbMemHeader->m_ulRefCount++; + } + + Exit: + pShbInstance = (tShbInstance*)pShbMemInst; + *pfShbNewCreated_p = fShMemNewCreated; + *ppShbInstance_p = pShbInstance; + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Release Shared Buffer +//--------------------------------------------------------------------------- + +tShbError ShbIpcReleaseBuffer (tShbInstance pShbInstance_p) +{ +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +tShbError ShbError; +tShbError ShbError2; + + DEBUG_LVL_26_TRACE1("ShbIpcReleaseBuffer(%p)\n", pShbInstance_p); + if (pShbInstance_p == NULL) + { + return (kShbOk); + } + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); + + // stop threads in any case, because they are bound to that specific instance + ShbError2 = ShbIpcStopSignalingNewData (pShbInstance_p); + // d.k.: Whats up with JobReady thread? + // Just wake it up, but without setting the semaphore variable + wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady); + + if ( !--pShbMemHeader->m_ulRefCount ) + { + ShbError = kShbOk; + // delete mem table element + ShbIpcDeleteListElement(pShbMemHeader->m_iBufferId); + // delete shared mem + kfree(pShbMemInst->m_pShbMemHeader); + } + else + { + ShbError = kShbMemUsedByOtherProcs; + } + //delete privat mem + kfree(pShbMemInst); + return (ShbError); +} + + +#endif // !defined(SHBIPC_INLINE_ENABLED) + +#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) + + +//--------------------------------------------------------------------------- +// Enter atomic section for Shared Buffer access +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +tShbError ShbError = kShbOk; + + if (pShbInstance_p == NULL) + { + ShbError = kShbInvalidArg; + goto Exit; + } + DEBUG_LVL_29_TRACE0("enter atomic\n"); + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); + + // lock interrupts + spin_lock_irqsave(&pShbMemHeader->m_SpinlockBuffAccess, pShbMemInst->m_ulFlagsBuffAccess); + +Exit: + return ShbError; + +} + + + +//--------------------------------------------------------------------------- +// Leave atomic section for Shared Buffer access +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +tShbError ShbError = kShbOk; + + if (pShbInstance_p == NULL) + { + ShbError = kShbInvalidArg; + goto Exit; + } + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); + // unlock interrupts + spin_unlock_irqrestore(&pShbMemHeader->m_SpinlockBuffAccess, pShbMemInst->m_ulFlagsBuffAccess); + +Exit: + DEBUG_LVL_29_TRACE0("Leave Atomic \n"); + return ShbError; + +} + + + +//--------------------------------------------------------------------------- +// Start signaling of new data (called from reading process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData ( + tShbInstance pShbInstance_p, + tSigHndlrNewData pfnSignalHandlerNewData_p, + tShbPriority ShbPriority_p) +{ +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +tShbError ShbError; + + DEBUG_LVL_29_TRACE0("------->ShbIpcStartSignalingNewData\n"); + if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) + { + return (kShbInvalidArg); + } + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); + ShbError = kShbOk; + + if ((pShbMemInst->m_tThreadNewDataId != INVALID_ID) + || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) + { + ShbError = kShbAlreadySignaling; + goto Exit; + } + DEBUG_LVL_26_TRACE2("ShbIpcStartSignalingNewData(%p) m_pfnSigHndlrNewData = %p\n", pShbInstance_p, pfnSignalHandlerNewData_p); + pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p; + pShbMemHeader->m_fNewData = FALSE; + pShbMemInst->m_iThreadTermFlag = 0; + + switch (ShbPriority_p) + { + case kShbPriorityLow: + pShbMemInst->m_lThreadNewDataNice = -2; + break; + + case kShbPriorityNormal: + pShbMemInst->m_lThreadNewDataNice = -9; + break; + + case kshbPriorityHigh: + pShbMemInst->m_lThreadNewDataNice = -20; + break; + + } + + //create thread for signalling new data + pShbMemInst->m_tThreadNewDataId = kernel_thread(ShbIpcThreadSignalNewData,pShbInstance_p,CLONE_KERNEL); + +Exit: + return ShbError; + +} + + + +//--------------------------------------------------------------------------- +// Stop signaling of new data (called from reading process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData ( + tShbInstance pShbInstance_p) +{ +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +tShbError ShbError; + + DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n"); + if (pShbInstance_p == NULL) + { + return (kShbInvalidArg); + } + ShbError = kShbOk; + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); + + DEBUG_LVL_26_TRACE2("ShbIpcStopSignalingNewData(%p) pfnSignHndlrNewData=%p\n", pShbInstance_p, pShbMemInst->m_pfnSigHndlrNewData); + if (pShbMemInst->m_pfnSigHndlrNewData != NULL) + { // signal handler was set before + int iErr; + //set termination flag in mem header + pShbMemInst->m_iThreadTermFlag = 1; + + // check if thread is still running at all by sending the null-signal to this thread + /* iErr = kill_proc(pShbMemInst->m_tThreadNewDataId, 0, 1); */ + iErr = send_sig(0, pShbMemInst->m_tThreadNewDataId, 1); + if (iErr == 0) + { + // wake up thread, because it is still running + wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData); + + //wait for termination of thread + wait_for_completion(&pShbMemInst->m_CompletionNewData); + } + + pShbMemInst->m_pfnSigHndlrNewData = NULL; + pShbMemInst->m_tThreadNewDataId = INVALID_ID; + } + + return ShbError; + +} + + + +//--------------------------------------------------------------------------- +// Signal new data (called from writing process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcSignalNewData ( + tShbInstance pShbInstance_p) +{ +tShbMemHeader* pShbMemHeader; + + if (pShbInstance_p == NULL) + { + return (kShbInvalidArg); + } + pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p)); + //set semaphore + pShbMemHeader->m_fNewData = TRUE; + DEBUG_LVL_29_TRACE0("ShbIpcSignalNewData set Sem -> New Data\n"); + + wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData); + return (kShbOk); +} + + + +//--------------------------------------------------------------------------- +// Start signaling for job ready (called from waiting process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady ( + tShbInstance pShbInstance_p, + unsigned long ulTimeOut_p, + tSigHndlrJobReady pfnSignalHandlerJobReady_p) +{ +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +tShbError ShbError; + + if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) + { + return (kShbInvalidArg); + } + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); + + ShbError = kShbOk; + if ((pShbMemInst->m_tThreadJobReadyId != INVALID_ID)||(pShbMemInst->m_pfnSigHndlrJobReady!= NULL)) + { + ShbError = kShbAlreadySignaling; + goto Exit; + } + pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p; + pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p; + pShbMemHeader->m_fJobReady = FALSE; + //create thread for signalling new data + pShbMemInst->m_tThreadJobReadyId=kernel_thread(ShbIpcThreadSignalJobReady,pShbInstance_p,CLONE_KERNEL); + Exit: + return ShbError; +} + + + +//--------------------------------------------------------------------------- +// Signal job ready (called from executing process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcSignalJobReady ( + tShbInstance pShbInstance_p) +{ +tShbMemHeader* pShbMemHeader; + + + DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady\n"); + if (pShbInstance_p == NULL) + { + return (kShbInvalidArg); + } + pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p)); + //set semaphore + pShbMemHeader->m_fJobReady = TRUE; + DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady set Sem -> Job Ready \n"); + + wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady); + return (kShbOk); +} + + + +//--------------------------------------------------------------------------- +// Get pointer to common used share memory area +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void* ShbIpcGetShMemPtr (tShbInstance pShbInstance_p) +{ + +tShbMemHeader* pShbMemHeader; +void* pShbShMemPtr; + + + pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p)); + if (pShbMemHeader != NULL) + { + pShbShMemPtr = (BYTE*)pShbMemHeader + sizeof(tShbMemHeader); + } + else + { + pShbShMemPtr = NULL; + } + + return (pShbShMemPtr); + +} + +#endif + + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +#if !defined(SHBIPC_INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// Get pointer to process local information structure +//--------------------------------------------------------------------------- + +/*tShbMemInst* ShbIpcGetShbMemInst ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; + + + pShbMemInst = (tShbMemInst*)pShbInstance_p; + + + return (pShbMemInst); + +} +*/ + + +//--------------------------------------------------------------------------- +// Get pointer to shared memory header +//--------------------------------------------------------------------------- + +/*tShbMemHeader* ShbIpcGetShbMemHeader ( + tShbMemInst* pShbMemInst_p) +{ + +tShbMemHeader* pShbMemHeader; + + + pShbMemHeader = pShbMemInst_p->m_pShbMemHeader; + + return (pShbMemHeader); + +} +*/ + + +//--------------------------------------------------------------------------- +// Allocate a memory block from process specific mempool +//--------------------------------------------------------------------------- + +static void* ShbIpcAllocPrivateMem (unsigned long ulMemSize_p) +{ +tShbError ShbError; +void* pMem; + + DEBUG_LVL_29_TRACE0("ShbIpcAllocPrivateMem \n"); + //get private mem + pMem = kmalloc(ulMemSize_p, GFP_KERNEL); + if (pMem == NULL) + { + //unable to create mem + ShbError = kShbOutOfMem; + goto Exit; + } +Exit: + return (pMem); + +} + + +//--------------------------------------------------------------------------- +// Thread for new data signaling +//--------------------------------------------------------------------------- + +int ShbIpcThreadSignalNewData (void *pvThreadParam_p) +{ +tShbInstance pShbInstance; +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +int iRetVal=-1; +int fCallAgain; + + daemonize("ShbND%p", pvThreadParam_p); + allow_signal(SIGTERM); + pShbInstance = (tShbMemInst*)pvThreadParam_p; + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); + + DEBUG_LVL_26_TRACE1("ShbIpcThreadSignalNewData(%p)\n",pvThreadParam_p); + + set_user_nice(current, pShbMemInst->m_lThreadNewDataNice); + +// DEBUG_LVL_29_TRACE1("ShbIpcThreadSignalNewData wait for New Data Sem %p\n",pShbMemInst->m_pSemNewData); + do + { + iRetVal = wait_event_interruptible(pShbMemHeader->m_WaitQueueNewData, + (pShbMemInst->m_iThreadTermFlag != 0) || (pShbMemHeader->m_fNewData != FALSE)); + + if (iRetVal != 0) + { // signal pending + break; + } + + if (pShbMemHeader->m_fNewData != FALSE) + { + pShbMemHeader->m_fNewData = FALSE; + do + { + fCallAgain = pShbMemInst->m_pfnSigHndlrNewData(pShbInstance); + // call scheduler, which will execute any task with higher priority + schedule(); + } while (fCallAgain != FALSE); + } + } while (pShbMemInst->m_iThreadTermFlag==0); + DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalNewData terminated \n"); + //set thread completed + complete_and_exit(&pShbMemInst->m_CompletionNewData, 0); + return 0; +} + + + +//--------------------------------------------------------------------------- +// Thread for new data Job Ready signaling +//--------------------------------------------------------------------------- + +int ShbIpcThreadSignalJobReady (void *pvThreadParam_p) +{ +tShbInstance pShbInstance; +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +long lTimeOut; +int iRetVal=-1; + + daemonize("ShbJR%p", pvThreadParam_p); + allow_signal(SIGTERM); + pShbInstance = (tShbMemInst*)pvThreadParam_p; + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); + + DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalJobReady wait for job ready Sem\n"); + if (pShbMemInst->m_ulTimeOutJobReady != 0) + { + lTimeOut = (long) pShbMemInst->m_ulTimeOutJobReady; + //wait for job ready semaphore + iRetVal = wait_event_interruptible_timeout(pShbMemHeader->m_WaitQueueJobReady, + (pShbMemHeader->m_fJobReady != FALSE), lTimeOut); + } + else + { + //wait for job ready semaphore + iRetVal = wait_event_interruptible(pShbMemHeader->m_WaitQueueJobReady, + (pShbMemHeader->m_fJobReady != FALSE)); + } + + if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) + { + //call Handler + pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, !pShbMemHeader->m_fJobReady); + } + + pShbMemInst->m_pfnSigHndlrJobReady=NULL; + return 0; +} + + + +//Build the crc table +static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256]) +{ + unsigned long ulCrc,ulPoly; + int iIndexI,iIndexJ; + + ulPoly = 0xEDB88320L; + for (iIndexI = 0; iIndexI < 256; iIndexI++) + { + ulCrc = iIndexI; + for (iIndexJ = 8; iIndexJ > 0; iIndexJ--) + { + if (ulCrc & 1) + { + ulCrc = (ulCrc >> 1) ^ ulPoly; + } + else + { + ulCrc >>= 1; + } + } + aulCrcTable[iIndexI] = ulCrc; + } +} + +//Calculate the crc value +static unsigned long ShbIpcCrc32GetCrc(const char *pcString,unsigned long aulCrcTable[256]) +{ + unsigned long ulCrc; + int iIndex; + + ulCrc = 0xFFFFFFFF; + for (iIndex=0;iIndex<strlen(pcString);iIndex++) + { + ulCrc = ((ulCrc>>8) & 0x00FFFFFF) ^ aulCrcTable[ (ulCrc^pcString[iIndex]) & 0xFF ]; + } + return( ulCrc^0xFFFFFFFF ); + +} + +static void ShbIpcAppendListElement (struct sShbMemTable *psNewMemTableElement) +{ + struct sShbMemTable *psMemTableElement=psMemTableElementFirst_g; + psNewMemTableElement->m_psNextMemTableElement=NULL; + + if (psMemTableElementFirst_g!= NULL ) + { /* sind Elemente vorhanden */ + while (psMemTableElement->m_psNextMemTableElement != NULL ) + { /* suche das letzte Element */ + psMemTableElement=psMemTableElement->m_psNextMemTableElement; + } + psMemTableElement->m_psNextMemTableElement=psNewMemTableElement; /* Haenge das Element hinten an */ + } + else + { /* wenn die liste leer ist, bin ich das erste Element */ + psMemTableElementFirst_g=psNewMemTableElement; + } +} + + + + +static int ShbIpcFindListElement (int iBufferId, struct sShbMemTable **ppsReturnMemTableElement) +{ + struct sShbMemTable *psMemTableElement=psMemTableElementFirst_g; + while (psMemTableElement!=NULL) + { + if(psMemTableElement->m_iBufferId==iBufferId) + { +//printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",psMemTableElement->m_pBuffer,psMemTableElement->m_iBufferId); + *ppsReturnMemTableElement=psMemTableElement; +//printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",(*ppsReturnMemTableElement)->m_pBuffer,(*ppsReturnMemTableElement)->m_iBufferId); + return 0; + } + psMemTableElement=psMemTableElement->m_psNextMemTableElement; + } + return -1; +} + +static void ShbIpcDeleteListElement(int iBufferId) +{ + struct sShbMemTable *psMemTableElement=psMemTableElementFirst_g; + struct sShbMemTable *psMemTableElementOld=psMemTableElementFirst_g; + if (psMemTableElement!=NULL) + { + while((psMemTableElement!=NULL)&&(psMemTableElement->m_iBufferId!=iBufferId)) + { + psMemTableElementOld=psMemTableElement; + psMemTableElement=psMemTableElement->m_psNextMemTableElement; + } + if (psMemTableElement!=NULL) + { + if (psMemTableElement!=psMemTableElementFirst_g) + { + psMemTableElementOld->m_psNextMemTableElement=psMemTableElement->m_psNextMemTableElement; + kfree(psMemTableElement); + } + else + { + kfree(psMemTableElement); + psMemTableElementFirst_g=NULL; + } + + } + } + +} + +#endif diff --git a/drivers/staging/epl/ShbIpc-Win32.c b/drivers/staging/epl/ShbIpc-Win32.c new file mode 100644 index 0000000..a528266 --- /dev/null +++ b/drivers/staging/epl/ShbIpc-Win32.c @@ -0,0 +1,1328 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: Project independend shared buffer (linear + circular) + + Description: Implementation of platform specific part for the + shared buffer + (Implementation for Win32) + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + 2006/06/27 -rs: V 1.00 (initial version) + +****************************************************************************/ + +#define WINVER 0x0400 // #defines necessary for usage of +#define _WIN32_WINNT 0x0400 // function <SignalObjectAndWait> + +#include <windows.h> +#include <stdio.h> +#include "global.h" +#include "sharedbuff.h" +#include "shbipc.h" + + + + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// Configuration +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Constant definitions +//--------------------------------------------------------------------------- + +#define MAX_LEN_BUFFER_ID MAX_PATH + +#define IDX_EVENT_NEW_DATA 0 +#define IDX_EVENT_TERM_REQU 1 +#define IDX_EVENT_TERM_RESP 2 + +#define NAME_MUTEX_BUFF_ACCESS "BuffAccess" +#define NAME_EVENT_NEW_DATA "NewData" +#define NAME_EVENT_TERM_REQU "TermRequ" +#define NAME_EVENT_TERM_RESP "TermResp" +#define NAME_EVENT_JOB_READY "JobReady" + +#define TIMEOUT_ENTER_ATOMIC 1000 // for debgging: INFINITE +#define TIMEOUT_TERM_THREAD 2000 + +#define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+") +#define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*") + + + +//--------------------------------------------------------------------------- +// Local types +//--------------------------------------------------------------------------- + +// This structure is the common header for the shared memory region used +// by all processes attached this shared memory. It includes common +// information to administrate/manage the shared buffer from a couple of +// separated processes (e.g. the refernce counter). This structure is +// located at the start of the shared memory region itself and exists +// consequently only one times per shared memory instance. +typedef struct +{ + unsigned long m_SbhMagicID; // magic ID ("SBH*") + unsigned long m_ulShMemSize; + unsigned long m_ulRefCount; + char m_szBufferID[MAX_LEN_BUFFER_ID]; + + #ifndef NDEBUG + unsigned long m_ulOwnerProcID; + #endif + +} tShbMemHeader; + + +// This structure is the "external entry point" from a separate process +// to get access to a shared buffer. This structure includes all platform +// resp. target specific information to administrate/manage the shared +// buffer from a separate process. Every process attached to the shared +// buffer has its own runtime instance of this structure with its individual +// runtime data (e.g. the scope of an event handle is limitted to the +// owner process only). The structure member <m_pShbMemHeader> points +// to the (process specific) start address of the shared memory region +// itself. +typedef struct +{ + unsigned long m_SbiMagicID; // magic ID ("SBI+") + HANDLE m_hSharedMem; + HANDLE m_hMutexBuffAccess; + HANDLE m_hThreadNewData; // thraed to signal that new data are available + HANDLE m_ahEventNewData[3]; // IDX_EVENT_NEW_DATA + IDX_EVENT_TERM_REQU + ID_EVENT_TERM_RESP + tSigHndlrNewData m_pfnSigHndlrNewData; + HANDLE m_hThreadJobReady; // thread to signal that a job/operation is ready now (e.g. reset buffer) + HANDLE m_hEventJobReady; + unsigned long m_ulTimeOutJobReady; + tSigHndlrJobReady m_pfnSigHndlrJobReady; + tShbMemHeader* m_pShbMemHeader; + + #ifndef NDEBUG + unsigned long m_ulThreadIDNewData; + unsigned long m_ulThreadIDJobReady; + #endif + +} tShbMemInst; + + + +//--------------------------------------------------------------------------- +// Global variables +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Local variables +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Prototypes of internal functions +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Get pointer to process local information structure +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbMemInst* ShbIpcGetShbMemInst ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; + + + pShbMemInst = (tShbMemInst*)pShbInstance_p; + ASSERT (pShbMemInst->m_SbiMagicID == SBI_MAGIC_ID); + + return (pShbMemInst); + +} + + + +//--------------------------------------------------------------------------- +// Get pointer to shared memory header +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbMemHeader* ShbIpcGetShbMemHeader ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; + + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = pShbMemInst->m_pShbMemHeader; + ASSERT(pShbMemHeader->m_SbhMagicID == SBH_MAGIC_ID); + + return (pShbMemHeader); + +} + + +// not inlined internal functions +DWORD WINAPI ShbIpcThreadSignalNewData (LPVOID pvThreadParam_p); +DWORD WINAPI ShbIpcThreadSignalJobReady (LPVOID pvThreadParam_p); +const char* ShbIpcGetUniformObjectName (const char* pszEventJobName_p, const char* pszBufferID_p, BOOL fGlobalObject_p); + +#endif + +#if !defined(SHBIPC_INLINE_ENABLED) +// true internal functions (not inlined) +static void* ShbIpcAllocPrivateMem (unsigned long ulMemSize_p); +static void ShbIpcReleasePrivateMem (void* pMem_p); +#endif + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +#if !defined(SHBIPC_INLINE_ENABLED) +// not inlined external functions + +//--------------------------------------------------------------------------- +// Initialize IPC for Shared Buffer Module +//--------------------------------------------------------------------------- + +tShbError ShbIpcInit (void) +{ + + return (kShbOk); + +} + + + +//--------------------------------------------------------------------------- +// Deinitialize IPC for Shared Buffer Module +//--------------------------------------------------------------------------- + +tShbError ShbIpcExit (void) +{ + + return (kShbOk); + +} + + + +//--------------------------------------------------------------------------- +// Allocate Shared Buffer +//--------------------------------------------------------------------------- + +tShbError ShbIpcAllocBuffer ( + unsigned long ulBufferSize_p, + const char* pszBufferID_p, + tShbInstance* ppShbInstance_p, + unsigned int* pfShbNewCreated_p) +{ + +HANDLE hSharedMem; +LPVOID pSharedMem; +unsigned long ulShMemSize; +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +tShbInstance pShbInstance; +unsigned int fShMemNewCreated; +const char* pszObjectName; +HANDLE hMutexBuffAccess; +HANDLE hEventNewData; +HANDLE hEventJobReady; +tShbError ShbError; + + + ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader); + pSharedMem = NULL; + pShbInstance = NULL; + fShMemNewCreated = FALSE; + ShbError = kShbOk; + + + //--------------------------------------------------------------- + // (1) open an existing or create a new shared memory + //--------------------------------------------------------------- + // try to open an already existing shared memory + // (created by an another process) + hSharedMem = OpenFileMapping (FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess + FALSE, // BOOL bInheritHandle + pszBufferID_p); // LPCTSTR lpName + if (hSharedMem != NULL) + { + // a shared memory already exists + fShMemNewCreated = FALSE; + } + else + { + // it seams that this process is the first who wants to use the + // shared memory, so it has to create a new shared memory + hSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE,// HANDLE hFile + NULL, // LPSECURITY_ATTRIBUTES lpAttributes + PAGE_READWRITE, // DWORD flProtect + 0, // DWORD dwMaximumSizeHigh + ulShMemSize, // DWORD dwMaximumSizeLow + pszBufferID_p); // LPCTSTR lpName + + fShMemNewCreated = TRUE; + } + + if (hSharedMem == NULL) + { + ShbError = kShbOutOfMem; + goto Exit; + } + + + //--------------------------------------------------------------- + // (2) get the pointer to the shared memory + //--------------------------------------------------------------- + pSharedMem = MapViewOfFile (hSharedMem, // HANDLE hFileMappingObject + FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess, + 0, // DWORD dwFileOffsetHigh, + 0, // DWORD dwFileOffsetLow, + ulShMemSize); // SIZE_T dwNumberOfBytesToMap + + if (pSharedMem == NULL) + { + ShbError = kShbOutOfMem; + goto Exit; + } + + + //--------------------------------------------------------------- + // (3) setup or update header and management information + //--------------------------------------------------------------- + pShbMemHeader = (tShbMemHeader*)pSharedMem; + + // allocate a memory block from process specific mempool to save + // process local information to administrate/manage the shared buffer + pShbMemInst = (tShbMemInst*) ShbIpcAllocPrivateMem (sizeof(tShbMemInst)); + if (pShbMemInst == NULL) + { + ShbError = kShbOutOfMem; + goto Exit; + } + + // reset complete header to default values + pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID; + pShbMemInst->m_hSharedMem = hSharedMem; + pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE; + pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE; + pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = INVALID_HANDLE_VALUE; + pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = INVALID_HANDLE_VALUE; + pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = INVALID_HANDLE_VALUE; + pShbMemInst->m_pfnSigHndlrNewData = NULL; + pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE; + pShbMemInst->m_hEventJobReady = INVALID_HANDLE_VALUE; + pShbMemInst->m_ulTimeOutJobReady = 0; + pShbMemInst->m_pfnSigHndlrJobReady = NULL; + pShbMemInst->m_pShbMemHeader = pShbMemHeader; + + #ifndef NDEBUG + { + pShbMemInst->m_ulThreadIDNewData = 0; + pShbMemInst->m_ulThreadIDJobReady = 0; + } + #endif + + // create mutex for buffer access + pszObjectName = ShbIpcGetUniformObjectName (NAME_MUTEX_BUFF_ACCESS, pszBufferID_p, TRUE); + hMutexBuffAccess = CreateMutex (NULL, // LPSECURITY_ATTRIBUTES lpMutexAttributes + FALSE, // BOOL bInitialOwner + pszObjectName); // LPCTSTR lpName + pShbMemInst->m_hMutexBuffAccess = hMutexBuffAccess; + ASSERT(pShbMemInst->m_hMutexBuffAccess != NULL); + + // The EventNewData is used for signaling of new data after a write + // operation (SetEvent) as well as for waiting for new data on the + // reader side (WaitForMultipleObjects). Because it's not known if + // this process will be read or write data, the event will be + // always created here. + pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_NEW_DATA, pszBufferID_p, TRUE); + hEventNewData = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes + FALSE, // BOOL bManualReset + FALSE, // BOOL bInitialState + pszObjectName); // LPCTSTR lpName + pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = hEventNewData; + ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != NULL); + + // The EventJobReady is used for signaling that a job is done (SetEvent) + // as well as for waiting for finishing of a job (WaitForMultipleObjects). + // Because it's not known if this process will signal or wait, the event + // will be always created here. + pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_JOB_READY, pszBufferID_p, TRUE); + hEventJobReady = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes + FALSE, // BOOL bManualReset + FALSE, // BOOL bInitialState + pszObjectName); // LPCTSTR lpName + pShbMemInst->m_hEventJobReady = hEventJobReady; + ASSERT(pShbMemInst->m_hEventJobReady != NULL); + + if ( fShMemNewCreated ) + { + // this process was the first who wanted to use the shared memory, + // so a new shared memory was created + // -> setup new header information inside the shared memory region + // itself + pShbMemHeader->m_SbhMagicID = SBH_MAGIC_ID; + pShbMemHeader->m_ulShMemSize = ulShMemSize; + pShbMemHeader->m_ulRefCount = 1; + strncpy (pShbMemHeader->m_szBufferID, pszBufferID_p, sizeof(pShbMemHeader->m_szBufferID)-1); + + #ifndef NDEBUG + { + pShbMemHeader->m_ulOwnerProcID = GetCurrentProcessId(); + } + #endif + } + else + { + // any other process has created the shared memory and this + // process has only attached to it + // -> check and update existing header information inside the + // shared memory region itself + if (pShbMemHeader->m_ulShMemSize != ulShMemSize) + { + ShbError = kShbOpenMismatch; + goto Exit; + } + + #ifndef NDEBUG + { + if ( strncmp(pShbMemHeader->m_szBufferID, pszBufferID_p, sizeof(pShbMemHeader->m_szBufferID)-1) ) + { + ShbError = kShbOpenMismatch; + goto Exit; + } + } + #endif + + pShbMemHeader->m_ulRefCount++; + } + + + // set abstarct "handle" for returning to application + pShbInstance = (tShbInstance*)pShbMemInst; + + +Exit: + + if (ShbError != kShbOk) + { + if (pShbMemInst != NULL) + { + ShbIpcReleasePrivateMem (pShbMemInst); + } + if (pSharedMem != NULL) + { + UnmapViewOfFile (pSharedMem); + } + if (hSharedMem != NULL) + { + CloseHandle (hSharedMem); + } + } + + *pfShbNewCreated_p = fShMemNewCreated; + *ppShbInstance_p = pShbInstance; + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Release Shared Buffer +//--------------------------------------------------------------------------- + +tShbError ShbIpcReleaseBuffer ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +HANDLE hEventNewData; +HANDLE hMutexBuffAccess; +tShbError ShbError; +tShbError ShbError2; + + + if (pShbInstance_p == NULL) + { + return (kShbOk); + } + + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); + + + if ( !--pShbMemHeader->m_ulRefCount ) + { + ShbError = kShbOk; + } + else + { + ShbError = kShbMemUsedByOtherProcs; + } + + + ShbError2 = ShbIpcStopSignalingNewData (pShbInstance_p); + hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]; + if (hEventNewData != INVALID_HANDLE_VALUE) + { + CloseHandle (hEventNewData); + pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = INVALID_HANDLE_VALUE; + } + + hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess; + if (hMutexBuffAccess != INVALID_HANDLE_VALUE) + { + CloseHandle (hMutexBuffAccess); + pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE; + } + + UnmapViewOfFile (pShbMemHeader); + if (pShbMemInst->m_hSharedMem != INVALID_HANDLE_VALUE) + { + CloseHandle (pShbMemInst->m_hSharedMem); + pShbMemInst->m_hSharedMem = INVALID_HANDLE_VALUE; + } + + ShbIpcReleasePrivateMem (pShbMemInst); + + + if (ShbError == kShbOk) + { + ShbError = ShbError2; + } + + return (ShbError); + +} + +#endif // !defined(SHBIPC_INLINE_ENABLED) + +#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// Enter atomic section for Shared Buffer access +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; +HANDLE hMutexBuffAccess; +DWORD dwWaitResult; +tShbError ShbError; + + + if (pShbInstance_p == NULL) + { + return (kShbInvalidArg); + } + + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + ShbError = kShbOk; + + hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess; + if (hMutexBuffAccess != INVALID_HANDLE_VALUE) + { + dwWaitResult = WaitForSingleObject (hMutexBuffAccess, TIMEOUT_ENTER_ATOMIC); + switch (dwWaitResult) + { + case WAIT_OBJECT_0 + 0: + { + break; + } + + case WAIT_TIMEOUT: + { + TRACE0("\nShbIpcEnterAtomicSection(): WAIT_TIMEOUT"); + ASSERT(0); + ShbError = kShbBufferInvalid; + break; + } + + case WAIT_ABANDONED: + { + TRACE0("\nShbIpcEnterAtomicSection(): WAIT_ABANDONED"); + ASSERT(0); + ShbError = kShbBufferInvalid; + break; + } + + case WAIT_FAILED: + { + TRACE1("\nShbIpcEnterAtomicSection(): WAIT_FAILED -> LastError=%ld", GetLastError()); + ASSERT(0); + ShbError = kShbBufferInvalid; + break; + } + + default: + { + TRACE1("\nShbIpcEnterAtomicSection(): unknown error -> LastError=%ld", GetLastError()); + ASSERT(0); + ShbError = kShbBufferInvalid; + break; + } + } + } + else + { + ShbError = kShbBufferInvalid; + } + + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Leave atomic section for Shared Buffer access +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; +HANDLE hMutexBuffAccess; +BOOL fRes; +tShbError ShbError; + + + if (pShbInstance_p == NULL) + { + return (kShbInvalidArg); + } + + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + ShbError = kShbOk; + + hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess; + if (hMutexBuffAccess != INVALID_HANDLE_VALUE) + { + fRes = ReleaseMutex (hMutexBuffAccess); + ASSERT( fRes ); + } + else + { + ShbError = kShbBufferInvalid; + } + + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Start signaling of new data (called from reading process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData ( + tShbInstance pShbInstance_p, + tSigHndlrNewData pfnSignalHandlerNewData_p, + tShbPriority ShbPriority_p) +{ + +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +const char* pszObjectName; +HANDLE hEventTermRequ; +HANDLE hEventTermResp; +HANDLE hThreadNewData; +unsigned long ulThreadIDNewData; +tShbError ShbError; +int iPriority; + + if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) + { + return (kShbInvalidArg); + } + + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); + ShbError = kShbOk; + + if ( (pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) || + (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != INVALID_HANDLE_VALUE) || + (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != INVALID_HANDLE_VALUE) || + (pShbMemInst->m_pfnSigHndlrNewData != NULL) ) + { + ShbError = kShbAlreadySignaling; + goto Exit; + } + + + pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p; + + + // Because the event <pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]> + // is used for signaling of new data after a write operation too (using + // SetEvent), it is always created here (see <ShbIpcAllocBuffer>). + + pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_TERM_REQU, pShbMemHeader->m_szBufferID, FALSE); + hEventTermRequ = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes + FALSE, // BOOL bManualReset + FALSE, // BOOL bInitialState + pszObjectName); // LPCTSTR lpName + pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = hEventTermRequ; + ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != NULL); + + pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_TERM_RESP, pShbMemHeader->m_szBufferID, FALSE); + hEventTermResp = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes + FALSE, // BOOL bManualReset + FALSE, // BOOL bInitialState + pszObjectName); // LPCTSTR lpName + pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = hEventTermResp; + ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != NULL); + + hThreadNewData = CreateThread (NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes + 0, // SIZE_T dwStackSize + ShbIpcThreadSignalNewData, // LPTHREAD_START_ROUTINE lpStartAddress + pShbInstance_p, // LPVOID lpParameter + 0, // DWORD dwCreationFlags + &ulThreadIDNewData); // LPDWORD lpThreadId + + switch (ShbPriority_p) + { + case kShbPriorityLow: + iPriority = THREAD_PRIORITY_BELOW_NORMAL; + break; + + case kShbPriorityNormal: + iPriority = THREAD_PRIORITY_NORMAL; + break; + + case kshbPriorityHigh: + iPriority = THREAD_PRIORITY_ABOVE_NORMAL; + break; + + } + + ASSERT(pShbMemInst->m_hThreadNewData != NULL); + + SetThreadPriority(hThreadNewData, iPriority); + + pShbMemInst->m_hThreadNewData = hThreadNewData; + + #ifndef NDEBUG + { + pShbMemInst->m_ulThreadIDNewData = ulThreadIDNewData; + } + #endif + + +Exit: + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Stop signaling of new data (called from reading process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; +HANDLE hEventTermRequ; +HANDLE hEventTermResp; +DWORD dwWaitResult; + + + if (pShbInstance_p == NULL) + { + return (kShbInvalidArg); + } + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + + + // terminate new data signaling thread + // (set event <hEventTermRequ> to wakeup the thread and dispose it + // to exit, then wait for confirmation using event <hEventTermResp>) + hEventTermRequ = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU]; + hEventTermResp = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]; + if ( (hEventTermRequ != INVALID_HANDLE_VALUE) && + (hEventTermResp != INVALID_HANDLE_VALUE) ) + { + TRACE0("\nShbIpcStopSignalingNewData(): enter wait state"); + dwWaitResult = SignalObjectAndWait (hEventTermRequ, // HANDLE hObjectToSignal + hEventTermResp, // HANDLE hObjectToWaitOn + TIMEOUT_TERM_THREAD, // DWORD dwMilliseconds + FALSE); // BOOL bAlertable + TRACE0("\nShbIpcStopSignalingNewData(): wait state leaved: ---> "); + switch (dwWaitResult) + { + case WAIT_OBJECT_0 + 0: // event "new data signaling thread terminated" + { + TRACE0("Event = WAIT_OBJECT_0+0"); + break; + } + + default: + { + TRACE0("Unhandled Event"); + ASSERT(0); + break; + } + } + } + + + if (pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) + { + CloseHandle (pShbMemInst->m_hThreadNewData); + pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE; + } + + if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != INVALID_HANDLE_VALUE) + { + CloseHandle (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU]); + pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = INVALID_HANDLE_VALUE; + } + + if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != INVALID_HANDLE_VALUE) + { + CloseHandle (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]); + pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = INVALID_HANDLE_VALUE; + } + + pShbMemInst->m_pfnSigHndlrNewData = NULL; + + + return (kShbOk); + +} + + + +//--------------------------------------------------------------------------- +// Signal new data (called from writing process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcSignalNewData ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; +HANDLE hEventNewData; +BOOL fRes; + + + // TRACE0("\nShbIpcSignalNewData(): enter\n"); + + if (pShbInstance_p == NULL) + { + return (kShbInvalidArg); + } + + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + + ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != INVALID_HANDLE_VALUE); + hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]; + if (hEventNewData != INVALID_HANDLE_VALUE) + { + fRes = SetEvent (hEventNewData); + // TRACE1("\nShbIpcSignalNewData(): EventNewData set (Result=%d)\n", (int)fRes); + ASSERT( fRes ); + } + + // TRACE0("\nShbIpcSignalNewData(): leave\n"); + return (kShbOk); + +} + + + +//--------------------------------------------------------------------------- +// Start signaling for job ready (called from waiting process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady ( + tShbInstance pShbInstance_p, + unsigned long ulTimeOut_p, + tSigHndlrJobReady pfnSignalHandlerJobReady_p) +{ + +tShbMemInst* pShbMemInst; +tShbMemHeader* pShbMemHeader; +HANDLE hThreadJobReady; +unsigned long ulThreadIDJobReady; +tShbError ShbError; + + + if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) + { + return (kShbInvalidArg); + } + + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); + ShbError = kShbOk; + + if ( (pShbMemInst->m_hThreadJobReady != INVALID_HANDLE_VALUE) || + (pShbMemInst->m_pfnSigHndlrJobReady != NULL) ) + { + ShbError = kShbAlreadySignaling; + goto Exit; + } + + + pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p; + pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p; + + + // Because the event <pShbMemInst->m_ahEventJobReady> is used for + // signaling of a finished job too (using SetEvent), it is always + // created here (see <ShbIpcAllocBuffer>). + + hThreadJobReady = CreateThread (NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes + 0, // SIZE_T dwStackSize + ShbIpcThreadSignalJobReady, // LPTHREAD_START_ROUTINE lpStartAddress + pShbInstance_p, // LPVOID lpParameter + 0, // DWORD dwCreationFlags + &ulThreadIDJobReady); // LPDWORD lpThreadId + + pShbMemInst->m_hThreadJobReady = hThreadJobReady; + ASSERT(pShbMemInst->m_hThreadJobReady != NULL); + + #ifndef NDEBUG + { + pShbMemInst->m_ulThreadIDJobReady = ulThreadIDJobReady; + } + #endif + + +Exit: + + return (ShbError); + +} + + + +//--------------------------------------------------------------------------- +// Signal job ready (called from executing process) +//--------------------------------------------------------------------------- + +INLINE_FUNCTION tShbError ShbIpcSignalJobReady ( + tShbInstance pShbInstance_p) +{ + +tShbMemInst* pShbMemInst; +HANDLE hEventJobReady; +BOOL fRes; + + + // TRACE0("\nShbIpcSignalJobReady(): enter\n"); + + if (pShbInstance_p == NULL) + { + return (kShbInvalidArg); + } + + + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); + + ASSERT(pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE); + hEventJobReady = pShbMemInst->m_hEventJobReady; + if (hEventJobReady != INVALID_HANDLE_VALUE) + { + fRes = SetEvent (hEventJobReady); + // TRACE1("\nShbIpcSignalJobReady(): EventJobReady set (Result=%d)\n", (int)fRes); + ASSERT( fRes ); + } + + // TRACE0("\nShbIpcSignalJobReady(): leave\n"); + return (kShbOk); + +} + + + +//--------------------------------------------------------------------------- +// Get pointer to common used share memory area +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void* ShbIpcGetShMemPtr ( + tShbInstance pShbInstance_p) +{ + +tShbMemHeader* pShbMemHeader; +void* pShbShMemPtr; + + + pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); + if (pShbMemHeader != NULL) + { + pShbShMemPtr = (BYTE*)pShbMemHeader + sizeof(tShbMemHeader); + } + else + { + pShbShMemPtr = NULL; + } + + return (pShbShMemPtr); + +} + +#endif + + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +#if !defined(SHBIPC_INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// Allocate a memory block from process specific mempool +//--------------------------------------------------------------------------- + +static void* ShbIpcAllocPrivateMem ( + unsigned long ulMemSize_p) +{ + +HGLOBAL hMem; +void* pMem; + + + hMem = GlobalAlloc (GMEM_FIXED, ulMemSize_p+sizeof(HGLOBAL)); + pMem = GlobalLock (hMem); + if (pMem != NULL) + { + *(HGLOBAL*)pMem = hMem; + (BYTE*)pMem += sizeof(HGLOBAL); + } + + + #ifndef NDEBUG + { + memset (pMem, 0xaa, ulMemSize_p); + } + #endif + + + return (pMem); + +} + + + +//--------------------------------------------------------------------------- +// Release a memory block from process specific mempool +//--------------------------------------------------------------------------- + +static void ShbIpcReleasePrivateMem ( + void* pMem_p) +{ + +HGLOBAL hMem; + + + if (pMem_p == NULL) + { + return; + } + + + (BYTE*)pMem_p -= sizeof(HGLOBAL); + hMem = *(HGLOBAL*)pMem_p; + + GlobalUnlock (hMem); + GlobalFree (hMem); + + return; + +} + + + +//--------------------------------------------------------------------------- +// Create uniform object name (needed for inter-process communication) +//--------------------------------------------------------------------------- + +const char* ShbIpcGetUniformObjectName ( + const char* pszObjectJobName_p, + const char* pszBufferID_p, + BOOL fGlobalObject_p) +{ + +static char szObjectName[MAX_PATH]; +char szObjectPrefix[MAX_PATH]; + + + if ( fGlobalObject_p ) + { + strncpy (szObjectPrefix, "Global\\", sizeof(szObjectPrefix)); + } + else + { + _snprintf (szObjectPrefix, sizeof(szObjectPrefix), "PID%08lX_", + (unsigned long)GetCurrentProcessId()); + } + + + _snprintf (szObjectName, sizeof(szObjectName), "%s%s#%s", + szObjectPrefix, pszBufferID_p, pszObjectJobName_p); + + + return (szObjectName); + +} + + + +//--------------------------------------------------------------------------- +// Thread for new data signaling +//--------------------------------------------------------------------------- + +DWORD WINAPI ShbIpcThreadSignalNewData ( + LPVOID pvThreadParam_p) +{ + +tShbInstance pShbInstance; +tShbMemInst* pShbMemInst; +DWORD dwWaitResult; +BOOL fTermRequ; +int fCallAgain; + + + TRACE1("\nShbIpcThreadSignalNewData(): SignalThread started (pShbInstance=0x%08lX)\n", (DWORD)pvThreadParam_p); + + pShbInstance = (tShbMemInst*)pvThreadParam_p; + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); + fTermRequ = FALSE; + + do + { + ASSERT((pShbMemInst->m_ahEventNewData[0] != INVALID_HANDLE_VALUE) && (pShbMemInst->m_ahEventNewData[0] != NULL)); + ASSERT((pShbMemInst->m_ahEventNewData[1] != INVALID_HANDLE_VALUE) && (pShbMemInst->m_ahEventNewData[1] != NULL)); + + TRACE0("\nShbIpcThreadSignalNewData(): enter wait state"); + dwWaitResult = WaitForMultipleObjects (2, // DWORD nCount + pShbMemInst->m_ahEventNewData, // const HANDLE* lpHandles + FALSE, // BOOL bWaitAll + INFINITE); // DWORD dwMilliseconds + TRACE0("\nShbIpcThreadSignalNewData(): wait state leaved: ---> "); + switch (dwWaitResult) + { + case WAIT_OBJECT_0 + 0: // event "new data" + { + TRACE0("Event = WAIT_OBJECT_0+0"); + if (pShbMemInst->m_pfnSigHndlrNewData != NULL) + { + TRACE0("\nShbIpcThreadSignalNewData(): calling SignalHandlerNewData"); + do + { + fCallAgain = pShbMemInst->m_pfnSigHndlrNewData (pShbInstance); + // d.k.: try to run any shared buffer which has higher priority. + // under Windows this is not really necessary because the Windows scheduler + // already preempts tasks with lower priority. + } while (fCallAgain != FALSE); + } + break; + } + + case WAIT_OBJECT_0 + 1: // event "terminate" + { + TRACE0("Event = WAIT_OBJECT_0+1"); + fTermRequ = TRUE; + break; + } + + default: + { + TRACE0("Unhandled Event"); + ASSERT(0); + fTermRequ = TRUE; + break; + } + } + } + while ( !fTermRequ ); + + + if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != INVALID_HANDLE_VALUE) + { + SetEvent (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]); + } + + TRACE1("\nShbIpcThreadSignalNewData(): SignalThread terminated (pShbInstance=0x%08lX)\n", (DWORD)pShbInstance); + + ExitThread (0); + +} + + + +//--------------------------------------------------------------------------- +// Thread for new data signaling +//--------------------------------------------------------------------------- + +DWORD WINAPI ShbIpcThreadSignalJobReady ( + LPVOID pvThreadParam_p) +{ + +tShbInstance* pShbInstance; +tShbMemInst* pShbMemInst; +DWORD ulTimeOut; +DWORD dwWaitResult; +unsigned int fTimeOut; + + + TRACE1("\nShbIpcThreadSignalJobReady(): SignalThread started (pShbInstance=0x%08lX)\n", (DWORD)pvThreadParam_p); + + + pShbInstance = (tShbInstance*)pvThreadParam_p; + pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); + fTimeOut = FALSE; + + if (pShbMemInst->m_ulTimeOutJobReady != 0) + { + ulTimeOut = pShbMemInst->m_ulTimeOutJobReady; + } + else + { + ulTimeOut = INFINITE; + } + + ASSERT((pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE) && (pShbMemInst->m_hEventJobReady != NULL)); + + TRACE0("\nShbIpcThreadSignalJobReady(): enter wait state"); + dwWaitResult = WaitForSingleObject (pShbMemInst->m_hEventJobReady, // HANDLE hHandle + ulTimeOut); // DWORD dwMilliseconds + TRACE0("\nShbIpcThreadSignalJobReady(): wait state leaved: ---> "); + switch (dwWaitResult) + { + case WAIT_OBJECT_0 + 0: // event "new data" + { + TRACE0("Event = WAIT_OBJECT_0+0"); + fTimeOut = FALSE; + break; + } + + case WAIT_TIMEOUT: + { + TRACE0("\nEvent = WAIT_TIMEOUT"); + fTimeOut = TRUE; + // ASSERT(0); + break; + } + + default: + { + TRACE0("Unhandled Event"); + fTimeOut = TRUE; + ASSERT(0); + break; + } + } + + + if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) + { + TRACE0("\nShbIpcThreadSignalJobReady(): calling SignalHandlerJobReady"); + pShbMemInst->m_pfnSigHndlrJobReady (pShbInstance, fTimeOut); + } + + + pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE; + pShbMemInst->m_pfnSigHndlrJobReady = NULL; + + + TRACE1("\nShbIpcThreadSignalJobReady(): SignalThread terminated (pShbInstance=0x%08lX)\n", (DWORD)pShbInstance); + + ExitThread (0); + +} + +#endif + +// EOF + diff --git a/drivers/staging/epl/ShbIpc.h b/drivers/staging/epl/ShbIpc.h new file mode 100644 index 0000000..7840b03 --- /dev/null +++ b/drivers/staging/epl/ShbIpc.h @@ -0,0 +1,120 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: Project independend shared buffer (linear + circular) + + Description: Declaration of platform specific part for the + shared buffer + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + 2006/06/27 -rs: V 1.00 (initial version) + +****************************************************************************/ + +#ifndef _SHBIPC_H_ +#define _SHBIPC_H_ + + + +//--------------------------------------------------------------------------- +// Type definitions +//--------------------------------------------------------------------------- + +typedef int (*tSigHndlrNewData) (tShbInstance pShbInstance_p); +typedef void (*tSigHndlrJobReady) (tShbInstance pShbInstance_p, unsigned int fTimeOut_p); + + +#if (TARGET_SYSTEM == _WIN32_) + #if defined(INLINE_FUNCTION_DEF) + #undef INLINE_FUNCTION + #define INLINE_FUNCTION INLINE_FUNCTION_DEF + #define SHBIPC_INLINE_ENABLED TRUE + #define SHBIPC_INLINED + #include "ShbIpc-Win32.c" + #endif + +#elif (TARGET_SYSTEM == _LINUX_) + #if defined(INLINE_FUNCTION_DEF) + #undef INLINE_FUNCTION + #define INLINE_FUNCTION INLINE_FUNCTION_DEF + #define SHBIPC_INLINE_ENABLED TRUE + #define SHBIPC_INLINED + #include "ShbIpc-LinuxKernel.c" + #endif +#endif + + +//--------------------------------------------------------------------------- +// Prototypes +//--------------------------------------------------------------------------- + +tShbError ShbIpcInit (void); +tShbError ShbIpcExit (void); + +tShbError ShbIpcAllocBuffer (unsigned long ulBufferSize_p, const char* pszBufferID_p, tShbInstance* ppShbInstance_p, unsigned int* pfShbNewCreated_p); +tShbError ShbIpcReleaseBuffer (tShbInstance pShbInstance_p); + +#if !defined(SHBIPC_INLINE_ENABLED) + +tShbError ShbIpcEnterAtomicSection (tShbInstance pShbInstance_p); +tShbError ShbIpcLeaveAtomicSection (tShbInstance pShbInstance_p); + +tShbError ShbIpcStartSignalingNewData (tShbInstance pShbInstance_p, tSigHndlrNewData pfnSignalHandlerNewData_p, tShbPriority ShbPriority_p); +tShbError ShbIpcStopSignalingNewData (tShbInstance pShbInstance_p); +tShbError ShbIpcSignalNewData (tShbInstance pShbInstance_p); + +tShbError ShbIpcStartSignalingJobReady (tShbInstance pShbInstance_p, unsigned long ulTimeOut_p, tSigHndlrJobReady pfnSignalHandlerJobReady_p); +tShbError ShbIpcSignalJobReady (tShbInstance pShbInstance_p); + +void* ShbIpcGetShMemPtr (tShbInstance pShbInstance_p); +#endif + +#undef SHBIPC_INLINE_ENABLED // disable actual inlining of functions +#undef INLINE_FUNCTION +#define INLINE_FUNCTION // define INLINE_FUNCTION to nothing + +#endif // #ifndef _SHBIPC_H_ + diff --git a/drivers/staging/epl/ShbLinuxKernel.h b/drivers/staging/epl/ShbLinuxKernel.h new file mode 100644 index 0000000..30b5faf --- /dev/null +++ b/drivers/staging/epl/ShbLinuxKernel.h @@ -0,0 +1,68 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: Project independend shared buffer (linear + circular) + + Description: Declaration of platform specific part for the + shared buffer + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + 2006/07/20 -rs: V 1.00 (initial version) + +****************************************************************************/ + +#ifndef _SHBLINUXKERNEL_H_ +#define _SHBLINUXKERNEL_H_ + +struct sShbMemTable{ + int m_iBufferId; + void* m_pBuffer; + struct sShbMemTable *m_psNextMemTableElement; +}; + +extern struct sShbMemTable *psMemTableElementFirst_g; + +#endif // _SHBLINUXKERNEL_H_ diff --git a/drivers/staging/epl/SocketLinuxKernel.c b/drivers/staging/epl/SocketLinuxKernel.c new file mode 100644 index 0000000..c78a6eb --- /dev/null +++ b/drivers/staging/epl/SocketLinuxKernel.c @@ -0,0 +1,210 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: Wrapper for BSD socket API for Linux kernel + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: SocketLinuxKernel.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + Dev C++ and GNU-Compiler for m68k + + ------------------------------------------------------------------------- + + Revision History: + + 2006/08/25 d.k.: start of implementation + +****************************************************************************/ + + +#include <linux/net.h> +#include <linux/in.h> +#include "SocketLinuxKernel.h" + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// Kernel Module specific Data Structures +//--------------------------------------------------------------------------- + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + +SOCKET socket(int af, int type, int protocol) +{ +int rc; +SOCKET socket; + + rc = sock_create_kern(af, type, protocol, &socket); + if (rc < 0) + { + socket = NULL; + goto Exit; + } + +Exit: + return socket; +} + +int bind(SOCKET socket_p, const struct sockaddr *addr, int addrlen) +{ +int rc; + + rc = socket_p->ops->bind(socket_p, + (struct sockaddr *)addr, + addrlen); + + return rc; +} + +int closesocket(SOCKET socket_p) +{ + sock_release(socket_p); + + return 0; +} + +int recvfrom(SOCKET socket_p, char* buf, int len, int flags, struct sockaddr *from, int * fromlen) +{ +int rc; +struct msghdr msg; +struct kvec iov; + + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_name = from; // will be struct sock_addr + msg.msg_namelen = *fromlen; + iov.iov_len = len; + iov.iov_base = buf; + + rc = kernel_recvmsg(socket_p, &msg, &iov, 1, iov.iov_len, 0); + + return rc; +} + +int sendto(SOCKET socket_p, const char* buf, int len, int flags, const struct sockaddr *to, int tolen) +{ +int rc; +struct msghdr msg; +struct kvec iov; + + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_name = (struct sockaddr *)to; // will be struct sock_addr + msg.msg_namelen = tolen; + msg.msg_flags = 0; + iov.iov_len = len; + iov.iov_base = (char *)buf; + + rc = kernel_sendmsg(socket_p, &msg, &iov, 1, len); + + return rc; +} + + +// EOF + diff --git a/drivers/staging/epl/SocketLinuxKernel.h b/drivers/staging/epl/SocketLinuxKernel.h new file mode 100644 index 0000000..c248a78 --- /dev/null +++ b/drivers/staging/epl/SocketLinuxKernel.h @@ -0,0 +1,108 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for BSD socket API for Linux kernel + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: SocketLinuxKernel.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + KEIL uVision 2 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/08/25 d.k.: start of the implementation + + +****************************************************************************/ + + +#ifndef _SOCKETLINUXKERNEL_H_ +#define _SOCKETLINUXKERNEL_H_ + +#include <linux/net.h> +#include <linux/in.h> + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#define INVALID_SOCKET 0 + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef struct socket* SOCKET; + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +int bind(SOCKET s, const struct sockaddr *addr, int addrlen); + +int closesocket(SOCKET s); + +int recvfrom(SOCKET s, char* buf, int len, int flags, struct sockaddr *from, int * fromlen); + +int sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr *to, int tolen); + +SOCKET socket(int af, int type, int protocol); + +#endif // #ifndef _SOCKETLINUXKERNEL_H_ + + diff --git a/drivers/staging/epl/TimerHighReskX86.c b/drivers/staging/epl/TimerHighReskX86.c new file mode 100644 index 0000000..70ba2d6 --- /dev/null +++ b/drivers/staging/epl/TimerHighReskX86.c @@ -0,0 +1,555 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: target specific implementation of + high resolution timer module for X86 under Linux + The Linux kernel has to be compiled with high resolution + timers enabled. This is done by configuring the kernel + with CONFIG_HIGH_RES_TIMERS enabled. + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: TimerHighReskX86.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:38:01 $ + + $State: Exp $ + + Build Environment: + GNU + + ------------------------------------------------------------------------- + + Revision History: + +****************************************************************************/ + +#include "EplInc.h" +#include "kernel/EplTimerHighResk.h" +#include "Benchmark.h" + +//#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/hrtimer.h> + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#define TIMER_COUNT 2 /* max 15 timers selectable */ +#define TIMER_MIN_VAL_SINGLE 5000 /* min 5us */ +#define TIMER_MIN_VAL_CYCLE 100000 /* min 100us */ + +#define PROVE_OVERRUN + + +#ifndef CONFIG_HIGH_RES_TIMERS + #error "Kernel symbol CONFIG_HIGH_RES_TIMERS is required." +#endif + + +// TracePoint support for realtime-debugging +#ifdef _DBG_TRACE_POINTS_ + void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); + void PUBLIC TgtDbgPostTraceValue (DWORD dwTraceValue_p); + #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) + #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) +#else + #define TGT_DBG_SIGNAL_TRACE_POINT(p) + #define TGT_DBG_POST_TRACE_VALUE(v) +#endif +#define HRT_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \ + TGT_DBG_POST_TRACE_VALUE((0xE << 28) | (Event_p << 24) \ + | (uiNodeId_p << 16) | wErrorCode_p) + +#define TIMERHDL_MASK 0x0FFFFFFF +#define TIMERHDL_SHIFT 28 +#define HDL_TO_IDX(Hdl) ((Hdl >> TIMERHDL_SHIFT) - 1) +#define HDL_INIT(Idx) ((Idx + 1) << TIMERHDL_SHIFT) +#define HDL_INC(Hdl) (((Hdl + 1) & TIMERHDL_MASK) \ + | (Hdl & ~TIMERHDL_MASK)) + +//--------------------------------------------------------------------------- +// modul global types +//--------------------------------------------------------------------------- + +typedef struct +{ + tEplTimerEventArg m_EventArg; + tEplTimerkCallback m_pfnCallback; + struct hrtimer m_Timer; + BOOL m_fContinuously; + unsigned long long m_ullPeriod; + +} tEplTimerHighReskTimerInfo; + +typedef struct +{ + tEplTimerHighReskTimerInfo m_aTimerInfo[TIMER_COUNT]; + +} tEplTimerHighReskInstance; + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +static tEplTimerHighReskInstance EplTimerHighReskInstance_l; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +enum hrtimer_restart EplTimerHighReskCallback (struct hrtimer* pTimer_p); + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + + +//--------------------------------------------------------------------------- +// +// Function: EplTimerHighReskInit() +// +// Description: initializes the high resolution timer module. +// +// Parameters: void +// +// Return: tEplKernel = error code +// +// State: not tested +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimerHighReskInit(void) +{ +tEplKernel Ret; + + Ret = EplTimerHighReskAddInstance(); + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimerHighReskAddInstance() +// +// Description: initializes the high resolution timer module. +// +// Parameters: void +// +// Return: tEplKernel = error code +// +// State: not tested +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimerHighReskAddInstance(void) +{ +tEplKernel Ret; +unsigned int uiIndex; + + Ret = kEplSuccessful; + + EPL_MEMSET(&EplTimerHighReskInstance_l, 0, sizeof (EplTimerHighReskInstance_l)); + +#ifndef CONFIG_HIGH_RES_TIMERS + printk("EplTimerHighResk: Kernel symbol CONFIG_HIGH_RES_TIMERS is required.\n"); + Ret = kEplNoResource; + return Ret; +#endif + + /* + * Initialize hrtimer structures for all usable timers. + */ + for (uiIndex = 0; uiIndex < TIMER_COUNT; uiIndex++) + { + tEplTimerHighReskTimerInfo* pTimerInfo; + struct hrtimer* pTimer; + + pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[uiIndex]; + pTimer = &pTimerInfo->m_Timer; + hrtimer_init(pTimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + + pTimer->function = EplTimerHighReskCallback; + + /* + * We use HRTIMER_CB_SOFTIRQ here. + * HRTIMER_CB_IRQSAFE is critical as the callback function + * would be called with IRQs disabled. + */ + pTimer->cb_mode = HRTIMER_CB_SOFTIRQ; + } + + return Ret; +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimerHighReskDelInstance() +// +// Description: shuts down the high resolution timer module. +// +// Parameters: void +// +// Return: tEplKernel = error code +// +// State: not tested +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimerHighReskDelInstance(void) +{ +tEplTimerHighReskTimerInfo* pTimerInfo; +tEplKernel Ret; +unsigned int uiIndex; + + Ret = kEplSuccessful; + + for (uiIndex = 0; uiIndex < TIMER_COUNT; uiIndex++) + { + pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[0]; + pTimerInfo->m_pfnCallback = NULL; + pTimerInfo->m_EventArg.m_TimerHdl = 0; + /* + * In this case we can not just try to cancel the timer. + * We actually have to wait until its callback function + * has returned. + */ + hrtimer_cancel(&pTimerInfo->m_Timer); + } + + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimerHighReskModifyTimerNs() +// +// Description: modifies the timeout of the timer with the specified handle. +// If the handle the pointer points to is zero, the timer must +// be created first. +// If it is not possible to stop the old timer, +// this function always assures that the old timer does not +// trigger the callback function with the same handle as the new +// timer. That means the callback function must check the passed +// handle with the one returned by this function. If these are +// unequal, the call can be discarded. +// +// Parameters: pTimerHdl_p = pointer to timer handle +// ullTimeNs_p = relative timeout in [ns] +// pfnCallback_p = callback function, which is called mutual +// exclusive with the Edrv callback functions +// (Rx and Tx). +// ulArgument_p = user-specific argument +// fContinuously_p = if TRUE, callback function will be called +// continuously; +// otherwise, it is a oneshot timer. +// +// Return: tEplKernel = error code +// +// State: not tested +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimerHighReskModifyTimerNs(tEplTimerHdl* pTimerHdl_p, + unsigned long long ullTimeNs_p, + tEplTimerkCallback pfnCallback_p, + unsigned long ulArgument_p, + BOOL fContinuously_p) +{ +tEplKernel Ret; +unsigned int uiIndex; +tEplTimerHighReskTimerInfo* pTimerInfo; +ktime_t RelTime; + + Ret = kEplSuccessful; + + // check pointer to handle + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + if (*pTimerHdl_p == 0) + { // no timer created yet + + // search free timer info structure + pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[0]; + for (uiIndex = 0; uiIndex < TIMER_COUNT; uiIndex++, pTimerInfo++) + { + if (pTimerInfo->m_EventArg.m_TimerHdl == 0) + { // free structure found + break; + } + } + if (uiIndex >= TIMER_COUNT) + { // no free structure found + Ret = kEplTimerNoTimerCreated; + goto Exit; + } + + pTimerInfo->m_EventArg.m_TimerHdl = HDL_INIT(uiIndex); + } + else + { + uiIndex = HDL_TO_IDX(*pTimerHdl_p); + if (uiIndex >= TIMER_COUNT) + { // invalid handle + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[uiIndex]; + } + + /* + * increment timer handle + * (if timer expires right after this statement, the user + * would detect an unknown timer handle and discard it) + */ + pTimerInfo->m_EventArg.m_TimerHdl = HDL_INC(pTimerInfo->m_EventArg.m_TimerHdl); + *pTimerHdl_p = pTimerInfo->m_EventArg.m_TimerHdl; + + // reject too small time values + if ( (fContinuously_p && (ullTimeNs_p < TIMER_MIN_VAL_CYCLE)) + || (!fContinuously_p && (ullTimeNs_p < TIMER_MIN_VAL_SINGLE)) ) + { + Ret = kEplTimerNoTimerCreated; + goto Exit; + } + + pTimerInfo->m_EventArg.m_ulArg = ulArgument_p; + pTimerInfo->m_pfnCallback = pfnCallback_p; + pTimerInfo->m_fContinuously = fContinuously_p; + pTimerInfo->m_ullPeriod = ullTimeNs_p; + + /* + * HRTIMER_MODE_REL does not influence general handling of this timer. + * It only sets relative mode for this start operation. + * -> Expire time is calculated by: Now + RelTime + * hrtimer_start also skips pending timer events. + * The state HRTIMER_STATE_CALLBACK is ignored. + * We have to cope with that in our callback function. + */ + RelTime = ktime_add_ns(ktime_set(0,0), ullTimeNs_p); + hrtimer_start(&pTimerInfo->m_Timer, RelTime, HRTIMER_MODE_REL); + +Exit: + return Ret; + +} + + +//--------------------------------------------------------------------------- +// +// Function: EplTimerHighReskDeleteTimer() +// +// Description: deletes the timer with the specified handle. Afterward the +// handle is set to zero. +// +// Parameters: pTimerHdl_p = pointer to timer handle +// +// Return: tEplKernel = error code +// +// State: not tested +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimerHighReskDeleteTimer(tEplTimerHdl* pTimerHdl_p) +{ +tEplKernel Ret = kEplSuccessful; +unsigned int uiIndex; +tEplTimerHighReskTimerInfo* pTimerInfo; + + // check pointer to handle + if(pTimerHdl_p == NULL) + { + Ret = kEplTimerInvalidHandle; + goto Exit; + } + + if (*pTimerHdl_p == 0) + { // no timer created yet + goto Exit; + } + else + { + uiIndex = HDL_TO_IDX(*pTimerHdl_p); + if (uiIndex >= TIMER_COUNT) + { // invalid handle + Ret = kEplTimerInvalidHandle; + goto Exit; + } + pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[uiIndex]; + if (pTimerInfo->m_EventArg.m_TimerHdl != *pTimerHdl_p) + { // invalid handle + goto Exit; + } + } + + *pTimerHdl_p = 0; + pTimerInfo->m_EventArg.m_TimerHdl = 0; + pTimerInfo->m_pfnCallback = NULL; + + /* + * Three return cases of hrtimer_try_to_cancel have to be tracked: + * 1 - timer has been removed + * 0 - timer was not active + * We need not do anything. hrtimer timers just consist of + * a hrtimer struct, which we might enqueue in the hrtimers + * event list by calling hrtimer_start(). + * If a timer is not enqueued, it is not present in hrtimers. + * -1 - callback function is running + * In this case we have to ensure that the timer is not + * continuously restarted. This has been done by clearing + * its handle. + */ + hrtimer_try_to_cancel(&pTimerInfo->m_Timer); + +Exit: + return Ret; + +} + + + +//--------------------------------------------------------------------------- +// +// Function: EplTimerHighReskCallback() +// +// Description: Callback function commonly used for all timers. +// +// Parameters: pTimer_p = pointer to hrtimer +// +// Return: +// +// State: not tested +// +//--------------------------------------------------------------------------- + +enum hrtimer_restart EplTimerHighReskCallback (struct hrtimer* pTimer_p) +{ +unsigned int uiIndex; +tEplTimerHighReskTimerInfo* pTimerInfo; +tEplTimerHdl OrgTimerHdl; +enum hrtimer_restart Ret; + + BENCHMARK_MOD_24_SET(4); + + Ret = HRTIMER_NORESTART; + pTimerInfo = container_of(pTimer_p, tEplTimerHighReskTimerInfo, m_Timer); + uiIndex = HDL_TO_IDX(pTimerInfo->m_EventArg.m_TimerHdl); + if (uiIndex >= TIMER_COUNT) + { // invalid handle + goto Exit; + } + + /* + * We store the timer handle before calling the callback function + * as the timer can be modified inside it. + */ + OrgTimerHdl = pTimerInfo->m_EventArg.m_TimerHdl; + + if (pTimerInfo->m_pfnCallback != NULL) + { + pTimerInfo->m_pfnCallback(&pTimerInfo->m_EventArg); + } + + if (pTimerInfo->m_fContinuously) + { + ktime_t Interval; +#ifdef PROVE_OVERRUN + ktime_t Now; + unsigned long Overruns; +#endif + + if (OrgTimerHdl != pTimerInfo->m_EventArg.m_TimerHdl) + { + /* modified timer has already been restarted */ + goto Exit; + } + +#ifdef PROVE_OVERRUN + Now = ktime_get(); + Interval = ktime_add_ns(ktime_set(0,0), pTimerInfo->m_ullPeriod); + Overruns = hrtimer_forward(pTimer_p, Now, Interval); + if (Overruns > 1) + { + printk("EplTimerHighResk: Continuous timer (handle 0x%lX) had to skip %lu interval(s)!\n", pTimerInfo->m_EventArg.m_TimerHdl, Overruns-1); + } +#else + pTimer_p->expires = ktime_add_ns(pTimer_p->expires, + pTimerInfo->m_ullPeriod); +#endif + + Ret = HRTIMER_RESTART; + } + +Exit: + BENCHMARK_MOD_24_RESET(4); + return Ret; +} + diff --git a/drivers/staging/epl/VirtualEthernetLinux.c b/drivers/staging/epl/VirtualEthernetLinux.c new file mode 100644 index 0000000..c21189c --- /dev/null +++ b/drivers/staging/epl/VirtualEthernetLinux.c @@ -0,0 +1,358 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: Virtual Ethernet Driver for Linux + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: VirtualEthernetLinux.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/11/20 17:06:51 $ + + $State: Exp $ + + Build Environment: + + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/12 -ar: start of the implementation, version 1.00 + + 2006/09/18 d.k.: integration into EPL DLLk module + + ToDo: + + void netif_carrier_off(struct net_device *dev); + void netif_carrier_on(struct net_device *dev); + +****************************************************************************/ + + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/if_arp.h> +#include <net/arp.h> + +#include <net/protocol.h> +#include <net/pkt_sched.h> +#include <linux/if_ether.h> +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/udp.h> +#include <linux/mm.h> +#include <linux/types.h> +#include <linux/skbuff.h> /* for struct sk_buff */ + +#include "kernel/VirtualEthernet.h" +#include "kernel/EplDllkCal.h" +#include "kernel/EplDllk.h" + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0) + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#ifndef EPL_VETH_TX_TIMEOUT +//#define EPL_VETH_TX_TIMEOUT (2*HZ) +#define EPL_VETH_TX_TIMEOUT 0 // d.k.: we use no timeout +#endif + + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +static struct net_device * pVEthNetDevice_g = NULL; + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static int VEthOpen(struct net_device *pNetDevice_p); +static int VEthClose(struct net_device *pNetDevice_p); +static int VEthXmit(struct sk_buff *pSkb_p, struct net_device *pNetDevice_p); +static struct net_device_stats* VEthGetStats(struct net_device *pNetDevice_p); +static void VEthTimeout(struct net_device *pNetDevice_p); +static tEplKernel VEthRecvFrame(tEplFrameInfo * pFrameInfo_p); + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- + +static int VEthOpen(struct net_device *pNetDevice_p) +{ +tEplKernel Ret = kEplSuccessful; + + //open the device +// struct net_device_stats* pStats = (struct net_device_stats*)pNetDevice_p->priv; + + //start the interface queue for the network subsystem + netif_start_queue(pNetDevice_p); + + // register callback function in DLL + Ret = EplDllkRegAsyncHandler(VEthRecvFrame); + + EPL_DBGLVL_VETH_TRACE1("VEthOpen: EplDllkRegAsyncHandler returned 0x%02X\n", Ret); + + return 0; +} + +static int VEthClose(struct net_device *pNetDevice_p) +{ +tEplKernel Ret = kEplSuccessful; + + EPL_DBGLVL_VETH_TRACE0("VEthClose\n"); + + Ret = EplDllkDeregAsyncHandler(VEthRecvFrame); + + //stop the interface queue for the network subsystem + netif_stop_queue(pNetDevice_p); + return 0; +} + + +static int VEthXmit(struct sk_buff *pSkb_p, struct net_device *pNetDevice_p) +{ +tEplKernel Ret = kEplSuccessful; +tEplFrameInfo FrameInfo; + + //transmit function + struct net_device_stats* pStats = (struct net_device_stats*)pNetDevice_p->priv; + + //save timestemp + pNetDevice_p->trans_start = jiffies; + + FrameInfo.m_pFrame = (tEplFrame *)pSkb_p->data; + FrameInfo.m_uiFrameSize = pSkb_p->len; + + //call send fkt on DLL + Ret = EplDllkCalAsyncSend(&FrameInfo, kEplDllAsyncReqPrioGeneric); + if (Ret != kEplSuccessful) + { + EPL_DBGLVL_VETH_TRACE1("VEthXmit: EplDllkCalAsyncSend returned 0x%02X\n", Ret); + netif_stop_queue(pNetDevice_p); + goto Exit; + } + else + { + EPL_DBGLVL_VETH_TRACE0("VEthXmit: frame passed to DLL\n"); + dev_kfree_skb(pSkb_p); + + //set stats for the device + pStats->tx_packets++; + pStats->tx_bytes += FrameInfo.m_uiFrameSize; + } + +Exit: + return 0; + +} + + +static struct net_device_stats* VEthGetStats(struct net_device *pNetDevice_p) +{ + EPL_DBGLVL_VETH_TRACE0("VEthGetStats\n"); + + return (struct net_device_stats *)pNetDevice_p->priv; +} + + + +static void VEthTimeout(struct net_device *pNetDevice_p) +{ + EPL_DBGLVL_VETH_TRACE0("VEthTimeout(\n"); + + // $$$ d.k.: move to extra function, which is called by DLL when new space is available in TxFifo + if (netif_queue_stopped (pNetDevice_p)) + { + netif_wake_queue (pNetDevice_p); + } +} + + + +static tEplKernel VEthRecvFrame(tEplFrameInfo * pFrameInfo_p) +{ +tEplKernel Ret = kEplSuccessful; + struct net_device* pNetDevice = pVEthNetDevice_g; + struct net_device_stats* pStats = (struct net_device_stats*)pNetDevice->priv; + struct sk_buff *pSkb; + + EPL_DBGLVL_VETH_TRACE1("VEthRecvFrame: FrameSize=%u\n", pFrameInfo_p->m_uiFrameSize); + + pSkb = dev_alloc_skb(pFrameInfo_p->m_uiFrameSize + 2); + if (pSkb == NULL) + { + pStats->rx_dropped++; + goto Exit; + } + pSkb->dev = pNetDevice; + + skb_reserve(pSkb, 2); + + memcpy((void *)skb_put(pSkb, pFrameInfo_p->m_uiFrameSize), pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize); + + pSkb->protocol = eth_type_trans(pSkb, pNetDevice); + pSkb->ip_summed = CHECKSUM_UNNECESSARY; + + // call netif_rx with skb + netif_rx(pSkb); + + EPL_DBGLVL_VETH_TRACE1("VEthRecvFrame: SrcMAC=0x%llx\n", AmiGetQword48FromBe(pFrameInfo_p->m_pFrame->m_be_abSrcMac)); + + // update receive statistics + pStats->rx_packets++; + pStats->rx_bytes += pFrameInfo_p->m_uiFrameSize; + +Exit: + return Ret; +} + + +tEplKernel PUBLIC VEthAddInstance(tEplDllkInitParam * pInitParam_p) +{ +tEplKernel Ret = kEplSuccessful; + + // allocate net device structure with priv pointing to stats structure + pVEthNetDevice_g = alloc_netdev(sizeof (struct net_device_stats), EPL_VETH_NAME, ether_setup); +// pVEthNetDevice_g = alloc_etherdev(sizeof (struct net_device_stats)); + + if (pVEthNetDevice_g == NULL) + { + Ret = kEplNoResource; + goto Exit; + } + + pVEthNetDevice_g->open = VEthOpen; + pVEthNetDevice_g->stop = VEthClose; + pVEthNetDevice_g->get_stats = VEthGetStats; + pVEthNetDevice_g->hard_start_xmit = VEthXmit; + pVEthNetDevice_g->tx_timeout = VEthTimeout; + pVEthNetDevice_g->watchdog_timeo = EPL_VETH_TX_TIMEOUT; + pVEthNetDevice_g->destructor = free_netdev; + + // copy own MAC address to net device structure + memcpy(pVEthNetDevice_g->dev_addr, pInitParam_p->m_be_abSrcMac, 6); + + //register VEth to the network subsystem + if (register_netdev(pVEthNetDevice_g)) + { + EPL_DBGLVL_VETH_TRACE0("VEthAddInstance: Could not register VEth...\n"); + } + else + { + EPL_DBGLVL_VETH_TRACE0("VEthAddInstance: Register VEth successfull...\n"); + } + +Exit: + return Ret; +} + + +tEplKernel PUBLIC VEthDelInstance(void) +{ +tEplKernel Ret = kEplSuccessful; + + if (pVEthNetDevice_g != NULL) + { + //unregister VEth from the network subsystem + unregister_netdev(pVEthNetDevice_g); + // destructor was set to free_netdev, + // so we do not need to call free_netdev here + pVEthNetDevice_g = NULL; + } + + return Ret; +} + +#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0) diff --git a/drivers/staging/epl/amix86.c b/drivers/staging/epl/amix86.c new file mode 100644 index 0000000..808fa64 --- /dev/null +++ b/drivers/staging/epl/amix86.c @@ -0,0 +1,945 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: Abstract Memory Interface for x86 compatible + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: amix86.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + ... + + ------------------------------------------------------------------------- + + Revision History: + + r.s.: first implemetation + + 2006-06-13 d.k.: duplicate functions for little endian and big endian + +****************************************************************************/ + +//#include "global.h" +//#include "EplAmi.h" +#include "EplInc.h" + +#if (!defined(EPL_AMI_INLINED)) || defined(INLINE_ENABLED) + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef struct +{ + WORD m_wWord; + +} twStruct; + +typedef struct +{ + DWORD m_dwDword; + +} tdwStruct; + +typedef struct +{ + QWORD m_qwQword; + +} tqwStruct; + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: AmiSetXXXToBe() +// +// Description: writes the specified value to the absolute address in +// big endian +// +// Parameters: pAddr_p = absolute address +// xXXXVal_p = value +// +// Returns: (none) +// +// State: +// +//--------------------------------------------------------------------------- + +//------------< write BYTE in big endian >-------------------------- +/* +void PUBLIC AmiSetByteToBe (void FAR* pAddr_p, BYTE bByteVal_p) +{ + + *(BYTE FAR*)pAddr_p = bByteVal_p; + +} +*/ + + + +//------------< write WORD in big endian >-------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetWordToBe (void FAR* pAddr_p, WORD wWordVal_p) +{ +twStruct FAR* pwStruct; +twStruct wValue; + + wValue.m_wWord = (WORD)((wWordVal_p & 0x00FF) << 8); //LSB to MSB + wValue.m_wWord |= (WORD)((wWordVal_p & 0xFF00) >> 8); //MSB to LSB + + pwStruct = (twStruct FAR*)pAddr_p; + pwStruct->m_wWord = wValue.m_wWord; + +} + + + +//------------< write DWORD in big endian >------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetDwordToBe (void FAR* pAddr_p, DWORD dwDwordVal_p) +{ +tdwStruct FAR* pdwStruct; +tdwStruct dwValue; + + + dwValue.m_dwDword = ((dwDwordVal_p & 0x000000FF)<<24); //LSB to MSB + dwValue.m_dwDword|= ((dwDwordVal_p & 0x0000FF00)<<8); + dwValue.m_dwDword|= ((dwDwordVal_p & 0x00FF0000)>>8 ); + dwValue.m_dwDword|= ((dwDwordVal_p & 0xFF000000)>>24); //MSB to LSB + + pdwStruct = (tdwStruct FAR*)pAddr_p; + pdwStruct->m_dwDword = dwValue.m_dwDword; + +} + + + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetXXXToLe() +// +// Description: writes the specified value to the absolute address in +// little endian +// +// Parameters: pAddr_p = absolute address +// xXXXVal_p = value +// +// Returns: (none) +// +// State: +// +//--------------------------------------------------------------------------- + +//------------< write BYTE in little endian >-------------------------- +/* +void PUBLIC AmiSetByteToLe (void FAR* pAddr_p, BYTE bByteVal_p) +{ + + *(BYTE FAR*)pAddr_p = bByteVal_p; + +} +*/ + + + +//------------< write WORD in little endian >-------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetWordToLe (void FAR* pAddr_p, WORD wWordVal_p) +{ +twStruct FAR* pwStruct; + + pwStruct = (twStruct FAR*)pAddr_p; + pwStruct->m_wWord = wWordVal_p; + +} + + + +//------------< write DWORD in little endian >------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetDwordToLe (void FAR* pAddr_p, DWORD dwDwordVal_p) +{ +tdwStruct FAR* pdwStruct; + + pdwStruct = (tdwStruct FAR*)pAddr_p; + pdwStruct->m_dwDword = dwDwordVal_p; + +} + + + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetXXXFromBe() +// +// Description: reads the specified value from the absolute address in +// big endian +// +// Parameters: pAddr_p = absolute address +// +// Returns: XXX = value +// +// State: +// +//--------------------------------------------------------------------------- + +//------------< read BYTE in big endian >--------------------------- +/* +BYTE PUBLIC AmiGetByteFromBe (void FAR* pAddr_p) +{ + + return ( *(BYTE FAR*)pAddr_p ); + +} +*/ + + + +//------------< read WORD in big endian >--------------------------- + +INLINE_FUNCTION WORD PUBLIC AmiGetWordFromBe (void FAR* pAddr_p) +{ +twStruct FAR* pwStruct; +twStruct wValue; + + pwStruct = (twStruct FAR*)pAddr_p; + + wValue.m_wWord = (WORD)((pwStruct->m_wWord & 0x00FF) << 8); //LSB to MSB + wValue.m_wWord |= (WORD)((pwStruct->m_wWord & 0xFF00) >> 8); //MSB to LSB + + return ( wValue.m_wWord ); + +} + + + + +//------------< read DWORD in big endian >-------------------------- + +INLINE_FUNCTION DWORD PUBLIC AmiGetDwordFromBe (void FAR* pAddr_p) +{ +tdwStruct FAR* pdwStruct; +tdwStruct dwValue; + + pdwStruct = (tdwStruct FAR*)pAddr_p; + + dwValue.m_dwDword = ((pdwStruct->m_dwDword & 0x000000FF)<<24); //LSB to MSB + dwValue.m_dwDword|= ((pdwStruct->m_dwDword & 0x0000FF00)<<8); + dwValue.m_dwDword|= ((pdwStruct->m_dwDword & 0x00FF0000)>>8 ); + dwValue.m_dwDword|= ((pdwStruct->m_dwDword & 0xFF000000)>>24); //MSB to LSB + + return ( dwValue.m_dwDword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetXXXFromLe() +// +// Description: reads the specified value from the absolute address in +// little endian +// +// Parameters: pAddr_p = absolute address +// +// Returns: XXX = value +// +// State: +// +//--------------------------------------------------------------------------- + +//------------< read BYTE in little endian >--------------------------- +/* +BYTE PUBLIC AmiGetByteFromLe (void FAR* pAddr_p) +{ + + return ( *(BYTE FAR*)pAddr_p ); + +} +*/ + + + +//------------< read WORD in little endian >--------------------------- + +INLINE_FUNCTION WORD PUBLIC AmiGetWordFromLe (void FAR* pAddr_p) +{ +twStruct FAR* pwStruct; + + pwStruct = (twStruct FAR*)pAddr_p; + return ( pwStruct->m_wWord ); + +} + + + + +//------------< read DWORD in little endian >-------------------------- + +INLINE_FUNCTION DWORD PUBLIC AmiGetDwordFromLe (void FAR* pAddr_p) +{ +tdwStruct FAR* pdwStruct; + + pdwStruct = (tdwStruct FAR*)pAddr_p; + return ( pdwStruct->m_dwDword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetDword24ToBe() +// +// Description: sets a 24 bit value to a buffer in big endian +// +// Parameters: pAddr_p = pointer to destination buffer +// dwDwordVal_p = value to set +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetDword24ToBe (void FAR* pAddr_p, DWORD dwDwordVal_p) +{ + + ((BYTE FAR*) pAddr_p)[0] = ((BYTE FAR*) &dwDwordVal_p)[2]; + ((BYTE FAR*) pAddr_p)[1] = ((BYTE FAR*) &dwDwordVal_p)[1]; + ((BYTE FAR*) pAddr_p)[2] = ((BYTE FAR*) &dwDwordVal_p)[0]; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetDword24ToLe() +// +// Description: sets a 24 bit value to a buffer in little endian +// +// Parameters: pAddr_p = pointer to destination buffer +// dwDwordVal_p = value to set +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetDword24ToLe (void FAR* pAddr_p, DWORD dwDwordVal_p) +{ + + ((BYTE FAR*) pAddr_p)[0] = ((BYTE FAR*) &dwDwordVal_p)[0]; + ((BYTE FAR*) pAddr_p)[1] = ((BYTE FAR*) &dwDwordVal_p)[1]; + ((BYTE FAR*) pAddr_p)[2] = ((BYTE FAR*) &dwDwordVal_p)[2]; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetDword24FromBe() +// +// Description: reads a 24 bit value from a buffer in big endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: DWORD = read value +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION DWORD PUBLIC AmiGetDword24FromBe (void FAR* pAddr_p) +{ + +tdwStruct dwStruct; + + dwStruct.m_dwDword = AmiGetDwordFromBe (pAddr_p); + dwStruct.m_dwDword >>= 8; + + return ( dwStruct.m_dwDword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetDword24FromLe() +// +// Description: reads a 24 bit value from a buffer in little endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: DWORD = read value +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION DWORD PUBLIC AmiGetDword24FromLe (void FAR* pAddr_p) +{ + +tdwStruct dwStruct; + + dwStruct.m_dwDword = AmiGetDwordFromLe (pAddr_p); + dwStruct.m_dwDword &= 0x00FFFFFF; + + return ( dwStruct.m_dwDword ); + +} + + +//#ifdef USE_VAR64 + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword64ToBe() +// +// Description: sets a 64 bit value to a buffer in big endian +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetQword64ToBe (void FAR* pAddr_p, QWORD qwQwordVal_p) +{ + + ((BYTE FAR*) pAddr_p)[0] = ((BYTE FAR*) &qwQwordVal_p)[7]; + ((BYTE FAR*) pAddr_p)[1] = ((BYTE FAR*) &qwQwordVal_p)[6]; + ((BYTE FAR*) pAddr_p)[2] = ((BYTE FAR*) &qwQwordVal_p)[5]; + ((BYTE FAR*) pAddr_p)[3] = ((BYTE FAR*) &qwQwordVal_p)[4]; + ((BYTE FAR*) pAddr_p)[4] = ((BYTE FAR*) &qwQwordVal_p)[3]; + ((BYTE FAR*) pAddr_p)[5] = ((BYTE FAR*) &qwQwordVal_p)[2]; + ((BYTE FAR*) pAddr_p)[6] = ((BYTE FAR*) &qwQwordVal_p)[1]; + ((BYTE FAR*) pAddr_p)[7] = ((BYTE FAR*) &qwQwordVal_p)[0]; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword64ToLe() +// +// Description: sets a 64 bit value to a buffer in little endian +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetQword64ToLe (void FAR* pAddr_p, QWORD qwQwordVal_p) +{ + +QWORD FAR* pqwDst; + + pqwDst = (QWORD FAR*) pAddr_p; + *pqwDst = qwQwordVal_p; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword64FromBe() +// +// Description: reads a 64 bit value from a buffer in big endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION QWORD PUBLIC AmiGetQword64FromBe (void FAR* pAddr_p) +{ + +tqwStruct qwStruct; + + ((BYTE FAR*) &qwStruct.m_qwQword)[0] = ((BYTE FAR*) pAddr_p)[7]; + ((BYTE FAR*) &qwStruct.m_qwQword)[1] = ((BYTE FAR*) pAddr_p)[6]; + ((BYTE FAR*) &qwStruct.m_qwQword)[2] = ((BYTE FAR*) pAddr_p)[5]; + ((BYTE FAR*) &qwStruct.m_qwQword)[3] = ((BYTE FAR*) pAddr_p)[4]; + ((BYTE FAR*) &qwStruct.m_qwQword)[4] = ((BYTE FAR*) pAddr_p)[3]; + ((BYTE FAR*) &qwStruct.m_qwQword)[5] = ((BYTE FAR*) pAddr_p)[2]; + ((BYTE FAR*) &qwStruct.m_qwQword)[6] = ((BYTE FAR*) pAddr_p)[1]; + ((BYTE FAR*) &qwStruct.m_qwQword)[7] = ((BYTE FAR*) pAddr_p)[0]; + + return ( qwStruct.m_qwQword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword64FromLe() +// +// Description: reads a 64 bit value from a buffer in little endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION QWORD PUBLIC AmiGetQword64FromLe (void FAR* pAddr_p) +{ + +tqwStruct FAR* pqwStruct; +tqwStruct qwStruct; + + pqwStruct = (tqwStruct FAR*) pAddr_p; + qwStruct.m_qwQword = pqwStruct->m_qwQword; + + return ( qwStruct.m_qwQword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword40ToBe() +// +// Description: sets a 40 bit value to a buffer in big endian +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetQword40ToBe (void FAR* pAddr_p, QWORD qwQwordVal_p) +{ + + ((BYTE FAR*) pAddr_p)[0] = ((BYTE FAR*) &qwQwordVal_p)[4]; + ((BYTE FAR*) pAddr_p)[1] = ((BYTE FAR*) &qwQwordVal_p)[3]; + ((BYTE FAR*) pAddr_p)[2] = ((BYTE FAR*) &qwQwordVal_p)[2]; + ((BYTE FAR*) pAddr_p)[3] = ((BYTE FAR*) &qwQwordVal_p)[1]; + ((BYTE FAR*) pAddr_p)[4] = ((BYTE FAR*) &qwQwordVal_p)[0]; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword40ToLe() +// +// Description: sets a 40 bit value to a buffer in little endian +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetQword40ToLe (void FAR* pAddr_p, QWORD qwQwordVal_p) +{ + + ((DWORD FAR*) pAddr_p)[0] = ((DWORD FAR*) &qwQwordVal_p)[0]; + ((BYTE FAR*) pAddr_p)[4] = ((BYTE FAR*) &qwQwordVal_p)[4]; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword40FromBe() +// +// Description: reads a 40 bit value from a buffer in big endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: QWORD +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION QWORD PUBLIC AmiGetQword40FromBe (void FAR* pAddr_p) +{ + +tqwStruct qwStruct; + + qwStruct.m_qwQword = AmiGetQword64FromBe (pAddr_p); + qwStruct.m_qwQword >>= 24; + + return ( qwStruct.m_qwQword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword40FromLe() +// +// Description: reads a 40 bit value from a buffer in little endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: QWORD +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION QWORD PUBLIC AmiGetQword40FromLe (void FAR* pAddr_p) +{ + +tqwStruct qwStruct; + + qwStruct.m_qwQword = AmiGetQword64FromLe (pAddr_p); + qwStruct.m_qwQword &= 0x000000FFFFFFFFFFLL; + + return ( qwStruct.m_qwQword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword48ToBe() +// +// Description: sets a 48 bit value to a buffer in big endian +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetQword48ToBe (void FAR* pAddr_p, QWORD qwQwordVal_p) +{ + + ((BYTE FAR*) pAddr_p)[0] = ((BYTE FAR*) &qwQwordVal_p)[5]; + ((BYTE FAR*) pAddr_p)[1] = ((BYTE FAR*) &qwQwordVal_p)[4]; + ((BYTE FAR*) pAddr_p)[2] = ((BYTE FAR*) &qwQwordVal_p)[3]; + ((BYTE FAR*) pAddr_p)[3] = ((BYTE FAR*) &qwQwordVal_p)[2]; + ((BYTE FAR*) pAddr_p)[4] = ((BYTE FAR*) &qwQwordVal_p)[1]; + ((BYTE FAR*) pAddr_p)[5] = ((BYTE FAR*) &qwQwordVal_p)[0]; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword48ToLe() +// +// Description: sets a 48 bit value to a buffer in little endian +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetQword48ToLe (void FAR* pAddr_p, QWORD qwQwordVal_p) +{ + + ((DWORD FAR*) pAddr_p)[0] = ((DWORD FAR*) &qwQwordVal_p)[0]; + ((WORD FAR*) pAddr_p)[2] = ((WORD FAR*) &qwQwordVal_p)[2]; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword48FromBe() +// +// Description: reads a 48 bit value from a buffer in big endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: QWORD +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION QWORD PUBLIC AmiGetQword48FromBe (void FAR* pAddr_p) +{ + +tqwStruct qwStruct; + + qwStruct.m_qwQword = AmiGetQword64FromBe (pAddr_p); + qwStruct.m_qwQword >>= 16; + + return ( qwStruct.m_qwQword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword48FromLe() +// +// Description: reads a 48 bit value from a buffer in little endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: QWORD +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION QWORD PUBLIC AmiGetQword48FromLe (void FAR* pAddr_p) +{ + +tqwStruct qwStruct; + + qwStruct.m_qwQword = AmiGetQword64FromLe (pAddr_p); + qwStruct.m_qwQword &= 0x0000FFFFFFFFFFFFLL; + + return ( qwStruct.m_qwQword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword56ToBe() +// +// Description: sets a 56 bit value to a buffer in big endian +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetQword56ToBe (void FAR* pAddr_p, QWORD qwQwordVal_p) +{ + + ((BYTE FAR*) pAddr_p)[0] = ((BYTE FAR*) &qwQwordVal_p)[6]; + ((BYTE FAR*) pAddr_p)[1] = ((BYTE FAR*) &qwQwordVal_p)[5]; + ((BYTE FAR*) pAddr_p)[2] = ((BYTE FAR*) &qwQwordVal_p)[4]; + ((BYTE FAR*) pAddr_p)[3] = ((BYTE FAR*) &qwQwordVal_p)[3]; + ((BYTE FAR*) pAddr_p)[4] = ((BYTE FAR*) &qwQwordVal_p)[2]; + ((BYTE FAR*) pAddr_p)[5] = ((BYTE FAR*) &qwQwordVal_p)[1]; + ((BYTE FAR*) pAddr_p)[6] = ((BYTE FAR*) &qwQwordVal_p)[0]; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetQword56ToLe() +// +// Description: sets a 56 bit value to a buffer in little endian +// +// Parameters: pAddr_p = pointer to destination buffer +// qwQwordVal_p = quadruple word value +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetQword56ToLe (void FAR* pAddr_p, QWORD qwQwordVal_p) +{ + + ((DWORD FAR*) pAddr_p)[0] = ((DWORD FAR*) &qwQwordVal_p)[0]; + ((WORD FAR*) pAddr_p)[2] = ((WORD FAR*) &qwQwordVal_p)[2]; + ((BYTE FAR*) pAddr_p)[6] = ((BYTE FAR*) &qwQwordVal_p)[6]; + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword56FromBe() +// +// Description: reads a 56 bit value from a buffer in big endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: QWORD +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION QWORD PUBLIC AmiGetQword56FromBe (void FAR* pAddr_p) +{ + +tqwStruct qwStruct; + + qwStruct.m_qwQword = AmiGetQword64FromBe (pAddr_p); + qwStruct.m_qwQword >>= 8; + + return ( qwStruct.m_qwQword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetQword56FromLe() +// +// Description: reads a 56 bit value from a buffer in little endian +// +// Parameters: pAddr_p = pointer to source buffer +// +// Return: QWORD +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION QWORD PUBLIC AmiGetQword56FromLe (void FAR* pAddr_p) +{ + +tqwStruct qwStruct; + + qwStruct.m_qwQword = AmiGetQword64FromLe (pAddr_p); + qwStruct.m_qwQword &= 0x00FFFFFFFFFFFFFFLL; + + return ( qwStruct.m_qwQword ); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiSetTimeOfDay() +// +// Description: sets a TIME_OF_DAY (CANopen) value to a buffer +// +// Parameters: pAddr_p = pointer to destination buffer +// pTimeOfDay_p = pointer to struct TIME_OF_DAY +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiSetTimeOfDay (void FAR* pAddr_p, tTimeOfDay FAR* pTimeOfDay_p) +{ + + AmiSetDwordToLe (((BYTE FAR*) pAddr_p), pTimeOfDay_p->m_dwMs & 0x0FFFFFFF); + AmiSetWordToLe (((BYTE FAR*) pAddr_p) + 4, pTimeOfDay_p->m_wDays); + +} + + +//--------------------------------------------------------------------------- +// +// Function: AmiGetTimeOfDay() +// +// Description: reads a TIME_OF_DAY (CANopen) value from a buffer +// +// Parameters: pAddr_p = pointer to source buffer +// pTimeOfDay_p = pointer to struct TIME_OF_DAY +// +// Return: void +// +// State: not tested +// +//--------------------------------------------------------------------------- + +INLINE_FUNCTION void PUBLIC AmiGetTimeOfDay (void FAR* pAddr_p, tTimeOfDay FAR* pTimeOfDay_p) +{ + + pTimeOfDay_p->m_dwMs = AmiGetDwordFromLe (((BYTE FAR*) pAddr_p)) & 0x0FFFFFFF; + pTimeOfDay_p->m_wDays = AmiGetWordFromLe (((BYTE FAR*) pAddr_p) + 4); + +} + + +#endif + + + +// EOF + +// Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler +// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder). + diff --git a/drivers/staging/epl/demo_main.c b/drivers/staging/epl/demo_main.c new file mode 100644 index 0000000..24e4b71 --- /dev/null +++ b/drivers/staging/epl/demo_main.c @@ -0,0 +1,937 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: demoapplication for EPL MN (with SDO over UDP) + under Linux on X86 with RTL8139 Ethernet controller + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: demo_main.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.10 $ $Date: 2008/11/19 18:11:43 $ + + $State: Exp $ + + Build Environment: + GCC + + ------------------------------------------------------------------------- + + Revision History: + + 2006/09/01 d.k.: start of implementation + +****************************************************************************/ + + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/major.h> +#include <linux/version.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/atomic.h> +#include <linux/sched.h> +#include <linux/kmod.h> +#include <linux/slab.h> +#include <linux/pci.h> +#include <linux/proc_fs.h> + + +#include "Epl.h" +#include "proc_fs.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + // remove ("make invisible") obsolete symbols for kernel versions 2.6 + // and higher + #define MOD_INC_USE_COUNT + #define MOD_DEC_USE_COUNT + #define EXPORT_NO_SYMBOLS +#else + #error "This driver needs a 2.6.x kernel or higher" +#endif + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +// Metainformation +MODULE_LICENSE("Dual BSD/GPL"); +#ifdef MODULE_AUTHOR + MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com"); + MODULE_DESCRIPTION("EPL MN demo"); +#endif + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + + +// TracePoint support for realtime-debugging +#ifdef _DBG_TRACE_POINTS_ + void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); + #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) +#else + #define TGT_DBG_SIGNAL_TRACE_POINT(p) +#endif + +#define NODEID 0xF0 //=> MN +#define CYCLE_LEN 5000 // [us] +#define IP_ADDR 0xc0a86401 // 192.168.100.1 +#define SUBNET_MASK 0xFFFFFF00 // 255.255.255.0 +#define HOSTNAME "SYS TEC electronic EPL Stack " +#define IF_ETH EPL_VETH_NAME + + +// LIGHT EFFECT +#define DEFAULT_MAX_CYCLE_COUNT 20 // 6 is very fast +#define APP_DEFAULT_MODE 0x01 +#define APP_LED_COUNT 5 // number of LEDs in one row +#define APP_LED_MASK ((1 << APP_LED_COUNT) - 1) +#define APP_DOUBLE_LED_MASK ((1 << (APP_LED_COUNT * 2)) - 1) +#define APP_MODE_COUNT 5 +#define APP_MODE_MASK ((1 << APP_MODE_COUNT) - 1) + + +//--------------------------------------------------------------------------- +// local types +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// modul globale vars +//--------------------------------------------------------------------------- + +CONST BYTE abMacAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +BYTE bVarIn1_l; +BYTE bVarOut1_l; +BYTE bVarOut1Old_l; +BYTE bModeSelect_l; // state of the pushbuttons to select the mode +BYTE bSpeedSelect_l; // state of the pushbuttons to increase/decrease the speed +BYTE bSpeedSelectOld_l; // old state of the pushbuttons +DWORD dwLeds_l; // current state of all LEDs +BYTE bLedsRow1_l; // current state of the LEDs in row 1 +BYTE bLedsRow2_l; // current state of the LEDs in row 2 +BYTE abSelect_l[3]; // pushbuttons from CNs + +DWORD dwMode_l; // current mode +int iCurCycleCount_l; // current cycle count +int iMaxCycleCount_l; // maximum cycle count (i.e. number of cycles until next light movement step) +int iToggle; // indicates the light movement direction + +BYTE abDomain_l[3000]; + +static wait_queue_head_t WaitQueueShutdown_g; // wait queue for tEplNmtEventSwitchOff +static atomic_t AtomicShutdown_g = ATOMIC_INIT(FALSE); + +static DWORD dw_le_CycleLen_g; + +static uint uiNodeId_g = EPL_C_ADR_INVALID; +module_param_named(nodeid, uiNodeId_g, uint, 0); + +static uint uiCycleLen_g = CYCLE_LEN; +module_param_named(cyclelen, uiCycleLen_g, uint, 0); + + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +// This function is the entry point for your object dictionary. It is defined +// in OBJDICT.C by define EPL_OBD_INIT_RAM_NAME. Use this function name to define +// this function prototype here. If you want to use more than one Epl +// instances then the function name of each object dictionary has to differ. + +tEplKernel PUBLIC EplObdInitRam (tEplObdInitParam MEM* pInitParam_p); + +tEplKernel PUBLIC AppCbEvent( + tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg* pEventArg_p, // IN: event argument (union) + void GENERIC* pUserArg_p); + +tEplKernel PUBLIC AppCbSync(void); + +static int __init EplLinInit (void); +static void __exit EplLinExit (void); + +//--------------------------------------------------------------------------- +// Kernel Module specific Data Structures +//--------------------------------------------------------------------------- + +EXPORT_NO_SYMBOLS; + + +//module_init(EplLinInit); +//module_exit(EplLinExit); + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: +// +// Description: +// +// +// +// Parameters: +// +// +// Returns: +// +// +// State: +// +//--------------------------------------------------------------------------- +static int __init EplLinInit (void) +{ +tEplKernel EplRet; +int iRet; +static tEplApiInitParam EplApiInitParam = {0}; +char* sHostname = HOSTNAME; +char* argv[4], *envp[3]; +char sBuffer[16]; +unsigned int uiVarEntries; +tEplObdSize ObdSize; + + atomic_set(&AtomicShutdown_g, TRUE); + + // get node ID from insmod command line + EplApiInitParam.m_uiNodeId = uiNodeId_g; + + if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID) + { // invalid node ID set + // set default node ID + EplApiInitParam.m_uiNodeId = NODEID; + } + + uiNodeId_g = EplApiInitParam.m_uiNodeId; + + // calculate IP address + EplApiInitParam.m_dwIpAddress = (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId; + + EplApiInitParam.m_fAsyncOnly = FALSE; + + EplApiInitParam.m_uiSizeOfStruct = sizeof (EplApiInitParam); + EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof (EplApiInitParam.m_abMacAddress)); +// EplApiInitParam.m_abMacAddress[5] = (BYTE) EplApiInitParam.m_uiNodeId; + EplApiInitParam.m_dwFeatureFlags = -1; + EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection + EplApiInitParam.m_uiIsochrTxMaxPayload = 100; // const + EplApiInitParam.m_uiIsochrRxMaxPayload = 100; // const + EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes + EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes) + EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes) + EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes + EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection + EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size + EplApiInitParam.m_uiPrescaler = 2; // required for sync + EplApiInitParam.m_dwLossOfFrameTolerance = 500000; + EplApiInitParam.m_dwAsyncSlotTimeout = 3000000; + EplApiInitParam.m_dwWaitSocPreq = 150000; + EplApiInitParam.m_dwDeviceType = -1; // NMT_DeviceType_U32 + EplApiInitParam.m_dwVendorId = -1; // NMT_IdentityObject_REC.VendorId_U32 + EplApiInitParam.m_dwProductCode = -1; // NMT_IdentityObject_REC.ProductCode_U32 + EplApiInitParam.m_dwRevisionNumber = -1; // NMT_IdentityObject_REC.RevisionNo_U32 + EplApiInitParam.m_dwSerialNumber = -1; // NMT_IdentityObject_REC.SerialNo_U32 + EplApiInitParam.m_dwSubnetMask = SUBNET_MASK; + EplApiInitParam.m_dwDefaultGateway = 0; + EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname, sizeof(EplApiInitParam.m_sHostname)); + + // currently unset parameters left at default value 0 + //EplApiInitParam.m_qwVendorSpecificExt1; + //EplApiInitParam.m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 + //EplApiInitParam.m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 + //EplApiInitParam.m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device + //EplApiInitParam.m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device + //EplApiInitParam.m_abVendorSpecificExt2[48]; + + // set callback functions + EplApiInitParam.m_pfnCbEvent = AppCbEvent; + EplApiInitParam.m_pfnCbSync = AppCbSync; + + + printk("\n\n Hello, I'm a simple POWERLINK node running as %s!\n (build: %s / %s)\n\n", + (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID ? + "Managing Node" : "Controlled Node"), + __DATE__, __TIME__); + + // initialize the Linux a wait queue for shutdown of this module + init_waitqueue_head(&WaitQueueShutdown_g); + + // initialize the procfs device + EplRet = EplLinProcInit(); + if (EplRet != kEplSuccessful) + { + goto Exit; + } + + // initialize POWERLINK stack + EplRet = EplApiInitialize(&EplApiInitParam); + if(EplRet != kEplSuccessful) + { + goto Exit; + } + + // link process variables used by CN to object dictionary + ObdSize = sizeof(bVarIn1_l); + uiVarEntries = 1; + EplRet = EplApiLinkObject(0x6000, &bVarIn1_l, &uiVarEntries, &ObdSize, 0x01); + if (EplRet != kEplSuccessful) + { + goto Exit; + } + + ObdSize = sizeof(bVarOut1_l); + uiVarEntries = 1; + EplRet = EplApiLinkObject(0x6200, &bVarOut1_l, &uiVarEntries, &ObdSize, 0x01); + if (EplRet != kEplSuccessful) + { + goto Exit; + } + + // link process variables used by MN to object dictionary +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + ObdSize = sizeof(bLedsRow1_l); + uiVarEntries = 1; + EplRet = EplApiLinkObject(0x2000, &bLedsRow1_l, &uiVarEntries, &ObdSize, 0x01); + if (EplRet != kEplSuccessful) + { + goto Exit; + } + + ObdSize = sizeof(bLedsRow2_l); + uiVarEntries = 1; + EplRet = EplApiLinkObject(0x2000, &bLedsRow2_l, &uiVarEntries, &ObdSize, 0x02); + if (EplRet != kEplSuccessful) + { + goto Exit; + } + + ObdSize = sizeof(bSpeedSelect_l); + uiVarEntries = 1; + EplRet = EplApiLinkObject(0x2000, &bSpeedSelect_l, &uiVarEntries, &ObdSize, 0x03); + if (EplRet != kEplSuccessful) + { + goto Exit; + } + + ObdSize = sizeof(bSpeedSelectOld_l); + uiVarEntries = 1; + EplRet = EplApiLinkObject(0x2000, &bSpeedSelectOld_l, &uiVarEntries, &ObdSize, 0x04); + if (EplRet != kEplSuccessful) + { + goto Exit; + } + + ObdSize = sizeof(abSelect_l[0]); + uiVarEntries = sizeof(abSelect_l); + EplRet = EplApiLinkObject(0x2200, &abSelect_l[0], &uiVarEntries, &ObdSize, 0x01); + if (EplRet != kEplSuccessful) + { + goto Exit; + } +#endif + + // link a DOMAIN to object 0x6100, but do not exit, if it is missing + ObdSize = sizeof(abDomain_l); + uiVarEntries = 1; + EplRet = EplApiLinkObject(0x6100, &abDomain_l, &uiVarEntries, &ObdSize, 0x00); + if (EplRet != kEplSuccessful) + { + printk("EplApiLinkObject(0x6100): returns 0x%X\n", EplRet); + } + + // reset old process variables + bVarOut1Old_l = 0; + bSpeedSelectOld_l = 0; + dwMode_l = APP_DEFAULT_MODE; + iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT; + + + // configure IP address of virtual network interface + // for TCP/IP communication over the POWERLINK network + sprintf(sBuffer, "%lu.%lu.%lu.%lu", (EplApiInitParam.m_dwIpAddress >> 24), ((EplApiInitParam.m_dwIpAddress >> 16) & 0xFF), ((EplApiInitParam.m_dwIpAddress >> 8) & 0xFF), (EplApiInitParam.m_dwIpAddress & 0xFF)); + /* set up a minimal environment */ + iRet = 0; + envp[iRet++] = "HOME=/"; + envp[iRet++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; + envp[iRet] = NULL; + + /* set up the argument list */ + iRet = 0; + argv[iRet++] = "/sbin/ifconfig"; + argv[iRet++] = IF_ETH; + argv[iRet++] = sBuffer; + argv[iRet] = NULL; + + /* call ifconfig to configure the virtual network interface */ + iRet = call_usermodehelper(argv[0], argv, envp, 1); + printk("ifconfig %s %s returned %d\n", argv[1], argv[2], iRet); + + // start the NMT state machine + EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset); + atomic_set(&AtomicShutdown_g, FALSE); + +Exit: + printk("EplLinInit(): returns 0x%X\n", EplRet); + return EplRet; +} + +static void __exit EplLinExit (void) +{ +tEplKernel EplRet; + + // halt the NMT state machine + // so the processing of POWERLINK frames stops + EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff); + + // wait until NMT state machine is shut down + wait_event_interruptible(WaitQueueShutdown_g, + (atomic_read(&AtomicShutdown_g) == TRUE)); +/* if ((iErr != 0) || (atomic_read(&AtomicShutdown_g) == EVENT_STATE_IOCTL)) + { // waiting was interrupted by signal or application called wrong function + EplRet = kEplShutdown; + }*/ + // delete instance for all modules + EplRet = EplApiShutdown(); + printk("EplApiShutdown(): 0x%X\n", EplRet); + + // deinitialize proc fs + EplRet = EplLinProcFree(); + printk("EplLinProcFree(): 0x%X\n", EplRet); + +} + + +//=========================================================================// +// // +// P R I V A T E F U N C T I O N S // +// // +//=========================================================================// + +//--------------------------------------------------------------------------- +// +// Function: AppCbEvent +// +// Description: event callback function called by EPL API layer within +// user part (low priority). +// +// Parameters: EventType_p = event type +// pEventArg_p = pointer to union, which describes +// the event in detail +// pUserArg_p = user specific argument +// +// Returns: tEplKernel = error code, +// kEplSuccessful = no error +// kEplReject = reject further processing +// otherwise = post error event to API layer +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC AppCbEvent( + tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg* pEventArg_p, // IN: event argument (union) + void GENERIC* pUserArg_p) +{ +tEplKernel EplRet = kEplSuccessful; + + // check if NMT_GS_OFF is reached + switch (EventType_p) + { + case kEplApiEventNmtStateChange: + { + switch (pEventArg_p->m_NmtStateChange.m_NewNmtState) + { + case kEplNmtGsOff: + { // NMT state machine was shut down, + // because of user signal (CTRL-C) or critical EPL stack error + // -> also shut down EplApiProcess() and main() + EplRet = kEplShutdown; + + printk("AppCbEvent(kEplNmtGsOff) originating event = 0x%X\n", pEventArg_p->m_NmtStateChange.m_NmtEvent); + + // wake up EplLinExit() + atomic_set(&AtomicShutdown_g, TRUE); + wake_up_interruptible(&WaitQueueShutdown_g); + break; + } + + case kEplNmtGsResetCommunication: + { + DWORD dwBuffer; + + // configure OD for MN in state ResetComm after reseting the OD + // TODO: setup your own network configuration here + dwBuffer = (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS); // 0x00000003L + EplRet = EplApiWriteLocalObject(0x1F81, 0x01, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0x02, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0x03, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0x04, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0x05, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0x06, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0x07, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0x08, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0x20, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0xFE, &dwBuffer, 4); + EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4); + +// dwBuffer |= EPL_NODEASSIGN_MANDATORY_CN; // 0x0000000BL +// EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4); + dwBuffer = (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS); // 0x00010001L + EplRet = EplApiWriteLocalObject(0x1F81, 0xF0, &dwBuffer, 4); + + // continue + } + + case kEplNmtGsResetConfiguration: + { + unsigned int uiSize; + + // fetch object 0x1006 NMT_CycleLen_U32 from local OD (in little endian byte order) + // for configuration of remote CN + uiSize = 4; + EplRet = EplApiReadObject(NULL, 0, 0x1006, 0x00, &dw_le_CycleLen_g, &uiSize, kEplSdoTypeAsnd, NULL); + if (EplRet != kEplSuccessful) + { // local OD access failed + break; + } + + // continue + } + + case kEplNmtMsPreOperational1: + { + printk("AppCbEvent(0x%X) originating event = 0x%X\n", + pEventArg_p->m_NmtStateChange.m_NewNmtState, + pEventArg_p->m_NmtStateChange.m_NmtEvent); + + // continue + } + + case kEplNmtGsInitialising: + case kEplNmtGsResetApplication: + case kEplNmtMsNotActive: + case kEplNmtCsNotActive: + case kEplNmtCsPreOperational1: + { + break; + } + + case kEplNmtCsOperational: + case kEplNmtMsOperational: + { + break; + } + + default: + { + break; + } + } + +/* + switch (pEventArg_p->m_NmtStateChange.m_NmtEvent) + { + case kEplNmtEventSwReset: + case kEplNmtEventResetNode: + case kEplNmtEventResetCom: + case kEplNmtEventResetConfig: + case kEplNmtEventInternComError: + case kEplNmtEventNmtCycleError: + { + printk("AppCbEvent(0x%X) originating event = 0x%X\n", + pEventArg_p->m_NmtStateChange.m_NewNmtState, + pEventArg_p->m_NmtStateChange.m_NmtEvent); + break; + } + + default: + { + break; + } + } +*/ + break; + } + + case kEplApiEventCriticalError: + case kEplApiEventWarning: + { // error or warning occured within the stack or the application + // on error the API layer stops the NMT state machine + + printk("AppCbEvent(Err/Warn): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError); + // check additional argument + switch (pEventArg_p->m_InternalError.m_EventSource) + { + case kEplEventSourceEventk: + case kEplEventSourceEventu: + { // error occured within event processing + // either in kernel or in user part + printk(" OrgSource=%02X\n", pEventArg_p->m_InternalError.m_Arg.m_EventSource); + break; + } + + case kEplEventSourceDllk: + { // error occured within the data link layer (e.g. interrupt processing) + // the DWORD argument contains the DLL state and the NMT event + printk(" val=%lX\n", pEventArg_p->m_InternalError.m_Arg.m_dwArg); + break; + } + + default: + { + printk("\n"); + break; + } + } + break; + } + + case kEplApiEventNode: + { +// printk("AppCbEvent(Node): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError); + // check additional argument + switch (pEventArg_p->m_Node.m_NodeEvent) + { + case kEplNmtNodeEventCheckConf: + { + tEplSdoComConHdl SdoComConHdl; + // update object 0x1006 on CN + EplRet = EplApiWriteObject(&SdoComConHdl, pEventArg_p->m_Node.m_uiNodeId, 0x1006, 0x00, &dw_le_CycleLen_g, 4, kEplSdoTypeAsnd, NULL); + if (EplRet == kEplApiTaskDeferred) + { // SDO transfer started + EplRet = kEplReject; + } + else if (EplRet == kEplSuccessful) + { // local OD access (should not occur) + printk("AppCbEvent(Node) write to local OD\n"); + } + else + { // error occured + TGT_DBG_SIGNAL_TRACE_POINT(1); + + EplRet = EplApiFreeSdoChannel(SdoComConHdl); + SdoComConHdl = 0; + + EplRet = EplApiWriteObject(&SdoComConHdl, pEventArg_p->m_Node.m_uiNodeId, 0x1006, 0x00, &dw_le_CycleLen_g, 4, kEplSdoTypeAsnd, NULL); + if (EplRet == kEplApiTaskDeferred) + { // SDO transfer started + EplRet = kEplReject; + } + else + { + printk("AppCbEvent(Node): EplApiWriteObject() returned 0x%02X\n", EplRet); + } + } + + break; + } + + default: + { + break; + } + } + break; + } + + case kEplApiEventSdo: + { // SDO transfer finished + EplRet = EplApiFreeSdoChannel(pEventArg_p->m_Sdo.m_SdoComConHdl); + if (EplRet != kEplSuccessful) + { + break; + } +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + if (pEventArg_p->m_Sdo.m_SdoComConState == kEplSdoComTransferFinished) + { // continue boot-up of CN with NMT command Reset Configuration + EplRet = EplApiMnTriggerStateChange(pEventArg_p->m_Sdo.m_uiNodeId, kEplNmtNodeCommandConfReset); + } + else + { // indicate configuration error CN + EplRet = EplApiMnTriggerStateChange(pEventArg_p->m_Sdo.m_uiNodeId, kEplNmtNodeCommandConfErr); + } +#endif + + break; + } + + default: + break; + } + + return EplRet; +} + + +//--------------------------------------------------------------------------- +// +// Function: AppCbSync +// +// Description: sync event callback function called by event module within +// kernel part (high priority). +// This function sets the outputs, reads the inputs and runs +// the control loop. +// +// Parameters: void +// +// Returns: tEplKernel = error code, +// kEplSuccessful = no error +// otherwise = post error event to API layer +// +// State: +// +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC AppCbSync(void) +{ +tEplKernel EplRet = kEplSuccessful; + + if (bVarOut1Old_l != bVarOut1_l) + { // output variable has changed + bVarOut1Old_l = bVarOut1_l; + // set LEDs + +// printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (WORD) bVarIn_l, (WORD) bVarOut_l); + } + if (uiNodeId_g != EPL_C_ADR_MN_DEF_NODE_ID) + { + bVarIn1_l++; + } + + if (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID) + { // we are the master and must run the control loop + + // collect inputs from CNs and own input + bSpeedSelect_l = (bVarIn1_l | abSelect_l[0]) & 0x07; + + bModeSelect_l = abSelect_l[1] | abSelect_l[2]; + + if ((bModeSelect_l & APP_MODE_MASK) != 0) + { + dwMode_l = bModeSelect_l & APP_MODE_MASK; + } + + iCurCycleCount_l--; + + if (iCurCycleCount_l <= 0) + { + if ((dwMode_l & 0x01) != 0) + { // fill-up + if (iToggle) + { + if ((dwLeds_l & APP_DOUBLE_LED_MASK) == 0x00) + { + dwLeds_l = 0x01; + } + else + { + dwLeds_l <<= 1; + dwLeds_l++; + if (dwLeds_l >= APP_DOUBLE_LED_MASK) + { + iToggle = 0; + } + } + } + else + { + dwLeds_l <<= 1; + if ((dwLeds_l & APP_DOUBLE_LED_MASK) == 0x00) + { + iToggle = 1; + } + } + bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK); + bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK); + } + + else if ((dwMode_l & 0x02) != 0) + { // running light forward + dwLeds_l <<= 1; + if ((dwLeds_l > APP_DOUBLE_LED_MASK) || (dwLeds_l == 0x00000000L)) + { + dwLeds_l = 0x01; + } + bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK); + bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK); + } + + else if ((dwMode_l & 0x04) != 0) + { // running light backward + dwLeds_l >>= 1; + if ((dwLeds_l > APP_DOUBLE_LED_MASK) || (dwLeds_l == 0x00000000L)) + { + dwLeds_l = 1 << (APP_LED_COUNT * 2); + } + bLedsRow1_l = (unsigned char) (dwLeds_l & APP_LED_MASK); + bLedsRow2_l = (unsigned char) ((dwLeds_l >> APP_LED_COUNT) & APP_LED_MASK); + } + + else if ((dwMode_l & 0x08) != 0) + { // Knightrider + if (bLedsRow1_l == 0x00) + { + bLedsRow1_l = 0x01; + iToggle = 1; + } + else if (iToggle) + { + bLedsRow1_l <<= 1; + if ( bLedsRow1_l >= (1 << (APP_LED_COUNT - 1)) ) + { + iToggle = 0; + } + } + else + { + bLedsRow1_l >>= 1; + if( bLedsRow1_l <= 0x01 ) + { + iToggle = 1; + } + } + bLedsRow2_l = bLedsRow1_l; + } + + else if ((dwMode_l & 0x10) != 0) + { // Knightrider + if ((bLedsRow1_l == 0x00) + || (bLedsRow2_l == 0x00) + || ((bLedsRow2_l & ~APP_LED_MASK) != 0)) + { + bLedsRow1_l = 0x01; + bLedsRow2_l = (1 << (APP_LED_COUNT - 1)); + iToggle = 1; + } + else if (iToggle) + { + bLedsRow1_l <<= 1; + bLedsRow2_l >>= 1; + if ( bLedsRow1_l >= (1 << (APP_LED_COUNT - 1)) ) + { + iToggle = 0; + } + } + else + { + bLedsRow1_l >>= 1; + bLedsRow2_l <<= 1; + if ( bLedsRow1_l <= 0x01 ) + { + iToggle = 1; + } + } + } + + // set own output + bVarOut1_l = bLedsRow1_l; +// bVarOut1_l = (bLedsRow1_l & 0x03) | (bLedsRow2_l << 2); + + // restart cycle counter + iCurCycleCount_l = iMaxCycleCount_l; + } + + if (bSpeedSelectOld_l == 0) + { + if ((bSpeedSelect_l & 0x01) != 0) + { + if (iMaxCycleCount_l < 200) + { + iMaxCycleCount_l++; + } + bSpeedSelectOld_l = bSpeedSelect_l; + } + else if ((bSpeedSelect_l & 0x02) != 0) + { + if (iMaxCycleCount_l > 1) + { + iMaxCycleCount_l--; + } + bSpeedSelectOld_l = bSpeedSelect_l; + } + else if ((bSpeedSelect_l & 0x04) != 0) + { + iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT; + bSpeedSelectOld_l = bSpeedSelect_l; + } + } + else if (bSpeedSelect_l == 0) + { + bSpeedSelectOld_l = 0; + } + } + + TGT_DBG_SIGNAL_TRACE_POINT(1); + + return EplRet; +} + + + +// EOF + diff --git a/drivers/staging/epl/edrv.h b/drivers/staging/epl/edrv.h new file mode 100644 index 0000000..139523c --- /dev/null +++ b/drivers/staging/epl/edrv.h @@ -0,0 +1,183 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: interface for ethernetdriver + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: edrv.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + Dev C++ and GNU-Compiler for m68k + + ------------------------------------------------------------------------- + + Revision History: + + 2005/08/01 m.b.: start of implementation + +****************************************************************************/ + +#ifndef _EDRV_H_ +#define _EDRV_H_ + +#include "EplInc.h" +#include "EplFrame.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- +// -------------------------------------------------------------------------- +#define MAX_ETH_DATA_SIZE 1500 +#define MIN_ETH_DATA_SIZE 46 + +#define ETH_HDR_OFFSET 0 // Ethernet header at the top of the frame +#define ETH_HDR_SIZE 14 // size of Ethernet header +#define MIN_ETH_SIZE (MIN_ETH_DATA_SIZE + ETH_HDR_SIZE) // without CRC + +#define ETH_CRC_SIZE 4 // size of Ethernet CRC, i.e. FCS + + + +//--------------------------------------------------------------------------- +// types +//--------------------------------------------------------------------------- + +// position of a buffer in an ethernet-frame +typedef enum +{ + kEdrvBufferFirstInFrame = 0x01, // first data buffer in an ethernet frame + kEdrvBufferMiddleInFrame = 0x02, // a middle data buffer in an ethernet frame + kEdrvBufferLastInFrame = 0x04 // last data buffer in an ethernet frame +} tEdrvBufferInFrame; + + +// format of a tx-buffer +typedef struct _tEdrvTxBuffer +{ + tEplMsgType m_EplMsgType; // IN: type of EPL message, set by calling function + unsigned int m_uiTxMsgLen; // IN: length of message to be send (set for each transmit call) + // ---------------------- + unsigned int m_uiBufferNumber; // OUT: number of the buffer, set by ethernetdriver + BYTE * m_pbBuffer; // OUT: pointer to the buffer, set by ethernetdriver + tEplNetTime m_NetTime; // OUT: Timestamp of end of transmission, set by ethernetdriver + // ---------------------- + unsigned int m_uiMaxBufferLen; // IN/OUT: maximum length of the buffer +} tEdrvTxBuffer; + +// format of a rx-buffer +typedef struct _tEdrvRxBuffer +{ + tEdrvBufferInFrame m_BufferInFrame; // OUT position of received buffer in an ethernet-frame + unsigned int m_uiRxMsgLen; // OUT: length of received buffer (without CRC) + BYTE * m_pbBuffer; // OUT: pointer to the buffer, set by ethernetdriver + tEplNetTime m_NetTime; // OUT: Timestamp of end of receiption + +} tEdrvRxBuffer; + + + +//typedef void (*tEdrvRxHandler) (BYTE bBufferInFrame_p, tBufferDescr * pbBuffer_p); +//typedef void (*tEdrvRxHandler) (BYTE bBufferInFrame_p, BYTE * pbEthernetData_p, WORD wDataLen_p); +typedef void (*tEdrvRxHandler) (tEdrvRxBuffer * pRxBuffer_p); +typedef void (*tEdrvTxHandler) (tEdrvTxBuffer * pTxBuffer_p); + + +// format of init structure +typedef struct +{ + BYTE m_abMyMacAddr[6]; // the own MAC address + +// BYTE m_bNoOfRxBuffDescr; // number of entries in rx bufferdescriptor table +// tBufferDescr * m_pRxBuffDescrTable; // rx bufferdescriptor table +// WORD m_wRxBufferSize; // size of the whole rx buffer + + tEdrvRxHandler m_pfnRxHandler; + tEdrvTxHandler m_pfnTxHandler; + +} tEdrvInitParam; + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +tEplKernel EdrvInit (tEdrvInitParam* pEdrvInitParam_p); + +tEplKernel EdrvShutdown (void); + +tEplKernel EdrvDefineRxMacAddrEntry (BYTE * pbMacAddr_p); +tEplKernel EdrvUndefineRxMacAddrEntry (BYTE * pbMacAddr_p); + +//tEplKernel EdrvDefineUnicastEntry (BYTE * pbUCEntry_p); +//tEplKernel EdrvUndfineUnicastEntry (BYTE * pbUCEntry_p); + +tEplKernel EdrvAllocTxMsgBuffer (tEdrvTxBuffer * pBuffer_p); +tEplKernel EdrvReleaseTxMsgBuffer (tEdrvTxBuffer * pBuffer_p); + +//tEplKernel EdrvWriteMsg (tBufferDescr * pbBuffer_p); +tEplKernel EdrvSendTxMsg (tEdrvTxBuffer * pBuffer_p); +tEplKernel EdrvTxMsgReady (tEdrvTxBuffer * pBuffer_p); +tEplKernel EdrvTxMsgStart (tEdrvTxBuffer * pBuffer_p); + +//tEplKernel EdrvReadMsg (void); + +// interrupt handler called by target specific interrupt handler +void EdrvInterruptHandler (void); + + + +#endif // #ifndef _EDRV_H_ + + diff --git a/drivers/staging/epl/global.h b/drivers/staging/epl/global.h new file mode 100644 index 0000000..797e1f2 --- /dev/null +++ b/drivers/staging/epl/global.h @@ -0,0 +1,1468 @@ +/**************************************************************************** + + global project definition file + + 12.06.1998 -rs + 11.02.2002 r.d. Erweiterungen, Ergaenzungen + 20.08.2002 SYS TEC electronic -as + Definition Schluesselwort 'GENERIC' + fuer das Erzeugen von Generic Pointer + 28.08.2002 r.d. erweiterter SYS TEC Debug Code + 16.09.2002 r.d. komplette Uebersetzung in Englisch + 11.04.2003 f.j. Ergaenzung fuer Mitsubishi NC30 Compiler + 17.06.2003 -rs Definition von Basistypen in <#ifndef _WINDEF_> gesetzt + 16.04.2004 r.d. Ergaenzung fuer Borland C++ Builder + 30.08.2004 -rs TRACE5 eingefügt + 23.12.2005 d.k. Definitions for IAR compiler + + $Id: global.h,v 1.6 2008/11/07 13:55:56 D.Krueger Exp $ + +****************************************************************************/ + +#ifndef _GLOBAL_H_ +#define _GLOBAL_H_ + + +//--------------------------------------------------------------------------- +// elements of defines for development system +//--------------------------------------------------------------------------- + +// these defines are necessary to check some of characteristics of the development system +#define _DEV_BIGEND_ 0x80000000L // big endian (motorolla format) +#define _DEV_ALIGNMENT_4_ 0x00400000L // the CPU needs alignment of 4 bytes +#define _DEV_ONLY_INT_MAIN_ 0x00004000L // the compiler needs "int main(int)" instead of "void main(void)" +#define _DEV_COMMA_EXT_ 0x00002000L // support of last comma in struct predefinition +#define _DEV_64BIT_SUPPORT_ 0x00001000L // support of 64 bit operations +#define _DEV_BIT64_ 0x00000400L // count of bits: 64 bit +#define _DEV_BIT32_ 0x00000300L // 32 bit +#define _DEV_BIT16_ 0x00000200L // 16 bit +#define _DEV_BIT8_ 0x00000100L // 8 bit +#define _DEV_RVCT_ARM_ 0x0000001CL // RealView ARM +#define _DEV_RENESASM32C 0x0000001BL // compiler from: Renesas +#define _DEV_GNUC_MIPS2_ 0x0000001AL // GNU for MIPS2 +#define _DEV_MPLAB_C30_ 0x00000019L // MPLAB C30 for Microchip dsPIC33F series +#define _DEV_GNUC_TC_ 0x00000018L // GNU for Infineon TriCore +#define _DEV_GNUC_X86_ 0x00000017L // GNU for I386 +#define _DEV_IAR_ARM_ 0x00000016L // ARM IAR C/C++ Compiler +#define _DEV_PARADGM_X86 0x00000015L // Paradigm C/C++ for Beck 1x3 +#define _DEV_GNUC_CF_ 0x00000014L // GNU for Coldfire +#define _DEV_KEIL_ARM_ 0x00000013L // Keil ARM +#define _DEV_MSEVC_ 0x00000012L // Microsoft embedded Visual C/C++ +#define _DEV_HIGHTEC_GNUC_X86_ 0x00000011L // Hightec elf386 gcc +#define _DEV_MSVC_RTX_ 0x00000010L // VC600 + RTX +#define _DEV_MSVC_V1_5_ 0x0000000FL // Microsoft Visual C/C++ V1.5 +#define _DEV_GNUC_ARM7_ 0x0000000EL // GNU Compiler gcc for ARM7 +#define _DEV_METROWERKS_CW_ 0x0000000DL // Metrowerks Code Warrior +#define _DEV_MITSUBISHIM16C_ 0x0000000CL //compiler from: Mitsubishi +#define _DEV_GNUC_C16X_ 0x0000000BL // GNU Compiler gcc166 for Infineon C16x +#define _DEV_LINUX_GCC_ 0x0000000AL // Linux GNU Compiler gcc +#define _DEV_GNUC_MPC5X5 0x00000009L // GNU for Motorola PPC5x5 +#define _DEV_TASKINGM16C_ 0x00000008L // Tasking for Mitsubishi M16C +#define _DEV_FUJITSU_ 0x00000007L // Fujitsu +#define _DEV_TASKING8_ 0x00000006L // Tasking 8051 +#define _DEV_TASKING16_ 0x00000005L // Tasking 166 +#define _DEV_KEIL8_ 0x00000004L // Keil C51 +#define _DEV_KEIL16_ 0x00000003L // Keil C166 +#define _DEV_BORLANDC_ 0x00000002L // Borland C/C++ +#define _DEV_MSVC16_ 0x00000001L // Microsoft Visual C/C++ +#define _DEV_MSVC32_ 0x00000000L // Microsoft Visual C/C++ + +// these defines can be used to mask previous elements +#define _DEV_MASK_COMPILER 0x000000FFL +#define _DEV_MASK_BITCOUNT 0x00000F00L +#define _DEV_MASK_ADDSUPPORT 0x0000F000L +#define _DEV_MASK_ALIGNMENT 0x00F00000L + + +//--------------------------------------------------------------------------- +// defines for development system (DEV_SYSTEM) including previous elements +//--------------------------------------------------------------------------- + +#define _DEV_WIN16_ (_DEV_BIT16_ | _DEV_MSVC16_ ) +#define _DEV_WIN32_ (_DEV_BIT32_ | _DEV_MSVC32_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_MSVC_DOS_ (_DEV_BIT32_ | _DEV_MSVC_V1_5_ ) +#define _DEV_BORLAND_DOS_ (_DEV_BIT32_ | _DEV_BORLANDC_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_KEIL_C51X_ (_DEV_BIT8_ | _DEV_KEIL8_ | _DEV_BIGEND_ | _DEV_COMMA_EXT_) // at least C51 version 7.05 supports comma extension +#define _DEV_KEIL_C16X_ (_DEV_BIT16_ | _DEV_KEIL16_ | _DEV_COMMA_EXT_) // at least C166 version 5.03 supports comma extension +#define _DEV_TASKING_C51X_ (_DEV_BIT8_ | _DEV_TASKING8_ | _DEV_BIGEND_) +#define _DEV_TASKING_C16X_ (_DEV_BIT16_ | _DEV_TASKING16_ ) +#define _DEV_FUJITSU_F590_ (_DEV_BIT8_ | _DEV_FUJITSU_ | _DEV_COMMA_EXT_) // softune is not able to support 64 bit variables QWORD !!! +//f.j.29.04.03 M16C kann effektiv mit Bytes umgehen +//#define _DEV_TASKING_M16C_ (_DEV_BIT16_ | _DEV_TASKINGM16C_ ) +#define _DEV_TASKING_M16C_ (_DEV_BIT8_ | _DEV_TASKINGM16C_ ) +#define _DEV_MITSUBISHI_M16C_ (_DEV_BIT8_ | _DEV_MITSUBISHIM16C_ ) +#define _DEV_GNU_MPC5X5_ (_DEV_BIT32_ | _DEV_GNUC_MPC5X5| _DEV_BIGEND_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_LINUX_ (_DEV_BIT32_ | _DEV_LINUX_GCC_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_GNU_C16X_ (_DEV_BIT16_ | _DEV_GNUC_C16X_ ) //| _DEV_COMMA_EXT_) +#define _DEV_MCW_MPC5X5_ (_DEV_BIT32_ | _DEV_METROWERKS_CW_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_GNU_ARM7_ (_DEV_BIT32_ | _DEV_GNUC_ARM7_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_) +#define _DEV_WIN32_RTX_ (_DEV_BIT32_ | _DEV_MSVC_RTX_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_HIGHTEC_X86_ (_DEV_BIT32_ | _DEV_HIGHTEC_GNUC_X86_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_WIN_CE_ (_DEV_BIT32_ | _DEV_MSEVC_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_KEIL_CARM_ (_DEV_BIT32_ | _DEV_KEIL_ARM_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_IAR_CARM_ (_DEV_BIT32_ | _DEV_IAR_ARM_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_RVCT_CARM_ (_DEV_BIT32_ | _DEV_RVCT_ARM_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_) +#define _DEV_MCW_MCF5XXX_ (_DEV_BIT32_ | _DEV_METROWERKS_CW_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_GNU_CF5282_ (_DEV_BIT32_ | _DEV_GNUC_CF_ | _DEV_BIGEND_) +#define _DEV_PAR_BECK1X3_ (_DEV_BIT16_ | _DEV_PARADGM_X86) +#define _DEV_GNU_CF548X_ (_DEV_BIT32_ | _DEV_GNUC_CF_ | _DEV_BIGEND_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) +#define _DEV_GNU_I386_ (_DEV_BIT32_ | _DEV_GNUC_X86_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_) +#define _DEV_GNU_TRICORE_ (_DEV_BIT32_ | _DEV_GNUC_TC_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_ | _DEV_ALIGNMENT_4_) +#define _DEV_MPLAB_DSPIC33F_ (_DEV_BIT16_ | _DEV_MPLAB_C30_ ) //| _DEV_COMMA_EXT_) +#define _DEV_GNU_MIPSEL_ (_DEV_BIT32_ | _DEV_GNUC_MIPS2_ | _DEV_BIGEND_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_) + +#define _DEV_RENESAS_M32C_ (_DEV_BIT32_ | _DEV_RENESASM32C) + +//--------------------------------------------------------------------------- +// usefull macros +//--------------------------------------------------------------------------- + +#define CHECK_IF_ONLY_INT_MAIN() (DEV_SYSTEM & _DEV_ONLY_INT_MAIN_) +#define CHECK_MEMORY_ALINMENT() (DEV_SYSTEM & _DEV_MASK_ALIGNMENT) + + +//--------------------------------------------------------------------------- +// defines for target system (TARGET_SYSTEM) +//--------------------------------------------------------------------------- + +#define _DOS_ (16 + 0x10000) +#define _WIN16_ 16 +#define _WIN32_ 32 +#define _WINCE_ (32 + 0x20000) +#define _NO_OS_ 0 +#define _LINUX_ 1 +#define _PXROS_ 2 +#define _ECOSPRO_ 3 + + +//--------------------------------------------------------------------------- +// definitions for function inlining +//--------------------------------------------------------------------------- + +#define INLINE_FUNCTION // empty define +#undef INLINE_ENABLED // disable actual inlining of functions +#undef INLINE_FUNCTION_DEF // disable inlining for all compilers per default + +//--------------------------------------------------------------------------- +// definitions for Keil C51 +//--------------------------------------------------------------------------- + +#ifdef __C51__ + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_KEIL_C51X_ + + #pragma DEBUG OBJECTEXTEND + #pragma WARNINGLEVEL(2) // maximum warning level + + #define NEAR idata // variables mapped to internal data storage location + #define FAR xdata // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM code // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC xdata // hardware access through external memory (i.e. CAN) + #define LARGE large // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM xdata // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT reentrant + #define PUBLIC + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + + +//--------------------------------------------------------------------------- +// definitions for GNU Compiler for Infineon C16x +// - it have to be befor Keil (it has __C166__ too) +//--------------------------------------------------------------------------- +#elif defined (__GNUC__) && defined (__C166__) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_GNU_C16X_ + +// #define NEAR idata // variables mapped to internal data storage location + #define NEAR near // variables mapped to internal data storage location +// #define FAR xhuge // variables mapped to external data storage location + #define FAR huge // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; +// #define HWACC sdata // hardware access through external memory (i.e. CAN) + #define HWACC huge // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. +// #define GENERIC xhuge // generic pointer to point to application data + #define GENERIC huge // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + + #define ASSERT(p) \ + if (p) \ + { \ + ; \ + } \ + else \ + { \ + PRINTF0("Assert failed: " #p " (file %s line %d)\n", __FILE__, (int) __LINE__ ); \ + while (1); \ + } + #else + #define ASSERT(p) + #endif + +//--------------------------------------------------------------------------- +// definitions for Keil C166 +//--------------------------------------------------------------------------- +#elif defined (__C166__) // 24.01.2005 r.d.: Keil ARM7 needs directive 'defined' + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_KEIL_C16X_ + + #pragma CODE + #pragma MOD167 + #pragma NOINIT + #pragma DEBUG + #pragma WARNINGLEVEL(3) // maximum warning level + #pragma WARNING DISABLE = 47 // warning <unreferenced parameter> = OFF + #pragma WARNING DISABLE = 38 // warning <empty translation unit> = OFF +// #pragma WARNING DISABLE = 102 // warning <different const/volatile qualifiers> = OFF + #pragma WARNING DISABLE = 174 // warning <unreferenced 'static' function> = OFF + #pragma WARNING DISABLE = 183 // warning <dead assignement eliminated> = OFF + + #define NEAR idata // variables mapped to internal data storage location + #define FAR xhuge // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; +// #define HWACC sdata // hardware access through external memory (i.e. CAN) + #define HWACC huge // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC xhuge // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + +//--------------------------------------------------------------------------- +// definitions for MPLAB C30 for dsPIC33F series +//--------------------------------------------------------------------------- +#elif defined (__C30__) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_MPLAB_DSPIC33F_ + + #define NEAR // variables mapped to internal data storage location + #define FAR // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + +// #ifndef QWORD +// #define QWORD long long +// #endif + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + +//--------------------------------------------------------------------------- +// definitions for Keil ARM +//--------------------------------------------------------------------------- +#elif defined (__CA__) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_KEIL_CARM_ + + #define NEAR // variables mapped to internal data storage location + #define FAR // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + + #ifndef QWORD + #define QWORD long long + #endif + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + +//--------------------------------------------------------------------------- +// definitions for RealView ARM compilation tools (provided by recent Keil Microcontroller Development Kits) +//--------------------------------------------------------------------------- +#elif defined (__ARMCC_VERSION) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_RVCT_CARM_ + + #define NEAR // variables mapped to internal data storage location + #define FAR // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + + #ifndef QWORD + #define QWORD long long + #endif + + #ifndef NDEBUG + #define ASSERT(expr) if (!(expr)) {\ + TRACE0 ("Assertion failed: " #expr );\ + while (1);} + #else + #define ASSERT(expr) + #endif + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + +//--------------------------------------------------------------------------- +// definitions for ARM IAR C Compiler +//--------------------------------------------------------------------------- +#elif defined (__ICCARM__) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_IAR_CARM_ + + #define NEAR // variables mapped to internal data storage location + #define FAR // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + + #ifndef QWORD + #define QWORD long long + #endif + + // Workaround: + // If we use IAR and want to debug but don't want to use C-Spy Debugger + // assert() doesn't work in debug mode because it needs support for FILE descriptors + // (_DLIB_FILE_DESCRIPTOR == 1). + #ifndef NDEBUG + #define ASSERT(expr) if (!(expr)) {\ + TRACE0 ("Assertion failed: " #expr );\ + while (1);} + #else + #define ASSERT(expr) + #endif + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf +// #define TRACE PRINTF4 + #endif + +//--------------------------------------------------------------------------- +// definitions for Tasking 8051 +//--------------------------------------------------------------------------- + +#elif defined (_CC51) + + #include <cc51.h> + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_TASKING_C51X_ + + #define NEAR _data // variables mapped to internal data storage location + #define FAR _xdat // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC _xdat // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM _xdat // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT _reentrant + #define PUBLIC + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + + +//--------------------------------------------------------------------------- +// definitions for Tasking C167CR and C164CI +//--------------------------------------------------------------------------- + +#elif defined (_C166) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_TASKING_C16X_ + + #define NEAR near // variables mapped to internal data storage location + #define FAR far // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC /* to be defined */ // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + + // Stdio.h has to be alway included here. If printf() is used stdio.h defines NULL + // without checking if it is already included. So an error occurs while compiling. + // (r.d.) + #include <stdio.h> // prototype printf() (for TRACE) + #ifndef NDEBUG + #define TRACE printf + #endif + + +//--------------------------------------------------------------------------- +// definitions for FUJITSU FFMC-16LX MB90590 +//--------------------------------------------------------------------------- + +//#elif (defined (F590) || defined (F543) || defined (F598) || defined (F495) || defined (F350)) +#elif defined(__COMPILER_FCC907__) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_FUJITSU_F590_ + + #define NEAR /* to be defined */ // variables mapped to internal data storage location + #define FAR /* to be defined */ // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM /* to be defined */ // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC /* to be defined */ // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + // softune is not able to support 64 bit variables QWORD !!! + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + + +//--------------------------------------------------------------------------- +// definitions for Mitsubishi M16C family for TASKING Compiler CM16 +//--------------------------------------------------------------------------- + +#elif defined (_CM16C) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_TASKING_M16C_ + + #define NEAR _near // variables mapped to internal data storage location + #define FAR _far // variables mapped to external data storage location + #define CONST _farrom // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC _near // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC _far // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + // do you use memory model SMALL, than you have to set _far + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + + // Stdio.h has to be alway included here. If printf() is used stdio.h defines NULL + // without checking if it is already included. So an error occurs while compiling. + // (r.d.) + #include <stdio.h> // prototype printf() (for TRACE) + #ifndef NDEBUG + #define TRACE printf + #endif + + +//--------------------------------------------------------------------------- +// definitions for Mitsubishi M16C family for Mitsubishi Compiler NC30 +//--------------------------------------------------------------------------- +// name NC30, andere Form will der Compiler nicht !! +#elif defined (NC30) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_MITSUBISHI_M16C_ + + #define NEAR near // variables mapped to internal data storage location + #define FAR far // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC near // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC far // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + +//--------------------------------------------------------------------------- +// definitions for Renesas M32C family for Renesas Compiler +//--------------------------------------------------------------------------- +#elif defined (NC308) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_RENESAS_M32C_ + + #define NEAR near // variables mapped to internal data storage location + #define FAR far // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + #define HWACC // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM far // Memory attribute to optimize speed and code of pointer access. + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + +// #error ("RENESAS o.k.") + +//--------------------------------------------------------------------------- +// definitions for ARM7 family with GNU compiler +//--------------------------------------------------------------------------- + +#elif defined(__GNUC__) && defined(__arm__) && !defined(__LINUX_ARM_ARCH__) + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_GNU_ARM7_ + + #define NEAR // variables mapped to internal data storage location + #define FAR // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + #define HWACC // hardware access through external memory (i.e. CAN) + + #define REENTRANT + #define PUBLIC + + #ifndef QWORD + #define QWORD long long // i.A. durch Herr Kuschel + #endif + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + + +//--------------------------------------------------------------------------- +// definitions for Motorola PowerPC family 5x5 (555/565) +// definitions Linux-PC +//--------------------------------------------------------------------------- + +#elif defined (__GNUC__) + + #if defined (LINUX) || defined (linux) || defined (__linux__) + #define LINUX_SYSTEM // define 'LINUX_SYSTEM' uniform for all Linux based systems + // r.d.: We will need an other solution here! There are two sections here which do check the preproc-definitions: + // LINUX and __linux__ . The first one was Linux for PC, the second one is this section for embedded Linux (MCF5xxx). + // But Linux for PC does not need the definitions for embedded Linux. + #endif + + // GNU C compiler supports function inlining + #define INLINE_FUNCTION_DEF extern inline + + // to actually enable inlining just include the following three lines + // #undef INLINE_FUNCTION + // #define INLINE_FUNCTION INLINE_FUNCTION_DEF + // #define INLINE_ENABLED TRUE + + #ifdef PXROS + #define TARGET_SYSTEM _PXROS_ + #ifdef __i386__ + #undef LINUX // this define seems to be set from compiler + #define DEV_SYSTEM _DEV_HIGHTEC_X86_ + #elif defined (__tricore__) + #define DEV_SYSTEM _DEV_GNU_TRICORE_ + #else // MPC5x5 + #define DEV_SYSTEM _DEV_GNU_MPC5X5_ + #endif + + #elif defined (LINUX) || defined (__linux__) + #define TARGET_SYSTEM _LINUX_ // Linux definition + #define DEV_SYSTEM _DEV_LINUX_ + + #elif defined (GNU_CF5282) + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_GNU_CF5282_ + + #elif defined (ECOSPRO_I386_PEAK_PCI) + #define TARGET_SYSTEM _ECOSPRO_ + #define DEV_SYSTEM _DEV_GNU_I386_ + + #elif defined (GNU_CF548X) + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_GNU_CF548X_ + #else + #error 'ERROR: DEV_SYSTEM not found!' + #endif + + + #ifndef QWORD + #define QWORD long long int + #endif + + #if (TARGET_SYSTEM == _PXROS_) + + #ifndef __KERNEL__ + #include <string.h> + #endif + + + #define NEAR // variables mapped to internal data storage location + #define FAR // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM /* to be defined */ // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define HWACC // hardware access through external memory (i.e. CAN) + + #define REENTRANT + #define PUBLIC + + #ifndef QWORD + #define QWORD long long int + #endif + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + + #endif + + // ------------------ GNUC for I386 --------------------------------------------- + + #if (TARGET_SYSTEM == _LINUX_) || (TARGET_SYSTEM == _ECOSPRO_) + + #ifndef __KERNEL__ + #include <string.h> + #endif + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #ifndef NEAR + #define NEAR // variables mapped to internal data storage location + #endif + + #ifndef FAR + #define FAR // variables mapped to external data storage location + #endif + + #ifndef CONST + #define CONST const // variables mapped to ROM (i.e. flash) + #endif + + #define LARGE + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #ifndef __KERNEL__ + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #else + #define TRACE printk + #endif + #endif + #endif + + // ------------------ GNU without OS --------------------------------------------- + + #if (TARGET_SYSTEM == _NO_OS_) + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #ifndef NEAR + #define NEAR // variables mapped to internal data storage location + #endif + + #ifndef FAR + #define FAR // variables mapped to external data storage location + #endif + + #ifndef CONST + #define CONST const // variables mapped to ROM (i.e. flash) + #endif + + #define LARGE + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG +// #include "xuartdrv.h" +// #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf +// #define TRACE mprintf +// #ifndef TRACE +// #define TRACE trace +// void trace (char *fmt, ...); +// #endif + #endif + + #endif + +//--------------------------------------------------------------------------- +// definitions for MPC565 +//--------------------------------------------------------------------------- +#elif __MWERKS__ + + +#ifdef __MC68K__ + + #define TARGET_SYSTEM = _MCF548X_ + #define DEV_SYSTEM _DEV_MCW_MCF5XXX_ + +#else + #define TARGET_SYSTEM = _MPC565_ + #define DEV_SYSTEM _DEV_MCW_MPC5X5_ +#endif + + #define NEAR // variables mapped to internal data storage location + #define FAR // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define LARGE // functions set parameters to external data storage location + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #define HWACC // hardware access through external memory (i.e. CAN) + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #include <stdio.h> // prototype printf() (for TRACE) + #define TRACE printf + #endif + +//--------------------------------------------------------------------------- +// definitions for BECK 1x3 +//--------------------------------------------------------------------------- +#elif defined (__BORLANDC__) && defined (__PARADIGM__) + + + #define TARGET_SYSTEM _NO_OS_ + #define DEV_SYSTEM _DEV_PAR_BECK1X3_ + + + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + #define NEAR __near // variables mapped to internal data storage location + #define FAR __far // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define LARGE + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #ifndef TRACE + #include <stdio.h> + #define TRACE printf + #endif + #endif + + + +//--------------------------------------------------------------------------- +// definitions for PC +//--------------------------------------------------------------------------- + +#elif defined (__BORLANDC__) + + // ------------------ definition target system -------------------------- + + #ifdef _WIN32 + #define TARGET_SYSTEM _WIN32_ // WIN32 definition + #define DEV_SYSTEM _DEV_WIN32_ + #else + #define TARGET_SYSTEM _DOS_ + #define DEV_SYSTEM _DEV_BORLAND_DOS_ + #endif + + + // ------------------ WIN32 --------------------------------------------- + + #if (TARGET_SYSTEM == _WIN32_) + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #ifndef NEAR + #define NEAR // variables mapped to internal data storage location + #endif + + #ifndef FAR + #define FAR // variables mapped to external data storage location + #endif + + #ifndef CONST + #define CONST const // variables mapped to ROM (i.e. flash) + #endif + + #define LARGE + + #define REENTRANT + #define PUBLIC __stdcall + + #ifndef NDEBUG + #ifndef TRACE + #include <stdio.h> + #define TRACE printf + #endif + #endif + + #elif (TARGET_SYSTEM == _DOS_) + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + #define NEAR near // variables mapped to internal data storage location + #define FAR far // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define LARGE + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #ifndef TRACE + #include <stdio.h> + #define TRACE printf + #endif + #endif + + #endif + +#elif (_MSC_VER == 800) // PC MS Visual C/C++ for DOS applications + + #define TARGET_SYSTEM _DOS_ + #define DEV_SYSTEM _DEV_MSVC_DOS_ + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC near // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + #define NEAR near // variables mapped to internal data storage location + #define FAR far // variables mapped to external data storage location + #define CONST const // variables mapped to ROM (i.e. flash) + #define LARGE + + #define REENTRANT + #define PUBLIC + + #ifndef NDEBUG + #ifndef TRACE + #include <stdio.h> + #define TRACE printf + #endif + #endif + + +//--------------------------------------------------------------------------- +// definitions for RTX under WIN32 +//--------------------------------------------------------------------------- +#elif (defined (UNDER_RTSS) && defined (WIN32)) + + // ------------------ definition target system -------------------------- + #define TARGET_SYSTEM _WIN32_RTX_ + #define DEV_SYSTEM _DEV_WIN32_RTX_ + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #ifndef NEAR + #define NEAR // variables mapped to internal data storage location + #endif + + #ifndef FAR + #define FAR // variables mapped to external data storage location + #endif + + #ifndef CONST + #define CONST const // variables mapped to ROM (i.e. flash) + #endif + + #define LARGE + + #define REENTRANT + #define PUBLIC __stdcall + + #ifndef NDEBUG + #ifndef TRACE + #define TRACE RtPrintf + #endif + #endif + +//--------------------------------------------------------------------------- +// definitions for WinCE +//--------------------------------------------------------------------------- +#elif defined (_WIN32_WCE) + + // ------------------ definition target system -------------------------- + #define TARGET_SYSTEM _WINCE_ + #define DEV_SYSTEM _DEV_WIN_CE_ + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #ifndef NEAR + #define NEAR // variables mapped to internal data storage location + #endif + + #ifndef FAR + #define FAR // variables mapped to external data storage location + #endif + + #ifndef CONST + #define CONST const // variables mapped to ROM (i.e. flash) + #endif + + #define LARGE + + #ifndef QWORD + //#define QWORD long long int // MSVC .NET can use "long long int" too (like GNU) + #define QWORD __int64 + #endif + + #define REENTRANT + #define PUBLIC __cdecl + + #ifdef ASSERTMSG + #undef ASSERTMSG + #endif + + #ifndef NDEBUG + #ifndef TRACE + #define TRACE printf +// void trace (char *fmt, ...); + #endif + #endif + +#else // ===> PC MS Visual C/C++ + + // ------------------ definition target system -------------------------- + + #ifdef _WIN32 + #define TARGET_SYSTEM _WIN32_ // WIN32 definition + #define DEV_SYSTEM _DEV_WIN32_ + #else + #define TARGET_SYSTEM _WIN16_ // WIN16 definition + #define DEV_SYSTEM _DEV_WIN16_ + #endif + + + // ------------------ WIN16 --------------------------------------------- + + #if (TARGET_SYSTEM == _WIN16_) + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #ifndef NEAR + #define NEAR // variables mapped to internal data storage location + #endif + + #ifndef FAR + #define FAR far // variables mapped to external data storage location + #endif + + #ifndef CONST + #define CONST const // variables mapped to ROM (i.e. flash) + #endif + + #define LARGE + + #define REENTRANT + #define PUBLIC _far _pascal _export + + #ifndef NDEBUG + #ifndef TRACE + #define TRACE trace + #ifdef __cplusplus + extern "C" + { + #endif + void trace (const char *fmt, ...); + #ifdef __cplusplus + } + #endif + #endif + #endif + + #endif + + + // ------------------ WIN32 --------------------------------------------- + + #if (TARGET_SYSTEM == _WIN32_) + + #define ROM // code or variables mapped to ROM (i.e. flash) + // usage: CONST BYTE ROM foo = 0x00; + #define HWACC // hardware access through external memory (i.e. CAN) + + // These types can be adjusted by users to match application requirements. The goal is to + // minimize code memory and maximize speed. + #define GENERIC // generic pointer to point to application data + // Variables with this attribute can be located in external + // or internal data memory. + #define MEM // Memory attribute to optimize speed and code of pointer access. + + #ifndef NEAR + #define NEAR // variables mapped to internal data storage location + #endif + + #ifndef FAR + #define FAR // variables mapped to external data storage location + #endif + + #ifndef CONST + #define CONST const // variables mapped to ROM (i.e. flash) + #endif + + #define LARGE + + #define REENTRANT + #define PUBLIC __stdcall + + #ifndef QWORD + //#define QWORD long long int // MSVC .NET can use "long long int" too (like GNU) + #define QWORD __int64 + #endif + + #ifndef NDEBUG + #ifndef TRACE + #define TRACE trace + #ifdef __cplusplus + extern "C" + { + #endif + void trace (const char *fmt, ...); + #ifdef __cplusplus + } + #endif + #endif + #endif + + // MS Visual C++ compiler supports function inlining + #define INLINE_FUNCTION_DEF __forceinline + + // to actually enable inlining just include the following two lines + // #define INLINE_FUNCTION INLINE_FUNCTION_DEF + // #define INLINE_ENABLED TRUE + + #endif + +#endif // ===> PC + + +//--------------------------------------------------------------------------- +// definitions of basic types +//--------------------------------------------------------------------------- + +#ifndef _WINDEF_ // defined in WINDEF.H, included by <windows.h> + + // --- arithmetic types --- + #ifndef SHORT + #define SHORT short int + #endif + + #ifndef USHORT + #define USHORT unsigned short int + #endif + + #ifndef INT + #define INT int + #endif + + #ifndef UINT + #define UINT unsigned int + #endif + + #ifndef LONG + #define LONG long int + #endif + + #ifndef ULONG + #define ULONG unsigned long int + #endif + + + // --- logic types --- + #ifndef BYTE + #define BYTE unsigned char + #endif + + #ifndef WORD + #define WORD unsigned short int + #endif + + #ifndef DWORD + #define DWORD unsigned long int + #endif + + #ifndef BOOL + #define BOOL unsigned char + #endif + + + // --- alias types --- + #ifndef TRUE + #define TRUE 0xFF + #endif + + #ifndef FALSE + #define FALSE 0x00 + #endif + + #ifndef NULL + #define NULL ((void *) 0) + #endif + +#endif + + +#ifndef _TIME_OF_DAY_DEFINED_ + + typedef struct + { + unsigned long int m_dwMs; + unsigned short int m_wDays; + + } tTimeOfDay; + + #define _TIME_OF_DAY_DEFINED_ + +#endif + + +//--------------------------------------------------------------------------- +// Definition von TRACE +//--------------------------------------------------------------------------- + +#ifndef NDEBUG + + #ifndef TRACE0 + #define TRACE0(p0) TRACE(p0) + #endif + + #ifndef TRACE1 + #define TRACE1(p0, p1) TRACE(p0, p1) + #endif + + #ifndef TRACE2 + #define TRACE2(p0, p1, p2) TRACE(p0, p1, p2) + #endif + + #ifndef TRACE3 + #define TRACE3(p0, p1, p2, p3) TRACE(p0, p1, p2, p3) + #endif + + #ifndef TRACE4 + #define TRACE4(p0, p1, p2, p3, p4) TRACE(p0, p1, p2, p3, p4) + #endif + + #ifndef TRACE5 + #define TRACE5(p0, p1, p2, p3, p4, p5) TRACE(p0, p1, p2, p3, p4, p5) + #endif + + #ifndef TRACE6 + #define TRACE6(p0, p1, p2, p3, p4, p5, p6) TRACE(p0, p1, p2, p3, p4, p5, p6) + #endif + +#else + + #ifndef TRACE0 + #define TRACE0(p0) + #endif + + #ifndef TRACE1 + #define TRACE1(p0, p1) + #endif + + #ifndef TRACE2 + #define TRACE2(p0, p1, p2) + #endif + + #ifndef TRACE3 + #define TRACE3(p0, p1, p2, p3) + #endif + + #ifndef TRACE4 + #define TRACE4(p0, p1, p2, p3, p4) + #endif + + #ifndef TRACE5 + #define TRACE5(p0, p1, p2, p3, p4, p5) + #endif + + #ifndef TRACE6 + #define TRACE6(p0, p1, p2, p3, p4, p5, p6) + #endif + +#endif + + + +//--------------------------------------------------------------------------- +// definition of ASSERT +//--------------------------------------------------------------------------- + +#ifndef ASSERT + #if !defined (__linux__) && !defined (__KERNEL__) + #include <assert.h> + #ifndef ASSERT + #define ASSERT(p) assert(p) + #endif + #else + #define ASSERT(p) + #endif +#endif + + +//--------------------------------------------------------------------------- +// SYS TEC extensions +//--------------------------------------------------------------------------- + +// This macro doesn't print out C-file and line number of the failed assertion +// but a string, which exactly names the mistake. +#ifndef NDEBUG + + #define ASSERTMSG(expr,string) if (!(expr)) {\ + PRINTF0 ("Assertion failed: " string );\ + while (1);} +#else + #define ASSERTMSG(expr,string) +#endif + + + + +//--------------------------------------------------------------------------- + +#endif // #ifndef _GLOBAL_H_ + +// Please keep an empty line at the end of this file. + diff --git a/drivers/staging/epl/kernel/EplDllk.h b/drivers/staging/epl/kernel/EplDllk.h new file mode 100644 index 0000000..d48b8af --- /dev/null +++ b/drivers/staging/epl/kernel/EplDllk.h @@ -0,0 +1,171 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for kernelspace DLL module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDllk.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/08 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_DLLK_H_ +#define _EPL_DLLK_H_ + +#include "../EplDll.h" +#include "../EplEvent.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef tEplKernel (* tEplDllkCbAsync) (tEplFrameInfo * pFrameInfo_p); + +typedef struct +{ + BYTE m_be_abSrcMac[6]; + +} tEplDllkInitParam; + +// forward declaration +struct _tEdrvTxBuffer; + +struct _tEplDllkNodeInfo +{ + struct _tEplDllkNodeInfo* m_pNextNodeInfo; + struct _tEdrvTxBuffer* m_pPreqTxBuffer; + unsigned int m_uiNodeId; + DWORD m_dwPresTimeout; + unsigned long m_ulDllErrorEvents; + tEplNmtState m_NmtState; + WORD m_wPresPayloadLimit; + BYTE m_be_abMacAddr[6]; + BYTE m_bSoaFlag1; + BOOL m_fSoftDelete; // delete node after error and ignore error + +}; + +typedef struct _tEplDllkNodeInfo tEplDllkNodeInfo; + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + +tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p); + +tEplKernel EplDllkDelInstance(void); + +// called before NMT_GS_COMMUNICATING will be entered to configure fixed parameters +tEplKernel EplDllkConfig(tEplDllConfigParam * pDllConfigParam_p); + +// set identity of local node (may be at any time, e.g. in case of hostname change) +tEplKernel EplDllkSetIdentity(tEplDllIdentParam * pDllIdentParam_p); + +// process internal events and do work that cannot be done in interrupt-context +tEplKernel EplDllkProcess(tEplEvent * pEvent_p); + +// registers handler for non-EPL frames +tEplKernel EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p); + +// deregisters handler for non-EPL frames +tEplKernel EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p); + +// register C_DLL_MULTICAST_ASND in ethernet driver if any AsndServiceId is registered +tEplKernel EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p, tEplDllAsndFilter Filter_p); + +// creates the buffer for a Tx frame and registers it to the ethernet driver +tEplKernel EplDllkCreateTxFrame(unsigned int * puiHandle_p, + tEplFrame ** ppFrame_p, + unsigned int * puiFrameSize_p, + tEplMsgType MsgType_p, + tEplDllAsndServiceId ServiceId_p); + +tEplKernel EplDllkDeleteTxFrame(unsigned int uiHandle_p); + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +tEplKernel EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p); + +tEplKernel EplDllkDeleteNode(unsigned int uiNodeId_p); + +tEplKernel EplDllkSoftDeleteNode(unsigned int uiNodeId_p); + +tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, BYTE bSoaFlag1_p); + +tEplKernel EplDllkGetFirstNodeInfo(tEplDllkNodeInfo** ppNodeInfo_p); + +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + +#endif // #ifndef _EPL_DLLK_H_ + + diff --git a/drivers/staging/epl/kernel/EplDllkCal.h b/drivers/staging/epl/kernel/EplDllkCal.h new file mode 100644 index 0000000..2db6747 --- /dev/null +++ b/drivers/staging/epl/kernel/EplDllkCal.h @@ -0,0 +1,136 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for kernelspace DLL Communication Abstraction Layer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDllkCal.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/11/13 17:13:09 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/13 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_DLLKCAL_H_ +#define _EPL_DLLKCAL_H_ + +#include "../EplDll.h" +#include "../EplEvent.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef struct +{ + unsigned long m_ulCurTxFrameCountGen; + unsigned long m_ulCurTxFrameCountNmt; + unsigned long m_ulCurRxFrameCount; + unsigned long m_ulMaxTxFrameCountGen; + unsigned long m_ulMaxTxFrameCountNmt; + unsigned long m_ulMaxRxFrameCount; + +} tEplDllkCalStatistics; + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + +tEplKernel EplDllkCalAddInstance(void); + +tEplKernel EplDllkCalDelInstance(void); + +tEplKernel EplDllkCalAsyncGetTxCount(tEplDllAsyncReqPriority * pPriority_p, unsigned int * puiCount_p); +tEplKernel EplDllkCalAsyncGetTxFrame(void * pFrame_p, unsigned int * puiFrameSize_p, tEplDllAsyncReqPriority Priority_p); +// only frames with registered AsndServiceIds are passed to CAL +tEplKernel EplDllkCalAsyncFrameReceived(tEplFrameInfo * pFrameInfo_p); + +tEplKernel EplDllkCalAsyncSend(tEplFrameInfo * pFrameInfo_p, tEplDllAsyncReqPriority Priority_p); + +tEplKernel EplDllkCalAsyncClearBuffer(void); + +tEplKernel EplDllkCalGetStatistics(tEplDllkCalStatistics ** ppStatistics); + +tEplKernel EplDllkCalProcess(tEplEvent * pEvent_p); + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +tEplKernel EplDllkCalAsyncClearQueues(void); + +tEplKernel EplDllkCalIssueRequest(tEplDllReqServiceId Service_p, unsigned int uiNodeId_p, BYTE bSoaFlag1_p); + +tEplKernel EplDllkCalAsyncGetSoaRequest(tEplDllReqServiceId* pReqServiceId_p, unsigned int* puiNodeId_p); + +tEplKernel EplDllkCalAsyncSetPendingRequests(unsigned int uiNodeId_p, tEplDllAsyncReqPriority AsyncReqPrio_p, unsigned int uiCount_p); + +#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) + +#endif // #ifndef _EPL_DLLKCAL_H_ + + diff --git a/drivers/staging/epl/kernel/EplErrorHandlerk.h b/drivers/staging/epl/kernel/EplErrorHandlerk.h new file mode 100644 index 0000000..0f09ef3 --- /dev/null +++ b/drivers/staging/epl/kernel/EplErrorHandlerk.h @@ -0,0 +1,104 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for kernel error handler module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplErrorHandlerk.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/10/02 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_ERRORHANDLERK_H_ +#define _EPL_ERRORHANDLERK_H_ + +#include "../EplEvent.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +// init function +tEplKernel PUBLIC EplErrorHandlerkInit(void); + +// add instance +tEplKernel PUBLIC EplErrorHandlerkAddInstance(void); + +// delete instance +tEplKernel PUBLIC EplErrorHandlerkDelInstance(void); + +// processes error events +tEplKernel PUBLIC EplErrorHandlerkProcess(tEplEvent * pEvent_p); + + +#endif // #ifndef _EPL_ERRORHANDLERK_H_ + + diff --git a/drivers/staging/epl/kernel/EplEventk.h b/drivers/staging/epl/kernel/EplEventk.h new file mode 100644 index 0000000..b889a62 --- /dev/null +++ b/drivers/staging/epl/kernel/EplEventk.h @@ -0,0 +1,114 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for kernel event module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplEventk.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/12 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_EVENTK_H_ +#define _EPL_EVENTK_H_ + +#include "../EplEvent.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +// init function +tEplKernel PUBLIC EplEventkInit(tEplSyncCb fpSyncCb); + +// add instance +tEplKernel PUBLIC EplEventkAddInstance(tEplSyncCb fpSyncCb); + +// delete instance +tEplKernel PUBLIC EplEventkDelInstance(void); + +// Kernelthread that dispatches events in kernelspace +tEplKernel PUBLIC EplEventkProcess(tEplEvent * pEvent_p); + +// post events from kernelspace +tEplKernel PUBLIC EplEventkPost(tEplEvent * pEvent_p); + +// post errorevents from kernelspace +tEplKernel PUBLIC EplEventkPostError(tEplEventSource EventSource_p, + tEplKernel EplError_p, + unsigned int uiArgSize_p, + void* pArg_p); + + + +#endif // #ifndef _EPL_EVENTK_H_ + + diff --git a/drivers/staging/epl/kernel/EplNmtk.h b/drivers/staging/epl/kernel/EplNmtk.h new file mode 100644 index 0000000..a54dae6 --- /dev/null +++ b/drivers/staging/epl/kernel/EplNmtk.h @@ -0,0 +1,110 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for NMT-Kernelspace-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtk.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/09 k.t.: start of the implementation + + +****************************************************************************/ + +#ifndef _EPLNMTK_H_ +#define _EPLNMTK_H_ + +#include "../EplNmt.h" +#include "EplEventk.h" + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) +EPLDLLEXPORT tEplKernel PUBLIC EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_ + tEplEvent * pEvent_p); + +EPLDLLEXPORT tEplNmtState PUBLIC EplNmtkGetNmtState(EPL_MCO_DECL_PTR_INSTANCE_PTR); + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) + + + +#endif // #ifndef _EPLNMTK_H_ + + diff --git a/drivers/staging/epl/kernel/EplNmtkCal.h b/drivers/staging/epl/kernel/EplNmtkCal.h new file mode 100644 index 0000000..2c76793 --- /dev/null +++ b/drivers/staging/epl/kernel/EplNmtkCal.h @@ -0,0 +1,96 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for communication abstraction layer of the + NMT-Kernel-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtkCal.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + KEIL uVision 2 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/16 -k.t.: start of the implementation + + +****************************************************************************/ + +#include "EplNmtk.h" + +#ifndef _EPLNMTKCAL_H_ +#define _EPLNMTKCAL_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPLNMTKCAL_H_ + + diff --git a/drivers/staging/epl/kernel/EplObdk.h b/drivers/staging/epl/kernel/EplObdk.h new file mode 100644 index 0000000..ac2b17f --- /dev/null +++ b/drivers/staging/epl/kernel/EplObdk.h @@ -0,0 +1,196 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for Epl-Obd-Kernel-Modul + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObdk.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.8 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/19 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplObd.h" + +#ifndef _EPLOBDK_H_ +#define _EPLOBDK_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// global variables +//--------------------------------------------------------------------------- + +extern BYTE MEM abEplObdTrashObject_g[8]; + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdInit (EPL_MCO_DECL_PTR_INSTANCE_PTR_ + tEplObdInitParam MEM* pInitParam_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdAddInstance (EPL_MCO_DECL_PTR_INSTANCE_PTR_ + tEplObdInitParam MEM* pInitParam_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdDeleteInstance (EPL_MCO_DECL_INSTANCE_PTR); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize *pSize_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdSetStoreLoadObjCallback (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdStoreLoadObjCallback fpCallback_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdAccessOdPart (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdPart ObdPart_p, + tEplObdDir Direction_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdDefineVar (EPL_MCO_DECL_INSTANCE_PTR_ + tEplVarParam MEM* pVarParam_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT void* PUBLIC EplObdGetObjectDataPtr (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p); +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdRegisterUserOd (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdEntryPtr pUserOd_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT void PUBLIC EplObdInitVarEntry (EPL_MCO_DECL_INSTANCE_PTR_ + tEplObdVarEntry MEM* pVarEntry_p, + tEplObdType Type_p, tEplObdSize ObdSize_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplObdSize PUBLIC EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT unsigned int PUBLIC EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdSetNodeId(EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + BOOL* pfEntryNumerical); +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize *pSize_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess* pAccessTyp_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObdSearchVarEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry MEM** ppVarEntry_p); + +#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) + +#endif // #ifndef _EPLOBDK_H_ + + diff --git a/drivers/staging/epl/kernel/EplObdkCal.h b/drivers/staging/epl/kernel/EplObdkCal.h new file mode 100644 index 0000000..7f4f5ad --- /dev/null +++ b/drivers/staging/epl/kernel/EplObdkCal.h @@ -0,0 +1,96 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for communication abstraction layer + for the Epl-Obd-Kernelspace-Modul + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObdkCal.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/19 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplObd.h" + +#ifndef _EPLOBDKCAL_H_ +#define _EPLOBDKCAL_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + + +#endif // #ifndef _EPLOBDKCAL_H_ + + diff --git a/drivers/staging/epl/kernel/EplPdok.h b/drivers/staging/epl/kernel/EplPdok.h new file mode 100644 index 0000000..a9358ec --- /dev/null +++ b/drivers/staging/epl/kernel/EplPdok.h @@ -0,0 +1,116 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for kernel PDO module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplPdok.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/06/23 14:56:33 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/05/22 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_PDOK_H_ +#define _EPL_PDOK_H_ + +#include "../EplPdo.h" +#include "../EplEvent.h" +#include "../EplDll.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +// process events from queue (PDOs/frames and SoA for synchronization) +tEplKernel EplPdokProcess(tEplEvent * pEvent_p); + +// copies RPDO to event queue for processing +// is called by DLL in NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL +// PDO needs not to be valid +tEplKernel EplPdokCbPdoReceived(tEplFrameInfo * pFrameInfo_p); + +// posts pointer and size of TPDO to event queue +// is called by DLL in NMT_CS_PRE_OPERATIONAL_2, +// NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL +tEplKernel EplPdokCbPdoTransmitted(tEplFrameInfo * pFrameInfo_p); + +// posts SoA event to queue +tEplKernel EplPdokCbSoa(tEplFrameInfo * pFrameInfo_p); + +tEplKernel EplPdokAddInstance(void); + +tEplKernel EplPdokDelInstance(void); + + +#endif // #ifndef _EPL_PDOK_H_ + + diff --git a/drivers/staging/epl/kernel/EplPdokCal.h b/drivers/staging/epl/kernel/EplPdokCal.h new file mode 100644 index 0000000..c852c77 --- /dev/null +++ b/drivers/staging/epl/kernel/EplPdokCal.h @@ -0,0 +1,106 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for kernel PDO Communication Abstraction Layer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplPdokCal.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/26 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_PDOKCAL_H_ +#define _EPL_PDOKCAL_H_ + +#include "../EplInc.h" +//#include "EplPdo.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +tEplKernel EplPdokCalAddInstance(void); + +tEplKernel EplPdokCalDelInstance(void); + +// sets flag for validity of TPDOs in shared memory +tEplKernel EplPdokCalSetTpdosValid(BOOL fValid_p); + +// gets flag for validity of TPDOs from shared memory +tEplKernel EplPdokCalAreTpdosValid(BOOL * pfValid_p); + + + +#endif // #ifndef _EPL_PDOKCAL_H_ + + diff --git a/drivers/staging/epl/kernel/EplTimerHighResk.h b/drivers/staging/epl/kernel/EplTimerHighResk.h new file mode 100644 index 0000000..abee2fd --- /dev/null +++ b/drivers/staging/epl/kernel/EplTimerHighResk.h @@ -0,0 +1,112 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for EPL high resolution Timermodule + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplTimerHighResk.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/09/29 d.k.: start of the implementation + + +****************************************************************************/ + +#include "../EplTimer.h" + +#ifndef _EPLTIMERHIGHRESK_H_ +#define _EPLTIMERHIGHRESK_H_ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimerHighReskInit(void); + +tEplKernel PUBLIC EplTimerHighReskAddInstance(void); + +tEplKernel PUBLIC EplTimerHighReskDelInstance(void); + +tEplKernel PUBLIC EplTimerHighReskSetTimerNs(tEplTimerHdl* pTimerHdl_p, + unsigned long long ullTimeNs_p, + tEplTimerkCallback pfnCallback_p, + unsigned long ulArgument_p, + BOOL fContinuously_p); + +tEplKernel PUBLIC EplTimerHighReskModifyTimerNs(tEplTimerHdl* pTimerHdl_p, + unsigned long long ullTimeNs_p, + tEplTimerkCallback pfnCallback_p, + unsigned long ulArgument_p, + BOOL fContinuously_p); + +tEplKernel PUBLIC EplTimerHighReskDeleteTimer(tEplTimerHdl* pTimerHdl_p); + +#endif // #ifndef _EPLTIMERHIGHRESK_H_ + + diff --git a/drivers/staging/epl/kernel/EplTimerk.h b/drivers/staging/epl/kernel/EplTimerk.h new file mode 100644 index 0000000..ab2bb05 --- /dev/null +++ b/drivers/staging/epl/kernel/EplTimerk.h @@ -0,0 +1,122 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for EPL Kernel-Timermodule + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplTimerk.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/06 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplTimer.h" +#include "../user/EplEventu.h" + +#ifndef _EPLTIMERK_H_ +#define _EPLTIMERK_H_ + +#if EPL_TIMER_USE_USER != FALSE +#include "../user/EplTimeru.h" +#endif + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#if EPL_TIMER_USE_USER != FALSE +#define EplTimerkInit EplTimeruInit +#define EplTimerkAddInstance EplTimeruAddInstance +#define EplTimerkDelInstance EplTimeruDelInstance +#define EplTimerkSetTimerMs EplTimeruSetTimerMs +#define EplTimerkModifyTimerMs EplTimeruModifyTimerMs +#define EplTimerkDeleteTimer EplTimeruDeleteTimer +#endif + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +#if EPL_TIMER_USE_USER == FALSE +tEplKernel PUBLIC EplTimerkInit(void); + +tEplKernel PUBLIC EplTimerkAddInstance(void); + +tEplKernel PUBLIC EplTimerkDelInstance(void); + +tEplKernel PUBLIC EplTimerkSetTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p); + +tEplKernel PUBLIC EplTimerkModifyTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p); + +tEplKernel PUBLIC EplTimerkDeleteTimer(tEplTimerHdl* pTimerHdl_p); +#endif +#endif // #ifndef _EPLTIMERK_H_ + + diff --git a/drivers/staging/epl/kernel/VirtualEthernet.h b/drivers/staging/epl/kernel/VirtualEthernet.h new file mode 100644 index 0000000..8501747 --- /dev/null +++ b/drivers/staging/epl/kernel/VirtualEthernet.h @@ -0,0 +1,101 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for virtual ethernet driver module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: VirtualEthernet.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + KEIL uVision 2 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/09/19 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_VETH_H_ +#define _EPL_VETH_H_ + +#include "EplDllk.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0) + +tEplKernel PUBLIC VEthAddInstance(tEplDllkInitParam * pInitParam_p); + +tEplKernel PUBLIC VEthDelInstance(void); + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0) + +#endif // #ifndef _EPL_VETH_H_ + + diff --git a/drivers/staging/epl/proc_fs.c b/drivers/staging/epl/proc_fs.c new file mode 100644 index 0000000..5258e49 --- /dev/null +++ b/drivers/staging/epl/proc_fs.c @@ -0,0 +1,420 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: proc fs entry with diagnostic information under Linux + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: proc_fs.c,v $ + + $Author: D.Krueger $ + + $Revision: 1.13 $ $Date: 2008/11/07 13:55:56 $ + + $State: Exp $ + + Build Environment: + GNU + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/31 d.k.: start of implementation + +****************************************************************************/ + +#include "kernel/EplNmtk.h" +#include "user/EplNmtu.h" + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) +#include "user/EplNmtMnu.h" +#endif + +#include "kernel/EplDllkCal.h" + +//#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/major.h> +#include <linux/version.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/atomic.h> +#include <linux/proc_fs.h> +#include <linux/spinlock.h> + +#ifdef CONFIG_COLDFIRE + #include <asm/coldfire.h> + #include "fec.h" +#endif + + +/***************************************************************************/ +/* */ +/* */ +/* G L O B A L D E F I N I T I O N S */ +/* */ +/* */ +/***************************************************************************/ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +#ifndef EPL_PROC_DEV_NAME +#define EPL_PROC_DEV_NAME "epl" +#endif + +#ifndef DBG_TRACE_POINTS +#define DBG_TRACE_POINTS 23 // # of supported debug trace points +#endif + +#ifndef DBG_TRACE_VALUES +#define DBG_TRACE_VALUES 24 // # of supported debug trace values (size of circular buffer) +#endif + +//--------------------------------------------------------------------------- +// modul global types +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// local vars +//--------------------------------------------------------------------------- + +#ifdef _DBG_TRACE_POINTS_ + atomic_t aatmDbgTracePoint_l[DBG_TRACE_POINTS]; + DWORD adwDbgTraceValue_l[DBG_TRACE_VALUES]; + DWORD dwDbgTraceValueOld_l; + unsigned int uiDbgTraceValuePos_l; + spinlock_t spinlockDbgTraceValue_l; + unsigned long ulDbTraceValueFlags_l; +#endif + +//--------------------------------------------------------------------------- +// local function prototypes +//--------------------------------------------------------------------------- + +static int EplLinProcRead (char* pcBuffer_p, char** ppcStart_p, off_t Offset_p, int nBufferSize_p, int* pEof_p, void* pData_p); +static int EplLinProcWrite(struct file *file, const char __user *buffer, unsigned long count, void *data); + +void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p); +void PUBLIC TgtDbgPostTraceValue (DWORD dwTraceValue_p); + + +EPLDLLEXPORT DWORD PUBLIC EplIdentuGetRunningRequests(void); + + +//=========================================================================// +// // +// P U B L I C F U N C T I O N S // +// // +//=========================================================================// + +tEplKernel EplLinProcInit(void) +{ + struct proc_dir_entry* pProcDirEntry; + pProcDirEntry = create_proc_entry (EPL_PROC_DEV_NAME, S_IRUGO, NULL); + if (pProcDirEntry != NULL) + { + pProcDirEntry->read_proc = EplLinProcRead; + pProcDirEntry->write_proc = EplLinProcWrite; + pProcDirEntry->data = NULL; // device number or something else + + } + else + { + return kEplNoResource; + } + +#ifdef _DBG_TRACE_POINTS_ + // initialize spinlock and circular buffer position + spin_lock_init(&spinlockDbgTraceValue_l); + uiDbgTraceValuePos_l = 0; + dwDbgTraceValueOld_l = 0; +#endif + + return kEplSuccessful; +} + +tEplKernel EplLinProcFree(void) +{ + remove_proc_entry (EPL_PROC_DEV_NAME, NULL); + + return kEplSuccessful; +} + +//--------------------------------------------------------------------------- +// Target specific event signaling (FEC Tx-/Rx-Interrupt, used by Edrv) +//--------------------------------------------------------------------------- + +#ifdef _DBG_TRACE_POINTS_ +void PUBLIC TgtDbgSignalTracePoint ( + BYTE bTracePointNumber_p) +{ + + if (bTracePointNumber_p >= (sizeof(aatmDbgTracePoint_l) / sizeof(aatmDbgTracePoint_l[0]))) + { + goto Exit; + } + + + atomic_inc (&aatmDbgTracePoint_l[bTracePointNumber_p]); + +Exit: + + return; + +} + +void PUBLIC TgtDbgPostTraceValue (DWORD dwTraceValue_p) +{ + + spin_lock_irqsave(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l); + if (dwDbgTraceValueOld_l != dwTraceValue_p) + { + adwDbgTraceValue_l[uiDbgTraceValuePos_l] = dwTraceValue_p; + uiDbgTraceValuePos_l = (uiDbgTraceValuePos_l + 1) % DBG_TRACE_VALUES; + dwDbgTraceValueOld_l = dwTraceValue_p; + } + spin_unlock_irqrestore(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l); + + return; + +} +#endif + + +//--------------------------------------------------------------------------- +// Read function for PROC-FS read access +//--------------------------------------------------------------------------- + +static int EplLinProcRead ( + char* pcBuffer_p, + char** ppcStart_p, + off_t Offset_p, + int nBufferSize_p, + int* pEof_p, + void* pData_p) +{ + +int nSize; +int Eof; +tEplDllkCalStatistics* pDllkCalStats; + + nSize = 0; + Eof = 0; + + // count calls of this function +#ifdef _DBG_TRACE_POINTS_ + TgtDbgSignalTracePoint(0); +#endif + + //--------------------------------------------------------------- + // generate static information + //--------------------------------------------------------------- + + // ---- Driver information ---- + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "%s %s (c) 2006 %s\n", + EPL_PRODUCT_NAME, EPL_PRODUCT_VERSION, EPL_PRODUCT_MANUFACTURER); + + + //--------------------------------------------------------------- + // generate process information + //--------------------------------------------------------------- + + // ---- EPL state ---- + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "NMT state: 0x%04X\n", + (WORD) EplNmtkGetNmtState()); + + EplDllkCalGetStatistics(&pDllkCalStats); + + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "CurAsyncTxGen=%lu CurAsyncTxNmt=%lu CurAsyncRx=%lu\nMaxAsyncTxGen=%lu MaxAsyncTxNmt=%lu MaxAsyncRx=%lu\n", pDllkCalStats->m_ulCurTxFrameCountGen, pDllkCalStats->m_ulCurTxFrameCountNmt, pDllkCalStats->m_ulCurRxFrameCount, pDllkCalStats->m_ulMaxTxFrameCountGen, pDllkCalStats->m_ulMaxTxFrameCountNmt, pDllkCalStats->m_ulMaxRxFrameCount); + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + // fetch running IdentRequests + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "running IdentRequests: 0x%08lX\n", + EplIdentuGetRunningRequests()); + + // fetch state of NmtMnu module + { + unsigned int uiMandatorySlaveCount; + unsigned int uiSignalSlaveCount; + WORD wFlags; + + EplNmtMnuGetDiagnosticInfo(&uiMandatorySlaveCount, + &uiSignalSlaveCount, + &wFlags); + + + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "MN MandSlaveCount: %u SigSlaveCount: %u Flags: 0x%X\n", + uiMandatorySlaveCount, uiSignalSlaveCount, wFlags); + + } +#endif + + // ---- FEC state ---- + #ifdef CONFIG_COLDFIRE + { + // Receive the base address + unsigned long base_addr; + #if (EDRV_USED_ETH_CTRL == 0) + // Set the base address of FEC0 + base_addr = FEC_BASE_ADDR_FEC0; + #else + // Set the base address of FEC1 + base_addr = FEC_BASE_ADDR_FEC1; + #endif + + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "FEC_ECR = 0x%08X FEC_EIR = 0x%08X FEC_EIMR = 0x%08X\nFEC_TCR = 0x%08X FECTFSR = 0x%08X FECRFSR = 0x%08X\n", + FEC_ECR(base_addr), FEC_EIR(base_addr), FEC_EIMR(base_addr), FEC_TCR(base_addr), FEC_FECTFSR(base_addr), FEC_FECRFSR(base_addr)); + } + #endif + + + // ---- DBG: TracePoints ---- + #ifdef _DBG_TRACE_POINTS_ + { + int nNum; + + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "DbgTracePoints:\n"); + for (nNum=0; nNum<(sizeof(aatmDbgTracePoint_l)/sizeof(atomic_t)); nNum++) + { + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + " TracePoint[%2d]: %d\n", (int)nNum, + atomic_read(&aatmDbgTracePoint_l[nNum])); + } + + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "DbgTraceValues:\n"); + for (nNum=0; nNum<DBG_TRACE_VALUES; nNum++) + { + if (nNum == uiDbgTraceValuePos_l) + { // next value will be stored at that position + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "*%08lX", adwDbgTraceValue_l[nNum]); + } + else + { + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + " %08lX", adwDbgTraceValue_l[nNum]); + } + if ((nNum & 0x00000007) == 0x00000007) + { // 8 values printed -> end of line reached + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "\n"); + } + } + if ((nNum & 0x00000007) != 0x00000007) + { // number of values printed is not a multiple of 8 -> print new line + nSize += snprintf (pcBuffer_p + nSize, nBufferSize_p - nSize, + "\n"); + } + } + #endif + + + Eof = 1; + goto Exit; + + +Exit: + + *pEof_p = Eof; + + return (nSize); + +} + + +//--------------------------------------------------------------------------- +// Write function for PROC-FS write access +//--------------------------------------------------------------------------- + +static int EplLinProcWrite(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ +char abBuffer[count + 1]; +int iErr; +int iVal = 0; +tEplNmtEvent NmtEvent; + + if (count > 0) + { + iErr = copy_from_user(abBuffer, buffer, count); + if (iErr != 0) + { + return count; + } + abBuffer[count] = '\0'; + + iErr = sscanf(abBuffer, "%i", &iVal); + } + if ((iVal <= 0) || (iVal > 0x2F)) + { + NmtEvent = kEplNmtEventSwReset; + } + else + { + NmtEvent = (tEplNmtEvent) iVal; + } + // execute specified NMT command on write access of /proc/epl + EplNmtuNmtEvent(NmtEvent); + + return count; +} + + diff --git a/drivers/staging/epl/proc_fs.h b/drivers/staging/epl/proc_fs.h new file mode 100644 index 0000000..5af2d3a --- /dev/null +++ b/drivers/staging/epl/proc_fs.h @@ -0,0 +1,94 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: interface for proc fs entry under Linux + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: proc_fs.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:33 $ + + $State: Exp $ + + Build Environment: + GNU + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/31 d.k.: start of implementation + +****************************************************************************/ + +#ifndef _EPLPROCFS_H_ +#define _EPLPROCFS_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// types +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +tEplKernel EplLinProcInit(void); +tEplKernel EplLinProcFree(void); + + +#endif // #ifndef _EPLPROCFS_H_ + + diff --git a/drivers/staging/epl/user/EplCfgMau.h b/drivers/staging/epl/user/EplCfgMau.h new file mode 100644 index 0000000..3d96daf --- /dev/null +++ b/drivers/staging/epl/user/EplCfgMau.h @@ -0,0 +1,299 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for Epl Configuration Manager Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplCfgMau.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + VC7 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/14 k.t.: start of the implementation + -> based on CANopen CfgMa-Modul (CANopen version 5.34) + +****************************************************************************/ + +#include "../EplInc.h" + +#ifndef _EPLCFGMA_H_ +#define _EPLCFGMA_H_ + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_CFGMA)) != 0) + +#include "EplObdu.h" +#include "EplSdoComu.h" + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- +//define max number of timeouts for configuration of 1 device +#define EPL_CFGMA_MAX_TIMEOUT 3 + +//callbackfunction, called if configuration is finished +typedef void (PUBLIC* tfpEplCfgMaCb) (unsigned int uiNodeId_p, + tEplKernel Errorstate_p); + +//State for configuartion manager Statemachine +typedef enum +{ + // general states + kEplCfgMaIdle = 0x0000, // Configurationsprocess + // is idle + kEplCfgMaWaitForSdocEvent = 0x0001, // wait until the last + // SDOC is finisched + kEplCfgMaSkipMappingSub0 = 0x0002, // write Sub0 of mapping + // parameter with 0 + + kEplCfgMaFinished = 0x0004 // configuartion is finished + +} tEplCfgState; + +typedef enum +{ + kEplCfgMaDcfTypSystecSeg = 0x00, + kEplCfgMaDcfTypConDcf = 0x01, + kEplCfgMaDcfTypDcf = 0x02, // not supported + kEplCfgMaDcfTypXdc = 0x03 // not supported + + +}tEplCfgMaDcfTyp; + +typedef enum +{ + kEplCfgMaCommon = 0, // all other index + kEplCfgMaPdoComm = 1, // communication index + kEplCfgMaPdoMapp = 2, // mapping index + kEplCfgMaPdoCommAfterMapp = 3, // write PDO Cob-Id after mapping subindex 0(set PDO valid) + +} tEplCfgMaIndexType; + + +//bitcoded answer about the last sdo transfer saved in m_SdocState +// also used to singal start of the State Maschine +typedef enum +{ + kEplCfgMaSdocBusy = 0x00, // SDOC activ + kEplCfgMaSdocReady = 0x01, // SDOC finished + kEplCfgMaSdocTimeout = 0x02, // SDOC Timeout + kEplCfgMaSdocAbortReceived = 0x04, // SDOC Abort, see Abortcode + kEplCfgMaSdocStart = 0x08 // start State Mschine +}tEplSdocState; + +//internal structure (instancetable for modul configuration manager) +typedef struct +{ + tEplCfgState m_CfgState; // state of the configuration state maschine + tEplSdoComConHdl m_SdoComConHdl; // handle for sdo connection + DWORD m_dwLastAbortCode; + unsigned int m_uiLastIndex; // last index of configuration, to compair with actual index + BYTE* m_pbConcise; // Ptr to concise DCF + BYTE* m_pbActualIndex; // Ptr to actual index in the DCF segment + tfpEplCfgMaCb m_pfnCfgMaCb; // Ptr to CfgMa Callback, is call if configuration finished + tEplKernel m_EplKernelError; // errorcode + DWORD m_dwNumValueCopy; // numeric values are copied in this variable + unsigned int m_uiPdoNodeId; // buffer for PDO node id + BYTE m_bNrOfMappedObject; // number of mapped objects + unsigned int m_uiNodeId; // Epl node addresse + tEplSdocState m_SdocState; // bitcoded state of the SDO transfer + unsigned int m_uiLastSubIndex; // last subindex of configuration + BOOL m_fOneTranferOk; // atleased one transfer was successful + BYTE m_bEventFlag; // for Eventsignaling to the State Maschine + DWORD m_dwCntObjectInDcf; // number of Objects in DCF + tEplCfgMaIndexType m_SkipCfg; // TRUE if a adsitional Configurationprocess + // have to insert e.g. PDO-mapping + WORD m_wTimeOutCnt; // Timeout Counter, break configuration is + // m_wTimeOutCnt == CFGMA_MAX_TIMEOUT + +} tEplCfgMaNode; + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Function: EplCfgMaInit() +// +// Description: Function creates first instance of Configuration Manager +// +// Parameters: +// +// Returns: tEplKernel = error code +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplCfgMaInit(); + +//--------------------------------------------------------------------------- +// Function: EplCfgMaAddInstance() +// +// Description: Function creates additional instance of Configuration Manager +// +// Parameters: +// +// Returns: tEplKernel = error code +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplCfgMaAddInstance(); + +//--------------------------------------------------------------------------- +// Function: EplCfgMaDelInstance() +// +// Description: Function delete instance of Configuration Manager +// +// Parameters: +// +// Returns: tEplKernel = error code +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplCfgMaDelInstance(); + +//--------------------------------------------------------------------------- +// Function: EplCfgMaStartConfig() +// +// Description: Function starts the configuration process +// initialization the statemachine for CfgMa- process +// +// Parameters: uiNodeId_p = NodeId of the node to configure +// pbConcise_p = pointer to DCF +// fpCfgMaCb_p = pointer to callback function (should not be NULL) +// SizeOfConcise_p = size of DCF in BYTE -> for future use +// DcfType_p = type of the DCF +// +// Returns: tCopKernel = error code +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplCfgMaStartConfig(unsigned int uiNodeId_p, + BYTE* pbConcise_p, + tfpEplCfgMaCb fpCfgMaCb_p, + tEplObdSize SizeOfConcise_p, + tEplCfgMaDcfTyp DcfType_p); + + +//--------------------------------------------------------------------------- +// Function: CfgMaStartConfigurationNode() +// +// Description: Function started the configuration process +// with the DCF from according OD-entry Subindex == bNodeId_p +// +// Parameters: uiNodeId_p = NodeId of the node to configure +// fpCfgMaCb_p = pointer to callback function (should not be NULL) +// DcfType_p = type of the DCF +// +// Returns: tCopKernel = error code +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplCfgMaStartConfigNode(unsigned int uiNodeId_p, + tfpEplCfgMaCb fpCfgMaCb_p, + tEplCfgMaDcfTyp DcfType_p); + + +//--------------------------------------------------------------------------- +// Function: EplCfgMaStartConfigNodeDcf() +// +// Description: Function starts the configuration process +// and links the configuration data to the OD +// +// Parameters: uiNodeId_p = NodeId of the node to configure +// pbConcise_p = pointer to DCF +// fpCfgMaCb_p = pointer to callback function (should not be NULL) +// SizeOfConcise_p = size of DCF in BYTE -> for future use +// DcfType_p = type of the DCF +// +// Returns: tCopKernel = error code +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplCfgMaStartConfigNodeDcf(unsigned int uiNodeId_p, + BYTE* pbConcise_p, + tfpEplCfgMaCb fpCfgMaCb_p, + tEplObdSize SizeOfConcise_p, + tEplCfgMaDcfTyp DcfType_p); + +//--------------------------------------------------------------------------- +// Function: EplCfgMaLinkDcf() +// +// Description: Function links the configuration data to the OD +// +// Parameters: uiNodeId_p = NodeId of the node to configure +// pbConcise_p = pointer to DCF +// SizeOfConcise_p = size of DCF in BYTE -> for future use +// DcfType_p = type of the DCF +// +// Returns: tCopKernel = error code +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplCfgMaLinkDcf(unsigned int uiNodeId_p, + BYTE* pbConcise_p, + tEplObdSize SizeOfConcise_p, + tEplCfgMaDcfTyp DcfType_p); + +//--------------------------------------------------------------------------- +// Function: EplCfgMaCheckDcf() +// +// Description: Function check if there is allready a configuration file linked +// to the OD (type is given by DcfType_p) +// +// Parameters: uiNodeId_p = NodeId +// DcfType_p = type of the DCF +// +// Returns: tCopKernel = error code +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplCfgMaCheckDcf(unsigned int uiNodeId_p, + tEplCfgMaDcfTyp DcfType_p); + + + + + +#endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_CFGMA)) != 0) + +#endif // _EPLCFGMA_H_ + +// EOF diff --git a/drivers/staging/epl/user/EplDllu.h b/drivers/staging/epl/user/EplDllu.h new file mode 100644 index 0000000..2beb390 --- /dev/null +++ b/drivers/staging/epl/user/EplDllu.h @@ -0,0 +1,108 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for userspace DLL module for asynchronous communication + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDllu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/20 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_DLLU_H_ +#define _EPL_DLLU_H_ + +#include "../EplDll.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef tEplKernel (PUBLIC * tEplDlluCbAsnd) (tEplFrameInfo * pFrameInfo_p); + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + +tEplKernel EplDlluAddInstance(void); + +tEplKernel EplDlluDelInstance(void); + +tEplKernel EplDlluRegAsndService(tEplDllAsndServiceId ServiceId_p, tEplDlluCbAsnd pfnDlluCbAsnd_p, tEplDllAsndFilter Filter_p); + +tEplKernel EplDlluAsyncSend(tEplFrameInfo * pFrameInfo_p, tEplDllAsyncReqPriority Priority_p); + +// processes asynch frames +tEplKernel EplDlluProcess(tEplFrameInfo * pFrameInfo_p); + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) + +#endif // #ifndef _EPL_DLLU_H_ + + diff --git a/drivers/staging/epl/user/EplDlluCal.h b/drivers/staging/epl/user/EplDlluCal.h new file mode 100644 index 0000000..b2b85ba --- /dev/null +++ b/drivers/staging/epl/user/EplDlluCal.h @@ -0,0 +1,120 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for DLL Communication Abstraction Layer module in EPL user part + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplDlluCal.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/20 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_DLLUCAL_H_ +#define _EPL_DLLUCAL_H_ + +#include "../EplDll.h" +#include "../EplEvent.h" + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef tEplKernel (PUBLIC * tEplDlluCbAsnd) (tEplFrameInfo * pFrameInfo_p); + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +tEplKernel EplDlluCalAddInstance(void); + +tEplKernel EplDlluCalDelInstance(void); + +tEplKernel EplDlluCalRegAsndService(tEplDllAsndServiceId ServiceId_p, + tEplDlluCbAsnd pfnDlluCbAsnd_p, + tEplDllAsndFilter Filter_p); + +tEplKernel EplDlluCalAsyncSend(tEplFrameInfo * pFrameInfo, tEplDllAsyncReqPriority Priority_p); + +tEplKernel EplDlluCalProcess(tEplEvent * pEvent_p); + + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +tEplKernel EplDlluCalAddNode(tEplDllNodeInfo * pNodeInfo_p); + +tEplKernel EplDlluCalDeleteNode(unsigned int uiNodeId_p); + +tEplKernel EplDlluCalSoftDeleteNode(unsigned int uiNodeId_p); + +tEplKernel EplDlluCalIssueRequest(tEplDllReqServiceId Service_p, unsigned int uiNodeId_p, BYTE bSoaFlag1_p); + +#endif + + +#endif // #ifndef _EPL_DLLUCAL_H_ + + diff --git a/drivers/staging/epl/user/EplEventu.h b/drivers/staging/epl/user/EplEventu.h new file mode 100644 index 0000000..57f8b42 --- /dev/null +++ b/drivers/staging/epl/user/EplEventu.h @@ -0,0 +1,115 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for kernel event module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplEventu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/12 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_EVENTU_H_ +#define _EPL_EVENTU_H_ + +#include "../EplEvent.h" + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +// init function +tEplKernel PUBLIC EplEventuInit(tEplProcessEventCb pfnApiProcessEventCb_p); + +// add instance +tEplKernel PUBLIC EplEventuAddInstance(tEplProcessEventCb pfnApiProcessEventCb_p); + +// delete instance +tEplKernel PUBLIC EplEventuDelInstance(void); + +// Task that dispatches events in userspace +tEplKernel PUBLIC EplEventuProcess(tEplEvent * pEvent_p); + +// post events from userspace +tEplKernel PUBLIC EplEventuPost(tEplEvent * pEvent_p); + +// post errorevents from userspace +tEplKernel PUBLIC EplEventuPostError(tEplEventSource EventSource_p, + tEplKernel EplError_p, + unsigned int uiArgSize_p, + void* pArg_p); + + + +#endif // #ifndef _EPL_EVENTU_H_ + + diff --git a/drivers/staging/epl/user/EplIdentu.h b/drivers/staging/epl/user/EplIdentu.h new file mode 100644 index 0000000..b53afa0 --- /dev/null +++ b/drivers/staging/epl/user/EplIdentu.h @@ -0,0 +1,113 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for Identu-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplIdentu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/11/15 d.k.: start of the implementation + + +****************************************************************************/ + +#include "../EplDll.h" + +#ifndef _EPLIDENTU_H_ +#define _EPLIDENTU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef tEplKernel (PUBLIC * tEplIdentuCbResponse) ( + unsigned int uiNodeId_p, + tEplIdentResponse* pIdentResponse_p); + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplIdentuInit(void); + +tEplKernel PUBLIC EplIdentuAddInstance(void); + +tEplKernel PUBLIC EplIdentuDelInstance(void); + +tEplKernel PUBLIC EplIdentuReset(void); + +tEplKernel PUBLIC EplIdentuGetIdentResponse( + unsigned int uiNodeId_p, + tEplIdentResponse** ppIdentResponse_p); + +tEplKernel PUBLIC EplIdentuRequestIdentResponse( + unsigned int uiNodeId_p, + tEplIdentuCbResponse pfnCbResponse_p); + +#endif // #ifndef _EPLIDENTU_H_ + + diff --git a/drivers/staging/epl/user/EplLedu.h b/drivers/staging/epl/user/EplLedu.h new file mode 100644 index 0000000..10a8b6b --- /dev/null +++ b/drivers/staging/epl/user/EplLedu.h @@ -0,0 +1,116 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for status and error LED user part module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplLedu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.1 $ $Date: 2008/11/17 16:40:39 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2008/11/17 d.k.: start of the implementation + + +****************************************************************************/ + +#include "../EplLed.h" +#include "../EplNmt.h" +#include "EplEventu.h" + +#ifndef _EPLLEDU_H_ +#define _EPLLEDU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +typedef tEplKernel (PUBLIC * tEplLeduStateChangeCallback) ( + tEplLedType LedType_p, BOOL fOn_p); + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) + +tEplKernel PUBLIC EplLeduInit(tEplLeduStateChangeCallback pfnCbStateChange_p); + +tEplKernel PUBLIC EplLeduAddInstance(tEplLeduStateChangeCallback pfnCbStateChange_p); + +tEplKernel PUBLIC EplLeduDelInstance(void); + +tEplKernel PUBLIC EplLeduCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p); + +tEplKernel PUBLIC EplLeduProcessEvent( + tEplEvent* pEplEvent_p); + + +#endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) + +#endif // #ifndef _EPLLEDU_H_ + + diff --git a/drivers/staging/epl/user/EplNmtCnu.h b/drivers/staging/epl/user/EplNmtCnu.h new file mode 100644 index 0000000..93a3289 --- /dev/null +++ b/drivers/staging/epl/user/EplNmtCnu.h @@ -0,0 +1,112 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for NMT-CN-Userspace-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtCnu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/09 k.t.: start of the implementation + + +****************************************************************************/ + +#include "EplNmtu.h" +#include "../EplDll.h" +#include "../EplFrame.h" + +#ifndef _EPLNMTCNU_H_ +#define _EPLNMTCNU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuInit(unsigned int uiNodeId_p); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuAddInstance(unsigned int uiNodeId_p); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuDelInstance(void); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuSendNmtRequest (unsigned int uiNodeId_p, + tEplNmtCommand NmtCommand_p); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuRegisterCheckEventCb( + tEplNmtuCheckEventCallback pfnEplNmtCheckEventCb_p); + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) + +#endif // #ifndef _EPLNMTCNU_H_ + + diff --git a/drivers/staging/epl/user/EplNmtMnu.h b/drivers/staging/epl/user/EplNmtMnu.h new file mode 100644 index 0000000..a101fde --- /dev/null +++ b/drivers/staging/epl/user/EplNmtMnu.h @@ -0,0 +1,136 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for NMT-MN-Userspace-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtMnu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/09 k.t.: start of the implementation + + +****************************************************************************/ + +#include "EplNmtu.h" + +#ifndef _EPLNMTMNU_H_ +#define _EPLNMTMNU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef tEplKernel (PUBLIC * tEplNmtMnuCbNodeEvent) ( + unsigned int uiNodeId_p, + tEplNmtNodeEvent NodeEvent_p, + tEplNmtState NmtState_p, + WORD wErrorCode_p, + BOOL fMandatory_p); + + +typedef tEplKernel (PUBLIC * tEplNmtMnuCbBootEvent) ( + tEplNmtBootEvent BootEvent_p, + tEplNmtState NmtState_p, + WORD wErrorCode_p); + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) + +tEplKernel EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p, + tEplNmtMnuCbBootEvent pfnCbBootEvent_p); + +tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p, + tEplNmtMnuCbBootEvent pfnCbBootEvent_p); + +tEplKernel EplNmtMnuDelInstance(void); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent( + tEplEvent* pEvent_p); + +tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p, + tEplNmtCommand NmtCommand_p); + +tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p, + tEplNmtNodeCommand NodeCommand_p); + +tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p); + +tEplKernel PUBLIC EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p); + +tEplKernel PUBLIC EplNmtMnuGetDiagnosticInfo(unsigned int* puiMandatorySlaveCount_p, + unsigned int* puiSignalSlaveCount_p, + WORD* pwFlags_p); + +#endif + +#endif // #ifndef _EPLNMTMNU_H_ + + diff --git a/drivers/staging/epl/user/EplNmtu.h b/drivers/staging/epl/user/EplNmtu.h new file mode 100644 index 0000000..0ed7fff --- /dev/null +++ b/drivers/staging/epl/user/EplNmtu.h @@ -0,0 +1,161 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for NMT-Userspace-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/09 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplNmt.h" +#include "EplEventu.h" + +#ifndef _EPLNMTU_H_ +#define _EPLNMTU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- +// nmt commands +typedef enum +{ + // requestable ASnd ServiceIds 0x01..0x1F + kEplNmtCmdIdentResponse = 0x01, + kEplNmtCmdStatusResponse = 0x02, + // plain NMT state commands 0x20..0x3F + kEplNmtCmdStartNode = 0x21, + kEplNmtCmdStopNode = 0x22, + kEplNmtCmdEnterPreOperational2 = 0x23, + kEplNmtCmdEnableReadyToOperate = 0x24, + kEplNmtCmdResetNode = 0x28, + kEplNmtCmdResetCommunication = 0x29, + kEplNmtCmdResetConfiguration = 0x2A, + kEplNmtCmdSwReset = 0x2B, + // extended NMT state commands 0x40..0x5F + kEplNmtCmdStartNodeEx = 0x41, + kEplNmtCmdStopNodeEx = 0x42, + kEplNmtCmdEnterPreOperational2Ex = 0x43, + kEplNmtCmdEnableReadyToOperateEx = 0x44, + kEplNmtCmdResetNodeEx = 0x48, + kEplNmtCmdResetCommunicationEx = 0x49, + kEplNmtCmdResetConfigurationEx = 0x4A, + kEplNmtCmdSwResetEx = 0x4B, + // NMT managing commands 0x60..0x7F + kEplNmtCmdNetHostNameSet = 0x62, + kEplNmtCmdFlushArpEntry = 0x63, + // NMT info services 0x80..0xBF + kEplNmtCmdPublishConfiguredCN = 0x80, + kEplNmtCmdPublishActiveCN = 0x90, + kEplNmtCmdPublishPreOperational1 = 0x91, + kEplNmtCmdPublishPreOperational2 = 0x92, + kEplNmtCmdPublishReadyToOperate = 0x93, + kEplNmtCmdPublishOperational = 0x94, + kEplNmtCmdPublishStopped = 0x95, + kEplNmtCmdPublishEmergencyNew = 0xA0, + kEplNmtCmdPublishTime = 0xB0, + + kEplNmtCmdInvalidService = 0xFF + +} tEplNmtCommand; + +typedef tEplKernel (PUBLIC * tEplNmtuStateChangeCallback) ( + tEplEventNmtStateChange NmtStateChange_p); + +typedef tEplKernel (PUBLIC * tEplNmtuCheckEventCallback) ( + tEplNmtEvent NmtEvent_p); + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuInit(void); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuAddInstance(void); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuDelInstance(void); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p); + +EPLDLLEXPORT tEplNmtState PUBLIC EplNmtuGetNmtState(void); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent( + tEplEvent* pEplEvent_p); + +EPLDLLEXPORT tEplKernel PUBLIC EplNmtuRegisterStateChangeCb( + tEplNmtuStateChangeCallback pfnEplNmtStateChangeCb_p); + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) + +#endif // #ifndef _EPLNMTU_H_ + + diff --git a/drivers/staging/epl/user/EplNmtuCal.h b/drivers/staging/epl/user/EplNmtuCal.h new file mode 100644 index 0000000..6d964bb --- /dev/null +++ b/drivers/staging/epl/user/EplNmtuCal.h @@ -0,0 +1,97 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for communication abstraction layer of the + NMT-Userspace-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplNmtuCal.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/16 -k.t.: start of the implementation + + +****************************************************************************/ + +#include "EplNmtu.h" +#include "../kernel/EplNmtk.h" + +#ifndef _EPLNMTUCAL_H_ +#define _EPLNMTUCAL_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplNmtState PUBLIC EplNmtkCalGetNmtState(void); + +#endif // #ifndef _EPLNMTUCAL_H_ + + diff --git a/drivers/staging/epl/user/EplObdu.h b/drivers/staging/epl/user/EplObdu.h new file mode 100644 index 0000000..14dd879 --- /dev/null +++ b/drivers/staging/epl/user/EplObdu.h @@ -0,0 +1,196 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for Epl-Obd-Userspace-module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObdu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/19 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplObd.h" + +#ifndef _EPLOBDU_H_ +#define _EPLOBDU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + +#if EPL_OBD_USE_KERNEL != FALSE +#error "EPL OBDu module enabled, but OBD_USE_KERNEL == TRUE" +#endif + +EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntry (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntry (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize *pSize_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduAccessOdPart (tEplObdPart ObdPart_p, + tEplObdDir Direction_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduDefineVar (tEplVarParam MEM* pVarParam_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT void* PUBLIC EplObduGetObjectDataPtr (unsigned int uiIndex_p, + unsigned int uiSubIndex_p); +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduRegisterUserOd ( + tEplObdEntryPtr pUserOd_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT void PUBLIC EplObduInitVarEntry (tEplObdVarEntry MEM* pVarEntry_p, + BYTE bType_p, + tEplObdSize ObdSize_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplObdSize PUBLIC EplObduGetDataSize(unsigned int uiIndex_p, + unsigned int uiSubIndex_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT unsigned int PUBLIC EplObduGetNodeId(void); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduSetNodeId(unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p); +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduGetAccessType(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess* pAccessTyp_p); +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntryToLe (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize * pSize_p); +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntryFromLe (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p); + +// --------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduSearchVarEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry MEM** ppVarEntry_p); + +#elif EPL_OBD_USE_KERNEL != FALSE +#include "../kernel/EplObdk.h" + +#define EplObduWriteEntry EplObdWriteEntry + +#define EplObduReadEntry EplObdReadEntry + +#define EplObduAccessOdPart EplObdAccessOdPart + +#define EplObduDefineVar EplObdDefineVar + +#define EplObduGetObjectDataPtr EplObdGetObjectDataPtr + +#define EplObduRegisterUserOd EplObdRegisterUserOd + +#define EplObduInitVarEntry EplObdInitVarEntry + +#define EplObduGetDataSize EplObdGetDataSize + +#define EplObduGetNodeId EplObdGetNodeId + +#define EplObduSetNodeId EplObdSetNodeId + +#define EplObduGetAccessType EplObdGetAccessType + +#define EplObduReadEntryToLe EplObdReadEntryToLe + +#define EplObduWriteEntryFromLe EplObdWriteEntryFromLe + +#define EplObduSearchVarEntry EplObdSearchVarEntry + +#define EplObduIsNumerical EplObdIsNumerical + +#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) + +#endif // #ifndef _EPLOBDU_H_ + + diff --git a/drivers/staging/epl/user/EplObduCal.h b/drivers/staging/epl/user/EplObduCal.h new file mode 100644 index 0000000..26d23c5 --- /dev/null +++ b/drivers/staging/epl/user/EplObduCal.h @@ -0,0 +1,148 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for communication abstraction layer + for the Epl-Obd-Userspace-Modul + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplObduCal.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/19 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplObd.h" + +#ifndef _EPLOBDUCAL_H_ +#define _EPLOBDUCAL_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntry ( + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntry ( + unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize *pSize_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalAccessOdPart ( + tEplObdPart ObdPart_p, + tEplObdDir Direction_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalDefineVar (tEplVarParam MEM* pVarParam_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT void* PUBLIC EplObduCalGetObjectDataPtr ( unsigned int uiIndex_p, + unsigned int uiSubIndex_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalRegisterUserOd (tEplObdEntryPtr pUserOd_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT void PUBLIC EplObduCalInitVarEntry (tEplObdVarEntry MEM* pVarEntry_p, + BYTE bType_p, tEplObdSize ObdSize_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplObdSize PUBLIC EplObduCalGetDataSize(unsigned int uiIndex_p, + unsigned int uiSubIndex_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT unsigned int PUBLIC EplObduCalGetNodeId(void); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalSetNodeId(unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalGetAccessType(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess* pAccessTyp_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntryToLe (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pDstData_p, + tEplObdSize * pSize_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntryFromLe (unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void * pSrcData_p, + tEplObdSize Size_p); +//--------------------------------------------------------------------------- +EPLDLLEXPORT tEplKernel PUBLIC EplObduCalSearchVarEntry (EPL_MCO_DECL_INSTANCE_PTR_ + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry MEM** ppVarEntry_p); + + +#endif // #ifndef _EPLOBDUCAL_H_ + + diff --git a/drivers/staging/epl/user/EplPdou.h b/drivers/staging/epl/user/EplPdou.h new file mode 100644 index 0000000..293f0f7 --- /dev/null +++ b/drivers/staging/epl/user/EplPdou.h @@ -0,0 +1,114 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for userspace PDO module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplPdou.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/11/19 17:14:38 $ + + $State: Exp $ + + Build Environment: + + ------------------------------------------------------------------------- + + Revision History: + + 2006/05/22 d.k.: start of the implementation, version 1.00 + + +****************************************************************************/ + +#ifndef _EPL_PDOU_H_ +#define _EPL_PDOU_H_ + +#include "../EplPdo.h" + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +tEplKernel EplPdouAddInstance(void); + +tEplKernel EplPdouDelInstance(void); + +#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0) +tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM* pParam_p); +#else +#define EplPdouCbObdAccess NULL +#endif + +// returns error if bPdoId_p is already valid +/* +tEplKernel EplPdouSetMapping( + BYTE bPdoId_p, BOOL fTxRx_p, BYTE bNodeId, BYTE bMappingVersion, + tEplPdoMapping * pMapping_p, BYTE bMaxEntries_p); + +tEplKernel EplPdouGetMapping( + BYTE bPdoId_p, BOOL fTxRx_p, BYTE * pbNodeId, BYTE * pbMappingVersion, + tEplPdoMapping * pMapping_p, BYTE * pbMaxEntries_p); +*/ + +#endif // #ifndef _EPL_PDOU_H_ + + diff --git a/drivers/staging/epl/user/EplSdoAsndu.h b/drivers/staging/epl/user/EplSdoAsndu.h new file mode 100644 index 0000000..bc2650e --- /dev/null +++ b/drivers/staging/epl/user/EplSdoAsndu.h @@ -0,0 +1,113 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for SDO/Asnd-Protocolabstractionlayer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdoAsndu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/07 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplSdo.h" +#include "../EplDll.h" + +#ifndef _EPLSDOASNDU_H_ +#define _EPLSDOASNDU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + +tEplKernel PUBLIC EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p); + +tEplKernel PUBLIC EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p); + +tEplKernel PUBLIC EplSdoAsnduDelInstance(void); + +tEplKernel PUBLIC EplSdoAsnduInitCon(tEplSdoConHdl* pSdoConHandle_p, + unsigned int uiTargetNodeId_p); + +tEplKernel PUBLIC EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p, + tEplFrame * pSrcData_p, + DWORD dwDataSize_p); + +tEplKernel PUBLIC EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p); + +#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) + +#endif // #ifndef _EPLSDOASNDU_H_ + + diff --git a/drivers/staging/epl/user/EplSdoAsySequ.h b/drivers/staging/epl/user/EplSdoAsySequ.h new file mode 100644 index 0000000..a9017ed --- /dev/null +++ b/drivers/staging/epl/user/EplSdoAsySequ.h @@ -0,0 +1,123 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for asychrionus SDO Sequence Layer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdoAsySequ.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/26 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplSdo.h" +#include "EplSdoUdpu.h" +#include "EplSdoAsndu.h" +#include "../EplEvent.h" +#include "EplTimeru.h" + +#ifndef _EPLSDOASYSEQU_H_ +#define _EPLSDOASYSEQU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p, + tEplSdoComConCb fpSdoComConCb_p); + +tEplKernel PUBLIC EplSdoAsySeqAddInstance (tEplSdoComReceiveCb fpSdoComCb_p, + tEplSdoComConCb fpSdoComConCb_p); + +tEplKernel PUBLIC EplSdoAsySeqDelInstance(void); + +tEplKernel PUBLIC EplSdoAsySeqInitCon(tEplSdoSeqConHdl* pSdoSeqConHdl_p, + unsigned int uiNodeId_p, + tEplSdoType SdoType); + +tEplKernel PUBLIC EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p, + unsigned int uiDataSize_p, + tEplFrame* pData_p ); + +tEplKernel PUBLIC EplSdoAsySeqProcessEvent(tEplEvent* pEvent_p); + +tEplKernel PUBLIC EplSdoAsySeqDelCon(tEplSdoSeqConHdl SdoSeqConHdl_p); + + + + + + + +#endif // #ifndef _EPLSDOASYSEQU_H_ + + diff --git a/drivers/staging/epl/user/EplSdoComu.h b/drivers/staging/epl/user/EplSdoComu.h new file mode 100644 index 0000000..16c8d7c --- /dev/null +++ b/drivers/staging/epl/user/EplSdoComu.h @@ -0,0 +1,135 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for SDO Command Layer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdoComu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/26 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplSdo.h" +#include "../EplObd.h" +#include "../EplSdoAc.h" +#include "EplObdu.h" +#include "EplSdoAsySequ.h" + +#ifndef _EPLSDOCOMU_H_ +#define _EPLSDOCOMU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +tEplKernel PUBLIC EplSdoComInit(void); + +tEplKernel PUBLIC EplSdoComAddInstance(void); + +tEplKernel PUBLIC EplSdoComDelInstance(void); + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) + +tEplKernel PUBLIC EplSdoComDefineCon(tEplSdoComConHdl* pSdoComConHdl_p, + unsigned int uiTargetNodeId_p, + tEplSdoType ProtType_p); + +tEplKernel PUBLIC EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex* pSdoComTransParam_p); + +tEplKernel PUBLIC EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p); + +tEplKernel PUBLIC EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p, + tEplSdoComFinished* pSdoComFinished_p); + +tEplKernel PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, + DWORD dwAbortCode_p); + +#endif + +// for future extention +/* +tEplKernel PUBLIC EplSdoComInitTransferAllByIndex(tEplSdoComTransParamAllByIndex* pSdoComTransParam_p); + +tEplKernel PUBLIC EplSdoComInitTransferByName(tEplSdoComTransParamByName* pSdoComTransParam_p); + +tEplKernel PUBLIC EplSdoComInitTransferFile(tEplSdoComTransParamFile* pSdoComTransParam_p); + +*/ + + + + + +#endif // #ifndef _EPLSDOCOMU_H_ + + diff --git a/drivers/staging/epl/user/EplSdoUdpu.h b/drivers/staging/epl/user/EplSdoUdpu.h new file mode 100644 index 0000000..ecd6814 --- /dev/null +++ b/drivers/staging/epl/user/EplSdoUdpu.h @@ -0,0 +1,114 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for SDO/UDP-Protocollabstractionlayer module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplSdoUdpu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/06/26 k.t.: start of the implementation + + +****************************************************************************/ + + +#include "../EplSdo.h" + +#ifndef _EPLSDOUDPU_H_ +#define _EPLSDOUDPU_H_ + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + +tEplKernel PUBLIC EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p); + +tEplKernel PUBLIC EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p); + +tEplKernel PUBLIC EplSdoUdpuDelInstance(void); + +tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p, unsigned int uiPort_p); + +tEplKernel PUBLIC EplSdoUdpuInitCon(tEplSdoConHdl* pSdoConHandle_p, + unsigned int uiTargetNodeId_p); + +tEplKernel PUBLIC EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p, + tEplFrame * pSrcData_p, + DWORD dwDataSize_p); + +tEplKernel PUBLIC EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p); + +#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) + +#endif // #ifndef _EPLSDOUDPU_H_ + + diff --git a/drivers/staging/epl/user/EplStatusu.h b/drivers/staging/epl/user/EplStatusu.h new file mode 100644 index 0000000..22547eb --- /dev/null +++ b/drivers/staging/epl/user/EplStatusu.h @@ -0,0 +1,109 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for Statusu-Module + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplStatusu.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/11/15 d.k.: start of the implementation + + +****************************************************************************/ + +#include "../EplDll.h" + +#ifndef _EPLSTATUSU_H_ +#define _EPLSTATUSU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + +typedef tEplKernel (PUBLIC * tEplStatusuCbResponse) ( + unsigned int uiNodeId_p, + tEplStatusResponse* pStatusResponse_p); + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplStatusuInit(void); + +tEplKernel PUBLIC EplStatusuAddInstance(void); + +tEplKernel PUBLIC EplStatusuDelInstance(void); + +tEplKernel PUBLIC EplStatusuReset(void); + +tEplKernel PUBLIC EplStatusuRequestStatusResponse( + unsigned int uiNodeId_p, + tEplStatusuCbResponse pfnCbResponse_p); + +#endif // #ifndef _EPLSTATUSU_H_ + + diff --git a/drivers/staging/epl/user/EplTimeru.h b/drivers/staging/epl/user/EplTimeru.h new file mode 100644 index 0000000..d5f1eaf --- /dev/null +++ b/drivers/staging/epl/user/EplTimeru.h @@ -0,0 +1,113 @@ +/**************************************************************************** + + (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 + www.systec-electronic.com + + Project: openPOWERLINK + + Description: include file for Epl Userspace-Timermodule + + License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of SYSTEC electronic GmbH nor the names of its + contributors may be used to endorse or promote products derived + from this software without prior written permission. For written + permission, please contact info@systec-electronic.com. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Severability Clause: + + If a provision of this License is or becomes illegal, invalid or + unenforceable in any jurisdiction, that shall not affect: + 1. the validity or enforceability in that jurisdiction of any other + provision of this License; or + 2. the validity or enforceability in other jurisdictions of that or + any other provision of this License. + + ------------------------------------------------------------------------- + + $RCSfile: EplTimeru.h,v $ + + $Author: D.Krueger $ + + $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $ + + $State: Exp $ + + Build Environment: + GCC V3.4 + + ------------------------------------------------------------------------- + + Revision History: + + 2006/07/06 k.t.: start of the implementation + + +****************************************************************************/ + +#include "../EplTimer.h" +#include "EplEventu.h" + +#ifndef _EPLTIMERU_H_ +#define _EPLTIMERU_H_ + + +//--------------------------------------------------------------------------- +// const defines +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// typedef +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// function prototypes +//--------------------------------------------------------------------------- + +tEplKernel PUBLIC EplTimeruInit(void); + +tEplKernel PUBLIC EplTimeruAddInstance(void); + +tEplKernel PUBLIC EplTimeruDelInstance(void); + +tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p); + +tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl* pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p); + +tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl* pTimerHdl_p); + +BOOL PUBLIC EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p); + +#endif // #ifndef _EPLTIMERU_H_ + + |