diff options
Diffstat (limited to 'drivers/staging/epl/EplApiLinuxKernel.c')
-rw-r--r-- | drivers/staging/epl/EplApiLinuxKernel.c | 1173 |
1 files changed, 0 insertions, 1173 deletions
diff --git a/drivers/staging/epl/EplApiLinuxKernel.c b/drivers/staging/epl/EplApiLinuxKernel.c deleted file mode 100644 index cb3e275e3aad..000000000000 --- a/drivers/staging/epl/EplApiLinuxKernel.c +++ /dev/null @@ -1,1173 +0,0 @@ -/**************************************************************************** - - (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/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> - -#include "Epl.h" -#include "EplApiLinux.h" -//#include "kernel/EplPdokCal.h" -#include "proc_fs.h" - - -/***************************************************************************/ -/* */ -/* */ -/* 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 TgtDbgSignalTracePoint(u8 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 -//--------------------------------------------------------------------------- - - // device number (major and minor) -static dev_t nDevNum_g; -static struct cdev *pEpl_cdev_g; - -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 EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) - tEplApiEventArg *pEventArg_p, // IN: event argument (union) - void *pUserArg_p); - -tEplKernel 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 -//--------------------------------------------------------------------------- - -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; - - 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); - - // 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; - } - - // 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"); - - // remove cdev structure - cdev_del(pEpl_cdev_g); - - // unregister character device handler - unregister_chrdev_region(nDevNum_g, 1); - - 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"); - - 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; - - 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 EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) - tEplApiEventArg *pEventArg_p, // IN: event argument (union) - void *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; |