3714 lines
141 KiB
C
3714 lines
141 KiB
C
|
|
/**************************************************************************************
|
||
|
|
|
||
|
|
Copyright (c) Hilscher Gesellschaft fuer Systemautomation mbH. All Rights Reserved.
|
||
|
|
|
||
|
|
***************************************************************************************
|
||
|
|
|
||
|
|
$Id: cifXFunctions.c 14699 2023-04-27 07:51:13Z RMayer $:
|
||
|
|
|
||
|
|
Description:
|
||
|
|
cifX API function implementation
|
||
|
|
|
||
|
|
Changes:
|
||
|
|
Date Description
|
||
|
|
-----------------------------------------------------------------------------------
|
||
|
|
2023-04-26 - Added new compiler option CIFX_TOOLKIT_USE_CUSTOM_DRV_FUNCS
|
||
|
|
- Moved check parameter macros to cifXtoolkit.h
|
||
|
|
2022-06-14 - Added option and handling for cached PLC memory pointers
|
||
|
|
- Reorganized xChannelPLCMemoryPtr() to handle caching option for IO area 0
|
||
|
|
2022-01-18 Fixed xSysdeviceResetEx() to allow additional flags passing to underlying functions
|
||
|
|
2021-09-13 Propagate changes of cifXErrors.h (spelling of name
|
||
|
|
CIFX_DEV_DMA_HANDSHAKEMODE_NOT_SUPPORTED)
|
||
|
|
2020-02-06 xDriverEnumBoards() should return CIFX_NO_MORE_ENTRIES
|
||
|
|
if ulBoard exceeds actual board count, instead of invalid board
|
||
|
|
2019-10-11 Use internal buffer for endian conversion in xChannelControlBlock()
|
||
|
|
Propagate prototype changes of endian conversion function
|
||
|
|
2018-11-06 Added new function xSysdeviceResetEx()
|
||
|
|
2018-10-10 - Updated header and definitions to new Hilscher defines
|
||
|
|
- Derived from cifX Toolkit V1.6.0.0
|
||
|
|
|
||
|
|
**************************************************************************************/
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! \file cifXFunctions.c
|
||
|
|
* cifX API function implementation */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
#include "cifXToolkit.h"
|
||
|
|
#include "cifXErrors.h"
|
||
|
|
#include "cifXEndianess.h"
|
||
|
|
|
||
|
|
#include "Hil_Results.h"
|
||
|
|
#include "Hil_Packet.h"
|
||
|
|
#include "Hil_SystemCmd.h"
|
||
|
|
|
||
|
|
/* Commonly used function from cifXInit.c, not exposed to the user interface */
|
||
|
|
int32_t cifXStartModule ( PDEVICEINSTANCE ptDevInstance, uint32_t ulChannelNumber, char* pszModuleName,
|
||
|
|
uint32_t ulFileSize, PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser);
|
||
|
|
int32_t cifXReadFirmwareIdent( PDEVICEINSTANCE ptDevInstance, uint32_t ulChannel,
|
||
|
|
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser);
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_TIME
|
||
|
|
void cifXInitTime ( PDEVICEINSTANCE ptDevInstance);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! \addtogroup CIFX_DRIVER_API cifX Driver API implementation
|
||
|
|
* \{ */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Errorcode to Errordescription lookup table (english only) */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static struct CIFX_ERROR_TO_DESCRtag
|
||
|
|
{
|
||
|
|
int32_t lError;
|
||
|
|
char* szErrorDescr;
|
||
|
|
|
||
|
|
} s_atErrorToDescrTable[] =
|
||
|
|
{
|
||
|
|
#ifndef CIFX_TOOLKIT_NO_ERRORLOOKUP
|
||
|
|
/*******************************************************************************
|
||
|
|
* cifX Device Driver Errors (Global)
|
||
|
|
*******************************************************************************/
|
||
|
|
{CIFX_INVALID_POINTER ,"Invalid pointer (e.g. NULL) passed to driver" },
|
||
|
|
{CIFX_INVALID_BOARD ,"No board with the given name / index available"},
|
||
|
|
{CIFX_INVALID_CHANNEL ,"No channel with the given index available" },
|
||
|
|
{CIFX_INVALID_HANDLE ,"Invalid handle passed to driver" },
|
||
|
|
{CIFX_INVALID_PARAMETER ,"Invalid parameter" },
|
||
|
|
{CIFX_INVALID_COMMAND ,"Invalid command" },
|
||
|
|
{CIFX_INVALID_BUFFERSIZE ,"Invalid buffer size" },
|
||
|
|
{CIFX_INVALID_ACCESS_SIZE ,"Invalid access size" },
|
||
|
|
{CIFX_FUNCTION_FAILED ,"Function failed" },
|
||
|
|
{CIFX_FILE_OPEN_FAILED ,"File could not be opened" },
|
||
|
|
{CIFX_FILE_SIZE_ZERO ,"File size is zero" },
|
||
|
|
{CIFX_FILE_LOAD_INSUFF_MEM ,"Insufficient memory to load file" },
|
||
|
|
{CIFX_FILE_READ_ERROR ,"Error reading from file" },
|
||
|
|
{CIFX_FILE_TYPE_INVALID ,"Invalid file type" },
|
||
|
|
{CIFX_FILE_NAME_INVALID ,"Invalid file name" },
|
||
|
|
{CIFX_FUNCTION_NOT_AVAILABLE ,"Driver function not available" },
|
||
|
|
{CIFX_BUFFER_TOO_SHORT ,"Given buffer is too short" },
|
||
|
|
{CIFX_MEMORY_MAPPING_FAILED ,"Failed to map the memory" },
|
||
|
|
{CIFX_NO_MORE_ENTRIES ,"No more entries available" },
|
||
|
|
{CIFX_CALLBACK_MODE_UNKNOWN ,"Unknown callback handling mode" },
|
||
|
|
{CIFX_CALLBACK_CREATE_EVENT_FAILED ,"Failed to create callback events" },
|
||
|
|
{CIFX_CALLBACK_CREATE_RECV_BUFFER ,"Failed to create callback receive buffer" },
|
||
|
|
{CIFX_CALLBACK_ALREADY_USED ,"Callback already used" },
|
||
|
|
{CIFX_CALLBACK_NOT_REGISTERED ,"Callback was not registered before" },
|
||
|
|
{CIFX_INTERRUPT_DISABLED ,"Interrupt is disabled" },
|
||
|
|
/*******************************************************************************
|
||
|
|
* Generic Driver Errors
|
||
|
|
*******************************************************************************/
|
||
|
|
{CIFX_DRV_NOT_INITIALIZED ,"Driver not initialized" },
|
||
|
|
{CIFX_DRV_INIT_STATE_ERROR ,"Driver init state error" },
|
||
|
|
{CIFX_DRV_READ_STATE_ERROR ,"Driver read state error" },
|
||
|
|
{CIFX_DRV_CMD_ACTIVE ,"Command is active on device" },
|
||
|
|
{CIFX_DRV_DOWNLOAD_FAILED ,"General error during download" },
|
||
|
|
{CIFX_DRV_WRONG_DRIVER_VERSION ,"Wrong driver version" },
|
||
|
|
{CIFX_DRV_DRIVER_NOT_LOADED ,"CIFx driver is not running" },
|
||
|
|
{CIFX_DRV_INIT_ERROR ,"Failed to initialize the device" },
|
||
|
|
{CIFX_DRV_CHANNEL_NOT_INITIALIZED ,"Channel not initialized (xChannelOpen not called)"},
|
||
|
|
{CIFX_DRV_IO_CONTROL_FAILED ,"IOControl call failed" },
|
||
|
|
{CIFX_DRV_NOT_OPENED ,"Driver was not opened" },
|
||
|
|
{CIFX_DRV_DOWNLOAD_STORAGE_UNKNOWN ,"Unknown download storage type (RAM/FLASH based) found"},
|
||
|
|
{CIFX_DRV_DOWNLOAD_FW_WRONG_CHANNEL,"Channel number for a firmware download not supported" },
|
||
|
|
{CIFX_DRV_DOWNLOAD_MODULE_NO_BASEOS,"Modules are not allowed without a Base OS firmware" },
|
||
|
|
/*******************************************************************************
|
||
|
|
* Generic Device Errors
|
||
|
|
*******************************************************************************/
|
||
|
|
{CIFX_DEV_DPM_ACCESS_ERROR ,"Dual port memory not accessible (board not found)"},
|
||
|
|
{CIFX_DEV_NOT_READY ,"Device not ready (ready flag failed)" },
|
||
|
|
{CIFX_DEV_NOT_RUNNING ,"Device not running (running flag failed)" },
|
||
|
|
{CIFX_DEV_WATCHDOG_FAILED ,"Watchdog test failed" },
|
||
|
|
{CIFX_DEV_SYSERR ,"Error in handshake flags" },
|
||
|
|
{CIFX_DEV_MAILBOX_FULL ,"Send mailbox is full" },
|
||
|
|
{CIFX_DEV_PUT_TIMEOUT ,"Send packet timeout" },
|
||
|
|
{CIFX_DEV_GET_TIMEOUT ,"Receive packet timeout" },
|
||
|
|
{CIFX_DEV_GET_NO_PACKET ,"No packet available" },
|
||
|
|
{CIFX_DEV_RESET_TIMEOUT ,"Reset command timeout" },
|
||
|
|
{CIFX_DEV_NO_COM_FLAG ,"COM-flag not set" },
|
||
|
|
{CIFX_DEV_EXCHANGE_FAILED ,"I/O data exchange failed" },
|
||
|
|
{CIFX_DEV_EXCHANGE_TIMEOUT ,"I/O data exchange timeout" },
|
||
|
|
{CIFX_DEV_COM_MODE_UNKNOWN ,"Unknown I/O exchange mode " },
|
||
|
|
{CIFX_DEV_FUNCTION_FAILED ,"Device function failed " },
|
||
|
|
{CIFX_DEV_DPMSIZE_MISMATCH ,"DPM size differs from configuration" },
|
||
|
|
{CIFX_DEV_STATE_MODE_UNKNOWN ,"Unknown state mode" },
|
||
|
|
{CIFX_DEV_HW_PORT_IS_USED ,"Output port already in use" },
|
||
|
|
{CIFX_DEV_CONFIG_LOCK_TIMEOUT ,"Configuration locking timeout" },
|
||
|
|
{CIFX_DEV_CONFIG_UNLOCK_TIMEOUT ,"Configuration unlocking timeout" },
|
||
|
|
{CIFX_DEV_HOST_STATE_SET_TIMEOUT ,"Set HOST state timeout" },
|
||
|
|
{CIFX_DEV_HOST_STATE_CLEAR_TIMEOUT ,"Clear HOST state timeout" },
|
||
|
|
{CIFX_DEV_INITIALIZATION_TIMEOUT ,"Timeout during channel initialization" },
|
||
|
|
{CIFX_DEV_BUS_STATE_ON_TIMEOUT ,"Set Bus ON timeout" },
|
||
|
|
{CIFX_DEV_BUS_STATE_OFF_TIMEOUT ," Set Bus OFF timeout" },
|
||
|
|
{CIFX_DEV_MODULE_ALREADY_RUNNING ,"Module already running" },
|
||
|
|
{CIFX_DEV_MODULE_ALREADY_EXISTS ,"Module already exists" },
|
||
|
|
{CIFX_DEV_DMA_INSUFF_BUFFER_COUNT ,"Number of configured DMA buffers insufficient" },
|
||
|
|
{CIFX_DEV_DMA_BUFFER_TOO_SMALL ,"DMA buffers size too small (min size 256Byte)" },
|
||
|
|
{CIFX_DEV_DMA_BUFFER_TOO_BIG ,"DMA buffers size too big (max size 63,75KByte)" },
|
||
|
|
{CIFX_DEV_DMA_BUFFER_NOT_ALIGNED ,"DMA buffer alignment failed (must be 256Byte)" },
|
||
|
|
{CIFX_DEV_DMA_HANDSHAKEMODE_NOT_SUPPORTED ,"I/O data uncontrolled handshake mode not supported" },
|
||
|
|
{CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED,"I/O area in DMA mode not supported (only area 0 possible)" },
|
||
|
|
{CIFX_DEV_DMA_STATE_ON_TIMEOUT ,"Set DMA ON timeout" },
|
||
|
|
{CIFX_DEV_DMA_STATE_OFF_TIMEOUT ,"Set DMA OFF timeout" },
|
||
|
|
{CIFX_DEV_SYNC_STATE_INVALID_MODE ,"Device is in invalid mode for this operation" },
|
||
|
|
{CIFX_DEV_SYNC_STATE_TIMEOUT ,"Waiting for synchronization event bits timed out" },
|
||
|
|
|
||
|
|
/*******************************************************************************/
|
||
|
|
#else
|
||
|
|
{CIFX_NO_ERROR, ""},
|
||
|
|
#endif
|
||
|
|
};
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Structure description of NETX_SYSTEM_CHANNEL_INFO */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static const CIFX_ENDIANESS_ENTRY_T s_atSystemChannelInfo[] =
|
||
|
|
{
|
||
|
|
/* Offset, Width, Elements */
|
||
|
|
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 1}, /* ulSizeOfChannel */
|
||
|
|
{ 0x08, eCIFX_ENDIANESS_WIDTH_16BIT, 2}, /* usSizeOfMailbox
|
||
|
|
usMailboxStartOffset */
|
||
|
|
};
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Structure description of NETX_HANDSHAKE_CHANNEL_INFO */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static const CIFX_ENDIANESS_ENTRY_T s_atHandshakeChannelInfo[] =
|
||
|
|
{
|
||
|
|
/* Offset, Width, Elements */
|
||
|
|
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 1}, /* ulSizeOfChannel */
|
||
|
|
};
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Structure description of NETX_COMMUNICATION_CHANNEL_INFO */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static const CIFX_ENDIANESS_ENTRY_T s_atCommChannelInfo[] =
|
||
|
|
{
|
||
|
|
/* Offset, Width, Elements */
|
||
|
|
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 1}, /* ulSizeOfChannel */
|
||
|
|
{ 0x08, eCIFX_ENDIANESS_WIDTH_16BIT, 3}, /* usCommunicationClass
|
||
|
|
usProtocolClass
|
||
|
|
usProtocolConformanceClass */
|
||
|
|
};
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Structure description of NETX_APPLICATION_CHANNEL_INFO */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static const CIFX_ENDIANESS_ENTRY_T s_atAppChannelInfo[] =
|
||
|
|
{
|
||
|
|
/* Offset, Width, Elements */
|
||
|
|
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 1}, /* ulSizeOfChannel */
|
||
|
|
};
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Structure description of NETX_SYSTEM_INFO_BLOCK */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static const CIFX_ENDIANESS_ENTRY_T s_atSystemInfoBlock[] =
|
||
|
|
{
|
||
|
|
/* Offset, Width, Elements */
|
||
|
|
{ 0x04, eCIFX_ENDIANESS_WIDTH_32BIT, 3}, /* DpmTotalSize, DevNr, SerNr */
|
||
|
|
{ 0x10, eCIFX_ENDIANESS_WIDTH_16BIT, 6}, /* ausHwOptions, usMfg, usProdDat */
|
||
|
|
{ 0x1C, eCIFX_ENDIANESS_WIDTH_32BIT, 2}, /* ulLicenseFlags1/2 */
|
||
|
|
{ 0x24, eCIFX_ENDIANESS_WIDTH_16BIT, 3}, /* LicenseId/flags, DeviceClass */
|
||
|
|
{ 0x2C, eCIFX_ENDIANESS_WIDTH_16BIT, 2}, /* ausReserved */
|
||
|
|
};
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Structure description of NETX_SYSTEM_CONTROL_BLOCK */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static const CIFX_ENDIANESS_ENTRY_T s_atSystemControlBlock[] =
|
||
|
|
{
|
||
|
|
/* Offset, Width, Elements */
|
||
|
|
{ 0x00, eCIFX_ENDIANESS_WIDTH_32BIT, 2}, /* ulSystemCmdCOS, ulReserved */
|
||
|
|
};
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Structure description of NETX_SYSTEM_STATUS_BLOCK */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static const CIFX_ENDIANESS_ENTRY_T s_atSystemStatusBlock[] =
|
||
|
|
{
|
||
|
|
/* Offset, Width, Elements */
|
||
|
|
{ 0x00, eCIFX_ENDIANESS_WIDTH_32BIT, 5}, /* ulSystem-COS/Status/Error
|
||
|
|
ulReserved1 */
|
||
|
|
{ 0x14, eCIFX_ENDIANESS_WIDTH_16BIT, 1}, /* usCpuLoad */
|
||
|
|
};
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Structure description of NETX_CONTROL_BLOCK */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static const CIFX_ENDIANESS_ENTRY_T s_atControlBlock[] =
|
||
|
|
{
|
||
|
|
/* Offset, Width, Elements */
|
||
|
|
{ 0x00, eCIFX_ENDIANESS_WIDTH_32BIT, 2}, /* ulApplCos, ulWatchdog */
|
||
|
|
};
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Structure description of NETX_COMMON_STATUS_BLOCK */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static const CIFX_ENDIANESS_ENTRY_T s_atCommonStatusBlock[] =
|
||
|
|
{
|
||
|
|
/* Offset, Width, Elements */
|
||
|
|
{ 0x00, eCIFX_ENDIANESS_WIDTH_32BIT, 3}, /* ulCommCos,ulCommState,
|
||
|
|
ulCommError */
|
||
|
|
{ 0x0C, eCIFX_ENDIANESS_WIDTH_16BIT, 2}, /* usVersion,usWatchDogTime
|
||
|
|
*/
|
||
|
|
{ 0x14, eCIFX_ENDIANESS_WIDTH_32BIT, 2}, /* ulHostWatchDog, ulErrorCount,
|
||
|
|
*/
|
||
|
|
{ 0x22, eCIFX_ENDIANESS_WIDTH_16BIT, 3}, /* ausReserved[3]
|
||
|
|
*/
|
||
|
|
{ 0x28, eCIFX_ENDIANESS_WIDTH_32BIT, 6}, /* ulSlaveState, ulSlaveErrLogInd
|
||
|
|
ulNumOfConfigSlaves,ulNumOfActiveSlaves
|
||
|
|
ulNumOfDiagSlaves, ulReserved */
|
||
|
|
};
|
||
|
|
|
||
|
|
extern uint32_t g_ulDeviceCount; /*!< Number of available device (Array size of g_pptDevices) */
|
||
|
|
extern PDEVICEINSTANCE* g_pptDevices; /*!< Array containing all handled device instances */
|
||
|
|
extern TKIT_DRIVER_INFORMATION g_tDriverInfo; /*!< Global driver information */
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_PARAMETER_CHECK
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Checks if the given sysdevice handle is valid
|
||
|
|
* \param hChannel Sysdevice handle
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static int32_t CheckSysdeviceHandle(CIFXHANDLE hChannel)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_INVALID_HANDLE;
|
||
|
|
|
||
|
|
if ( NULL != hChannel)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hChannel;
|
||
|
|
if ( ptSysDevice->fIsSysDevice)
|
||
|
|
{
|
||
|
|
if( 0 == ptSysDevice->ulOpenCount)
|
||
|
|
{
|
||
|
|
/* We are probably in the initialization phase without an opened device handle */
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
}else if ( (0 == g_ulDeviceCount) ||
|
||
|
|
(NULL == g_pptDevices) )
|
||
|
|
{
|
||
|
|
/* We can't search for the handle in the device list, because the list is not available. */
|
||
|
|
/* Maybe we are in the initialization phase and the list is not created yet. */
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
}else
|
||
|
|
{
|
||
|
|
/* Try to find the ptSysDevice pointer in one of the device instances */
|
||
|
|
uint32_t ulDev = 0;
|
||
|
|
|
||
|
|
for(ulDev = 0; ulDev < g_ulDeviceCount; ++ulDev)
|
||
|
|
{
|
||
|
|
if (ptSysDevice == &g_pptDevices[ulDev]->tSystemDevice)
|
||
|
|
{
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Checks if the given channel handle is valid
|
||
|
|
* \param hChannel Channel handle
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
static int32_t CheckChannelHandle(CIFXHANDLE hChannel)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_INVALID_HANDLE;
|
||
|
|
|
||
|
|
if ( NULL != hChannel)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptDevice = (PCHANNELINSTANCE)hChannel;
|
||
|
|
if ( ptDevice->fIsChannel)
|
||
|
|
{
|
||
|
|
/* Check if we can find our device in the device table */
|
||
|
|
if ( 0 == g_ulDeviceCount)
|
||
|
|
{
|
||
|
|
/* We are in the initialization phase without an device entry in the g_pptDevices table */
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
}else if ( (0 == g_ulDeviceCount) ||
|
||
|
|
(NULL == g_pptDevices) )
|
||
|
|
{
|
||
|
|
/* We can't search for the handle in the device list, because the list is not available. */
|
||
|
|
/* Maybe we are in the initialization phase and the list is not created yet. */
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
}else
|
||
|
|
{
|
||
|
|
/* Try to find the ptSysDevice pointer in one of the device instances */
|
||
|
|
uint32_t ulDev = 0;
|
||
|
|
|
||
|
|
/* Check if we can find our channel inside a device */
|
||
|
|
for(ulDev = 0; ulDev < g_ulDeviceCount; ++ulDev)
|
||
|
|
{
|
||
|
|
uint32_t ulChannel = 0;
|
||
|
|
for( ulChannel = 0; ulChannel < g_pptDevices[ulDev]->ulCommChannelCount; ++ulChannel)
|
||
|
|
{
|
||
|
|
if ( ptDevice == g_pptDevices[ulDev]->pptCommChannels[ulChannel])
|
||
|
|
{
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Opens the System device on the given board
|
||
|
|
* \param hDriver Driver handle
|
||
|
|
* \param szBoard Name of the board to open
|
||
|
|
* \param phSysdevice Returned handle to the System device area
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceOpen(CIFXHANDLE hDriver, char* szBoard, CIFXHANDLE* phSysdevice)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_INVALID_BOARD;
|
||
|
|
uint32_t ulIdx;
|
||
|
|
|
||
|
|
if(0 == g_tDriverInfo.ulOpenCount)
|
||
|
|
return CIFX_DRV_NOT_OPENED;
|
||
|
|
|
||
|
|
CHECK_DRIVERHANDLE(hDriver);
|
||
|
|
CHECK_POINTER(szBoard);
|
||
|
|
CHECK_POINTER(phSysdevice);
|
||
|
|
|
||
|
|
for(ulIdx = 0; ulIdx < g_ulDeviceCount; ++ulIdx)
|
||
|
|
{
|
||
|
|
if( (OS_Strcmp(g_pptDevices[ulIdx]->szName, szBoard) == 0) ||
|
||
|
|
(OS_Strcmp(g_pptDevices[ulIdx]->szAlias, szBoard) == 0) )
|
||
|
|
{
|
||
|
|
++g_pptDevices[ulIdx]->tSystemDevice.ulOpenCount;
|
||
|
|
*phSysdevice = (CIFXHANDLE)(&g_pptDevices[ulIdx]->tSystemDevice);
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet; /*lint !e438 */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Closes an open System device
|
||
|
|
* \param hSysdevice Handle to the System device to close
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceClose(CIFXHANDLE hSysdevice)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
|
||
|
|
CHECK_SYSDEVICEHANDLE(hSysdevice);
|
||
|
|
|
||
|
|
--ptSysDevice->ulOpenCount;
|
||
|
|
|
||
|
|
return CIFX_NO_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Gets the Mailbox state of an open system device
|
||
|
|
* \param hSysdevice Handle to the System device
|
||
|
|
* \param pulRecvPktCount Number of packets in receive mailbox
|
||
|
|
* \param pulSendPktCount Number of packets the application is able to send
|
||
|
|
* at once
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceGetMBXState(CIFXHANDLE hSysdevice, uint32_t* pulRecvPktCount, uint32_t* pulSendPktCount)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
|
||
|
|
return DEV_GetMBXState(ptSysDevice, pulRecvPktCount, pulSendPktCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Inserts a packet into the System Mailbox
|
||
|
|
* \param hSysdevice Handle to the System device
|
||
|
|
* \param ptSendPkt Packet to send to device
|
||
|
|
* \param ulTimeout maximum time to wait for packet to be accepted
|
||
|
|
* by device (in ms)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdevicePutPacket(CIFXHANDLE hSysdevice, CIFX_PACKET* ptSendPkt, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
|
||
|
|
if( !OS_WaitMutex( ptSysDevice->tSendMbx.pvSendMBXMutex, ulTimeout))
|
||
|
|
return CIFX_DRV_CMD_ACTIVE;
|
||
|
|
|
||
|
|
lRet = DEV_PutPacket(ptSysDevice, ptSendPkt, ulTimeout);
|
||
|
|
|
||
|
|
OS_ReleaseMutex( ptSysDevice->tSendMbx.pvSendMBXMutex);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Retrieves a packet from the System Mailbox
|
||
|
|
* \param hSysdevice Handle to the System device
|
||
|
|
* \param ulSize Size of the buffer to retrieve the packet
|
||
|
|
* \param ptRecvPkt Pointer to buffer for received packet
|
||
|
|
* \param ulTimeout maximum time to wait for packet to be delivered
|
||
|
|
* by device (in ms)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceGetPacket(CIFXHANDLE hSysdevice, uint32_t ulSize, CIFX_PACKET* ptRecvPkt, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
|
||
|
|
if( !OS_WaitMutex( ptSysDevice->tRecvMbx.pvRecvMBXMutex, ulTimeout))
|
||
|
|
return CIFX_DRV_CMD_ACTIVE;
|
||
|
|
|
||
|
|
lRet = DEV_GetPacket(ptSysDevice, ptRecvPkt, ulSize, ulTimeout);
|
||
|
|
|
||
|
|
OS_ReleaseMutex( ptSysDevice->tRecvMbx.pvRecvMBXMutex);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Download a file (Firmware, Configuration, etc) to the device
|
||
|
|
* \param hSysdevice Handle to the system device
|
||
|
|
* \param ulChannel Channel number to load the file to
|
||
|
|
* \param ulMode Download mode (DOWNLOAD_MODE_FIRMWARE, etc)
|
||
|
|
* \param pszFileName Name of the file
|
||
|
|
* \param pabFileData Pointer to the file data
|
||
|
|
* \param ulFileSize Length of the file data
|
||
|
|
* \param pfnCallback Callback for progress indication
|
||
|
|
* (NULL for no callback)
|
||
|
|
* \param pfnRecvPktCallback Callback Callback pointer for unsolicited receive packets
|
||
|
|
* (NULL for no callback)
|
||
|
|
* \param pvUser User parameter passed to callback
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceDownload( CIFXHANDLE hSysdevice,
|
||
|
|
uint32_t ulChannel,
|
||
|
|
uint32_t ulMode,
|
||
|
|
char* pszFileName,
|
||
|
|
uint8_t* pabFileData,
|
||
|
|
uint32_t ulFileSize,
|
||
|
|
PFN_PROGRESS_CALLBACK pfnCallback,
|
||
|
|
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback,
|
||
|
|
void* pvUser)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
uint32_t ulTransferType = 0;
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
CHECK_SYSDEVICEHANDLE(hSysdevice);
|
||
|
|
CHECK_POINTER(pszFileName);
|
||
|
|
CHECK_POINTER(pabFileData);
|
||
|
|
|
||
|
|
switch(ulMode)
|
||
|
|
{
|
||
|
|
case DOWNLOAD_MODE_FIRMWARE:
|
||
|
|
if( CIFX_NO_ERROR != (lRet = DEV_GetFWTransferTypeFromFileName( ((PDEVICEINSTANCE)(ptSysDevice->pvDeviceInstance))->eChipType,
|
||
|
|
pszFileName, &ulTransferType)))
|
||
|
|
return lRet;
|
||
|
|
|
||
|
|
lRet = DEV_DownloadFile(ptSysDevice,
|
||
|
|
ulChannel,
|
||
|
|
ptSysDevice->tSendMbx.ulSendMailboxLength,
|
||
|
|
ulTransferType,
|
||
|
|
pszFileName,
|
||
|
|
ulFileSize,
|
||
|
|
pabFileData,
|
||
|
|
DEV_TransferPacket,
|
||
|
|
pfnCallback,
|
||
|
|
pfnRecvPktCallback,
|
||
|
|
pvUser);
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
case DOWNLOAD_MODE_CONFIG:
|
||
|
|
case DOWNLOAD_MODE_FILE:
|
||
|
|
ulTransferType = HIL_FILE_XFER_FILE;
|
||
|
|
lRet = DEV_DownloadFile(ptSysDevice,
|
||
|
|
ulChannel,
|
||
|
|
ptSysDevice->tSendMbx.ulSendMailboxLength,
|
||
|
|
ulTransferType,
|
||
|
|
pszFileName,
|
||
|
|
ulFileSize,
|
||
|
|
pabFileData,
|
||
|
|
DEV_TransferPacket,
|
||
|
|
pfnCallback,
|
||
|
|
pfnRecvPktCallback,
|
||
|
|
pvUser);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case DOWNLOAD_MODE_LICENSECODE:
|
||
|
|
ulTransferType = HIL_FILE_XFER_LICENSE_CODE;
|
||
|
|
|
||
|
|
lRet = DEV_DownloadFile(ptSysDevice,
|
||
|
|
ulChannel,
|
||
|
|
ptSysDevice->tSendMbx.ulSendMailboxLength,
|
||
|
|
ulTransferType,
|
||
|
|
pszFileName,
|
||
|
|
ulFileSize,
|
||
|
|
pabFileData,
|
||
|
|
DEV_TransferPacket,
|
||
|
|
pfnCallback,
|
||
|
|
pfnRecvPktCallback,
|
||
|
|
pvUser);
|
||
|
|
|
||
|
|
break;
|
||
|
|
|
||
|
|
case DOWNLOAD_MODE_MODULE:
|
||
|
|
{
|
||
|
|
/* We downloading a NXO file */
|
||
|
|
PDEVICEINSTANCE ptDevInstance = (PDEVICEINSTANCE)ptSysDevice->pvDeviceInstance;
|
||
|
|
PCHANNELINSTANCE ptChannelInst = NULL;
|
||
|
|
|
||
|
|
/* Check if we have a NXO module file */
|
||
|
|
if ( !DEV_IsNXOFile( pszFileName))
|
||
|
|
{
|
||
|
|
lRet = CIFX_FILE_NAME_INVALID;
|
||
|
|
} else if(ulChannel >= ptDevInstance->ulCommChannelCount)
|
||
|
|
{
|
||
|
|
/* Invalid channel number */
|
||
|
|
lRet = CIFX_INVALID_CHANNEL;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check if the channel is READY and something is already loaded */
|
||
|
|
ptChannelInst = ptDevInstance->pptCommChannels[ulChannel];
|
||
|
|
|
||
|
|
/* Check if we are supporting modules */
|
||
|
|
if( !ptDevInstance->fModuleLoad)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_DOWNLOAD_MODULE_NO_BASEOS;
|
||
|
|
} else if( DEV_IsReady(ptChannelInst))
|
||
|
|
{
|
||
|
|
/* Channel already READY */
|
||
|
|
lRet = CIFX_DEV_MODULE_ALREADY_RUNNING;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
uint8_t bLoadState = CIFXTKIT_DOWNLOAD_NONE;
|
||
|
|
if ( CIFX_NO_ERROR == (lRet = DEV_ProcessFWDownload( ptDevInstance,
|
||
|
|
ulChannel,
|
||
|
|
NULL,
|
||
|
|
pszFileName,
|
||
|
|
ulFileSize,
|
||
|
|
pabFileData,
|
||
|
|
&bLoadState,
|
||
|
|
DEV_TransferPacket,
|
||
|
|
pfnCallback,
|
||
|
|
pfnRecvPktCallback,
|
||
|
|
pvUser)))
|
||
|
|
{
|
||
|
|
/* Start module */
|
||
|
|
if (CIFX_NO_ERROR == (lRet = cifXStartModule( ptDevInstance, ulChannel, pszFileName,
|
||
|
|
ulFileSize, pfnRecvPktCallback, pvUser)))
|
||
|
|
{
|
||
|
|
if ( CIFX_NO_ERROR == (lRet = cifXReadFirmwareIdent( ptDevInstance, ulChannel,
|
||
|
|
pfnRecvPktCallback, pvUser)))
|
||
|
|
{
|
||
|
|
if ( 0 == (bLoadState & CIFXTKIT_DOWNLOAD_EXECUTED))
|
||
|
|
{
|
||
|
|
/* Return download skipped, file exists */
|
||
|
|
lRet = CIFX_DEV_MODULE_ALREADY_EXISTS;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
return CIFX_INVALID_PARAMETER;
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Gets the information of a system device
|
||
|
|
* \param hSysdevice Handle to the system device
|
||
|
|
* \param ulCmd Information to fetch (see defines CIFX_INFO_CMD_SYSTEM_XXX)
|
||
|
|
* \param ulSize Size of the passed structure
|
||
|
|
* \param pvInfo Pointer to the structure for returned data
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceInfo(CIFXHANDLE hSysdevice, uint32_t ulCmd, uint32_t ulSize, void* pvInfo)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
HIL_DPM_SYSTEM_CHANNEL_T* ptSysChannel = NULL;
|
||
|
|
|
||
|
|
CHECK_SYSDEVICEHANDLE(hSysdevice);
|
||
|
|
CHECK_POINTER(pvInfo);
|
||
|
|
|
||
|
|
ptSysChannel = (HIL_DPM_SYSTEM_CHANNEL_T*)ptSysDevice->pbDPMChannelStart;
|
||
|
|
|
||
|
|
switch(ulCmd)
|
||
|
|
{
|
||
|
|
case CIFX_INFO_CMD_SYSTEM_INFORMATION:
|
||
|
|
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_INFORMATION))
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_BUFFERSIZE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Insert global system channel information */
|
||
|
|
SYSTEM_CHANNEL_SYSTEM_INFORMATION* ptInfo = (SYSTEM_CHANNEL_SYSTEM_INFORMATION*)pvInfo;
|
||
|
|
|
||
|
|
/* These values are directly read from DPM, so they need to be converted to host endianess */
|
||
|
|
ptInfo->ulSystemError = LE32_TO_HOST(HWIF_READ32(ptSysDevice->pvDeviceInstance, ptSysChannel->tSystemState.ulSystemError));
|
||
|
|
ptInfo->ulDpmTotalSize = LE32_TO_HOST(HWIF_READ32(ptSysDevice->pvDeviceInstance, ptSysChannel->tSystemInfo.ulDpmTotalSize));
|
||
|
|
ptInfo->ulDeviceNumber = LE32_TO_HOST(HWIF_READ32(ptSysDevice->pvDeviceInstance, ptSysChannel->tSystemInfo.ulDeviceNumber));
|
||
|
|
ptInfo->ulSerialNumber = LE32_TO_HOST(HWIF_READ32(ptSysDevice->pvDeviceInstance, ptSysChannel->tSystemInfo.ulSerialNumber));
|
||
|
|
|
||
|
|
ptInfo->ulMBXSize = ptSysDevice->tRecvMbx.ulRecvMailboxLength;
|
||
|
|
ptInfo->ulOpenCnt = ptSysDevice->ulOpenCount;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_INFO_CMD_SYSTEM_INFO_BLOCK:
|
||
|
|
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_INFO_BLOCK))
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_BUFFERSIZE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
uint32_t ulCopyLen = min( ulSize,
|
||
|
|
(uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_INFO_BLOCK));
|
||
|
|
|
||
|
|
HWIF_READN(ptSysDevice->pvDeviceInstance, pvInfo, &ptSysChannel->tSystemInfo, ulCopyLen);
|
||
|
|
|
||
|
|
(void)cifXConvertEndianess(0,
|
||
|
|
pvInfo,
|
||
|
|
ulCopyLen,
|
||
|
|
s_atSystemInfoBlock,
|
||
|
|
sizeof(s_atSystemInfoBlock) / sizeof(s_atSystemInfoBlock[0]));
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_INFO_CMD_SYSTEM_CHANNEL_BLOCK:
|
||
|
|
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_CHANNEL_INFO_BLOCK))
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_BUFFERSIZE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
SYSTEM_CHANNEL_CHANNEL_INFO_BLOCK* ptInfoBuffer = (SYSTEM_CHANNEL_CHANNEL_INFO_BLOCK*) pvInfo; /* use the read buffer for data conversion */
|
||
|
|
|
||
|
|
uint32_t ulCopyLen = min( ulSize,
|
||
|
|
(uint32_t)sizeof(SYSTEM_CHANNEL_CHANNEL_INFO_BLOCK));
|
||
|
|
int iChannel;
|
||
|
|
|
||
|
|
HWIF_READN(ptSysDevice->pvDeviceInstance, pvInfo, &ptSysChannel->atChannelInfo[0], ulCopyLen);
|
||
|
|
|
||
|
|
/* Convert channel information structure. This depends on the first byte (bChannelType),
|
||
|
|
so we need to parse the whole array */
|
||
|
|
for(iChannel = 0;
|
||
|
|
iChannel < (int) (sizeof(ptSysChannel->atChannelInfo) / sizeof(ptSysChannel->atChannelInfo[0]));
|
||
|
|
++iChannel)
|
||
|
|
{
|
||
|
|
uint32_t ulBlockLength = (uint32_t)sizeof(ptSysChannel->atChannelInfo[0]);
|
||
|
|
uint32_t ulOffset = (uint32_t)(iChannel * ulBlockLength);
|
||
|
|
|
||
|
|
if( ulOffset > ulCopyLen)
|
||
|
|
break;
|
||
|
|
|
||
|
|
if( (ulOffset + sizeof(ptSysChannel->atChannelInfo[0])) > ulCopyLen)
|
||
|
|
{
|
||
|
|
/* part of block copied, so calculate restlen */
|
||
|
|
ulBlockLength = ulCopyLen - ulOffset;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Convert endianess */
|
||
|
|
switch(ptInfoBuffer->abInfoBlock[iChannel][0])
|
||
|
|
{
|
||
|
|
case HIL_CHANNEL_TYPE_SYSTEM:
|
||
|
|
(void)cifXConvertEndianess(0,
|
||
|
|
&ptInfoBuffer->abInfoBlock[iChannel], /*lint !e545 */
|
||
|
|
ulBlockLength,
|
||
|
|
s_atSystemChannelInfo,
|
||
|
|
sizeof(s_atSystemChannelInfo) / sizeof(s_atSystemChannelInfo[0]));
|
||
|
|
break;
|
||
|
|
|
||
|
|
case HIL_CHANNEL_TYPE_HANDSHAKE:
|
||
|
|
(void)cifXConvertEndianess(0,
|
||
|
|
&ptInfoBuffer->abInfoBlock[iChannel], /*lint !e545 */
|
||
|
|
ulBlockLength,
|
||
|
|
s_atHandshakeChannelInfo,
|
||
|
|
sizeof(s_atHandshakeChannelInfo) / sizeof(s_atHandshakeChannelInfo[0]));
|
||
|
|
break;
|
||
|
|
|
||
|
|
case HIL_CHANNEL_TYPE_COMMUNICATION:
|
||
|
|
(void)cifXConvertEndianess(0,
|
||
|
|
&ptInfoBuffer->abInfoBlock[iChannel], /*lint !e545 */
|
||
|
|
ulBlockLength,
|
||
|
|
s_atCommChannelInfo,
|
||
|
|
sizeof(s_atCommChannelInfo) / sizeof(s_atCommChannelInfo[0]));
|
||
|
|
break;
|
||
|
|
|
||
|
|
case HIL_CHANNEL_TYPE_APPLICATION:
|
||
|
|
(void)cifXConvertEndianess(0,
|
||
|
|
&ptInfoBuffer->abInfoBlock[iChannel], /*lint !e545 */
|
||
|
|
ulBlockLength,
|
||
|
|
s_atAppChannelInfo,
|
||
|
|
sizeof(s_atAppChannelInfo) / sizeof(s_atAppChannelInfo[0]));
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
/* This should never happen */
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_INFO_CMD_SYSTEM_CONTROL_BLOCK:
|
||
|
|
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_CONTROL_BLOCK))
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_BUFFERSIZE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
uint32_t ulCopyLen = min(ulSize,
|
||
|
|
(uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_CONTROL_BLOCK));
|
||
|
|
HWIF_READN(ptSysDevice->pvDeviceInstance, pvInfo, &ptSysChannel->tSystemControl, ulCopyLen);
|
||
|
|
|
||
|
|
(void)cifXConvertEndianess(0,
|
||
|
|
pvInfo,
|
||
|
|
ulCopyLen,
|
||
|
|
s_atSystemControlBlock,
|
||
|
|
sizeof(s_atSystemControlBlock) / sizeof(s_atSystemControlBlock[0]));
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_INFO_CMD_SYSTEM_STATUS_BLOCK:
|
||
|
|
if( ulSize < (uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_STATUS_BLOCK))
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_BUFFERSIZE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
uint32_t ulCopyLen = min(ulSize,
|
||
|
|
(uint32_t)sizeof(SYSTEM_CHANNEL_SYSTEM_STATUS_BLOCK));
|
||
|
|
|
||
|
|
HWIF_READN(ptSysDevice->pvDeviceInstance, pvInfo, &ptSysChannel->tSystemState, ulCopyLen);
|
||
|
|
|
||
|
|
(void)cifXConvertEndianess(0,
|
||
|
|
pvInfo,
|
||
|
|
ulCopyLen,
|
||
|
|
s_atSystemStatusBlock,
|
||
|
|
sizeof(s_atSystemStatusBlock) / sizeof(s_atSystemStatusBlock[0]));
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
|
||
|
|
} /* end switch */
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Hard resets a complete device via system channel with reset parameter
|
||
|
|
* \param hSysdevice Handle to system device
|
||
|
|
* \param ulTimeout Timeout to wait for card to finish reset
|
||
|
|
* \param ulMode Reset mode with parameter
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceResetEx(CIFXHANDLE hSysdevice, uint32_t ulTimeout, uint32_t ulMode)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE) hSysdevice;
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
CHECK_SYSDEVICEHANDLE(hSysdevice);
|
||
|
|
|
||
|
|
/* Evaluate which mode is selected, only write reset parameter if reset mode is supported */
|
||
|
|
if(CIFX_RESETEX_SYSTEMSTART == (HIL_SYS_CONTROL_RESET_MODE_MASK & ulMode))
|
||
|
|
{
|
||
|
|
lRet = DEV_DoSystemStart(ptSysDevice, ulTimeout, (HIL_SYS_CONTROL_RESET_PARAM_FLAG_MASK & ulMode));
|
||
|
|
}
|
||
|
|
else if(CIFX_RESETEX_BOOTSTART == (HIL_SYS_CONTROL_RESET_MODE_MASK & ulMode))
|
||
|
|
{
|
||
|
|
lRet = DEV_DoSystemBootstart(ptSysDevice, ulTimeout, (HIL_SYS_CONTROL_RESET_PARAM_FLAG_MASK & ulMode));
|
||
|
|
}
|
||
|
|
else if(CIFX_RESETEX_UPDATESTART == (HIL_SYS_CONTROL_RESET_MODE_MASK & ulMode))
|
||
|
|
{
|
||
|
|
lRet = DEV_DoUpdateStart(ptSysDevice, ulTimeout, (HIL_SYS_CONTROL_RESET_PARAM_FLAG_MASK & ulMode));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* No handling for unknown reset mode */
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_TIME
|
||
|
|
if (CIFX_NO_ERROR == lRet)
|
||
|
|
cifXInitTime((PDEVICEINSTANCE)ptSysDevice->pvDeviceInstance);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Hard resets a complete device via system channel
|
||
|
|
* \param hSysdevice Handle to system device
|
||
|
|
* \param ulTimeout Timeout to wait for card to finish reset
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceReset(CIFXHANDLE hSysdevice, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet;
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
|
||
|
|
CHECK_SYSDEVICEHANDLE(hSysdevice);
|
||
|
|
|
||
|
|
lRet = DEV_DoSystemStart(ptSysDevice, ulTimeout, 0);
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_TIME
|
||
|
|
if (CIFX_NO_ERROR == lRet)
|
||
|
|
cifXInitTime((PDEVICEINSTANCE)ptSysDevice->pvDeviceInstance);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Boot start reset to via system channel
|
||
|
|
* \param hSysdevice Handle to system device
|
||
|
|
* \param ulTimeout Timeout to wait for card to finish reset
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceBootstart(CIFXHANDLE hSysdevice, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet;
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
|
||
|
|
CHECK_SYSDEVICEHANDLE(hSysdevice);
|
||
|
|
|
||
|
|
lRet = DEV_DoSystemBootstart(ptSysDevice, ulTimeout, 0);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Get/Return a memory pointer to an extended board memory if available
|
||
|
|
* \param hSysdevice Handle to system device
|
||
|
|
* \param ulCmd Command for get/free
|
||
|
|
* \param ptExtMemInfo Pointer to a user buffer to return the information
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceExtendedMemory(CIFXHANDLE hSysdevice, uint32_t ulCmd, CIFX_EXTENDED_MEMORY_INFORMATION* ptExtMemInfo)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
PDEVICEINSTANCE ptDevInst = (PDEVICEINSTANCE)ptSysDevice->pvDeviceInstance;
|
||
|
|
HIL_DPM_SYSTEM_CHANNEL_T* ptSysChannel = NULL;
|
||
|
|
|
||
|
|
CHECK_SYSDEVICEHANDLE(hSysdevice);
|
||
|
|
CHECK_POINTER(ptExtMemInfo);
|
||
|
|
|
||
|
|
ptSysChannel = (HIL_DPM_SYSTEM_CHANNEL_T*)ptSysDevice->pbDPMChannelStart;
|
||
|
|
|
||
|
|
if(0 == g_tDriverInfo.ulOpenCount)
|
||
|
|
return CIFX_DRV_NOT_OPENED;
|
||
|
|
|
||
|
|
switch(ulCmd)
|
||
|
|
{
|
||
|
|
case CIFX_GET_EXTENDED_MEMORY_POINTER:
|
||
|
|
{
|
||
|
|
void* pvMemoryPtr = NULL;
|
||
|
|
|
||
|
|
if( (NULL == ptDevInst->pbExtendedMemory) ||
|
||
|
|
(0 == ptDevInst->ulExtendedMemorySize))
|
||
|
|
|
||
|
|
{
|
||
|
|
lRet = CIFX_MEMORY_MAPPING_FAILED;
|
||
|
|
}else
|
||
|
|
{
|
||
|
|
|
||
|
|
ptExtMemInfo->pvMemoryID = NULL;
|
||
|
|
ptExtMemInfo->pvMemoryPtr = NULL;
|
||
|
|
ptExtMemInfo->ulMemorySize = 0;
|
||
|
|
ptExtMemInfo->ulMemoryType = 0;
|
||
|
|
|
||
|
|
|
||
|
|
/* Return global memory information */
|
||
|
|
if(NULL == (ptExtMemInfo->pvMemoryID = OS_MapUserPointer(ptDevInst->pbExtendedMemory,
|
||
|
|
ptDevInst->ulExtendedMemorySize,
|
||
|
|
&pvMemoryPtr,
|
||
|
|
ptDevInst->pvOSDependent,
|
||
|
|
0)))
|
||
|
|
{
|
||
|
|
lRet = CIFX_MEMORY_MAPPING_FAILED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ptExtMemInfo->pvMemoryPtr = pvMemoryPtr;
|
||
|
|
ptExtMemInfo->ulMemorySize = ptDevInst->ulExtendedMemorySize;
|
||
|
|
ptExtMemInfo->ulMemoryType = LE32_TO_HOST(HWIF_READ32( ptDevInst, ptSysChannel->tSystemState.ulHWFeatures)) & (HIL_SYSTEM_EXTMEM_ACCESS_MSK | HIL_SYSTEM_EXTMEM_TYPE_MSK);
|
||
|
|
|
||
|
|
if( HIL_SYSTEM_EXTMEM_ACCESS_BOTH == (ptExtMemInfo->ulMemoryType & HIL_SYSTEM_EXTMEM_ACCESS_MSK))
|
||
|
|
ptExtMemInfo->ulMemorySize = ptDevInst->ulExtendedMemorySize / 2;
|
||
|
|
else if( HIL_SYSTEM_EXTMEM_ACCESS_INTERNAL == (ptExtMemInfo->ulMemoryType & HIL_SYSTEM_EXTMEM_ACCESS_MSK))
|
||
|
|
ptExtMemInfo->ulMemorySize = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_FREE_EXTENDED_MEMORY_POINTER:
|
||
|
|
{
|
||
|
|
/* Clear user area */
|
||
|
|
if(!OS_UnmapUserPointer(ptExtMemInfo->pvMemoryID, ptDevInst->pvOSDependent))
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_HANDLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ptExtMemInfo->pvMemoryID = NULL;
|
||
|
|
ptExtMemInfo->pvMemoryPtr = NULL;
|
||
|
|
ptExtMemInfo->ulMemorySize = 0;
|
||
|
|
ptExtMemInfo->ulMemoryType = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_GET_EXTENDED_MEMORY_INFO:
|
||
|
|
{
|
||
|
|
ptExtMemInfo->pvMemoryID = NULL;
|
||
|
|
ptExtMemInfo->pvMemoryPtr = NULL;
|
||
|
|
ptExtMemInfo->ulMemorySize = ptDevInst->ulExtendedMemorySize;
|
||
|
|
ptExtMemInfo->ulMemoryType = LE32_TO_HOST(HWIF_READ32( ptDevInst, ptSysChannel->tSystemState.ulHWFeatures)) & (HIL_SYSTEM_EXTMEM_ACCESS_MSK | HIL_SYSTEM_EXTMEM_TYPE_MSK);
|
||
|
|
|
||
|
|
if( HIL_SYSTEM_EXTMEM_ACCESS_BOTH == (ptExtMemInfo->ulMemoryType & HIL_SYSTEM_EXTMEM_ACCESS_MSK))
|
||
|
|
ptExtMemInfo->ulMemorySize = ptDevInst->ulExtendedMemorySize / 2;
|
||
|
|
else if( HIL_SYSTEM_EXTMEM_ACCESS_INTERNAL == (ptExtMemInfo->ulMemoryType & HIL_SYSTEM_EXTMEM_ACCESS_MSK))
|
||
|
|
ptExtMemInfo->ulMemorySize = 0;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
} /* end switch */
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Opens a channel by name (Name can be obtained when enumerating Channels)
|
||
|
|
* \param hDriver Driver handle
|
||
|
|
* \param szBoard DOS Device Name of the Board to open
|
||
|
|
* \param ulChannel Channel number to open (0..n)
|
||
|
|
* \param phChannel Returned handle to the channel (Needed for all channel
|
||
|
|
* specific operations)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelOpen(CIFXHANDLE hDriver, char* szBoard, uint32_t ulChannel, CIFXHANDLE* phChannel)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_INVALID_BOARD;
|
||
|
|
uint32_t ulIdx;
|
||
|
|
|
||
|
|
if(0 == g_tDriverInfo.ulOpenCount)
|
||
|
|
return CIFX_DRV_NOT_OPENED;
|
||
|
|
|
||
|
|
CHECK_DRIVERHANDLE(hDriver);
|
||
|
|
CHECK_POINTER(szBoard);
|
||
|
|
CHECK_POINTER(phChannel);
|
||
|
|
|
||
|
|
for(ulIdx = 0; ulIdx < g_ulDeviceCount; ++ulIdx)
|
||
|
|
{
|
||
|
|
/* Try to find the requested board */
|
||
|
|
if( (OS_Strcmp(g_pptDevices[ulIdx]->szName, szBoard) == 0) ||
|
||
|
|
(OS_Strcmp(g_pptDevices[ulIdx]->szAlias, szBoard) == 0) )
|
||
|
|
{
|
||
|
|
/* Try to open the given channel */
|
||
|
|
lRet = CIFX_INVALID_CHANNEL;
|
||
|
|
if(ulChannel < g_pptDevices[ulIdx]->ulCommChannelCount)
|
||
|
|
{
|
||
|
|
/* We found the channel */
|
||
|
|
PCHANNELINSTANCE ptChannel = g_pptDevices[ulIdx]->pptCommChannels[ulChannel];
|
||
|
|
++ptChannel->ulOpenCount;
|
||
|
|
*phChannel = (CIFXHANDLE)ptChannel;
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet; /*lint !e438 */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Closes a previously opened channel
|
||
|
|
* \param hChannel Channel handle acquired by xChannelOpen
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelClose(CIFXHANDLE hChannel)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
|
||
|
|
--ptChannel->ulOpenCount;
|
||
|
|
|
||
|
|
return CIFX_NO_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Download a file (Firmware, Configuration, etc) to the device
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulMode Download mode (DOWNLOAD_MODE_FIRMWARE, etc)
|
||
|
|
* \param pszFileName Name of the file
|
||
|
|
* \param pabFileData Pointer to the file data
|
||
|
|
* \param ulFileSize Length of the file data
|
||
|
|
* \param pfnCallback Callback for progress indication
|
||
|
|
* (NULL for no callback)
|
||
|
|
* \param pfnRecvPktCallback Callback Callback pointer for unsolicited receive packets
|
||
|
|
* (NULL for no callback)
|
||
|
|
* \param pvUser User parameter passed to callback
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelDownload(CIFXHANDLE hChannel, uint32_t ulMode,
|
||
|
|
char* pszFileName, uint8_t* pabFileData, uint32_t ulFileSize,
|
||
|
|
PFN_PROGRESS_CALLBACK pfnCallback, PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
uint32_t ulTransferType = 0;
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pszFileName);
|
||
|
|
CHECK_POINTER(pabFileData);
|
||
|
|
|
||
|
|
switch(ulMode)
|
||
|
|
{
|
||
|
|
case DOWNLOAD_MODE_FIRMWARE:
|
||
|
|
if( CIFX_NO_ERROR != (lRet = DEV_GetFWTransferTypeFromFileName( ((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->eChipType,
|
||
|
|
pszFileName, &ulTransferType)))
|
||
|
|
return lRet;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case DOWNLOAD_MODE_CONFIG:
|
||
|
|
case DOWNLOAD_MODE_FILE:
|
||
|
|
ulTransferType = HIL_FILE_XFER_FILE;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case DOWNLOAD_MODE_LICENSECODE:
|
||
|
|
ulTransferType = HIL_FILE_XFER_LICENSE_CODE;
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
return CIFX_INVALID_PARAMETER;
|
||
|
|
}
|
||
|
|
|
||
|
|
lRet = DEV_DownloadFile(ptChannel,
|
||
|
|
ptChannel->ulChannelNumber,
|
||
|
|
ptChannel->tSendMbx.ulSendMailboxLength,
|
||
|
|
ulTransferType,
|
||
|
|
pszFileName,
|
||
|
|
ulFileSize,
|
||
|
|
pabFileData,
|
||
|
|
DEV_TransferPacket,
|
||
|
|
pfnCallback,
|
||
|
|
pfnRecvPktCallback,
|
||
|
|
pvUser);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Returns the Mailbox state from a specific channel
|
||
|
|
* \param hChannel Channel handle acquired by xChannelOpen
|
||
|
|
* \param pulRecvPktCount Number of Messages waiting in receive mailbox
|
||
|
|
* \param pulSendPktCount State of the Send Mailbox
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelGetMBXState(CIFXHANDLE hChannel, uint32_t* pulRecvPktCount, uint32_t* pulSendPktCount)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
return DEV_GetMBXState(ptChannel, pulRecvPktCount, pulSendPktCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Inserts a packet into the channels mailbox
|
||
|
|
* \param hChannel Channel handle acquired by xChannelOpen
|
||
|
|
* \param ptSendPkt Packet to send to channel
|
||
|
|
* \param ulTimeout Time in ms to wait for card to accept the packet
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelPutPacket(CIFXHANDLE hChannel, CIFX_PACKET* ptSendPkt, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
/* Check if another command is active */
|
||
|
|
if ( 0 == OS_WaitMutex( ptChannel->tSendMbx.pvSendMBXMutex, ulTimeout))
|
||
|
|
return CIFX_DRV_CMD_ACTIVE;
|
||
|
|
|
||
|
|
lRet = DEV_PutPacket(ptChannel, ptSendPkt, ulTimeout);
|
||
|
|
|
||
|
|
/* Release command */
|
||
|
|
OS_ReleaseMutex(ptChannel->tSendMbx.pvSendMBXMutex);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Gets a packet from the channels mailbox
|
||
|
|
* \param hChannel Channel handle acquired by xChannelOpen
|
||
|
|
* \param ulSize Size of the return packet buffer
|
||
|
|
* \param ptRecvPkt Returned packet
|
||
|
|
* \param ulTimeout Time in ms to wait for available message
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelGetPacket(CIFXHANDLE hChannel, uint32_t ulSize, CIFX_PACKET* ptRecvPkt, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
/* Check if another command is active */
|
||
|
|
if ( 0 == OS_WaitMutex( ptChannel->tRecvMbx.pvRecvMBXMutex, ulTimeout))
|
||
|
|
return CIFX_DRV_CMD_ACTIVE;
|
||
|
|
|
||
|
|
lRet = DEV_GetPacket(ptChannel, ptRecvPkt, ulSize, ulTimeout);
|
||
|
|
|
||
|
|
/* Release command */
|
||
|
|
OS_ReleaseMutex(ptChannel->tRecvMbx.pvRecvMBXMutex);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Gets send packet from the channels mailbox
|
||
|
|
* \param hChannel Channel handle acquired by xChannelOpen
|
||
|
|
* \param ulSize Size of the return packet buffer
|
||
|
|
* \param ptRecvPkt Returned packet
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelGetSendPacket(CIFXHANDLE hChannel, uint32_t ulSize, CIFX_PACKET* ptRecvPkt)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
CIFX_PACKET* ptPacket = (CIFX_PACKET*)ptChannel->tSendMbx.ptSendMailboxStart->abSendMailbox;
|
||
|
|
uint32_t ulCopySize = 0;
|
||
|
|
|
||
|
|
ulCopySize = HWIF_READ32(ptChannel->pvDeviceInstance, ptPacket->tHeader.ulLen) + HIL_PACKET_HEADER_SIZE;
|
||
|
|
|
||
|
|
if( ulCopySize > ulSize)
|
||
|
|
{
|
||
|
|
/* Use the user buffer length if packet does not fit in the user buffer */
|
||
|
|
ulCopySize = ulSize;
|
||
|
|
lRet = CIFX_BUFFER_TOO_SHORT;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Just copy the available data into the user buffer */
|
||
|
|
HWIF_READN(ptChannel->pvDeviceInstance, ptRecvPkt, ptPacket, ulCopySize);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Lock the configuration on a communication channel
|
||
|
|
* \param hChannel Channel handle
|
||
|
|
* \param ulCmd CIFX_CONFIGURATION_XXX defines
|
||
|
|
* \param pulState Return locking state
|
||
|
|
* \param ulTimeout Timeout in [ms]
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelConfigLock(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulState, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pulState);
|
||
|
|
|
||
|
|
/* Check if we are in interrupt mode */
|
||
|
|
if(!((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->fIrqEnabled)
|
||
|
|
DEV_ReadHandshakeFlags(ptChannel, 0, 1);
|
||
|
|
|
||
|
|
/* TODO: WAIT until card has recognized the LOCK command */
|
||
|
|
UNREFERENCED_PARAMETER(ulTimeout);
|
||
|
|
|
||
|
|
switch (ulCmd)
|
||
|
|
{
|
||
|
|
case CIFX_CONFIGURATION_LOCK:
|
||
|
|
{
|
||
|
|
/* Check if the configuration is already LOCKED */
|
||
|
|
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_CONFIG_LOCKED)
|
||
|
|
{
|
||
|
|
/* Configuration already locked */
|
||
|
|
*pulState = CIFX_CONFIGURATION_LOCK;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
lRet = DEV_DoHostCOSChange(ptChannel,
|
||
|
|
HIL_APP_COS_LOCK_CONFIGURATION | HIL_APP_COS_LOCK_CONFIGURATION_ENABLE,
|
||
|
|
0,
|
||
|
|
HIL_APP_COS_LOCK_CONFIGURATION_ENABLE,
|
||
|
|
CIFX_DEV_CONFIG_LOCK_TIMEOUT,
|
||
|
|
ulTimeout);
|
||
|
|
|
||
|
|
if(CIFX_NO_ERROR == lRet)
|
||
|
|
{
|
||
|
|
/* Set actual state */
|
||
|
|
*pulState = CIFX_CONFIGURATION_LOCK;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_CONFIGURATION_UNLOCK:
|
||
|
|
{
|
||
|
|
/* Check if the configuration is NOT LOCKED */
|
||
|
|
if( !(ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_CONFIG_LOCKED))
|
||
|
|
{
|
||
|
|
/* Configuration is NOT locked */
|
||
|
|
*pulState = CIFX_CONFIGURATION_UNLOCK;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
lRet = DEV_DoHostCOSChange(ptChannel,
|
||
|
|
HIL_APP_COS_LOCK_CONFIGURATION_ENABLE,
|
||
|
|
HIL_APP_COS_LOCK_CONFIGURATION,
|
||
|
|
HIL_APP_COS_LOCK_CONFIGURATION_ENABLE,
|
||
|
|
CIFX_DEV_CONFIG_UNLOCK_TIMEOUT,
|
||
|
|
ulTimeout);
|
||
|
|
|
||
|
|
if(CIFX_NO_ERROR == lRet)
|
||
|
|
{
|
||
|
|
/* Set actual state */
|
||
|
|
*pulState = CIFX_CONFIGURATION_UNLOCK;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_CONFIGURATION_GETLOCKSTATE:
|
||
|
|
/* Get the actual state of the config lock bit */
|
||
|
|
if( 0 == (LE32_TO_HOST(HWIF_READ32(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->ulCommunicationCOS)) & HIL_COMM_COS_CONFIG_LOCKED))
|
||
|
|
{
|
||
|
|
/* Configuration is not locked */
|
||
|
|
*pulState = CIFX_CONFIGURATION_UNLOCK;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Configuration is locked */
|
||
|
|
*pulState = CIFX_CONFIGURATION_LOCK;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
/* Unknown command */
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Set BUS state off a communication channel
|
||
|
|
* \param hChannel Channel handle
|
||
|
|
* \param ulCmd CIFX_CONFIGURATION_XXX defines
|
||
|
|
* \param pulState Return actual state on CIFX_GET_BUS_STATE
|
||
|
|
* \param ulTimeout Timeout in [ms]
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelBusState(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulState, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pulState);
|
||
|
|
|
||
|
|
lRet = DEV_BusState( (PCHANNELINSTANCE)hChannel,
|
||
|
|
ulCmd,
|
||
|
|
pulState,
|
||
|
|
ulTimeout);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Reset a communication channel
|
||
|
|
* \param hChannel Channel handle
|
||
|
|
* \param ulResetMode Reset Mode
|
||
|
|
* \param ulTimeout Timeout to wait for reset complete in [ms]
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelReset(CIFXHANDLE hChannel, uint32_t ulResetMode, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
|
||
|
|
/* TODO: Get packet and I/O mutexe before processing a channel init */
|
||
|
|
/* TODO: System start via channel ? */
|
||
|
|
switch(ulResetMode)
|
||
|
|
{
|
||
|
|
case CIFX_SYSTEMSTART:
|
||
|
|
lRet = DEV_DoSystemStart(ptChannel, ulTimeout, 0);
|
||
|
|
#ifdef CIFX_TOOLKIT_TIME
|
||
|
|
if (CIFX_NO_ERROR == lRet)
|
||
|
|
cifXInitTime((PDEVICEINSTANCE)ptChannel->pvDeviceInstance);
|
||
|
|
#endif
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_CHANNELINIT:
|
||
|
|
lRet = DEV_DoChannelInit(ptChannel, ulTimeout);
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Reads I/O Area information for the given Channel
|
||
|
|
* \param hChannel Channel handle
|
||
|
|
* \param ulCmd CIFX_IO_INPUT_AREA/CIFX_IO_OUTPUT_AREA
|
||
|
|
* \param ulAreaNumber Number of area to get information for
|
||
|
|
* \param ulSize Size of returned data structure
|
||
|
|
* \param pvData Pointer to returned data
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelIOInfo(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t ulAreaNumber, uint32_t ulSize, void* pvData)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
CHANNEL_IO_INFORMATION* ptIoInformation = (CHANNEL_IO_INFORMATION*)pvData;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pvData);
|
||
|
|
|
||
|
|
if(ulSize != sizeof(*ptIoInformation))
|
||
|
|
return CIFX_INVALID_BUFFERSIZE;
|
||
|
|
|
||
|
|
if(!DEV_IsRunning(ptChannel))
|
||
|
|
{
|
||
|
|
lRet = CIFX_DEV_NOT_RUNNING;
|
||
|
|
}
|
||
|
|
|
||
|
|
switch(ulCmd)
|
||
|
|
{
|
||
|
|
case CIFX_IO_INPUT_AREA:
|
||
|
|
{
|
||
|
|
if(0 == ptChannel->ulIOInputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
|
||
|
|
} else if(ulAreaNumber >= ptChannel->ulIOInputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
PIOINSTANCE ptIoArea = ptChannel->pptIOInputAreas[ulAreaNumber];
|
||
|
|
|
||
|
|
if(HIL_IO_MODE_DEFAULT != HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bPDInHskMode))
|
||
|
|
ptIoInformation->ulIOMode = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bPDInHskMode);
|
||
|
|
else
|
||
|
|
ptIoInformation->ulIOMode = ptIoArea->usHandshakeMode;
|
||
|
|
|
||
|
|
ptIoInformation->ulTotalSize = ptIoArea->ulDPMAreaLength;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_IO_OUTPUT_AREA:
|
||
|
|
{
|
||
|
|
if(0 == ptChannel->ulIOOutputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
|
||
|
|
} else if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
PIOINSTANCE ptIoArea = ptChannel->pptIOOutputAreas[ulAreaNumber];
|
||
|
|
|
||
|
|
if(HIL_IO_MODE_DEFAULT != HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bPDOutHskMode))
|
||
|
|
ptIoInformation->ulIOMode = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bPDOutHskMode);
|
||
|
|
else
|
||
|
|
ptIoInformation->ulIOMode = ptIoArea->usHandshakeMode;
|
||
|
|
ptIoInformation->ulTotalSize = ptIoArea->ulDPMAreaLength;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Reads the Input data from the channel
|
||
|
|
* \param hChannel Channel handle acquired by xChannelOpen
|
||
|
|
* \param ulAreaNumber Number of the I/O Area (0..n)
|
||
|
|
* \param ulOffset Data offset in Input area
|
||
|
|
* \param ulDataLen Length of data to read
|
||
|
|
* \param pvData Buffer to place returned data
|
||
|
|
* \param ulTimeout Timeout in ms to wait for finished I/O Handshake
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelIORead(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t ulOffset, uint32_t ulDataLen, void* pvData, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PIOINSTANCE ptIOArea = NULL;
|
||
|
|
uint8_t bIOBitState = HIL_FLAGS_NONE;
|
||
|
|
|
||
|
|
if(!DEV_IsRunning(ptChannel))
|
||
|
|
return CIFX_DEV_NOT_RUNNING;
|
||
|
|
|
||
|
|
if(ulAreaNumber >= ptChannel->ulIOInputAreas)
|
||
|
|
return CIFX_INVALID_PARAMETER;
|
||
|
|
|
||
|
|
ptIOArea = ptChannel->pptIOInputAreas[ulAreaNumber];
|
||
|
|
bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 0);
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_DMA
|
||
|
|
/* Check for DMA transfer */
|
||
|
|
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_DMA)
|
||
|
|
{
|
||
|
|
/*------------------------------*/
|
||
|
|
/* This is DMA IO data transfer */
|
||
|
|
/*------------------------------*/
|
||
|
|
/* This is DMACh n */
|
||
|
|
PDEVICEINSTANCE ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
|
||
|
|
uint32_t ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_INPUT_BUFFER_IDX;
|
||
|
|
PCIFX_DMABUFFER_T ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
|
||
|
|
|
||
|
|
if(0 != ulAreaNumber ) /* Only support for area 0 in DMA mode */
|
||
|
|
return CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED;
|
||
|
|
|
||
|
|
if( (ulOffset + ulDataLen) > ptDmaInfo->ulSize)
|
||
|
|
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
|
||
|
|
|
||
|
|
/* Check if another command is active */
|
||
|
|
if ( !OS_WaitMutex( ptIOArea->pvMutex, ulTimeout))
|
||
|
|
return CIFX_DRV_CMD_ACTIVE;
|
||
|
|
|
||
|
|
/* TODO: define read procedure ??Toggle -> Read or READ->Toggle */
|
||
|
|
if(HIL_FLAGS_NONE == bIOBitState)
|
||
|
|
{
|
||
|
|
/* Read data without handshake does not work in DMA operation*/
|
||
|
|
lRet = CIFX_DEV_DMA_HANDSHAKEMODE_NOT_SUPPORTED;
|
||
|
|
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Read data */
|
||
|
|
if(!DEV_WaitForBitState(ptChannel, ptIOArea->bHandshakeBit, bIOBitState, ulTimeout))
|
||
|
|
{
|
||
|
|
lRet = CIFX_DEV_EXCHANGE_FAILED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Read data */
|
||
|
|
OS_Memcpy( pvData,
|
||
|
|
((uint8_t*)(ptDmaInfo->pvBuffer)) + ulOffset,
|
||
|
|
ulDataLen);
|
||
|
|
|
||
|
|
/* Lock flag access */
|
||
|
|
OS_EnterLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
/* Read data done */
|
||
|
|
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOArea->bHandshakeBit));
|
||
|
|
|
||
|
|
/* Unlock flag access */
|
||
|
|
OS_LeaveLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
/* Check COMM Flag for return value */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Release command */
|
||
|
|
OS_ReleaseMutex( ptIOArea->pvMutex);
|
||
|
|
|
||
|
|
} else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
/*---------------------------*/
|
||
|
|
/* This is DPM data transfer */
|
||
|
|
/*---------------------------*/
|
||
|
|
if( (ulOffset + ulDataLen) > ptIOArea->ulDPMAreaLength)
|
||
|
|
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
|
||
|
|
|
||
|
|
/* Check if another command is active */
|
||
|
|
if ( !OS_WaitMutex( ptIOArea->pvMutex, ulTimeout))
|
||
|
|
return CIFX_DRV_CMD_ACTIVE;
|
||
|
|
|
||
|
|
/* Read data */
|
||
|
|
if(HIL_FLAGS_NONE == bIOBitState)
|
||
|
|
{
|
||
|
|
/* Read data */
|
||
|
|
HWIF_READN( ptChannel->pvDeviceInstance,
|
||
|
|
pvData,
|
||
|
|
&ptIOArea->pbDPMAreaStart[ulOffset],
|
||
|
|
ulDataLen);
|
||
|
|
|
||
|
|
/* Check COMM Flag for return value */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
|
||
|
|
} else if(!DEV_WaitForBitState(ptChannel, ptIOArea->bHandshakeBit, bIOBitState, ulTimeout))
|
||
|
|
{
|
||
|
|
lRet = CIFX_DEV_EXCHANGE_FAILED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Read data */
|
||
|
|
HWIF_READN( ptChannel->pvDeviceInstance,
|
||
|
|
pvData,
|
||
|
|
&ptIOArea->pbDPMAreaStart[ulOffset],
|
||
|
|
ulDataLen);
|
||
|
|
|
||
|
|
/* Lock flag access */
|
||
|
|
OS_EnterLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
/* Read data done */
|
||
|
|
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOArea->bHandshakeBit));
|
||
|
|
|
||
|
|
/* Unlock flag access */
|
||
|
|
OS_LeaveLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
/* Check COMM Flag for return value */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Release command */
|
||
|
|
OS_ReleaseMutex( ptIOArea->pvMutex);
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Writes the Output data to the channel
|
||
|
|
* \param hChannel Channel handle acquired by xChannelOpen
|
||
|
|
* \param ulAreaNumber Number of the I/O Area (0..n)
|
||
|
|
* \param ulOffset Data offset in Output area
|
||
|
|
* \param ulDataLen Length of data to send
|
||
|
|
* \param pvData Buffer containing send data
|
||
|
|
* \param ulTimeout Timeout in ms to wait for handshake completion
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelIOWrite(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t ulOffset, uint32_t ulDataLen, void* pvData, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PIOINSTANCE ptIOArea = NULL;
|
||
|
|
uint8_t bIOBitState = HIL_FLAGS_NONE;
|
||
|
|
|
||
|
|
if(!DEV_IsRunning(ptChannel))
|
||
|
|
return CIFX_DEV_NOT_RUNNING;
|
||
|
|
if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
|
||
|
|
return CIFX_INVALID_PARAMETER;
|
||
|
|
|
||
|
|
ptIOArea = ptChannel->pptIOOutputAreas[ulAreaNumber];
|
||
|
|
bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 1);
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_DMA
|
||
|
|
/* Check for DMA transfer */
|
||
|
|
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_DMA)
|
||
|
|
{
|
||
|
|
/*------------------------------*/
|
||
|
|
/* This is DMA IO data transfer */
|
||
|
|
/*------------------------------*/
|
||
|
|
/* This is DMACh n+1 */
|
||
|
|
PDEVICEINSTANCE ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
|
||
|
|
uint32_t ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_OUTPUT_BUFFER_IDX;
|
||
|
|
PCIFX_DMABUFFER_T ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
|
||
|
|
|
||
|
|
if(0 != ulAreaNumber ) /* Only support for area 0 in DMA mode */
|
||
|
|
return CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED;
|
||
|
|
|
||
|
|
if( (ulOffset + ulDataLen) > ptDmaInfo->ulSize)
|
||
|
|
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
|
||
|
|
|
||
|
|
/* Check if another command is active */
|
||
|
|
if ( !OS_WaitMutex( ptIOArea->pvMutex, ulTimeout))
|
||
|
|
return CIFX_DRV_CMD_ACTIVE;
|
||
|
|
|
||
|
|
/* Read data */
|
||
|
|
/* TODO: define read procedure ??Toggle -> Read or READ->Toggle */
|
||
|
|
if(HIL_FLAGS_NONE == bIOBitState)
|
||
|
|
{
|
||
|
|
/* Read data without handshake does not work in DMA operation*/
|
||
|
|
lRet = CIFX_DEV_DMA_HANDSHAKEMODE_NOT_SUPPORTED;
|
||
|
|
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
if(!DEV_WaitForBitState(ptChannel, ptIOArea->bHandshakeBit, bIOBitState, ulTimeout))
|
||
|
|
{
|
||
|
|
lRet = CIFX_DEV_EXCHANGE_FAILED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Read data */
|
||
|
|
OS_Memcpy( (((uint8_t*)(ptDmaInfo->pvBuffer)) + ulOffset),
|
||
|
|
pvData,
|
||
|
|
ulDataLen);
|
||
|
|
|
||
|
|
/* Lock flag access */
|
||
|
|
OS_EnterLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
/* Read data done */
|
||
|
|
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOArea->bHandshakeBit));
|
||
|
|
|
||
|
|
/* Unlock flag access */
|
||
|
|
OS_LeaveLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
/* Check COMM Flag for return value */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Release command */
|
||
|
|
OS_ReleaseMutex( ptIOArea->pvMutex);
|
||
|
|
|
||
|
|
} else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
/*---------------------------*/
|
||
|
|
/* This is DPM data transfer */
|
||
|
|
/*---------------------------*/
|
||
|
|
if( (ulOffset + ulDataLen) > ptIOArea->ulDPMAreaLength)
|
||
|
|
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
|
||
|
|
|
||
|
|
/* Check if another command is active */
|
||
|
|
if ( !OS_WaitMutex( ptIOArea->pvMutex, ulTimeout))
|
||
|
|
return CIFX_DRV_CMD_ACTIVE;
|
||
|
|
|
||
|
|
/* Read data */
|
||
|
|
/* TODO: define write procedure ??Toggle -> Write or Write->Toggle */
|
||
|
|
if(HIL_FLAGS_NONE == bIOBitState)
|
||
|
|
{
|
||
|
|
/* Read data without handshake */
|
||
|
|
HWIF_WRITEN( ptChannel->pvDeviceInstance,
|
||
|
|
&ptIOArea->pbDPMAreaStart[ulOffset],
|
||
|
|
pvData,
|
||
|
|
ulDataLen);
|
||
|
|
|
||
|
|
/* Check COMM Flag for return value */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
if(!DEV_WaitForBitState(ptChannel, ptIOArea->bHandshakeBit, bIOBitState, ulTimeout))
|
||
|
|
{
|
||
|
|
lRet = CIFX_DEV_EXCHANGE_FAILED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Read data */
|
||
|
|
HWIF_WRITEN( ptChannel->pvDeviceInstance,
|
||
|
|
&ptIOArea->pbDPMAreaStart[ulOffset],
|
||
|
|
pvData,
|
||
|
|
ulDataLen);
|
||
|
|
|
||
|
|
/* Lock flag access */
|
||
|
|
OS_EnterLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
/* Read data done */
|
||
|
|
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOArea->bHandshakeBit));
|
||
|
|
|
||
|
|
/* Unlock flag access */
|
||
|
|
OS_LeaveLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
/* Check COMM Flag for return value */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Release command */
|
||
|
|
OS_ReleaseMutex( ptIOArea->pvMutex);
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Read back Send Data Area from channel
|
||
|
|
* \param hChannel Channel handle acquired by xChannelOpen
|
||
|
|
* \param ulAreaNumber Number of the I/O Area (0..n)
|
||
|
|
* \param ulOffset Data start offset
|
||
|
|
* \param ulDataLen Data length to read
|
||
|
|
* \param pvData Data buffer
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelIOReadSendData(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_DMA
|
||
|
|
|
||
|
|
/* Check for DMA transfer */
|
||
|
|
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_DMA)
|
||
|
|
{
|
||
|
|
/* This is DMACh n */
|
||
|
|
PDEVICEINSTANCE ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
|
||
|
|
uint32_t ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_OUTPUT_BUFFER_IDX; /* We reading the Output buffer */
|
||
|
|
PCIFX_DMABUFFER_T ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
|
||
|
|
|
||
|
|
if(0 != ulAreaNumber ) /* Only support for area 0 in DMA mode */
|
||
|
|
return CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED;
|
||
|
|
|
||
|
|
if( (ulOffset + ulDataLen) > ptDmaInfo->ulSize)
|
||
|
|
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
|
||
|
|
|
||
|
|
/* Read data */
|
||
|
|
OS_Memcpy( pvData,
|
||
|
|
((uint8_t*)(ptDmaInfo->pvBuffer)) + ulOffset,
|
||
|
|
ulDataLen);
|
||
|
|
} else
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
{
|
||
|
|
PIOINSTANCE ptIOArea = NULL;
|
||
|
|
|
||
|
|
if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
|
||
|
|
return CIFX_INVALID_PARAMETER;
|
||
|
|
|
||
|
|
ptIOArea = ptChannel->pptIOOutputAreas[ulAreaNumber];
|
||
|
|
|
||
|
|
if( (ulOffset + ulDataLen) > ptIOArea->ulDPMAreaLength)
|
||
|
|
return CIFX_INVALID_ACCESS_SIZE; /* read size too long */
|
||
|
|
|
||
|
|
/* Read data */
|
||
|
|
HWIF_READN(ptChannel->pvDeviceInstance,
|
||
|
|
pvData,
|
||
|
|
&ptIOArea->pbDPMAreaStart[ulOffset],
|
||
|
|
ulDataLen);
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Read/Write Control block
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulCmd CIFX_CMD_READ_DATA/CIFX_CMD_WRITE_DATA
|
||
|
|
* \param ulOffset Start offset of read/write
|
||
|
|
* \param ulDataLen Length of data to read/write
|
||
|
|
* \param pvData Buffer to copy from/to
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelControlBlock(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pvData);
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
|
||
|
|
/* Check if CONTROL block is available */
|
||
|
|
} else if(NULL == ptChannel->ptControlBlock)
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
if ((ulOffset + ulDataLen) > ptChannel->ulControlBlockSize)
|
||
|
|
lRet = CIFX_INVALID_ACCESS_SIZE;
|
||
|
|
else
|
||
|
|
{
|
||
|
|
HIL_DPM_CONTROL_BLOCK_T tChannelControlBlockTmp = {0};
|
||
|
|
void* pvDataInternal = pvData; /* Default to user buffer */
|
||
|
|
int32_t lRetTmp = CIFX_NO_ERROR; /* Error from the conversion function */
|
||
|
|
|
||
|
|
if(CIFX_CMD_WRITE_DATA == ulCmd)
|
||
|
|
{
|
||
|
|
/* To prohibit changes to user supplied buffer on write, use a local copy instead */
|
||
|
|
pvDataInternal = (void*)(((uint8_t*)&tChannelControlBlockTmp) + ulOffset);
|
||
|
|
OS_Memcpy(pvDataInternal, pvData, ulDataLen);
|
||
|
|
lRetTmp = cifXConvertEndianess(ulOffset,
|
||
|
|
pvDataInternal,
|
||
|
|
ulDataLen,
|
||
|
|
s_atControlBlock,
|
||
|
|
sizeof(s_atControlBlock) / sizeof(s_atControlBlock[0]));
|
||
|
|
}
|
||
|
|
|
||
|
|
if(CIFX_NO_ERROR == lRetTmp)
|
||
|
|
{
|
||
|
|
lRet = DEV_ReadWriteBlock(ptChannel,
|
||
|
|
(void*)ptChannel->ptControlBlock,
|
||
|
|
ulOffset,
|
||
|
|
ptChannel->ulControlBlockSize,
|
||
|
|
pvDataInternal,
|
||
|
|
ulDataLen,
|
||
|
|
ulCmd,
|
||
|
|
1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Note: We accept errors from the DEV_ReadWriteBlock() function because we want to inform the user in any case */
|
||
|
|
/* (e.g. CIFX_DEV_NOT_RUNNING) even if we running the conversion on an not filled / empty buffer! */
|
||
|
|
if(CIFX_CMD_READ_DATA == ulCmd)
|
||
|
|
{
|
||
|
|
lRetTmp = cifXConvertEndianess(ulOffset,
|
||
|
|
pvDataInternal,
|
||
|
|
ulDataLen,
|
||
|
|
s_atControlBlock,
|
||
|
|
sizeof(s_atControlBlock) / sizeof(s_atControlBlock[0]));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Error of DEV_ReadWriteBlock() takes priority over (possible) Endianess conversion error */
|
||
|
|
if((CIFX_NO_ERROR == lRet) && (CIFX_NO_ERROR != lRetTmp))
|
||
|
|
lRet = lRetTmp;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Read/Write Common status block
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulCmd CIFX_CMD_READ_DATA
|
||
|
|
* \param ulOffset Start offset of read
|
||
|
|
* \param ulDataLen Length of data to read
|
||
|
|
* \param pvData Buffer to copy to
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelCommonStatusBlock(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pvData);
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
|
||
|
|
/* Check if STATUS block is available */
|
||
|
|
} else if(NULL == ptChannel->ptCommonStatusBlock)
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
lRet = DEV_ReadWriteBlock(ptChannel,
|
||
|
|
(void*)ptChannel->ptCommonStatusBlock,
|
||
|
|
ulOffset,
|
||
|
|
ptChannel->ulCommonStatusSize,
|
||
|
|
pvData,
|
||
|
|
ulDataLen,
|
||
|
|
ulCmd,
|
||
|
|
0);
|
||
|
|
|
||
|
|
/* Note: We accept errors from the DEV_ReadWriteBlock() function because we want to inform the user in any case */
|
||
|
|
/* (e.g. CIFX_DEV_NOT_RUNNING) even if we running the conversion on an not filled / empty buffer! */
|
||
|
|
if(CIFX_CMD_READ_DATA == ulCmd)
|
||
|
|
{
|
||
|
|
int32_t lRetTmp = cifXConvertEndianess(ulOffset,
|
||
|
|
pvData,
|
||
|
|
ulDataLen,
|
||
|
|
s_atCommonStatusBlock,
|
||
|
|
sizeof(s_atCommonStatusBlock) / sizeof(s_atCommonStatusBlock[0]));
|
||
|
|
|
||
|
|
/* Error of DEV_ReadWriteBlock() takes priority over (possible) Endianess conversion error */
|
||
|
|
if((CIFX_NO_ERROR == lRet) && (CIFX_NO_ERROR != lRetTmp))
|
||
|
|
lRet = lRetTmp;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Read Extended status block
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulCmd CIFX_CMD_READ_DATA
|
||
|
|
* \param ulOffset Start offset of read
|
||
|
|
* \param ulDataLen Length of data to read
|
||
|
|
* \param pvData Buffer to copy to
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelExtendedStatusBlock(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pvData);
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
|
||
|
|
/* Check if CONTROL block is available */
|
||
|
|
} else if(NULL == ptChannel->ptExtendedStatusBlock)
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
lRet = DEV_ReadWriteBlock(ptChannel,
|
||
|
|
(void*)ptChannel->ptExtendedStatusBlock,
|
||
|
|
ulOffset,
|
||
|
|
ptChannel->ulExtendedStatusSize,
|
||
|
|
pvData,
|
||
|
|
ulDataLen,
|
||
|
|
ulCmd,
|
||
|
|
0);
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Read a user block
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulAreaNumber Userblock number
|
||
|
|
* \param ulCmd CIFX_CMD_READ_DATA
|
||
|
|
* \param ulOffset Start offset of read
|
||
|
|
* \param ulDataLen Length of data to read
|
||
|
|
* \param pvData Buffer to copy to
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelUserBlock(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t ulCmd, uint32_t ulOffset, uint32_t ulDataLen, void* pvData)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pvData);
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
|
||
|
|
/* Check if CONTROL block is available */
|
||
|
|
} else if( (ulAreaNumber >= ptChannel->ulUserAreas) ||
|
||
|
|
(NULL == ptChannel->pptUserAreas[ulAreaNumber]) )
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
PUSERINSTANCE ptUserInstance = ptChannel->pptUserAreas[ulAreaNumber];
|
||
|
|
|
||
|
|
lRet = DEV_ReadWriteBlock(ptChannel,
|
||
|
|
(void*)ptUserInstance->pbUserBlockStart,
|
||
|
|
ulOffset,
|
||
|
|
ptUserInstance->ulUserBlockLength,
|
||
|
|
pvData,
|
||
|
|
ulDataLen,
|
||
|
|
ulCmd,
|
||
|
|
1);
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Gets a pointer to an IO Area
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulCmd CIFX_MEM_PTR_OPEN/CIFX_MEM_PTR_CLOSE
|
||
|
|
* \param pvMemoryInfo Pointer to requested memory structure
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelPLCMemoryPtr(CIFXHANDLE hChannel, uint32_t ulCmd, void* pvMemoryInfo)
|
||
|
|
{
|
||
|
|
PLC_MEMORY_INFORMATION* ptMemory = (PLC_MEMORY_INFORMATION*)pvMemoryInfo;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
int fUseCaching = 0;
|
||
|
|
unsigned long ulAreaDefinition = 0;
|
||
|
|
PDEVICEINSTANCE ptDevInst = NULL;
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pvMemoryInfo);
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
return CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
|
||
|
|
if( (0 == ptChannel->ulIOInputAreas) ||
|
||
|
|
(0 == ptChannel->ulIOOutputAreas) )
|
||
|
|
/* No IO blocks defined */
|
||
|
|
return CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
|
||
|
|
ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
|
||
|
|
fUseCaching = ptDevInst->fCachedMemAccess;
|
||
|
|
ulAreaDefinition = ptMemory->ulAreaDefinition;
|
||
|
|
|
||
|
|
#ifdef CIFX_CACHE_TEST
|
||
|
|
/* Check for additional option in area definition */
|
||
|
|
/* and overwrite if additional flags are set. */
|
||
|
|
if (0 != (ulAreaDefinition & ~CIFX_IO_AREA_MASK))
|
||
|
|
{
|
||
|
|
/* Override caching option to get uncached pointers */
|
||
|
|
ulAreaDefinition &= CIFX_IO_AREA_MASK;
|
||
|
|
fUseCaching = 0;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_DMA
|
||
|
|
|
||
|
|
/* Check for DMA transfer */
|
||
|
|
if( ptChannel->ulDeviceCOSFlags & HIL_COMM_COS_DMA)
|
||
|
|
{
|
||
|
|
/*------------------------------*/
|
||
|
|
/* This is DMA IO data transfer */
|
||
|
|
/*------------------------------*/
|
||
|
|
/* This is DMACh n */
|
||
|
|
PCIFX_DMABUFFER_T ptDmaInfo = NULL;
|
||
|
|
CACHED_MEMORY_AREA_T* ptCachedMemInfo = NULL;
|
||
|
|
uint32_t ulDMChIdx = 0;
|
||
|
|
|
||
|
|
if(0 != ptMemory->ulAreaNumber)
|
||
|
|
{
|
||
|
|
/* Invalid IO area */
|
||
|
|
lRet = CIFX_DEV_DMA_IO_AREA_NOT_SUPPORTED; /* Only support for area 0 in DMA mode */
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
if (ulAreaDefinition == CIFX_IO_INPUT_AREA)
|
||
|
|
{
|
||
|
|
ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_INPUT_BUFFER_IDX;
|
||
|
|
ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
|
||
|
|
ptCachedMemInfo = &ptChannel->tCachedIOInputArea;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ulDMChIdx = ptChannel->ulChannelNumber * 2 + eDMA_OUTPUT_BUFFER_IDX;
|
||
|
|
ptDmaInfo = &ptDevInst->atDmaBuffers[ulDMChIdx];
|
||
|
|
ptCachedMemInfo = &ptChannel->tCachedIOOutputArea;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Check user command */
|
||
|
|
switch(ulCmd)
|
||
|
|
{
|
||
|
|
case CIFX_MEM_PTR_OPEN:
|
||
|
|
{
|
||
|
|
void* pvMappedDPM = NULL;
|
||
|
|
void* pvDPM = ptDmaInfo->pvBuffer;
|
||
|
|
uint32_t ulDPMSize = ptDmaInfo->ulSize;
|
||
|
|
|
||
|
|
/* Check for caching option */
|
||
|
|
if ((0 != fUseCaching) &&
|
||
|
|
(NULL != ptCachedMemInfo->pvMemPtr))
|
||
|
|
{
|
||
|
|
/* Mapping already exists */
|
||
|
|
lRet = CIFX_NO_MORE_ENTRIES;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Return global memory information */
|
||
|
|
if (NULL == (ptMemory->pvMemoryID = OS_MapUserPointer(pvDPM, ulDPMSize, &pvMappedDPM, ptDevInst->pvOSDependent, (unsigned char)fUseCaching)))
|
||
|
|
{
|
||
|
|
lRet = CIFX_MEMORY_MAPPING_FAILED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
*(ptMemory->ppvMemoryPtr) = (void*)pvMappedDPM;
|
||
|
|
*(ptMemory->pulIOAreaStartOffset) = 0; /* In DMA mode, we don't have a DPM start offeset */
|
||
|
|
*(ptMemory->pulIOAreaSize) = ulDPMSize;
|
||
|
|
|
||
|
|
/* Store the memory pointer for later cache operation (e.g. flush) */
|
||
|
|
if (0 != fUseCaching)
|
||
|
|
{
|
||
|
|
ptCachedMemInfo->pvMemPtr = (void*)pvMappedDPM;
|
||
|
|
ptCachedMemInfo->ulAreaSize = ulDPMSize;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_MEM_PTR_CLOSE:
|
||
|
|
{
|
||
|
|
if(!OS_UnmapUserPointer(ptMemory->pvMemoryID, ptDevInst->pvOSDependent))
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_HANDLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ptMemory->pvMemoryID = NULL;
|
||
|
|
*(ptMemory->ppvMemoryPtr) = NULL;
|
||
|
|
*(ptMemory->pulIOAreaStartOffset) = 0;
|
||
|
|
*(ptMemory->pulIOAreaSize) = 0;
|
||
|
|
|
||
|
|
if (0 != fUseCaching)
|
||
|
|
{
|
||
|
|
/* Remove any stored cache buffer information */
|
||
|
|
ptCachedMemInfo->pvMemPtr = NULL;
|
||
|
|
ptCachedMemInfo->ulAreaSize = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
|
||
|
|
} /* end switch */
|
||
|
|
}
|
||
|
|
} else
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
{
|
||
|
|
PIOINSTANCE* pptIOInstances = NULL;
|
||
|
|
uint32_t ulAreaCount = 0;
|
||
|
|
CACHED_MEMORY_AREA_T* ptCachedMemInfo = NULL;
|
||
|
|
|
||
|
|
if(ulAreaDefinition == CIFX_IO_INPUT_AREA)
|
||
|
|
{
|
||
|
|
ulAreaCount = ptChannel->ulIOInputAreas;
|
||
|
|
pptIOInstances = ptChannel->pptIOInputAreas;
|
||
|
|
ptCachedMemInfo = &ptChannel->tCachedIOInputArea;
|
||
|
|
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ulAreaCount = ptChannel->ulIOOutputAreas;
|
||
|
|
pptIOInstances = ptChannel->pptIOOutputAreas;
|
||
|
|
ptCachedMemInfo = &ptChannel->tCachedIOOutputArea;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Check if IO area is available */
|
||
|
|
if (ptMemory->ulAreaNumber >= ulAreaCount)
|
||
|
|
{
|
||
|
|
/* Invalid IO area */
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check user command */
|
||
|
|
switch(ulCmd)
|
||
|
|
{
|
||
|
|
case CIFX_MEM_PTR_OPEN:
|
||
|
|
{
|
||
|
|
void* pvMappedDPM = NULL;
|
||
|
|
void* pvDPM = pptIOInstances[ptMemory->ulAreaNumber]->pbDPMAreaStart;
|
||
|
|
uint32_t ulDPMSize = pptIOInstances[ptMemory->ulAreaNumber]->ulDPMAreaLength;
|
||
|
|
|
||
|
|
/* Check for caching option */
|
||
|
|
if ((0 != fUseCaching) &&
|
||
|
|
(NULL != ptCachedMemInfo->pvMemPtr))
|
||
|
|
{
|
||
|
|
/* Mapping already exists */
|
||
|
|
lRet = CIFX_NO_MORE_ENTRIES;
|
||
|
|
|
||
|
|
}else
|
||
|
|
{
|
||
|
|
/* Return global memory information */
|
||
|
|
if (NULL == (ptMemory->pvMemoryID = OS_MapUserPointer(pvDPM, ulDPMSize, &pvMappedDPM, ptDevInst->pvOSDependent, (unsigned char)fUseCaching)))
|
||
|
|
{
|
||
|
|
lRet = CIFX_MEMORY_MAPPING_FAILED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
*(ptMemory->ppvMemoryPtr) = (void*)pvMappedDPM;
|
||
|
|
*(ptMemory->pulIOAreaStartOffset) = (uint32_t)(pptIOInstances[ptMemory->ulAreaNumber]->pbDPMAreaStart -
|
||
|
|
ptChannel->pbDPMChannelStart);
|
||
|
|
*(ptMemory->pulIOAreaSize) = ulDPMSize;
|
||
|
|
|
||
|
|
if (0 != fUseCaching)
|
||
|
|
{
|
||
|
|
/* Remove any stored cache buffer information */
|
||
|
|
ptCachedMemInfo->pvMemPtr = (void*)pvMappedDPM;
|
||
|
|
ptCachedMemInfo->ulAreaSize = ulDPMSize;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_MEM_PTR_CLOSE:
|
||
|
|
{
|
||
|
|
if(!OS_UnmapUserPointer(ptMemory->pvMemoryID, ptDevInst->pvOSDependent))
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_HANDLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ptMemory->pvMemoryID = NULL;
|
||
|
|
*(ptMemory->ppvMemoryPtr) = NULL;
|
||
|
|
*(ptMemory->pulIOAreaStartOffset) = 0;
|
||
|
|
*(ptMemory->pulIOAreaSize) = 0;
|
||
|
|
|
||
|
|
if (0 != fUseCaching)
|
||
|
|
{
|
||
|
|
/* Remove any stored cache buffer information */
|
||
|
|
ptCachedMemInfo->pvMemPtr = NULL;
|
||
|
|
ptCachedMemInfo->ulAreaSize = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
} /* end switch */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Checks if the given IO Area is ready for the next handshake
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulAreaNumber Area to check
|
||
|
|
* \param pulReadState Returned state of the area (!=0 means area is ready)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelPLCIsReadReady(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t* pulReadState)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
} else if(0 == ptChannel->ulIOInputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check if IO area is available */
|
||
|
|
if(ulAreaNumber >= ptChannel->ulIOInputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check if the device is communication. If only the COM flag is missing, we return the current bit state */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
|
||
|
|
if( (lRet != CIFX_DEV_NOT_READY) &&
|
||
|
|
(lRet != CIFX_DEV_NOT_RUNNING) )
|
||
|
|
{
|
||
|
|
/* Read back the send data area */
|
||
|
|
PIOINSTANCE ptIOInst = ptChannel->pptIOInputAreas[ulAreaNumber];
|
||
|
|
uint8_t bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOInst, 0);
|
||
|
|
|
||
|
|
*pulReadState = 0;
|
||
|
|
|
||
|
|
if( (HIL_FLAGS_NONE == bIOBitState) ||
|
||
|
|
(DEV_GetHandshakeBitState(ptChannel, (uint32_t)(1UL << ptIOInst->bHandshakeBit)) == bIOBitState) )
|
||
|
|
{
|
||
|
|
*pulReadState = 1;
|
||
|
|
|
||
|
|
/* Invalidate the IO input buffer, for cache refresh */
|
||
|
|
if (NULL != ptChannel->tCachedIOInputArea.pvMemPtr)
|
||
|
|
{
|
||
|
|
OS_InvalidateCacheMemory_FromDevice(ptChannel->tCachedIOInputArea.pvMemPtr, ptChannel->tCachedIOInputArea.ulAreaSize);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Assuming that the request was handled */
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Checks if the given IO Area is ready for the next handshake
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulAreaNumber Area to check
|
||
|
|
* \param pulWriteState Returned state of the area (!=0 means area is ready)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelPLCIsWriteReady(CIFXHANDLE hChannel, uint32_t ulAreaNumber, uint32_t* pulWriteState)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
} else if(0 == ptChannel->ulIOOutputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check if IO area is available */
|
||
|
|
if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check if the device is communication. If only the COM flag is missing, we return the current bit state */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
|
||
|
|
if( (lRet != CIFX_DEV_NOT_READY) &&
|
||
|
|
(lRet != CIFX_DEV_NOT_RUNNING) )
|
||
|
|
{
|
||
|
|
/* Read back the send data area */
|
||
|
|
PIOINSTANCE ptIOInst = ptChannel->pptIOOutputAreas[ulAreaNumber];
|
||
|
|
uint8_t bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOInst, 1);
|
||
|
|
|
||
|
|
*pulWriteState = 0;
|
||
|
|
|
||
|
|
if( (HIL_FLAGS_NONE == bIOBitState) ||
|
||
|
|
(DEV_GetHandshakeBitState(ptChannel, (uint32_t)(1UL << ptIOInst->bHandshakeBit)) == bIOBitState) )
|
||
|
|
{
|
||
|
|
*pulWriteState = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Assuming that the request was handled */
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Toggles the Handshake bit for the given IO Output Area
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulAreaNumber Areanumber
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelPLCActivateWrite(CIFXHANDLE hChannel, uint32_t ulAreaNumber)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
} else if(0 == ptChannel->ulIOOutputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check if IO area is available */
|
||
|
|
if(ulAreaNumber >= ptChannel->ulIOOutputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check if the device is communication. If only the COM flag is missing, we toggle the bits */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
|
||
|
|
if( (lRet != CIFX_DEV_NOT_READY) &&
|
||
|
|
(lRet != CIFX_DEV_NOT_RUNNING) )
|
||
|
|
{
|
||
|
|
PIOINSTANCE ptIOInst = ptChannel->pptIOOutputAreas[ulAreaNumber];
|
||
|
|
|
||
|
|
/* Flush the IO output cache to output buffer */
|
||
|
|
if (NULL != ptChannel->tCachedIOOutputArea.pvMemPtr)
|
||
|
|
{
|
||
|
|
OS_FlushCacheMemory_ToDevice(ptChannel->tCachedIOOutputArea.pvMemPtr, ptChannel->tCachedIOOutputArea.ulAreaSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Lock flag access */
|
||
|
|
OS_EnterLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOInst->bHandshakeBit));
|
||
|
|
|
||
|
|
/* Unlock flag access */
|
||
|
|
OS_LeaveLock(ptChannel->pvLock);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Toggles the Handshake bit for the given IO Input Area
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulAreaNumber Areanumber
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelPLCActivateRead(CIFXHANDLE hChannel, uint32_t ulAreaNumber)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
} else if(0 == ptChannel->ulIOInputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check if IO area is available */
|
||
|
|
if(ulAreaNumber >= ptChannel->ulIOInputAreas)
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Check if the device is communication. If only the COM flag is missing, we toggle the bits */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
|
||
|
|
if( (lRet != CIFX_DEV_NOT_READY) &&
|
||
|
|
(lRet != CIFX_DEV_NOT_RUNNING) )
|
||
|
|
{
|
||
|
|
PIOINSTANCE ptIOInst = ptChannel->pptIOInputAreas[ulAreaNumber];
|
||
|
|
|
||
|
|
/* Lock flag access */
|
||
|
|
OS_EnterLock(ptChannel->pvLock);
|
||
|
|
|
||
|
|
DEV_ToggleBit(ptChannel, (uint32_t)(1UL << ptIOInst->bHandshakeBit));
|
||
|
|
|
||
|
|
/* Unlock flag access */
|
||
|
|
OS_LeaveLock(ptChannel->pvLock);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifndef CIFX_TOOLKIT_USE_CUSTOM_DRV_FUNCS
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Open a connection to the driver
|
||
|
|
* \param phDriver Returned handle to the driver
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xDriverOpen(CIFXHANDLE* phDriver)
|
||
|
|
{
|
||
|
|
if(!g_tDriverInfo.fInitialized)
|
||
|
|
return CIFX_DRV_DRIVER_NOT_LOADED;
|
||
|
|
|
||
|
|
CHECK_POINTER(phDriver);
|
||
|
|
|
||
|
|
*phDriver = &g_tDriverInfo;
|
||
|
|
|
||
|
|
++g_tDriverInfo.ulOpenCount;
|
||
|
|
|
||
|
|
return CIFX_NO_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Close a connection to the driver
|
||
|
|
* \param hDriver Handle to connection, that is being closed
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xDriverClose(CIFXHANDLE hDriver)
|
||
|
|
{
|
||
|
|
if(!g_tDriverInfo.fInitialized)
|
||
|
|
return CIFX_DRV_DRIVER_NOT_LOADED;
|
||
|
|
|
||
|
|
if(g_tDriverInfo.ulOpenCount == 0)
|
||
|
|
return CIFX_DRV_NOT_OPENED;
|
||
|
|
|
||
|
|
CHECK_DRIVERHANDLE(hDriver);
|
||
|
|
|
||
|
|
--g_tDriverInfo.ulOpenCount;
|
||
|
|
|
||
|
|
return CIFX_NO_ERROR; /*lint !e438 */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Query Driver information
|
||
|
|
* \param hDriver Handle to the driver
|
||
|
|
* \param ulSize Size of the passed DRIVER_INFORMATION Structure
|
||
|
|
* \param pvDriverInfo Pointer to returned data (DRIVER_INFORMATION
|
||
|
|
* structure)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xDriverGetInformation(CIFXHANDLE hDriver, uint32_t ulSize, void* pvDriverInfo)
|
||
|
|
{
|
||
|
|
DRIVER_INFORMATION* ptDriverInfo = (DRIVER_INFORMATION*)pvDriverInfo;
|
||
|
|
|
||
|
|
if(g_tDriverInfo.ulOpenCount == 0)
|
||
|
|
return CIFX_DRV_NOT_OPENED;
|
||
|
|
|
||
|
|
CHECK_DRIVERHANDLE(hDriver);
|
||
|
|
CHECK_POINTER(pvDriverInfo);
|
||
|
|
|
||
|
|
if(ulSize < (uint32_t)sizeof(*ptDriverInfo))
|
||
|
|
return CIFX_INVALID_BUFFERSIZE;
|
||
|
|
|
||
|
|
ptDriverInfo->ulBoardCnt = g_ulDeviceCount;
|
||
|
|
(void)OS_Strncpy(ptDriverInfo->abDriverVersion, TOOLKIT_VERSION, sizeof(ptDriverInfo->abDriverVersion));
|
||
|
|
|
||
|
|
return CIFX_NO_ERROR; /*lint !e438 */
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Query human readable error description
|
||
|
|
* \param lError Error to look up
|
||
|
|
* \param szBuffer Pointer to return data
|
||
|
|
* \param ulBufferLen Length of return buffer
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xDriverGetErrorDescription(int32_t lError, char* szBuffer, uint32_t ulBufferLen)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_FUNCTION_FAILED;
|
||
|
|
int iIdx = 0;
|
||
|
|
|
||
|
|
CHECK_POINTER(szBuffer);
|
||
|
|
|
||
|
|
for(iIdx = 0; iIdx < (int)(sizeof(s_atErrorToDescrTable) / sizeof(s_atErrorToDescrTable[0])); ++iIdx)
|
||
|
|
{
|
||
|
|
if(s_atErrorToDescrTable[iIdx].lError == lError)
|
||
|
|
{
|
||
|
|
(void)OS_Strncpy(szBuffer, s_atErrorToDescrTable[iIdx].szErrorDescr, ulBufferLen);
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Enumerate over all handled boards/devices
|
||
|
|
* \param hDriver Driver handle
|
||
|
|
* \param ulBoard Board number (incremented from 0 up)
|
||
|
|
* \param ulSize Size of return buffer
|
||
|
|
* \param pvBoardInfo Return buffer (BOARD_INFORMATION structure)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xDriverEnumBoards(CIFXHANDLE hDriver, uint32_t ulBoard, uint32_t ulSize, void* pvBoardInfo)
|
||
|
|
{
|
||
|
|
BOARD_INFORMATION* ptBoardInfo = (BOARD_INFORMATION*)pvBoardInfo;
|
||
|
|
PDEVICEINSTANCE ptDevInstance = NULL;
|
||
|
|
HIL_DPM_SYSTEM_CHANNEL_T* ptSysChannel = NULL;
|
||
|
|
|
||
|
|
if(g_tDriverInfo.ulOpenCount == 0)
|
||
|
|
return CIFX_DRV_NOT_OPENED;
|
||
|
|
|
||
|
|
CHECK_DRIVERHANDLE(hDriver);
|
||
|
|
CHECK_POINTER(pvBoardInfo);
|
||
|
|
|
||
|
|
if(ulSize < (uint32_t)sizeof(*ptBoardInfo))
|
||
|
|
return CIFX_INVALID_BUFFERSIZE;
|
||
|
|
|
||
|
|
if(ulBoard >= g_ulDeviceCount)
|
||
|
|
return CIFX_NO_MORE_ENTRIES;
|
||
|
|
|
||
|
|
ptDevInstance = g_pptDevices[ulBoard];
|
||
|
|
ptSysChannel = (HIL_DPM_SYSTEM_CHANNEL_T*)ptDevInstance->pbDPM;
|
||
|
|
|
||
|
|
(void)OS_Strncpy(ptBoardInfo->abBoardName, ptDevInstance->szName, sizeof(ptBoardInfo->abBoardName));
|
||
|
|
(void)OS_Strncpy(ptBoardInfo->abBoardAlias, ptDevInstance->szAlias, sizeof(ptBoardInfo->abBoardAlias));
|
||
|
|
ptBoardInfo->ulBoardID = ulBoard;
|
||
|
|
|
||
|
|
{
|
||
|
|
ptBoardInfo->ulSystemError = LE32_TO_HOST(HWIF_READ32(ptDevInstance, ptSysChannel->tSystemState.ulSystemError));
|
||
|
|
|
||
|
|
ptBoardInfo->ulPhysicalAddress = ptDevInstance->ulPhysicalAddress;
|
||
|
|
ptBoardInfo->ulIrqNumber = ptDevInstance->ulIrqNumber;
|
||
|
|
ptBoardInfo->bIrqEnabled = ptDevInstance->fIrqEnabled? 1 : 0;
|
||
|
|
ptBoardInfo->ulDpmTotalSize = ptDevInstance->ulDPMSize;
|
||
|
|
ptBoardInfo->ulChannelCnt = ptDevInstance->ulCommChannelCount;
|
||
|
|
|
||
|
|
HWIF_READN(ptDevInstance, &ptBoardInfo->tSystemInfo, &ptSysChannel->tSystemInfo, sizeof(ptBoardInfo->tSystemInfo));
|
||
|
|
}
|
||
|
|
|
||
|
|
(void)cifXConvertEndianess(0,
|
||
|
|
&ptBoardInfo->tSystemInfo,
|
||
|
|
sizeof(ptBoardInfo->tSystemInfo),
|
||
|
|
s_atSystemInfoBlock,
|
||
|
|
sizeof(s_atSystemInfoBlock) / sizeof(s_atSystemInfoBlock[0]));
|
||
|
|
|
||
|
|
return CIFX_NO_ERROR; /*lint !e438 */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Enumerate over all channels on the given boards
|
||
|
|
* \param hDriver Driver handle
|
||
|
|
* \param ulBoard Board number
|
||
|
|
* \param ulChannel Channel number (incremented from 0 up)
|
||
|
|
* \param ulSize Size of return buffer
|
||
|
|
* \param pvChannelInfo Return buffer (CHANNEL_INFORMATION structure)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xDriverEnumChannels(CIFXHANDLE hDriver, uint32_t ulBoard, uint32_t ulChannel, uint32_t ulSize, void* pvChannelInfo)
|
||
|
|
{
|
||
|
|
CHANNEL_INFORMATION* ptChannelInfo = (CHANNEL_INFORMATION*)pvChannelInfo;
|
||
|
|
PDEVICEINSTANCE ptDevInstance = NULL;
|
||
|
|
PCHANNELINSTANCE ptChannel = NULL;
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
if(g_tDriverInfo.ulOpenCount == 0)
|
||
|
|
return CIFX_DRV_NOT_OPENED;
|
||
|
|
|
||
|
|
CHECK_DRIVERHANDLE(hDriver);
|
||
|
|
CHECK_POINTER(pvChannelInfo);
|
||
|
|
|
||
|
|
if(ulSize < (uint32_t)sizeof(*ptChannelInfo))
|
||
|
|
return CIFX_INVALID_BUFFERSIZE;
|
||
|
|
|
||
|
|
if(ulBoard >= g_ulDeviceCount)
|
||
|
|
return CIFX_INVALID_BOARD;
|
||
|
|
|
||
|
|
ptDevInstance = g_pptDevices[ulBoard];
|
||
|
|
|
||
|
|
if(ulChannel >= ptDevInstance->ulCommChannelCount)
|
||
|
|
return CIFX_NO_MORE_ENTRIES;
|
||
|
|
|
||
|
|
ptChannel = ptDevInstance->pptCommChannels[ulChannel];
|
||
|
|
|
||
|
|
/* Read the channel information */
|
||
|
|
lRet = xChannelInfo( ptChannel, ulSize, ptChannelInfo);
|
||
|
|
|
||
|
|
return lRet; /*lint !e438 */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*! **************************************************************************
|
||
|
|
* Get/Return a memory pointer to the boards dual-port memory
|
||
|
|
* \param hDriver Driver handle
|
||
|
|
* \param ulBoard The board number (0)
|
||
|
|
* \param ulCmd Function command (CIFX_MEM_PTR_OPEN/CIFX_MEM_PTR_CLOSE)
|
||
|
|
* \param pvMemoryInfo Memory information structure
|
||
|
|
* \return CIFX_NO_ERROR on success
|
||
|
|
******************************************************************************/
|
||
|
|
int32_t APIENTRY xDriverMemoryPointer(CIFXHANDLE hDriver, uint32_t ulBoard, uint32_t ulCmd, void* pvMemoryInfo)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
MEMORY_INFORMATION* ptMemory = (MEMORY_INFORMATION*)pvMemoryInfo;
|
||
|
|
|
||
|
|
if(0 == g_tDriverInfo.ulOpenCount)
|
||
|
|
return CIFX_DRV_NOT_OPENED;
|
||
|
|
|
||
|
|
CHECK_DRIVERHANDLE(hDriver);
|
||
|
|
CHECK_POINTER(pvMemoryInfo);
|
||
|
|
|
||
|
|
/* We only support 1 board */
|
||
|
|
if(ulBoard >= g_ulDeviceCount)
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_BOARD;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Get the device instance */
|
||
|
|
PDEVICEINSTANCE ptDevInst = g_pptDevices[ulBoard];
|
||
|
|
switch(ulCmd)
|
||
|
|
{
|
||
|
|
case CIFX_MEM_PTR_OPEN:
|
||
|
|
{
|
||
|
|
void* pvMappedDPM = NULL;
|
||
|
|
|
||
|
|
*(ptMemory->pulMemorySize) = 0;
|
||
|
|
*(ptMemory->ppvMemoryPtr) = NULL;
|
||
|
|
|
||
|
|
/* Return global memory information */
|
||
|
|
if(NULL == (ptMemory->pvMemoryID = OS_MapUserPointer(ptDevInst->pbDPM, ptDevInst->ulDPMSize, &pvMappedDPM, ptDevInst->pvOSDependent, 0)))
|
||
|
|
{
|
||
|
|
lRet = CIFX_MEMORY_MAPPING_FAILED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
*(ptMemory->ppvMemoryPtr) = (void*)pvMappedDPM;
|
||
|
|
*(ptMemory->pulMemorySize) = ptDevInst->ulDPMSize;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Check requested channel */
|
||
|
|
if(ptMemory->ulChannel != CIFX_NO_CHANNEL)
|
||
|
|
{
|
||
|
|
/* Process channel information */
|
||
|
|
if(ptMemory->ulChannel >= ptDevInst->ulCommChannelCount)
|
||
|
|
{
|
||
|
|
*(ptMemory->pulChannelStartOffset) = 0;
|
||
|
|
*(ptMemory->pulChannelSize) = 0;
|
||
|
|
lRet = CIFX_INVALID_CHANNEL;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = ptDevInst->pptCommChannels[ptMemory->ulChannel];
|
||
|
|
uint32_t ulOffset = (uint32_t)(ptChannel->pbDPMChannelStart -
|
||
|
|
ptDevInst->pbDPM);
|
||
|
|
|
||
|
|
/* Get Channel information */
|
||
|
|
*(ptMemory->pulChannelSize) = ptChannel->ulDPMChannelLength;
|
||
|
|
*(ptMemory->pulChannelStartOffset) = ulOffset;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_MEM_PTR_CLOSE:
|
||
|
|
/* Clear user area */
|
||
|
|
if(!OS_UnmapUserPointer(ptMemory->pvMemoryID, ptDevInst->pvOSDependent))
|
||
|
|
{
|
||
|
|
lRet = CIFX_INVALID_HANDLE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ptMemory->pvMemoryID = NULL;
|
||
|
|
*(ptMemory->ppvMemoryPtr) = NULL;
|
||
|
|
*(ptMemory->pulMemorySize) = 0;
|
||
|
|
*(ptMemory->ppvMemoryPtr) = NULL;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
} /* end switch */
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet; /*lint !e438 */
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Get Channel information on an open channel
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulSize Size of return buffer
|
||
|
|
* \param pvChannelInfo Return buffer (CHANNEL_INFORMATION structure)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelInfo(CIFXHANDLE hChannel, uint32_t ulSize, void* pvChannelInfo)
|
||
|
|
{
|
||
|
|
CHANNEL_INFORMATION* ptChannelInfo = (CHANNEL_INFORMATION*)pvChannelInfo;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
PDEVICEINSTANCE ptDevInstance = NULL;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pvChannelInfo);
|
||
|
|
|
||
|
|
ptDevInstance = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
|
||
|
|
|
||
|
|
if(ulSize < (uint32_t)sizeof(*ptChannelInfo))
|
||
|
|
return CIFX_INVALID_BUFFERSIZE;
|
||
|
|
|
||
|
|
(void)OS_Strncpy(ptChannelInfo->abBoardName,
|
||
|
|
ptDevInstance->szName,
|
||
|
|
(uint32_t)sizeof(ptChannelInfo->abBoardName));
|
||
|
|
(void)OS_Strncpy(ptChannelInfo->abBoardAlias,
|
||
|
|
ptDevInstance->szAlias,
|
||
|
|
(uint32_t)sizeof(ptChannelInfo->abBoardAlias));
|
||
|
|
|
||
|
|
ptChannelInfo->ulDeviceNumber = ptDevInstance->ulDeviceNumber;
|
||
|
|
ptChannelInfo->ulSerialNumber = ptDevInstance->ulSerialNumber;
|
||
|
|
|
||
|
|
ptChannelInfo->usFWMajor = ptChannel->tFirmwareIdent.tFwVersion.usMajor;
|
||
|
|
ptChannelInfo->usFWMinor = ptChannel->tFirmwareIdent.tFwVersion.usMinor;
|
||
|
|
ptChannelInfo->usFWRevision = ptChannel->tFirmwareIdent.tFwVersion.usRevision;
|
||
|
|
ptChannelInfo->usFWBuild = ptChannel->tFirmwareIdent.tFwVersion.usBuild;
|
||
|
|
ptChannelInfo->bFWNameLength = ptChannel->tFirmwareIdent.tFwName.bNameLength;
|
||
|
|
|
||
|
|
OS_Memcpy(ptChannelInfo->abFWName,
|
||
|
|
ptChannel->tFirmwareIdent.tFwName.abName,
|
||
|
|
sizeof(ptChannelInfo->abFWName));
|
||
|
|
|
||
|
|
ptChannelInfo->usFWYear = ptChannel->tFirmwareIdent.tFwDate.usYear;
|
||
|
|
ptChannelInfo->bFWMonth = ptChannel->tFirmwareIdent.tFwDate.bMonth;
|
||
|
|
ptChannelInfo->bFWDay = ptChannel->tFirmwareIdent.tFwDate.bDay;
|
||
|
|
|
||
|
|
ptChannelInfo->ulChannelError = 0;
|
||
|
|
if(0 != ptChannel->ptCommonStatusBlock)
|
||
|
|
{
|
||
|
|
ptChannelInfo->ulChannelError = LE32_TO_HOST(HWIF_READ32(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->ulCommunicationError));
|
||
|
|
}
|
||
|
|
|
||
|
|
ptChannelInfo->ulOpenCnt = ptChannel->ulOpenCount;
|
||
|
|
ptChannelInfo->ulPutPacketCnt = ptChannel->tSendMbx.ulSendPacketCnt;
|
||
|
|
ptChannelInfo->ulGetPacketCnt = ptChannel->tRecvMbx.ulRecvPacketCnt;
|
||
|
|
ptChannelInfo->ulMailboxSize = ptChannel->tSendMbx.ulSendMailboxLength;
|
||
|
|
ptChannelInfo->ulIOInAreaCnt = ptChannel->ulIOInputAreas;
|
||
|
|
ptChannelInfo->ulIOOutAreaCnt = ptChannel->ulIOOutputAreas;
|
||
|
|
ptChannelInfo->ulHskSize = ptChannel->bHandshakeWidth;
|
||
|
|
|
||
|
|
/* Check if we are in interrupt mode */
|
||
|
|
if(!((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->fIrqEnabled)
|
||
|
|
DEV_ReadHandshakeFlags(ptChannel, 0, 1);
|
||
|
|
|
||
|
|
ptChannelInfo->ulNetxFlags = ptChannel->usNetxFlags;
|
||
|
|
ptChannelInfo->ulHostFlags = ptChannel->usHostFlags;
|
||
|
|
ptChannelInfo->ulHostCOSFlags = ptChannel->ulHostCOSFlags;
|
||
|
|
ptChannelInfo->ulDeviceCOSFlags = ptChannel->ulDeviceCOSFlags;
|
||
|
|
|
||
|
|
return CIFX_NO_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Trigger channels watchdog
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulCmd Trigger command (CIFX_WATCHDOG_START to
|
||
|
|
* trigger/start, CIFX_WATCHDOG_STOP to end watchdog)
|
||
|
|
* \param pulTrigger Old trigger value from device
|
||
|
|
* (informational use only)
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelWatchdog(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulTrigger)
|
||
|
|
{
|
||
|
|
return DEV_TriggerWatchdog( (PCHANNELINSTANCE)hChannel, ulCmd, pulTrigger);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Set/Get Host state of the card
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ulCmd Host state command (CIFX_HOST_STATE_NOT_READY,
|
||
|
|
* CIFX_HOST_STATE_READY, CIFX_HOST_STATE_READ)
|
||
|
|
* \param pulState Returned state if command is CIFX_HOST_STATE_READ
|
||
|
|
* \param ulTimeout Time in ms to wait for start/stop communication
|
||
|
|
* flag
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelHostState(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulState, uint32_t ulTimeout)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pulState);
|
||
|
|
|
||
|
|
switch(ulCmd)
|
||
|
|
{
|
||
|
|
case CIFX_HOST_STATE_READ:
|
||
|
|
lRet = DEV_GetHostState( (PCHANNELINSTANCE)hChannel,
|
||
|
|
pulState);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_HOST_STATE_READY:
|
||
|
|
case CIFX_HOST_STATE_NOT_READY:
|
||
|
|
lRet = DEV_SetHostState( (PCHANNELINSTANCE)hChannel,
|
||
|
|
ulCmd,
|
||
|
|
ulTimeout);
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Starts directory enumeration on the given channel
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ptDirectoryInfo Pointer to enumeration result.
|
||
|
|
* (Will be initialized inside function)
|
||
|
|
* \param pfnRecvPktCallback Callback for unhandled packets
|
||
|
|
* \param pvUser User data for callback function
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelFindFirstFile(CIFXHANDLE hChannel, CIFX_DIRECTORYENTRY* ptDirectoryInfo,
|
||
|
|
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
|
||
|
|
return xSysdeviceFindFirstFile(hChannel, ptChannel->ulChannelNumber, ptDirectoryInfo, pfnRecvPktCallback, pvUser);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Enumerate next entry in directory on the given channel
|
||
|
|
* \param hChannel Handle to the channel
|
||
|
|
* \param ptDirectoryInfo Pointer to enumeration result.
|
||
|
|
* \param pfnRecvPktCallback Callback for unhandled packets
|
||
|
|
* \param pvUser User data for callback function
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelFindNextFile(CIFXHANDLE hChannel, CIFX_DIRECTORYENTRY* ptDirectoryInfo,
|
||
|
|
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
|
||
|
|
return xSysdeviceFindNextFile(hChannel, ptChannel->ulChannelNumber, ptDirectoryInfo, pfnRecvPktCallback, pvUser);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Starts directory enumeration on the given channel
|
||
|
|
* \param hSysdevice Handle to the system device
|
||
|
|
* \param ulChannel Channel number to get directory from
|
||
|
|
* \param ptDirectoryInfo Pointer to enumeration result.
|
||
|
|
* (Will be initialized inside function)
|
||
|
|
* \param pfnRecvPktCallback Callback for unhandled packets
|
||
|
|
* \param pvUser User data for callback function
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceFindFirstFile(CIFXHANDLE hSysdevice, uint32_t ulChannel, CIFX_DIRECTORYENTRY* ptDirectoryInfo,
|
||
|
|
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
union
|
||
|
|
{
|
||
|
|
CIFX_PACKET tPacket;
|
||
|
|
HIL_DIR_LIST_REQ_T tDirListReq;
|
||
|
|
|
||
|
|
} uSendPacket;
|
||
|
|
HIL_DIR_LIST_CNF_T tDirListCnf;
|
||
|
|
|
||
|
|
OS_Memset(&uSendPacket, 0, sizeof(uSendPacket));
|
||
|
|
OS_Memset(&tDirListCnf, 0, sizeof(tDirListCnf));
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_PARAMETER_CHECK
|
||
|
|
if ( (CIFX_NO_ERROR != CheckSysdeviceHandle(hSysdevice)) &&
|
||
|
|
(CIFX_NO_ERROR != CheckChannelHandle(hSysdevice)) )
|
||
|
|
return CIFX_INVALID_HANDLE;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
CHECK_POINTER(ptDirectoryInfo);
|
||
|
|
|
||
|
|
if(OS_Strlen(ptDirectoryInfo->szFilename) > 0)
|
||
|
|
{
|
||
|
|
uint16_t usDirNameLength = (uint16_t)(OS_Strlen(ptDirectoryInfo->szFilename) + 1);
|
||
|
|
|
||
|
|
uSendPacket.tDirListReq.tData.usDirNameLength = HOST_TO_LE16(usDirNameLength);
|
||
|
|
(void)OS_Strncpy( (char*)((&uSendPacket.tDirListReq.tData) + 1),
|
||
|
|
ptDirectoryInfo->szFilename,
|
||
|
|
usDirNameLength);
|
||
|
|
}
|
||
|
|
|
||
|
|
uSendPacket.tDirListReq.tHead.ulDest = HOST_TO_LE32(HIL_PACKET_DEST_SYSTEM);
|
||
|
|
uSendPacket.tDirListReq.tHead.ulSrc = HOST_TO_LE32(((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->ulPhysicalAddress);
|
||
|
|
uSendPacket.tDirListReq.tHead.ulCmd = HOST_TO_LE32(HIL_DIR_LIST_REQ);
|
||
|
|
uSendPacket.tDirListReq.tHead.ulLen = HOST_TO_LE32( ((uint32_t)sizeof(uSendPacket.tDirListReq.tData) +
|
||
|
|
uSendPacket.tDirListReq.tData.usDirNameLength) );
|
||
|
|
uSendPacket.tDirListReq.tData.ulChannelNo = HOST_TO_LE32(ulChannel);
|
||
|
|
|
||
|
|
|
||
|
|
lRet = DEV_TransferPacket(ptChannel,
|
||
|
|
&uSendPacket.tPacket,
|
||
|
|
(CIFX_PACKET*)&tDirListCnf,
|
||
|
|
sizeof(tDirListCnf),
|
||
|
|
CIFX_TO_SEND_PACKET,
|
||
|
|
pfnRecvPktCallback,
|
||
|
|
pvUser);
|
||
|
|
|
||
|
|
if( CIFX_NO_ERROR == lRet)
|
||
|
|
{
|
||
|
|
if( SUCCESS_HIL_OK == (lRet = LE32_TO_HOST(tDirListCnf.tHead.ulSta)) )
|
||
|
|
{
|
||
|
|
uint8_t* pbListEntry = (uint8_t*)&ptDirectoryInfo->hList;
|
||
|
|
if ((tDirListCnf.tHead.ulExt & HIL_PACKET_SEQ_MASK) == HIL_PACKET_SEQ_LAST)
|
||
|
|
{
|
||
|
|
/* this is the last packet */
|
||
|
|
lRet = CIFX_NO_MORE_ENTRIES;
|
||
|
|
/* invalidate handle */
|
||
|
|
*pbListEntry = 0;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* TODO: Store handle for directory list, which needs to be set by firmware */
|
||
|
|
*pbListEntry = 1;
|
||
|
|
|
||
|
|
(void)OS_Strncpy(ptDirectoryInfo->szFilename,
|
||
|
|
(const char*)tDirListCnf.tData.szName,
|
||
|
|
sizeof(ptDirectoryInfo->szFilename));
|
||
|
|
|
||
|
|
ptDirectoryInfo->bFiletype = tDirListCnf.tData.bFileType;
|
||
|
|
ptDirectoryInfo->ulFilesize = LE32_TO_HOST(tDirListCnf.tData.ulFileSize);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Enumerate next entry in directory on the given channel
|
||
|
|
* \param hSysdevice Handle to the system device
|
||
|
|
* \param ulChannel Channel number to get directory from
|
||
|
|
* \param ptDirectoryInfo Pointer to enumeration result
|
||
|
|
* \param pfnRecvPktCallback Callback for unhandled packets
|
||
|
|
* \param pvUser User data for callback function
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceFindNextFile(CIFXHANDLE hSysdevice, uint32_t ulChannel, CIFX_DIRECTORYENTRY* ptDirectoryInfo,
|
||
|
|
PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
union
|
||
|
|
{
|
||
|
|
CIFX_PACKET tPacket;
|
||
|
|
HIL_DIR_LIST_REQ_T tDirListReq;
|
||
|
|
|
||
|
|
} uSendPacket;
|
||
|
|
HIL_DIR_LIST_CNF_T tDirListCnf;
|
||
|
|
uint16_t usDirNameLen = 0;
|
||
|
|
|
||
|
|
OS_Memset(&uSendPacket, 0, sizeof(uSendPacket));
|
||
|
|
OS_Memset(&tDirListCnf, 0, sizeof(tDirListCnf));
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_PARAMETER_CHECK
|
||
|
|
if ( (CIFX_NO_ERROR != CheckSysdeviceHandle(hSysdevice)) &&
|
||
|
|
(CIFX_NO_ERROR != CheckChannelHandle(hSysdevice)) )
|
||
|
|
return CIFX_INVALID_HANDLE;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
CHECK_POINTER(ptDirectoryInfo);
|
||
|
|
|
||
|
|
usDirNameLen = (uint16_t)(OS_Strlen(ptDirectoryInfo->szFilename) + 1);
|
||
|
|
uSendPacket.tDirListReq.tData.usDirNameLength = HOST_TO_LE16(usDirNameLen);
|
||
|
|
(void)OS_Strncpy( (char*)((&uSendPacket.tDirListReq.tData) + 1),
|
||
|
|
ptDirectoryInfo->szFilename,
|
||
|
|
usDirNameLen);
|
||
|
|
|
||
|
|
uSendPacket.tDirListReq.tHead.ulDest = HOST_TO_LE32(HIL_PACKET_DEST_SYSTEM);
|
||
|
|
uSendPacket.tDirListReq.tHead.ulSrc = HOST_TO_LE32(((PDEVICEINSTANCE)(ptChannel->pvDeviceInstance))->ulPhysicalAddress);
|
||
|
|
uSendPacket.tDirListReq.tHead.ulCmd = HOST_TO_LE32(HIL_DIR_LIST_REQ);
|
||
|
|
uSendPacket.tDirListReq.tHead.ulLen = HOST_TO_LE32( ((uint32_t)sizeof(uSendPacket.tDirListReq.tData) + usDirNameLen) );
|
||
|
|
uSendPacket.tDirListReq.tHead.ulExt = HOST_TO_LE32(HIL_PACKET_SEQ_MIDDLE);
|
||
|
|
|
||
|
|
uSendPacket.tDirListReq.tData.ulChannelNo = HOST_TO_LE32(ulChannel);
|
||
|
|
|
||
|
|
lRet = DEV_TransferPacket(ptChannel,
|
||
|
|
&uSendPacket.tPacket,
|
||
|
|
(CIFX_PACKET*)&tDirListCnf,
|
||
|
|
sizeof(tDirListCnf),
|
||
|
|
CIFX_TO_SEND_PACKET,
|
||
|
|
pfnRecvPktCallback,
|
||
|
|
pvUser);
|
||
|
|
|
||
|
|
if(CIFX_NO_ERROR == lRet)
|
||
|
|
{
|
||
|
|
if( SUCCESS_HIL_OK == (lRet = (LE32_TO_HOST(tDirListCnf.tHead.ulSta))) )
|
||
|
|
{
|
||
|
|
if(( LE32_TO_HOST(tDirListCnf.tHead.ulExt) & HIL_PACKET_SEQ_MASK) == HIL_PACKET_SEQ_LAST)
|
||
|
|
{
|
||
|
|
uint8_t* pbListEntry = (uint8_t*)&ptDirectoryInfo->hList;
|
||
|
|
|
||
|
|
/* invalidate handle */
|
||
|
|
*pbListEntry = 0;
|
||
|
|
|
||
|
|
/* this is the last packet */
|
||
|
|
lRet = CIFX_NO_MORE_ENTRIES;
|
||
|
|
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
(void)OS_Strncpy(ptDirectoryInfo->szFilename,
|
||
|
|
(const char*)tDirListCnf.tData.szName,
|
||
|
|
sizeof(tDirListCnf.tData.szName));
|
||
|
|
|
||
|
|
ptDirectoryInfo->bFiletype = tDirListCnf.tData.bFileType;
|
||
|
|
ptDirectoryInfo->ulFilesize = LE32_TO_HOST(tDirListCnf.tData.ulFileSize);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Uploads a file via system channel
|
||
|
|
* \param hSysdevice Handle to the System device
|
||
|
|
* \param ulChannel Channel number to get directory from
|
||
|
|
* \param ulMode Transfer Mode
|
||
|
|
* \param pszFileName Filename to upload
|
||
|
|
* \param pabFileData Pointer to buffer receiving upload
|
||
|
|
* \param pulFileSize [in]Length of buffer, [out] Bytes copied to buffer
|
||
|
|
* \param pfnCallback Callback pointer for progress
|
||
|
|
* (NULL for no callback)
|
||
|
|
* \param pfnRecvPktCallback Callback pointer for unsolicited receive packets
|
||
|
|
* (NULL for no callback)
|
||
|
|
* \param pvUser User parameter on callback.
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xSysdeviceUpload(CIFXHANDLE hSysdevice, uint32_t ulChannel,
|
||
|
|
uint32_t ulMode, char* pszFileName, uint8_t* pabFileData, uint32_t* pulFileSize,
|
||
|
|
PFN_PROGRESS_CALLBACK pfnCallback, PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptSysDevice = (PCHANNELINSTANCE)hSysdevice;
|
||
|
|
uint32_t ulTransferType = 0;
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
#ifdef CIFX_TOOLKIT_PARAMETER_CHECK
|
||
|
|
if ( (CIFX_NO_ERROR != CheckSysdeviceHandle(hSysdevice)) &&
|
||
|
|
(CIFX_NO_ERROR != CheckChannelHandle(hSysdevice)) )
|
||
|
|
return CIFX_INVALID_HANDLE;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
CHECK_POINTER(pszFileName);
|
||
|
|
CHECK_POINTER(pabFileData);
|
||
|
|
CHECK_POINTER(pulFileSize);
|
||
|
|
|
||
|
|
switch(ulMode)
|
||
|
|
{
|
||
|
|
case DOWNLOAD_MODE_FIRMWARE:
|
||
|
|
if( CIFX_NO_ERROR != (lRet = DEV_GetFWTransferTypeFromFileName( ((PDEVICEINSTANCE)(ptSysDevice->pvDeviceInstance))->eChipType,
|
||
|
|
pszFileName, &ulTransferType)))
|
||
|
|
return lRet;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case DOWNLOAD_MODE_CONFIG:
|
||
|
|
case DOWNLOAD_MODE_FILE:
|
||
|
|
ulTransferType = HIL_FILE_XFER_FILE;
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
return CIFX_INVALID_PARAMETER;
|
||
|
|
}
|
||
|
|
|
||
|
|
lRet = DEV_UploadFile(ptSysDevice,
|
||
|
|
ulChannel,
|
||
|
|
ptSysDevice->tRecvMbx.ulRecvMailboxLength,
|
||
|
|
ulTransferType,
|
||
|
|
pszFileName,
|
||
|
|
pulFileSize,
|
||
|
|
pabFileData,
|
||
|
|
DEV_TransferPacket,
|
||
|
|
pfnCallback,
|
||
|
|
pfnRecvPktCallback,
|
||
|
|
pvUser);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Uploads a file via Communication channel
|
||
|
|
* \param hChannel Handle to the Channel
|
||
|
|
* \param ulMode Transfer Mode
|
||
|
|
* \param pszFileName Filename to upload
|
||
|
|
* \param pabFileData Pointer to buffer receiving upload
|
||
|
|
* \param pulFileSize [in]Length of buffer, [out] Bytes copied to buffer
|
||
|
|
* \param pfnCallback Callback pointer for progress
|
||
|
|
* (NULL for no callback)
|
||
|
|
* \param pfnRecvPktCallback Callback pointer for unsolicited receive packets
|
||
|
|
* (NULL for no callback)
|
||
|
|
* \param pvUser User parameter on callback.
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelUpload(CIFXHANDLE hChannel, uint32_t ulMode,
|
||
|
|
char* pszFileName, uint8_t* pabFileData, uint32_t* pulFileSize,
|
||
|
|
PFN_PROGRESS_CALLBACK pfnCallback, PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)
|
||
|
|
{
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
|
||
|
|
return xSysdeviceUpload(hChannel,
|
||
|
|
ptChannel->ulChannelNumber,
|
||
|
|
ulMode,
|
||
|
|
pszFileName,
|
||
|
|
pabFileData,
|
||
|
|
pulFileSize,
|
||
|
|
pfnCallback,
|
||
|
|
pfnRecvPktCallback,
|
||
|
|
pvUser);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Set DMA state of a communication channel
|
||
|
|
* \param hChannel Channel handle
|
||
|
|
* \param ulCmd Command CIFX_DMA_STATE_xxx
|
||
|
|
* \param pulState Return actual state on CIFX_GET_DMA_STATE
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelDMAState(CIFXHANDLE hChannel, uint32_t ulCmd, uint32_t* pulState)
|
||
|
|
{
|
||
|
|
#ifdef CIFX_TOOLKIT_DMA
|
||
|
|
|
||
|
|
int32_t lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
PDEVICEINSTANCE ptDevInstance = NULL;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pulState);
|
||
|
|
|
||
|
|
ptDevInstance = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
|
||
|
|
|
||
|
|
/* Only possible on PCI devices */
|
||
|
|
if( !ptDevInstance->fPCICard)
|
||
|
|
return CIFX_FUNCTION_NOT_AVAILABLE;
|
||
|
|
|
||
|
|
/* Only possible if user provided DMA buffers */
|
||
|
|
if(0 == ptDevInstance->ulDMABufferCount)
|
||
|
|
return CIFX_DEV_DMA_INSUFF_BUFFER_COUNT;
|
||
|
|
|
||
|
|
/* Check if firmware supports DMA functions */
|
||
|
|
|
||
|
|
/*TODO: Check this */
|
||
|
|
/*if( !ptChannel->ptCommonStatusBlock->ulCommunicationCOS->fPCICard) */
|
||
|
|
/* return CIFX_FUNCTION_NOT_AVAILABLE; */
|
||
|
|
|
||
|
|
lRet = DEV_DMAState( (PCHANNELINSTANCE)hChannel,
|
||
|
|
ulCmd,
|
||
|
|
pulState);
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
|
||
|
|
#else
|
||
|
|
|
||
|
|
UNREFERENCED_PARAMETER(hChannel);
|
||
|
|
UNREFERENCED_PARAMETER(ulCmd);
|
||
|
|
UNREFERENCED_PARAMETER(pulState);
|
||
|
|
return CIFX_FUNCTION_NOT_AVAILABLE; /*lint !e438 : unused variables */
|
||
|
|
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Register a callback notification
|
||
|
|
* \param hChannel Handle to the Channel
|
||
|
|
* \param ulNotification Notification
|
||
|
|
* \param pfnCallback Callback function
|
||
|
|
* \param pvUser User data pointer
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelRegisterNotification(CIFXHANDLE hChannel,
|
||
|
|
uint32_t ulNotification,
|
||
|
|
PFN_NOTIFY_CALLBACK pfnCallback,
|
||
|
|
void* pvUser)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
PDEVICEINSTANCE ptDevInst = NULL;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pfnCallback);
|
||
|
|
|
||
|
|
ptDevInst = (PDEVICEINSTANCE)ptChannel->pvDeviceInstance;
|
||
|
|
|
||
|
|
if(!ptDevInst->fIrqEnabled)
|
||
|
|
return CIFX_INTERRUPT_DISABLED;
|
||
|
|
|
||
|
|
switch (ulNotification)
|
||
|
|
{
|
||
|
|
case CIFX_NOTIFY_RX_MBX_FULL:
|
||
|
|
/* Check if already registered */
|
||
|
|
if( NULL != ptChannel->tRecvMbx.pfnCallback)
|
||
|
|
{
|
||
|
|
/* Already registered */
|
||
|
|
lRet = CIFX_CALLBACK_ALREADY_USED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ptChannel->tRecvMbx.pvUser = pvUser;
|
||
|
|
ptChannel->tRecvMbx.pfnCallback = pfnCallback;
|
||
|
|
|
||
|
|
if(DEV_WaitForBitState(ptChannel,
|
||
|
|
ptChannel->tRecvMbx.bRecvACKBitoffset,
|
||
|
|
HIL_FLAGS_NOT_EQUAL,
|
||
|
|
0))
|
||
|
|
{
|
||
|
|
CIFX_NOTIFY_RX_MBX_FULL_DATA_T tData;
|
||
|
|
tData.ulRecvCount = LE16_TO_HOST(HWIF_READ16(ptDevInst, ptChannel->tRecvMbx.ptRecvMailboxStart->usWaitingPackages));
|
||
|
|
|
||
|
|
pfnCallback(CIFX_NOTIFY_RX_MBX_FULL, sizeof(tData), &tData, pvUser);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_TX_MBX_EMPTY:
|
||
|
|
/* Check if already registered */
|
||
|
|
if( NULL != ptChannel->tSendMbx.pfnCallback)
|
||
|
|
{
|
||
|
|
/* Already registered */
|
||
|
|
lRet = CIFX_CALLBACK_ALREADY_USED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ptChannel->tSendMbx.pvUser = pvUser;
|
||
|
|
ptChannel->tSendMbx.pfnCallback = pfnCallback;
|
||
|
|
|
||
|
|
if(DEV_WaitForBitState(ptChannel,
|
||
|
|
ptChannel->tSendMbx.bSendCMDBitoffset,
|
||
|
|
HIL_FLAGS_EQUAL,
|
||
|
|
0))
|
||
|
|
{
|
||
|
|
CIFX_NOTIFY_TX_MBX_EMPTY_DATA_T tData;
|
||
|
|
tData.ulMaxSendCount = LE16_TO_HOST(HWIF_READ16(ptDevInst, ptChannel->tSendMbx.ptSendMailboxStart->usPackagesAccepted));
|
||
|
|
|
||
|
|
pfnCallback(CIFX_NOTIFY_TX_MBX_EMPTY, sizeof(tData), &tData, pvUser);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_PD0_IN:
|
||
|
|
case CIFX_NOTIFY_PD0_OUT:
|
||
|
|
{
|
||
|
|
IOINSTANCE* ptIOArea = ptChannel->pptIOInputAreas[0];
|
||
|
|
uint32_t ulAreaCount = ptChannel->ulIOInputAreas;
|
||
|
|
uint8_t bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 0);
|
||
|
|
|
||
|
|
if( CIFX_NOTIFY_PD0_OUT == ulNotification)
|
||
|
|
{
|
||
|
|
ptIOArea = ptChannel->pptIOOutputAreas[0];
|
||
|
|
ulAreaCount = ptChannel->ulIOOutputAreas;
|
||
|
|
bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Check if we have one input area */
|
||
|
|
if( 0 == ulAreaCount)
|
||
|
|
{
|
||
|
|
/* No input area */
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
|
||
|
|
} else if( NULL != ptIOArea->pfnCallback)
|
||
|
|
{
|
||
|
|
/* Already registered */
|
||
|
|
lRet = CIFX_CALLBACK_ALREADY_USED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Add the callback */
|
||
|
|
ptIOArea->pvUser = pvUser;
|
||
|
|
ptIOArea->pfnCallback = pfnCallback;
|
||
|
|
|
||
|
|
if(DEV_WaitForBitState(ptChannel,
|
||
|
|
ptIOArea->bHandshakeBit,
|
||
|
|
bIOBitState,
|
||
|
|
0))
|
||
|
|
{
|
||
|
|
pfnCallback(ulNotification, 0, NULL, pvUser);
|
||
|
|
}
|
||
|
|
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_PD1_IN:
|
||
|
|
case CIFX_NOTIFY_PD1_OUT:
|
||
|
|
{
|
||
|
|
IOINSTANCE* ptIOArea = ptChannel->pptIOInputAreas[1];
|
||
|
|
uint32_t ulAreaCount = ptChannel->ulIOInputAreas;
|
||
|
|
uint8_t bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 0);
|
||
|
|
|
||
|
|
if( CIFX_NOTIFY_PD1_OUT == ulNotification)
|
||
|
|
{
|
||
|
|
ptIOArea = ptChannel->pptIOOutputAreas[1];
|
||
|
|
ulAreaCount = ptChannel->ulIOOutputAreas;
|
||
|
|
bIOBitState = DEV_GetIOBitstate(ptChannel, ptIOArea, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Check if we have two input areas */
|
||
|
|
if( 1 <= ulAreaCount)
|
||
|
|
{
|
||
|
|
/* No input area */
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
|
||
|
|
} else if( NULL != ptIOArea->pfnCallback)
|
||
|
|
{
|
||
|
|
/* Already registered */
|
||
|
|
lRet = CIFX_CALLBACK_ALREADY_USED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Add the callback */
|
||
|
|
ptIOArea->pvUser = pvUser;
|
||
|
|
ptIOArea->pfnCallback = pfnCallback;
|
||
|
|
|
||
|
|
if(DEV_WaitForBitState(ptChannel,
|
||
|
|
ptIOArea->bHandshakeBit,
|
||
|
|
bIOBitState,
|
||
|
|
0))
|
||
|
|
{
|
||
|
|
pfnCallback(ulNotification, 0, NULL, pvUser);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_SYNC:
|
||
|
|
if( NULL != ptChannel->tSynch.pfnCallback)
|
||
|
|
{
|
||
|
|
/* Already registered */
|
||
|
|
lRet = CIFX_CALLBACK_ALREADY_USED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Add the callback */
|
||
|
|
uint8_t bState = HIL_FLAGS_NOT_EQUAL;
|
||
|
|
|
||
|
|
ptChannel->tSynch.pvUser = pvUser;
|
||
|
|
ptChannel->tSynch.pfnCallback = pfnCallback;
|
||
|
|
|
||
|
|
/* Add callback for sync on startup */
|
||
|
|
if( HIL_SYNC_MODE_HST_CTRL == HWIF_READ8(ptDevInst, ptChannel->ptCommonStatusBlock->bSyncHskMode))
|
||
|
|
bState = HIL_FLAGS_EQUAL;
|
||
|
|
|
||
|
|
if(DEV_WaitForSyncState(ptChannel,
|
||
|
|
bState,
|
||
|
|
0))
|
||
|
|
{
|
||
|
|
pfnCallback(ulNotification, 0, NULL, pvUser);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_COM_STATE:
|
||
|
|
/* Check if already registered */
|
||
|
|
if( NULL != ptChannel->tComState.pfnCallback)
|
||
|
|
{
|
||
|
|
/* Already registered */
|
||
|
|
lRet = CIFX_CALLBACK_ALREADY_USED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
CIFX_NOTIFY_COM_STATE_T tData;
|
||
|
|
|
||
|
|
ptChannel->tComState.pvUser = pvUser;
|
||
|
|
ptChannel->tComState.pfnCallback = pfnCallback;
|
||
|
|
|
||
|
|
/* Just update the actual flag state by reading it once */
|
||
|
|
(void)DEV_WaitForBitState(ptChannel,
|
||
|
|
NCF_COMMUNICATING_BIT_NO,
|
||
|
|
HIL_FLAGS_SET,
|
||
|
|
0);
|
||
|
|
|
||
|
|
tData.ulComState = ptChannel->usNetxFlags & NCF_COMMUNICATING;
|
||
|
|
pfnCallback(CIFX_NOTIFY_COM_STATE, sizeof(tData), &tData, pvUser);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Unregister a callback notification
|
||
|
|
* \param hChannel Handle to the Channel
|
||
|
|
* \param ulNotification Notification
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelUnregisterNotification( CIFXHANDLE hChannel,
|
||
|
|
uint32_t ulNotification)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
|
||
|
|
switch (ulNotification)
|
||
|
|
{
|
||
|
|
case CIFX_NOTIFY_RX_MBX_FULL:
|
||
|
|
/* Check if already registered */
|
||
|
|
if( NULL == ptChannel->tRecvMbx.pfnCallback)
|
||
|
|
{
|
||
|
|
/* Not registered */
|
||
|
|
lRet = CIFX_CALLBACK_NOT_REGISTERED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ptChannel->tRecvMbx.pfnCallback = NULL;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_TX_MBX_EMPTY:
|
||
|
|
/* Check if already registered */
|
||
|
|
if( NULL == ptChannel->tSendMbx.pfnCallback)
|
||
|
|
{
|
||
|
|
/* Already registered */
|
||
|
|
lRet = CIFX_CALLBACK_NOT_REGISTERED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
ptChannel->tSendMbx.pfnCallback = NULL;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_PD0_IN:
|
||
|
|
case CIFX_NOTIFY_PD0_OUT:
|
||
|
|
{
|
||
|
|
IOINSTANCE* ptIOArea = ptChannel->pptIOInputAreas[0];
|
||
|
|
uint32_t ulAreaCount = ptChannel->ulIOInputAreas;
|
||
|
|
|
||
|
|
if( CIFX_NOTIFY_PD0_OUT == ulNotification)
|
||
|
|
{
|
||
|
|
ptIOArea = ptChannel->pptIOOutputAreas[0];
|
||
|
|
ulAreaCount = ptChannel->ulIOOutputAreas;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Check if we have one input area */
|
||
|
|
if( 0 == ulAreaCount)
|
||
|
|
{
|
||
|
|
/* No input area */
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
|
||
|
|
} else if( NULL == ptIOArea->pfnCallback)
|
||
|
|
{
|
||
|
|
/* Not registered before */
|
||
|
|
lRet = CIFX_CALLBACK_NOT_REGISTERED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Add the callback */
|
||
|
|
ptIOArea->pfnCallback = NULL;
|
||
|
|
ptIOArea->pvUser = NULL;
|
||
|
|
lRet = CIFX_NO_ERROR;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_PD1_IN:
|
||
|
|
case CIFX_NOTIFY_PD1_OUT:
|
||
|
|
{
|
||
|
|
IOINSTANCE* ptIOArea = ptChannel->pptIOInputAreas[1];
|
||
|
|
uint32_t ulAreaCount = ptChannel->ulIOInputAreas;
|
||
|
|
|
||
|
|
if( CIFX_NOTIFY_PD1_OUT == ulNotification)
|
||
|
|
{
|
||
|
|
ptIOArea = ptChannel->pptIOOutputAreas[1];
|
||
|
|
ulAreaCount = ptChannel->ulIOOutputAreas;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Check if we have two input areas */
|
||
|
|
if( 1 <= ulAreaCount)
|
||
|
|
{
|
||
|
|
/* No input area */
|
||
|
|
lRet = CIFX_INVALID_PARAMETER;
|
||
|
|
|
||
|
|
} else if( NULL == ptIOArea->pfnCallback)
|
||
|
|
{
|
||
|
|
/* Not registered before */
|
||
|
|
lRet = CIFX_CALLBACK_NOT_REGISTERED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Add the callback */
|
||
|
|
ptIOArea->pfnCallback = NULL;
|
||
|
|
ptIOArea->pvUser = NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_SYNC:
|
||
|
|
if( NULL == ptChannel->tSynch.pfnCallback)
|
||
|
|
{
|
||
|
|
/* Not registered before */
|
||
|
|
lRet = CIFX_CALLBACK_NOT_REGISTERED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Add the callback */
|
||
|
|
ptChannel->tSynch.pfnCallback = NULL;
|
||
|
|
ptChannel->tSynch.pvUser = NULL;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_NOTIFY_COM_STATE:
|
||
|
|
if( NULL == ptChannel->tComState.pfnCallback)
|
||
|
|
{
|
||
|
|
/* Not registered before */
|
||
|
|
lRet = CIFX_CALLBACK_NOT_REGISTERED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* delete the callback */
|
||
|
|
ptChannel->tComState.pfnCallback = NULL;
|
||
|
|
ptChannel->tComState.pvUser = NULL;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! Signal a sync state, either a sync command or acknowledge
|
||
|
|
* \param hChannel Handle to the Channel
|
||
|
|
* \param ulCmd Sync command
|
||
|
|
* \param ulTimeout Timeout to wait for sync / sync signalling
|
||
|
|
* \param pulErrorCount Actual sync error counter
|
||
|
|
* \return CIFX_NO_ERROR on success */
|
||
|
|
/*****************************************************************************/
|
||
|
|
int32_t APIENTRY xChannelSyncState( CIFXHANDLE hChannel,
|
||
|
|
uint32_t ulCmd,
|
||
|
|
uint32_t ulTimeout,
|
||
|
|
uint32_t* pulErrorCount)
|
||
|
|
{
|
||
|
|
int32_t lRet = CIFX_NO_ERROR;
|
||
|
|
PCHANNELINSTANCE ptChannel = (PCHANNELINSTANCE)hChannel;
|
||
|
|
|
||
|
|
CHECK_CHANNELHANDLE(hChannel);
|
||
|
|
CHECK_POINTER(pulErrorCount);
|
||
|
|
|
||
|
|
/* Check if device installed and active */
|
||
|
|
if(ptChannel->ulOpenCount == 0)
|
||
|
|
{
|
||
|
|
lRet = CIFX_DRV_CHANNEL_NOT_INITIALIZED;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
switch (ulCmd)
|
||
|
|
{
|
||
|
|
case CIFX_SYNC_SIGNAL_CMD:
|
||
|
|
/* Check if SYNC mode is host controlled */
|
||
|
|
if(HIL_SYNC_MODE_HST_CTRL != HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode))
|
||
|
|
{
|
||
|
|
/* Invalid Device mode */
|
||
|
|
lRet = CIFX_DEV_SYNC_STATE_INVALID_MODE;
|
||
|
|
|
||
|
|
} else if(!DEV_WaitForSyncState(ptChannel, HIL_FLAGS_EQUAL, ulTimeout))
|
||
|
|
{
|
||
|
|
/* Sync cannot be signalled as bits are in wrong state */
|
||
|
|
lRet = CIFX_DEV_SYNC_STATE_TIMEOUT;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Signal new sync */
|
||
|
|
DEV_ToggleSyncBit( (PDEVICEINSTANCE)ptChannel->pvDeviceInstance, (1 << ptChannel->ulChannelNumber));
|
||
|
|
|
||
|
|
/* Return actual error counter */
|
||
|
|
*pulErrorCount = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bErrorSyncCnt);
|
||
|
|
|
||
|
|
/* Check if the device is communication */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_SYNC_ACKNOWLEDGE_CMD:
|
||
|
|
/* Check if SYNC mode is device controlled */
|
||
|
|
if(HIL_SYNC_MODE_DEV_CTRL != HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode))
|
||
|
|
{
|
||
|
|
/* Invalid Device mode */
|
||
|
|
lRet = CIFX_DEV_SYNC_STATE_INVALID_MODE;
|
||
|
|
|
||
|
|
} else if(!DEV_WaitForSyncState(ptChannel, HIL_FLAGS_NOT_EQUAL, ulTimeout))
|
||
|
|
{
|
||
|
|
/* Sync cannot be signalled as bits are in wrong state */
|
||
|
|
lRet = CIFX_DEV_SYNC_STATE_TIMEOUT;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Acknowledge an device sys */
|
||
|
|
DEV_ToggleSyncBit( (PDEVICEINSTANCE)ptChannel->pvDeviceInstance, (1 << ptChannel->ulChannelNumber));
|
||
|
|
|
||
|
|
/* Return actual error counter */
|
||
|
|
*pulErrorCount = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bErrorSyncCnt);
|
||
|
|
|
||
|
|
/* Check if the device is communication */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CIFX_SYNC_WAIT_CMD:
|
||
|
|
{
|
||
|
|
if( (HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode) != HIL_SYNC_MODE_HST_CTRL) &&
|
||
|
|
(HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode) != HIL_SYNC_MODE_DEV_CTRL) )
|
||
|
|
{
|
||
|
|
/* Invalid Device mode */
|
||
|
|
lRet = CIFX_DEV_SYNC_STATE_INVALID_MODE;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
uint8_t bState = HIL_FLAGS_NOT_EQUAL;
|
||
|
|
|
||
|
|
if( HIL_SYNC_MODE_HST_CTRL == HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bSyncHskMode))
|
||
|
|
bState = HIL_FLAGS_EQUAL;
|
||
|
|
|
||
|
|
/* Wait for sync */
|
||
|
|
if(!DEV_WaitForSyncState(ptChannel, bState, ulTimeout))
|
||
|
|
{
|
||
|
|
/* Sync timeout */
|
||
|
|
lRet = CIFX_DEV_SYNC_STATE_TIMEOUT;
|
||
|
|
} else
|
||
|
|
{
|
||
|
|
/* Return actual error counter */
|
||
|
|
*pulErrorCount = HWIF_READ8(ptChannel->pvDeviceInstance, ptChannel->ptCommonStatusBlock->bErrorSyncCnt);
|
||
|
|
|
||
|
|
/* Check if the device is communication */
|
||
|
|
(void)DEV_IsCommunicating(ptChannel, &lRet);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
lRet = CIFX_INVALID_COMMAND;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return lRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*! \} */
|
||
|
|
/*****************************************************************************/
|