Commit 2e42ec69 authored by Alessandro Rubini's avatar Alessandro Rubini

lib: move config-related code to config-zio.c. No tech change

Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 85535509
......@@ -4,6 +4,7 @@ ZIO ?= ../zio
LIB = libfmcadc.a
LOBJ := route.o
LOBJ += boards.o
LOBJ += config-zio.o
LOBJ += lib.o
LOBJ += fmcadc-lib-zio.o
......
/*
* ZIO-specific configuration (mostly device-independent)
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "fmcadc-lib.h"
#include "fmcadc-lib-int.h"
#define FMCADC_CONF_GET 0
#define FMCADC_CONF_SET 1
/*
* __fa_zio_sysfs_get
* @path: path to the sysfs attribute
* @resp: value returned by the sysfs attribute
*/
static int __fa_zio_sysfs_get(char *path, uint32_t *resp)
{
FILE *f = fopen(path, "r");
if (!f)
return -1;
errno = 0;
if (fscanf(f, "%i", resp) != 1) {
fclose(f);
if (!errno)
errno = EINVAL;
return -1;
}
fclose(f);
return 0;
}
/*
* __fa_zio_sysfs_set
* @path: path to the sysfs attribute
* @value: value to set in the sysfs attribute
*/
static int __fa_zio_sysfs_set(char *path, uint32_t *value)
{
char s[16];
int fd, ret, len;
len = sprintf(s, "%i\n", *value);
fd = open(path, O_WRONLY);
if (fd < 0)
return -1;
ret = write(fd, s, len);
close(fd);
if (ret < 0)
return -1;
if (ret == len)
return 0;
errno = EINVAL;
return -1;
}
/*
* fa_zio_sysfs_get
* @fa: device owner of the attribute
* @name: relative path to the sysfs attribute within the device
* @resp: value returned by the sysfs attribute
*/
static int fa_zio_sysfs_get(struct __fmcadc_dev_zio *fa, char *name,
uint32_t *resp)
{
char pathname[128];
int ret;
sprintf(pathname, "%s/%s", fa->sysbase, name);
ret = __fa_zio_sysfs_get(pathname, resp);
if (!(fa->flags & FMCADC_FLAG_VERBOSE))
return ret;
/* verbose tail */
if (ret)
fprintf(stderr, "lib-fmcadc: Error reading %s\n", pathname);
else
fprintf(stderr, "lib-fmcadc: %08x %5i <- %s\n",
(int)*resp, (int)*resp, pathname);
return ret;
}
/*
* fa_zio_sysfs_set
* @fa: device owner of the attribute
* @name: relative path to the sysfs attribute within the device
* @value: value to set in the sysfs attribute
*/
int fa_zio_sysfs_set(struct __fmcadc_dev_zio *fa, char *name,
uint32_t *value)
{
char pathname[128];
int ret;
sprintf(pathname, "%s/%s", fa->sysbase, name);
ret = __fa_zio_sysfs_set(pathname, value);
if (!(fa->flags & FMCADC_FLAG_VERBOSE))
return ret;
/* verbose tail */
if (ret)
fprintf(stderr, "lib-fmcadc: Error writing %s\n", pathname);
else
fprintf(stderr, "lib-fmcadc: %08x %5i -> %s\n",
(int)*value, (int)*value, pathname);
return ret;
}
static int fmcadc_zio_config_trg(struct __fmcadc_dev_zio *fa,
unsigned int index, uint32_t *value, unsigned int direction)
{
switch (index) {
case FMCADC_CONF_TRG_SOURCE:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/external",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/external",
value);
break;
case FMCADC_CONF_TRG_SOURCE_CHAN:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/int-channel",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/int-channel",
value);
break;
case FMCADC_CONF_TRG_THRESHOLD:
if (direction)
return fa_zio_sysfs_set(fa,
"cset0/trigger/int-threshold", value);
else
return fa_zio_sysfs_get(fa,
"cset0/trigger/int-threshold", value);
break;
case FMCADC_CONF_TRG_POLARITY:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/polarity",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/polarity",
value);
break;
case FMCADC_CONF_TRG_DELAY:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/delay",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/delay",
value);
break;
default:
errno = FMCADC_ENOCAP;
return -1;
}
}
static int fmcadc_zio_config_acq(struct __fmcadc_dev_zio *fa,
unsigned int index, uint32_t *value, unsigned int direction)
{
switch (index) {
case FMCADC_CONF_ACQ_N_SHOTS:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/nshots",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/nshots",
value);
break;
case FMCADC_CONF_ACQ_POST_SAMP:
if (direction)
return fa_zio_sysfs_set(fa,
"cset0/trigger/post-samples", value);
else
return fa_zio_sysfs_get(fa,
"cset0/trigger/post-samples", value);
break;
case FMCADC_CONF_ACQ_PRE_SAMP:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/pre-samples",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/pre-samples",
value);
break;
case FMCADC_CONF_ACQ_DECIMATION:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/sample-decimation",
value);
else
return fa_zio_sysfs_get(fa, "cset0/sample-decimation",
value);
break;
case FMCADC_CONF_ACQ_FREQ_HZ:
if (direction) {
errno = FMCADC_ENOSET;
return -1;
} else {
*value = 100000000; /* 100Mhz */
return 0;
}
break;
case FMCADC_CONF_ACQ_N_BITS:
if (direction) {
errno = FMCADC_ENOSET;
return -1;
} else {
*value = 14;
return 0;
}
break;
default:
errno = FMCADC_ENOCAP;
return -1;
}
}
static int fmcadc_zio_config_chn(struct __fmcadc_dev_zio *fa, unsigned int ch,
unsigned int index, uint32_t *value, unsigned int direction)
{
char path[128];
switch (index) {
case FMCADC_CONF_CHN_RANGE:
sprintf(path, "cset%d/ch%d-vref", fa->cset, ch);
if (direction)
return fa_zio_sysfs_set(fa, path, value);
else
return fa_zio_sysfs_get(fa, path, value);
break;
case FMCADC_CONF_CHN_TERMINATION:
sprintf(path, "cset%d/ch%d-50ohm-term", fa->cset, ch);
if (direction)
return fa_zio_sysfs_set(fa, path, value);
else
return fa_zio_sysfs_get(fa, path, value);
break;
case FMCADC_CONF_CHN_OFFSET:
sprintf(path, "cset%d/ch%d-offset", fa->cset, ch);
if (direction)
return fa_zio_sysfs_set(fa, path, value);
else
return fa_zio_sysfs_get(fa, path, value);
break;
default:
errno = FMCADC_ENOCAP;
return -1;
}
return 0;
}
static int fmcadc_zio_config_brd(struct __fmcadc_dev_zio *fa,
unsigned int index, uint32_t *value, unsigned int direction)
{
switch (index) {
case FMCADC_CONF_BRD_STATE_MACHINE_STATUS:
if (!direction)
return fa_zio_sysfs_get(fa, "cset0/fsm-state",
value);
errno = EINVAL;
return -1;
case FMCADC_CONF_BRD_N_CHAN:
if (!direction) {
*value = 4;
return 0;
}
errno = EINVAL;
return -1;
default:
errno = FMCADC_ENOCAP;
return -1;
}
}
static int fmcadc_zio_config(struct __fmcadc_dev_zio *fa, unsigned int flags,
struct fmcadc_conf *conf, unsigned int direction)
{
int err, i;
for (i = 0; i < __FMCADC_CONF_LEN; ++i) {
if (!(conf->mask & (1LL << i)))
continue;
/* Parameter to configure */
switch (conf->type) {
case FMCADC_CONF_TYPE_TRG:
err = fmcadc_zio_config_trg(fa, i, &conf->value[i],
direction);
break;
case FMCADC_CONF_TYPE_ACQ:
err = fmcadc_zio_config_acq(fa, i, &conf->value[i],
direction);
break;
case FMCADC_CONF_TYPE_CHN:
if (conf->route_to > 3) {
errno = FMCADC_ENOCHAN;
return -1;
}
err = fmcadc_zio_config_chn(fa, conf->route_to,
i, &conf->value[i],
direction);
break;
case FMCADC_CONT_TYPE_BRD:
err = fmcadc_zio_config_brd(fa, i, &conf->value[i],
direction);
break;
default:
errno = FMCADC_ENOCFG;
return -1;
}
if (err)
return err;
}
return 0;
}
int fmcadc_zio_apply_config(struct fmcadc_dev *dev, unsigned int flags,
struct fmcadc_conf *conf)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
return fmcadc_zio_config(fa, flags, conf, FMCADC_CONF_SET);
}
int fmcadc_zio_retrieve_config(struct fmcadc_dev *dev,
struct fmcadc_conf *conf)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
return fmcadc_zio_config(fa, 0, conf, FMCADC_CONF_GET);
}
......@@ -5,6 +5,15 @@
#ifndef FMCADC_LIB_INT_H_
#define FMCADC_LIB_INT_H_
/*
* offsetof and container_of come from kernel.h header file
*/
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = ((void *)ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define to_dev_zio(dev) (container_of(dev, struct __fmcadc_dev_zio, gid))
/*
* fmcadc_op: it describes the set of operation that a device library should
* support
......@@ -106,6 +115,19 @@ struct fmcadc_gid {
/* Definition of board types */
extern struct fmcadc_board_type fmcadc_100ms_4ch_14bit;
/* Internal structure (ZIO specific, for ZIO drivers only) */
struct __fmcadc_dev_zio {
unsigned int cset;
int fdc;
int fdd;
uint32_t dev_id;
unsigned long flags;
char *devbase;
char *sysbase;
/* Mandatory field */
struct fmcadc_gid gid;
};
#define FMCADC_FLAG_VERBOSE 0x00000001
/* The following functions are defined in fmc-adc-zio, at the time being */
......@@ -118,10 +140,6 @@ int fmcadc_zio_start_acquisition(struct fmcadc_dev *dev,
unsigned int flags, struct timeval *timeout);
int fmcadc_zio_stop_acquisition(struct fmcadc_dev *dev,
unsigned int flags);
int fmcadc_zio_apply_config(struct fmcadc_dev *dev, unsigned int flags,
struct fmcadc_conf *conf);
int fmcadc_zio_retrieve_config(struct fmcadc_dev *dev,
struct fmcadc_conf *conf);
struct fmcadc_buffer *fmcadc_zio_request_buffer(struct fmcadc_dev *dev,
int nsamples,
void *(*alloc)(size_t),
......@@ -132,5 +150,12 @@ int fmcadc_zio_release_buffer(struct fmcadc_dev *dev,
void (*free_fn)(void *));
/* The following functions are in config-zio.c */
int fmcadc_zio_apply_config(struct fmcadc_dev *dev, unsigned int flags,
struct fmcadc_conf *conf);
int fmcadc_zio_retrieve_config(struct fmcadc_dev *dev,
struct fmcadc_conf *conf);
int fa_zio_sysfs_set(struct __fmcadc_dev_zio *fa, char *name,
uint32_t *value);
#endif /* FMCADC_LIB_INT_H_ */
......@@ -32,130 +32,6 @@
#define FMCADC_NCHAN 4
#define FMCADC_CONF_GET 0
#define FMCADC_CONF_SET 1
/* Internal structure (ZIO specific) */
struct __fmcadc_dev_zio {
unsigned int cset;
int fdc;
int fdd;
uint32_t dev_id;
unsigned long flags;
char *devbase;
char *sysbase;
/* Mandatory field */
struct fmcadc_gid gid;
};
#define FMCADC_FLAG_VERBOSE 0x00000001
/*
* offsetof and container_of come from kernel.h header file
*/
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = ((void *)ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define to_dev_zio(dev) (container_of(dev, struct __fmcadc_dev_zio, gid))
/* * * * * * * * * * * * * * * * ZIO specific function * * * * * * * * * * * */
/*
* __fa_zio_sysfs_get
* @path: path to the sysfs attribute
* @resp: value returned by the sysfs attribute
*/
static int __fa_zio_sysfs_get(char *path, uint32_t *resp)
{
FILE *f = fopen(path, "r");
if (!f)
return -1;
errno = 0;
if (fscanf(f, "%i", resp) != 1) {
fclose(f);
if (!errno)
errno = EINVAL;
return -1;
}
fclose(f);
return 0;
}
/*
* __fa_zio_sysfs_set
* @path: path to the sysfs attribute
* @value: value to set in the sysfs attribute
*/
static int __fa_zio_sysfs_set(char *path, uint32_t *value)
{
char s[16];
int fd, ret, len;
len = sprintf(s, "%i\n", *value);
fd = open(path, O_WRONLY);
if (fd < 0)
return -1;
ret = write(fd, s, len);
close(fd);
if (ret < 0)
return -1;
if (ret == len)
return 0;
errno = EINVAL;
return -1;
}
/*
* fa_zio_sysfs_get
* @fa: device owner of the attribute
* @name: relative path to the sysfs attribute within the device
* @resp: value returned by the sysfs attribute
*/
static int fa_zio_sysfs_get(struct __fmcadc_dev_zio *fa, char *name,
uint32_t *resp)
{
char pathname[128];
int ret;
sprintf(pathname, "%s/%s", fa->sysbase, name);
ret = __fa_zio_sysfs_get(pathname, resp);
if (!(fa->flags & FMCADC_FLAG_VERBOSE))
return ret;
/* verbose tail */
if (ret)
fprintf(stderr, "lib-fmcadc: Error reading %s\n", pathname);
else
fprintf(stderr, "lib-fmcadc: %08x %5i <- %s\n",
(int)*resp, (int)*resp, pathname);
return ret;
}
/*
* fa_zio_sysfs_set
* @fa: device owner of the attribute
* @name: relative path to the sysfs attribute within the device
* @value: value to set in the sysfs attribute
*/
static int fa_zio_sysfs_set(struct __fmcadc_dev_zio *fa, char *name,
uint32_t *value)
{
char pathname[128];
int ret;
sprintf(pathname, "%s/%s", fa->sysbase, name);
ret = __fa_zio_sysfs_set(pathname, value);
if (!(fa->flags & FMCADC_FLAG_VERBOSE))
return ret;
/* verbose tail */
if (ret)
fprintf(stderr, "lib-fmcadc: Error writing %s\n", pathname);
else
fprintf(stderr, "lib-fmcadc: %08x %5i -> %s\n",
(int)*value, (int)*value, pathname);
return ret;
}
/* * * * * * * * * * Library Operations Implementation * * * * * * * * * * */
int fmcadc_zio_stop_acquisition(struct fmcadc_dev *dev,
unsigned int flags);
......@@ -301,232 +177,6 @@ int fmcadc_zio_stop_acquisition(struct fmcadc_dev *dev,
}
/* * * * * * * * * * * * * * * Handle configuration * * * * * * * * * * * * */
static int fmcadc_zio_config_trg(struct __fmcadc_dev_zio *fa,
unsigned int index, uint32_t *value, unsigned int direction)
{
switch (index) {
case FMCADC_CONF_TRG_SOURCE:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/external",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/external",
value);
break;
case FMCADC_CONF_TRG_SOURCE_CHAN:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/int-channel",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/int-channel",
value);
break;
case FMCADC_CONF_TRG_THRESHOLD:
if (direction)
return fa_zio_sysfs_set(fa,
"cset0/trigger/int-threshold", value);
else
return fa_zio_sysfs_get(fa,
"cset0/trigger/int-threshold", value);
break;
case FMCADC_CONF_TRG_POLARITY:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/polarity",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/polarity",
value);
break;
case FMCADC_CONF_TRG_DELAY:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/delay",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/delay",
value);
break;
default:
errno = FMCADC_ENOCAP;
return -1;
}
}
static int fmcadc_zio_config_acq(struct __fmcadc_dev_zio *fa,
unsigned int index, uint32_t *value, unsigned int direction)
{
switch (index) {
case FMCADC_CONF_ACQ_N_SHOTS:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/nshots",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/nshots",
value);
break;
case FMCADC_CONF_ACQ_POST_SAMP:
if (direction)
return fa_zio_sysfs_set(fa,
"cset0/trigger/post-samples", value);
else
return fa_zio_sysfs_get(fa,
"cset0/trigger/post-samples", value);
break;
case FMCADC_CONF_ACQ_PRE_SAMP:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/trigger/pre-samples",
value);
else
return fa_zio_sysfs_get(fa, "cset0/trigger/pre-samples",
value);
break;
case FMCADC_CONF_ACQ_DECIMATION:
if (direction)
return fa_zio_sysfs_set(fa, "cset0/sample-decimation",
value);
else
return fa_zio_sysfs_get(fa, "cset0/sample-decimation",
value);
break;
case FMCADC_CONF_ACQ_FREQ_HZ:
if (direction) {
errno = FMCADC_ENOSET;
return -1;
} else {
*value = 100000000; /* 100Mhz */
return 0;
}
break;
case FMCADC_CONF_ACQ_N_BITS:
if (direction) {
errno = FMCADC_ENOSET;
return -1;
} else {
*value = 14;
return 0;
}
break;
default:
errno = FMCADC_ENOCAP;
return -1;
}
}
static int fmcadc_zio_config_chn(struct __fmcadc_dev_zio *fa, unsigned int ch,
unsigned int index, uint32_t *value, unsigned int direction)
{
char path[128];
switch (index) {
case FMCADC_CONF_CHN_RANGE:
sprintf(path, "cset%d/ch%d-vref", fa->cset, ch);
if (direction)
return fa_zio_sysfs_set(fa, path, value);
else
return fa_zio_sysfs_get(fa, path, value);
break;
case FMCADC_CONF_CHN_TERMINATION:
sprintf(path, "cset%d/ch%d-50ohm-term", fa->cset, ch);
if (direction)
return fa_zio_sysfs_set(fa, path, value);
else
return fa_zio_sysfs_get(fa, path, value);
break;
case FMCADC_CONF_CHN_OFFSET:
sprintf(path, "cset%d/ch%d-offset", fa->cset, ch);
if (direction)
return fa_zio_sysfs_set(fa, path, value);
else
return fa_zio_sysfs_get(fa, path, value);
break;
default:
errno = FMCADC_ENOCAP;
return -1;
}
return 0;
}
static int fmcadc_zio_config_brd(struct __fmcadc_dev_zio *fa,
unsigned int index, uint32_t *value, unsigned int direction)
{
switch (index) {
case FMCADC_CONF_BRD_STATE_MACHINE_STATUS:
if (!direction)
return fa_zio_sysfs_get(fa, "cset0/fsm-state",
value);
errno = EINVAL;
return -1;
case FMCADC_CONF_BRD_N_CHAN:
if (!direction) {
*value = 4;
return 0;
}
errno = EINVAL;
return -1;
default:
errno = FMCADC_ENOCAP;
return -1;
}
}
static int fmcadc_zio_config(struct __fmcadc_dev_zio *fa, unsigned int flags,
struct fmcadc_conf *conf, unsigned int direction)
{
int err, i;
for (i = 0; i < __FMCADC_CONF_LEN; ++i) {
if (!(conf->mask & (1LL << i)))
continue;
/* Parameter to configure */
switch (conf->type) {
case FMCADC_CONF_TYPE_TRG:
err = fmcadc_zio_config_trg(fa, i, &conf->value[i],
direction);
break;
case FMCADC_CONF_TYPE_ACQ:
err = fmcadc_zio_config_acq(fa, i, &conf->value[i],
direction);
break;
case FMCADC_CONF_TYPE_CHN:
if (conf->route_to > 3) {
errno = FMCADC_ENOCHAN;
return -1;
}
err = fmcadc_zio_config_chn(fa, conf->route_to,
i, &conf->value[i],
direction);
break;
case FMCADC_CONT_TYPE_BRD:
err = fmcadc_zio_config_brd(fa, i, &conf->value[i],
direction);
break;
default:
errno = FMCADC_ENOCFG;
return -1;
}
if (err)
return err;
}
return 0;
}
int fmcadc_zio_apply_config(struct fmcadc_dev *dev, unsigned int flags,
struct fmcadc_conf *conf)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
return fmcadc_zio_config(fa, flags, conf, FMCADC_CONF_SET);
}
int fmcadc_zio_retrieve_config(struct fmcadc_dev *dev,
struct fmcadc_conf *conf)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
return fmcadc_zio_config(fa, 0, conf, FMCADC_CONF_GET);
}
/* * * * * * * * * * * * * * * * * Handle buffer * * * * * * * * * * * * * * */
static struct zio_control *fmcadc_zio_read_ctrl(struct __fmcadc_dev_zio *fa)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment