Skip to content
Snippets Groups Projects
Commit d67486b7 authored by Patrick Robbe's avatar Patrick Robbe
Browse files

Add ECS library

parent 3ee4b4c9
No related branches found
No related tags found
No related merge requests found
HERE :=$(strip $(realpath $(dir $(lastword $(MAKEFILE_LIST)))))
TOP :=$(realpath $(HERE)/..)
include $(TOP)/common/flags.mk
LIBPCIE40_ECS.A :=libpcie40_ecs.a
LIBPCIE40_ECS.A_OBJS =pcie40.o ecs.o
LIBPCIE40_ECS.A_CFLAGS =$(CFLAGS) -I$(TOP)/common -I$(TOP)/pcie40_driver
LIBPCIE40_ECS.A_ARFLAGS =rcs
LIBPCIE40_ECS.A_INSTALL =$(PREFIX)/lib$(LIBDIR_SUFFIX)
LIBPCIE40_ECS.SO :=libpcie40_ecs.so
LIBPCIE40_ECS.SO_OBJS =$(LIBPCIE40_ECS.A_OBJS:.o=.pic.o)
LIBPCIE40_ECS.SO_CFLAGS =$(LIBPCIE40_ECS.A_CFLAGS)
LIBPCIE40_ECS.SO_LDFLAGS =-shared
LIBPCIE40_ECS.SO_INSTALL =$(LIBPCIE40_ECS.A_INSTALL)
LIBPCIE40_ECS_HDRS :=ecs.h
LIBPCIE40_ECS_HDRS_INSTALL =$(PREFIX)/include/lhcb/pcie40
PCIE40_ECS :=pcie40_ecs
PCIE40_ECS_OBJS =main.o
PCIE40_ECS_CFLAGS =$(CFLAGS) -I$(TOP)/common -I$(TOP)/pcie40_driver
PCIE40_ECS_LIBS_S =libpcie40_ecs.a
PCIE40_ECS_INSTALL =$(PREFIX)/bin
PCIE40_ECS_MAN_DCRT =$(HERE)/man.dcrt
PCIE40_ECS_MAN_INSTALL =$(PREFIX)/share/man
VPATH :=$(TOP)/common
include $(TOP)/common/rules.mk
ifeq ($(ENABLE_PCIE40), true)
$(eval $(call ODIR_template,LIBPCIE40_ECS.A))
$(eval $(call ODIR_template,LIBPCIE40_ECS.SO))
$(eval $(call HDRS_template,LIBPCIE40_ECS,$(TOP)/pcie40_ecs))
$(eval $(call ODIR_template,PCIE40_ECS))
$(eval $(call MAN_template,PCIE40_ECS,1))
endif
$(eval $(call DEFAULT_template))
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/ioctl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "ecs.h"
#include "pcie40.h"
#include "pcie40_ioctl.h"
//`p40_ecs_open`
int p40_ecs_open(int dev, int bar, uint32_t **regs)
{
int fd;
char devname[32];
char *suffix;
switch (bar) {
case 0:
suffix = "bar0";
break;
case 2:
suffix = "bar2";
break;
default:
return -EINVAL;
}
if (p40_get_devname(dev, suffix, devname, sizeof(devname)) < 0) {
perror("p40_get_devname()");
return -1;
}
if ((fd = open(devname, O_RDWR)) == -1){
perror("open()");
return -1;
}
int bar_size = p40_ecs_bar_size(fd);
if (bar_size < 0) {
close(fd);
return -1;
}
*regs = mmap(NULL, bar_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (*regs == NULL) {
perror("mmap()");
close(fd);
return -1;
}
return fd;
}
//`p40_ecs_close`
void p40_ecs_close(int fd, uint32_t *regs)
{
int bar_size = p40_ecs_bar_size(fd);
munmap(regs, bar_size);
close(fd);
}
//`p40_ecs_bar_size`
int p40_ecs_bar_size(int fd)
{
int ret;
//? See ioctl.pcie`P40_ECS_GET_BAR_SIZE` .
ret = ioctl(fd, P40_ECS_GET_BAR_SIZE);
if (ret < 0) {
perror("ioctl(P40_ECS_GET_BAR_SIZE)");
return -1;
}
return ret;
}
//`p40_ecs_w32`
void p40_ecs_w32(uint32_t volatile *regs, uint32_t addr, uint32_t val)
{
regs[addr >> 2] = val;
}
//`p40_ecs_r32`
uint32_t p40_ecs_r32(uint32_t volatile *regs, uint32_t addr)
{
return regs[addr >> 2];
}
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ecs.h"
static int flag_devnum = 0;
static int flag_barnum = -1;
static int flag_address = 0;
static uint32_t flag_addroff;
static int flag_write = 0;
static uint32_t flag_writeval;
static int flag_read = 0;
//ug`pcie40_ecs.synopsis`
// *pcie40_ecs* [-i _interface_] -b _bar_ -a _address_ -w _value_ _
// *pcie40_ecs* [-i _interface_] -b _bar_ -a _address_ -r
static void usage()
{
fprintf(stderr, "usage: pcie40_ecs [options]\n");
fprintf(stderr, " -h Print this message\n");
fprintf(stderr, " -i {} Interface number (default: 0)\n");
fprintf(stderr, " -b {} BAR number\n");
fprintf(stderr, " -a {} Register address\n");
fprintf(stderr, " -w {} Write value to register\n");
fprintf(stderr, " -r Read register\n");
}
//ug`pcie40_ecs.description`
// Reads and writes PCIe40 BAR0 and BAR2 registers over PCI Express.
int main(int argc, char *argv[])
{
while (argc > 1 && argv[1][0] == '-') {
switch (argv[1][1]) {
//ug`pcie40_ecs.options`interface
// *-i* _interface_::
// Bind to PCIe40 interface number _interface_. This is optional and by default the tool will bind to the first interface available (typically 0).
case 'i':
++argv;
--argc;
flag_devnum = atoi(argv[1]);
break;
//ug`pcie40_ecs.options`bar
// *-b* _bar_::
// Access BAR number _bar_. Two PCI BARs are available:
// * 0 for user code (includes registers for DAQ, TFC, SCA...)
// * 2 for the common low-level interface
case 'b':
++argv;
--argc;
flag_barnum = atoi(argv[1]);
break;
//ug`pcie40_ecs.options`address
// *-a* _address_::
// Address to use for BAR access. Can be in decimal, hexadecimal or any other format supported by *strtol(3)*.
case 'a':
++argv;
--argc;
flag_address = 1;
flag_addroff = strtol(argv[1], NULL, 0);
break;
//ug`pcie40_ecs.options`write
// *-w* _value_::
// Write 32-bit _value_ to register at the given address. Same input format considerations apply as for the *-a* option.
case 'w':
++argv;
--argc;
flag_write = 1;
flag_writeval = strtoul(argv[1], NULL, 0);
break;
//ug`pcie40_ecs.options`read
// *-r*::
// Read value of register at given address. Value is printed to stdout in hexadecimal format.
case 'r':
flag_read = 1;
break;
//ug`pcie40_ecs.options`help
// *-h*::
// Output short program synopsis and exit.
default:
case 'h':
usage();
exit(1);
break;
}
--argc;
++argv;
}
//ug`pcie40_ecs.exit`
// -1 is returned in case of access error or wrong command line options, 0 otherwise.
if (!flag_address || flag_barnum < 0) {
usage();
exit(-1);
}
if (!flag_read && !flag_write) {
printf("-r and -w are mutually exclusive\n");
exit(-1);
}
uint32_t *regs;
int ecs = p40_ecs_open(flag_devnum, flag_barnum, &regs);
if (flag_write) {
p40_ecs_w32(regs, flag_addroff, flag_writeval);
} else if (flag_read) {
uint32_t reg = p40_ecs_r32(regs, flag_addroff);
printf("0x%08x", reg);
}
p40_ecs_close(ecs, regs);
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment