Commit d1165f23 authored by Federico Vaga's avatar Federico Vaga

lib: report alarms on configuration

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 1938dde0
...@@ -162,6 +162,8 @@ int fdelay_close(struct fdelay_board *userb) ...@@ -162,6 +162,8 @@ int fdelay_close(struct fdelay_board *userb)
for (j = 0; j < ARRAY_SIZE(b->fdc); j++) { for (j = 0; j < ARRAY_SIZE(b->fdc); j++) {
if (b->fdc[j] >= 0) if (b->fdc[j] >= 0)
close(b->fdc[j]); close(b->fdc[j]);
if (b->fda[j] != NULL)
fclose(b->fda[j]);
} }
free(b->sysbase); free(b->sysbase);
...@@ -219,6 +221,7 @@ float fdelay_read_temperature(struct fdelay_board *userb) ...@@ -219,6 +221,7 @@ float fdelay_read_temperature(struct fdelay_board *userb)
static const char *fdelay_error_string[] = { static const char *fdelay_error_string[] = {
[FDELAY_ERR_VERSION_MISMATCH - __FDELAY_ERR_MIN] = [FDELAY_ERR_VERSION_MISMATCH - __FDELAY_ERR_MIN] =
"Incompatible version driver-library", "Incompatible version driver-library",
[FDELAY_ERR_CONFIG - __FDELAY_ERR_MIN] = "Failed to configure delay engine",
}; };
/** /**
......
...@@ -18,6 +18,7 @@ extern "C" { ...@@ -18,6 +18,7 @@ extern "C" {
#define __FDELAY_ERR_MIN 4096 #define __FDELAY_ERR_MIN 4096
enum fmctdc_error_numbers { enum fmctdc_error_numbers {
FDELAY_ERR_VERSION_MISMATCH = __FDELAY_ERR_MIN, FDELAY_ERR_VERSION_MISMATCH = __FDELAY_ERR_MIN,
FDELAY_ERR_CONFIG,
__FDELAY_ERR_MAX, __FDELAY_ERR_MAX,
}; };
...@@ -139,6 +140,7 @@ struct __fdelay_board { ...@@ -139,6 +140,7 @@ struct __fdelay_board {
char *devbase; char *devbase;
char *sysbase; char *sysbase;
int fdc[5]; /* The 5 control channels */ int fdc[5]; /* The 5 control channels */
FILE *fda[5]; /* The 5 channels' alarms */
}; };
static inline int fdelay_is_verbose(void) static inline int fdelay_is_verbose(void)
......
...@@ -70,6 +70,50 @@ static int __fdelay_get_ch_fd(struct __fdelay_board *b, ...@@ -70,6 +70,50 @@ static int __fdelay_get_ch_fd(struct __fdelay_board *b,
return 0; return 0;
} }
/**
* Get pending FMC Fine Delay channel alarms.
*
* Getting the alarm will also clear them.
*
* @param[in] userb device token
* @param[in] channel channel number in range [0, 3] ([1,4] on the front-panel)
* @param[out] zio_alarms the current zio alarms
* @param[out] drv_alarms the current drv alarms
* @return 0 when no alarms, otherwise -1 and errno is appropriately set
*/
static int fdelay_alarm_get(struct fdelay_board *userb, int channel,
uint8_t *zio_alarms, uint8_t *drv_alarms)
{
__define_board(b, userb);
int ch14 = channel + 1;
int ret;
if (channel < 0 || channel > 3) {
errno = EINVAL;
return -1;
}
if (b->fda[ch14] <= 0) {
char fname[128];
snprintf(fname, sizeof(fname),
"%s/fd-ch%i/chan0/alarms", b->sysbase, ch14);
b->fda[ch14] = fopen(fname, "r+");
if (b->fda[ch14] == NULL)
return -1;
}
rewind(b->fda[ch14]);
ret = fscanf(b->fda[ch14], "%"SCNu8" %"SCNu8, zio_alarms, drv_alarms);
if (ret != 2) {
errno = EINVAL;
return -1;
}
rewind(b->fda[ch14]);
fprintf(b->fda[ch14], "%"PRIu8" %"PRIu8, *zio_alarms, *drv_alarms);
return 0;
}
/** /**
* Configure an FMC Fine Delay channel to produce a pulse * Configure an FMC Fine Delay channel to produce a pulse
* @param[in] userb device token * @param[in] userb device token
...@@ -83,7 +127,9 @@ int fdelay_config_pulse(struct fdelay_board *userb, ...@@ -83,7 +127,9 @@ int fdelay_config_pulse(struct fdelay_board *userb,
__define_board(b, userb); __define_board(b, userb);
struct zio_control ctrl = {0,}; struct zio_control ctrl = {0,};
uint32_t *a; uint32_t *a;
uint8_t zio_alarms = 0, drv_alarms = 0;
int fdc; int fdc;
int err;
if (__fdelay_get_ch_fd(b, channel, &fdc) < 0) if (__fdelay_get_ch_fd(b, channel, &fdc) < 0)
return -1; /* errno already set */ return -1; /* errno already set */
...@@ -126,6 +172,21 @@ int fdelay_config_pulse(struct fdelay_board *userb, ...@@ -126,6 +172,21 @@ int fdelay_config_pulse(struct fdelay_board *userb,
ctrl.nbits = 32; ctrl.nbits = 32;
write(fdc, &ctrl, sizeof(ctrl)); write(fdc, &ctrl, sizeof(ctrl));
/* The fdelay driver uses the zio trigger user. This implies that all writes
* are not queued but sent immediatly to the ZIO IO function. At that point
* an alarm could be raised. It should be save to read it immediatly.
*
* A more bullet proof solution would need a ZIO upgrade, involving a
* polling mechanism.
*/
err = fdelay_alarm_get(userb, channel, &zio_alarms, &drv_alarms);
if (err)
return err;
if (zio_alarms || drv_alarms) {
errno = FDELAY_ERR_CONFIG;
return -1;
}
return 0; return 0;
} }
......
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