From e2d3b1ca41000ca7fe44daaafbb35dbf0adf394f Mon Sep 17 00:00:00 2001 From: ROBBE Patrick <robbe@lal.in2p3.fr> Date: Sun, 27 Jan 2019 16:10:02 +0100 Subject: [PATCH] Add ECS file --- Lib/src/ecs/ecs.c | 351 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 351 insertions(+) create mode 100644 Lib/src/ecs/ecs.c diff --git a/Lib/src/ecs/ecs.c b/Lib/src/ecs/ecs.c new file mode 100644 index 0000000..3280865 --- /dev/null +++ b/Lib/src/ecs/ecs.c @@ -0,0 +1,351 @@ +/****************************************************************************************//** +* \file ecs.c +* +* \brief This file contains the user library to access PCI driver. +* +* \author JM : 02/11/2013 +* \version 1.0 +* \date 08/11/2013 + +* \copyright (c) Copyright CERN for the benefit of the LHCb Collaboration. +* Distributed under the terms of the GNU General Public Licence V3. +* ana.py script is free and open source software. + + CHANGELOG + JM : 02/11/2013 Initial version + JM/PYD : 04/11/2013 PYD code integration + PYD : adapt for Paolo driver with its library and add multiple board choice +*/ +/************************************************************************************************** +The *Bar*() type of functions concentrate the conditional code which depends of the driver type. + +The ecs_*Lli() or ecs_*User() type of functions are driver blind and used to match user registers +or lli registers. + +ecs_openUser() ecs_openLli() +ecs_iordUser() ecs_iordLli() +ecs_iowrUser() ecs_iowrLli() +ecs_iordBlocUser() ecs_iordBlocLli() +ecs_iowrBlocUser() ecs_iowrBlocLli() +ecs_closeUser() ecs_closeLli() +************************************************************************************************/ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <linux/ioctl.h> +#include <sys/ioctl.h> + +#include <ecs.h> +#include <systemConfig.h> + +// rpm includes +// PYD 20/03/2018 force the use of rpm for all borads types +#include <lhcb/pcie40/ecs.h> + +/** + * \var ecs_userFile + * \brief ecs_open function return a file description which is stored on userFile for bar 0. +*/ +static int ecs_userFile[MAX_DEV]; + +/** + * \var ecs_lliFile + * \brief ecs_open function return a file description which is stored on lliFile for bar 2. +*/ +static int ecs_lliFile[MAX_DEV]; +/** + * \var ecs_bar2_mm + * \brief ecs_open function for bar 2 mmaps registers area from a start address. +*/ +static unsigned *ecs_bar1_mm[MAX_DEV]; // bar1 start add of mmap +static unsigned *ecs_bar2_mm[MAX_DEV]; // bar2 start add of mmap + +/******************************************************//** + * \fn int ecs_close(int dev, int bar) + * \brief Function to close bar file + * + * \param dev: the selected board number + * \param bar: the bar number + *//******************************************************/ +void ecs_close(int dev, int bar){ + if (bar==2){ + p40_ecs_close(ecs_lliFile[dev],ecs_bar2_mm[dev]); + } + else if (bar==0){ + p40_ecs_close(ecs_lliFile[dev],ecs_bar1_mm[dev]); + } +} + +/******************************************************//** + * \fn int ecs_open(int dev, int bar) + * \brief Function to open bar file + * + * \param dev: the selected board number + * \param bar: number of bar + * \return -1 error / file descriptor + *//******************************************************/ +int ecs_open(int dev,int bar){ + if (bar==2){ + ecs_lliFile[dev] = p40_ecs_open(dev,bar,&(ecs_bar2_mm[dev])); + return ecs_lliFile[dev]; + } + else if (bar==0){ + ecs_userFile[dev] = p40_ecs_open(dev,bar,&(ecs_bar1_mm[dev])); + return ecs_userFile[dev]; + } +return -1; +} + +int ecs_write(int dev, int bar, unsigned add, int val){ + if (add%4 != 0) + return(-1); + + if (bar==2){ + p40_ecs_w32(ecs_bar2_mm[dev],add,val); + } + else if (bar==0){ + p40_ecs_w32(ecs_bar1_mm[dev],add,val); + } + return(0); +} + +unsigned ecs_read(int dev, int bar, unsigned add){ + uint32_t val; + if (add%4 != 0) + return(-1); + if (bar==2){ + val = p40_ecs_r32(ecs_bar2_mm[dev],add); + } + else if (bar==0){ + val = p40_ecs_r32(ecs_bar1_mm[dev],add); + } + return val; +} + +int ecs_iowrBar(int dev, int bar, unsigned add, unsigned *val){ + if (add%4 != 0) + return(-1); + if (bar==2){ + if (ecs_lliFile[dev] == 0) ecs_open(dev,bar); + } + else if (bar==0){ + if (ecs_userFile[dev] == 0) ecs_open(dev,bar); + } + ecs_write(dev,bar,add,*val); + return(0); +} + +int ecs_iordBar(int dev, int bar, unsigned add, unsigned *val){ + if (add%4 != 0) + return(-1); + if (bar==2){ + if (ecs_lliFile[dev] == 0) ecs_open(dev,bar); + } + else if (bar==0){ + if (ecs_userFile[dev] == 0) ecs_open(dev,bar); + } + *val = ecs_read(dev,bar,add); + return(0); +} +int ecs_writeBloc(int dev, int bar, unsigned add, int size, unsigned *val){ + int i; + unsigned wd; + if (add%sizeof(unsigned) != 0) + return(-1); + for (i=0; i<size; i = i + 1){ + wd = val[i]; + ecs_write(dev,bar, add+i*sizeof(unsigned), wd); + } + return 0; +} + +int ecs_readBloc(int dev, int bar, unsigned add, int size, unsigned *val){ + int i; + if (add%4 != 0) + return(-1); + for (i=0; i<size; i = i + 1){ + val[i] = ecs_read(dev,bar,add+i*sizeof(unsigned)); + } + return 0; +} +int ecs_iowrBarBloc(int dev, int bar, unsigned add, int size, unsigned *val){ + ecs_writeBloc(dev,bar,add,size,val); +return 0; +} + +int ecs_iordBarBloc(int dev, int bar, unsigned add, int size, unsigned *val){ + ecs_readBloc(dev,bar,add,size,val); +return 0; +} + +/***********************************************************************//** + * \fn int ecs_printSetup() + * \brief Function to print BAR configurations for checking + * + *//***********************************************************************/ +void ecs_printSetup(){ + printf("-------------------------------------------------\n"); + printf("driver type = MMAP (PCIe40 daq) version\n"); + printf("-------------------------------------------------\n"); + printf("BAR user = BAR%d\n",BAR_USER); + printf("BAR i2c = BAR%d\n",BAR_I2C); + + printf("BASE i2c bus %d TEMPERATURES = 0x%08x\n", I2C_BUS_TEMPERATURES, I2C_BUS_BASE_TEMPERATURES); + printf("BASE i2c bus %d CLEANER1 = 0x%08x\n", I2C_BUS_PLL_CLEANER1, I2C_BUS_BASE_PLL_CLEANER1); + printf("BASE i2c bus %d CLEANER2 = 0x%08x\n", I2C_BUS_PLL_CLEANER2, I2C_BUS_BASE_PLL_CLEANER2); + printf("BASE i2c bus %d PLL_TFC = 0x%08x\n", I2C_BUS_PLL_TFC, I2C_BUS_BASE_PLL_TFC); + printf("BASE i2c bus %d SFP1 = 0x%08x\n", I2C_BUS_SFP1, I2C_BUS_BASE_SFP1); + printf("BASE i2c bus %d SFP2 = 0x%08x\n", I2C_BUS_SFP2, I2C_BUS_BASE_SFP2); + printf("BASE i2c bus %d MINIPODS = 0x%08x\n", I2C_BUS_MINIPODS, I2C_BUS_BASE_MINIPODS); + printf("BASE i2c bus %d TEMP_MEZZANINE = 0x%08x\n", I2C_BUS_TEMP_MEZZANINE, I2C_BUS_BASE_TEMP_MEZZANINE); + printf("BASE i2c bus %d CURRENT1 = 0x%08x\n", I2C_BUS_CURRENT1, I2C_BUS_BASE_CURRENT1); + printf("BASE i2c bus %d CURRENT2 = 0x%08x\n", I2C_BUS_CURRENT2, I2C_BUS_BASE_CURRENT2); +} + +// Usefull for python wrappers when memory is allocated by the lli C libs +// it should be freed after python module has used it. +void ecs_free( int *data) { + free(data); +} +/***********************************************************************//** + * \fn int ecs_openUser(int dev) + * \brief Function to init the ecs pcie bus accesses for user space + * Thus function has to be done before any access. + * + * Here we have a detailed description of the function + * + * \param : dev the board number + * \return 0 success, -1 error + *//***********************************************************************/ +int ecs_openUser(int dev){ + return ecs_open(dev,0); +} + +/***********************************************************************//** + * \fn int ecs_closeUser(int dev) + * \brief Function to disconnect from the ecs user space. + * A new ecs_open() should be done before any new read or write + * + * \param : dev the board number + *//***********************************************************************/ +void ecs_closeUser(int dev){ + ecs_close(dev,0); +} + +/***********************************************************************//** + * \fn int ecs_openLli(int dev) + * \brief Function to init the ecs pcie bus accesses for LLI devices + * Thus function has to be done before any access. + * + * \param : dev the board number + * \return 0 success, -1 error + *//***********************************************************************/ +int ecs_openLli(int dev){ + return ecs_open(dev,2); +} + +/***********************************************************************//** + * \fn int ecs_closeLli(int dev) + * \brief Function to disconnect from the LLI devices io. + * A new ecs_openLli() should be done before any new read or write + * + * \param : dev the board number + *//***********************************************************************/ +void ecs_closeLli(int dev){ + ecs_close(dev,2); +} + +/***********************************************************************//** + * \fn int ecs_iordLli(int dev, unsigned add, unsigned *val) + * \brief Function to read a word at offset add in the lli registers space. + * + * \param : dev the board number + * \param add the offset of the word to read in the lli register space + * \param val a pointer to receive the read value in case of success + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iordLli(int dev, unsigned add, unsigned *val){ + return ecs_iordBar(dev, 2, add, val); +} + +/***********************************************************************//** + * \fn int ecs_iowrLli(int dev, unsigned add, unsigned *val) + * \brief Function to write a word at offset add in the Lli registers space. + * + * \param : dev the board number + * \param add the offset of the word to write in the Lli registers space + * \param val a pointer to the value to write + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iowrLli(int dev, unsigned add, unsigned *val){ + return ecs_iowrBar(dev, 2, add, val); +} + +/***********************************************************************//** + * \fn int ecs_iordBlocLli(unsigned add, int size, unsigned *val) + * \brief Function to read size words at offset add in the lli registers space. + * + * \param : dev the board number + * \param add : the offset of the word to read in the lli register space + * \param size : number of bytes to read + * \param val : a pointer to receive the read value in case of success + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iordBlocLli(int dev, unsigned add, int size, unsigned *val){ + return ecs_iordBarBloc(dev, 2, add, size, val); +} + +/***********************************************************************//** + * \fn int ecs_iowrBlocLli(unsigned add, int size, unsigned *val) + * \brief Function to write size words at offset add in the Lli registers space. + * + * \param : dev the board number + * \param add : the offset of the word to write in the Lli registers space + * \param size : number of bytes to write + * \param val : a pointer to the value to write + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iowrBlocLli(int dev, unsigned add, int size, unsigned *val){ + return ecs_iowrBarBloc(dev, 2, add, size, val); +} + +/***********************************************************************//** + * \fn int ecs_iordI2c(int dev, unsigned add, unsigned *val) + * \brief Function to read a word at offset add in the I2C core registers space. + * + * \param : dev the board number + * \param add the offset of the word to read in the I2C core register space + * \param val a pointer to receive the read value in case of success + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iordI2c(int dev, unsigned add, unsigned *val){ + return ecs_iordLli(dev, add, val); +} +int ecs_iordI2c_slow(int dev, unsigned add, unsigned *val){ + int dat = ecs_iordLli(dev, add, val); + usleep(0); + return dat; +} +/***********************************************************************//** + * \fn int ecs_iowrI2c(unsigned add, unsigned *val) + * \brief Function to write a word at offset add in the I2C core registers space. + * + * \param : dev the board number + * \param add the offset of the word to write in the I2C core registers space + * \param val a pointer to the value to write + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iowrI2c(int dev, unsigned add, unsigned *val){ + return ecs_iowrLli(dev, add, val); +} +int ecs_iowrI2c_slow(int dev, unsigned add, unsigned *val){ + int dat = ecs_iowrLli(dev, add, val); + usleep(0); + return dat; +} -- GitLab