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