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)
for (j = 0; j < ARRAY_SIZE(b->fdc); j++) {
if (b->fdc[j] >= 0)
close(b->fdc[j]);
if (b->fda[j] != NULL)
fclose(b->fda[j]);
}
free(b->sysbase);
......@@ -219,6 +221,7 @@ float fdelay_read_temperature(struct fdelay_board *userb)
static const char *fdelay_error_string[] = {
[FDELAY_ERR_VERSION_MISMATCH - __FDELAY_ERR_MIN] =
"Incompatible version driver-library",
[FDELAY_ERR_CONFIG - __FDELAY_ERR_MIN] = "Failed to configure delay engine",
};
/**
......
......@@ -18,6 +18,7 @@ extern "C" {
#define __FDELAY_ERR_MIN 4096
enum fmctdc_error_numbers {
FDELAY_ERR_VERSION_MISMATCH = __FDELAY_ERR_MIN,
FDELAY_ERR_CONFIG,
__FDELAY_ERR_MAX,
};
......@@ -139,6 +140,7 @@ struct __fdelay_board {
char *devbase;
char *sysbase;
int fdc[5]; /* The 5 control channels */
FILE *fda[5]; /* The 5 channels' alarms */
};
static inline int fdelay_is_verbose(void)
......
......@@ -70,6 +70,50 @@ static int __fdelay_get_ch_fd(struct __fdelay_board *b,
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
* @param[in] userb device token
......@@ -83,7 +127,9 @@ int fdelay_config_pulse(struct fdelay_board *userb,
__define_board(b, userb);
struct zio_control ctrl = {0,};
uint32_t *a;
uint8_t zio_alarms = 0, drv_alarms = 0;
int fdc;
int err;
if (__fdelay_get_ch_fd(b, channel, &fdc) < 0)
return -1; /* errno already set */
......@@ -126,6 +172,21 @@ int fdelay_config_pulse(struct fdelay_board *userb,
ctrl.nbits = 32;
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;
}
......
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