/************************************************************************************** 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; } /*****************************************************************************/ /*! \} */ /*****************************************************************************/