Module: xenomai-3 Branch: next Commit: add4ebedafb2ede14a4bd7ad61b1cfc72d5fc630 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=add4ebedafb2ede14a4bd7ad61b1cfc72d5fc630
Author: Jorge Ramirez-Ortiz <j...@xenomai.org> Date: Tue Aug 26 13:45:23 2014 -0400 drivers/analogy: NI M - cmd test update (from comedi) In order to mimic the comedi behaviour, the simulation comand shall update command fields specifics to the driver. To that end, the a4l_cmd_t structure defines a driver specific bitfield to indidate which states are allowed by the driver to not be reported as errors. --- include/rtdm/uapi/analogy.h | 33 +-- .../analogy/national_instruments/mio_common.c | 256 +++++++++++++------- 2 files changed, 190 insertions(+), 99 deletions(-) diff --git a/include/rtdm/uapi/analogy.h b/include/rtdm/uapi/analogy.h index 98c6154..458d5f7 100644 --- a/include/rtdm/uapi/analogy.h +++ b/include/rtdm/uapi/analogy.h @@ -236,7 +236,7 @@ typedef struct a4l_dev_info a4l_dvinfo_t; /** * Reference definition macro */ -#define AREF(a) (((a) & 0xf) << 24) +#define AREF(a) (((a) & 0x03) << 24) /** * Flags definition macro */ @@ -244,7 +244,7 @@ typedef struct a4l_dev_info a4l_dvinfo_t; /** * Channel + range + reference definition macro */ -#define PACK(a, b, c) (CHAN(a) | RNG(b) | AREF(c)) +#define PACK(a, b, c) (a | RNG(b) | AREF(c)) /** * Channel + range + reference + flags definition macro */ @@ -276,8 +276,8 @@ typedef struct a4l_dev_info a4l_dvinfo_t; #define CR_DITHER CR_ALT_FILTER #define CR_DEGLITCH CR_ALT_FILTER #define CR_ALT_SOURCE (1<<27) -#define CR_EDGE (1<<28) -#define CR_INVERT (1<<29) +#define CR_EDGE (1<<30) +#define CR_INVERT (1<<31) #endif /* !DOXYGEN_CPP */ @@ -288,43 +288,46 @@ typedef struct a4l_dev_info a4l_dvinfo_t; struct a4l_cmd_desc { unsigned char idx_subd; - /**< Subdevice to which the command will be applied. */ + /**< Subdevice to which the command will be applied. */ unsigned long flags; - /**< Command flags */ + /**< Command flags */ /* Command trigger characteristics */ unsigned int start_src; - /**< Start trigger type */ + /**< Start trigger type */ unsigned int start_arg; - /**< Start trigger argument */ + /**< Start trigger argument */ unsigned int scan_begin_src; - /**< Scan begin trigger type */ + /**< Scan begin trigger type */ unsigned int scan_begin_arg; - /**< Scan begin trigger argument */ + /**< Scan begin trigger argument */ unsigned int convert_src; - /**< Convert trigger type */ + /**< Convert trigger type */ unsigned int convert_arg; - /**< Convert trigger argument */ + /**< Convert trigger argument */ unsigned int scan_end_src; /**< Scan end trigger type */ unsigned int scan_end_arg; /**< Scan end trigger argument */ unsigned int stop_src; - /**< Stop trigger type */ + /**< Stop trigger type */ unsigned int stop_arg; /**< Stop trigger argument */ unsigned char nb_chan; /**< Count of channels related with the command */ unsigned int *chan_descs; - /**< Tab containing channels descriptors */ + /**< Tab containing channels descriptors */ /* Driver specific fields */ + unsigned int valid_simul_stages; + /** < cmd simulation valid stages (driver dependent) */ + unsigned int data_len; /**< Driver specific buffer size */ sampl_t *data; - /**< Driver specific buffer pointer */ + /**< Driver specific buffer pointer */ }; typedef struct a4l_cmd_desc a4l_cmd_t; diff --git a/kernel/drivers/analogy/national_instruments/mio_common.c b/kernel/drivers/analogy/national_instruments/mio_common.c index e5ccf7a..6c5bba0 100644 --- a/kernel/drivers/analogy/national_instruments/mio_common.c +++ b/kernel/drivers/analogy/national_instruments/mio_common.c @@ -2029,52 +2029,145 @@ int ni_ai_inttrig(struct a4l_subdevice *subd, lsampl_t trignum) return 1; } -static int ni_ai_cmdtest(struct a4l_subdevice *subd, struct a4l_cmd_desc * cmd) +#define cfc_check_trigger_arg_is(a,b) __cfc_check_trigger_arg_is(a,b, dev, __LINE__) +static inline int __cfc_check_trigger_arg_is(unsigned int *arg, + unsigned int val, + struct a4l_device *dev, + unsigned int line) +{ + if (*arg != val) { + a4l_dbg(1, drv_dbg, dev, "line %d: *arg (%d) != val (%d) \n", + line, *arg, val); + *arg = val; + return -EINVAL; + } + return 0; +} + +#define cfc_check_trigger_is_unique(a) __cfc_check_trigger_is_unique(a, dev, __LINE__) +static inline int __cfc_check_trigger_is_unique(unsigned int src, + struct a4l_device *dev, + unsigned int line) +{ + /* this test is true if more than one _src bit is set */ + if ((src & (src - 1)) != 0) { + a4l_dbg(1, drv_dbg, dev, "line %d: src (%d) \n", line, src); + return -EINVAL; + } + return 0; +} + +#define cfc_check_trigger_src(a,b) __cfc_check_trigger_src(a,b, dev, __LINE__) +static inline int __cfc_check_trigger_src(unsigned int *src, + unsigned int flags, + struct a4l_device *dev, + unsigned int line) +{ + unsigned int orig_src = *src; + + *src = orig_src & flags; + if (*src == 0 || *src != orig_src){ + a4l_dbg(1, drv_dbg, dev, "line %d: *src (%d) orig_src (%d) flags(%d) \n", + line, *src, orig_src, flags); + return -EINVAL; + } + + return 0; +} + +#define cfc_check_trigger_arg_min(a,b) __cfc_check_trigger_arg_min(a,b, dev, __LINE__) +static inline int __cfc_check_trigger_arg_min(unsigned int *arg, + unsigned int val, + struct a4l_device *dev, + unsigned int line) +{ + if (*arg < val) { + a4l_dbg(1, drv_dbg, dev, "line %d: *arg (%d) < val (%d) \n", + line, *arg, val); + *arg = val; + return -EINVAL; + } + return 0; +} + +#define cfc_check_trigger_arg_max(a,b) __cfc_check_trigger_arg_max(a,b, dev, __LINE__) +static inline int __cfc_check_trigger_arg_max(unsigned int *arg, + unsigned int val, + struct a4l_device *dev, + unsigned int line) +{ + if (*arg > val) { + a4l_dbg(1, drv_dbg, dev, "line %d: *arg (%d) > val (%d) \n", + line, *arg, val); + *arg = val; + return -EINVAL; + } + return 0; +} + +static int ni_ai_cmdtest(struct a4l_subdevice *subd, struct a4l_cmd_desc *cmd) { struct a4l_device *dev = subd->dev; - int tmp; + unsigned int sources; + int tmp, err = 0; + + /* Step 1 : check if triggers are trivially valid */ + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT | TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER | TRIG_EXT); - /* Make sure trigger sources are trivially valid */ + sources = TRIG_TIMER | TRIG_EXT; + if (boardtype.reg_type == ni_reg_611x || boardtype.reg_type == ni_reg_6143) + sources |= TRIG_NOW; - if ((boardtype.reg_type != ni_reg_611x) && - (boardtype.reg_type != ni_reg_6143) && - (boardtype.reg_type != ni_reg_622x) && - (cmd->scan_begin_src == TRIG_NOW)) + err |= cfc_check_trigger_src(&cmd->convert_src, sources); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + + if (err) { + if (cmd->valid_simul_stages & BIT(1)) + return 0; + + a4l_dbg(1, drv_dbg, dev, "ai_cmdtest ERR 1 \n"); return -EINVAL; + } - /* Make sure arguments are trivially compatible */ + /* Step 2a : make sure trigger sources are unique */ + err |= cfc_check_trigger_is_unique(cmd->start_src); + err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); + err |= cfc_check_trigger_is_unique(cmd->convert_src); + err |= cfc_check_trigger_is_unique(cmd->stop_src); + + /* Step 2b : and mutually compatible */ + + if (err) { + if (cmd->valid_simul_stages & BIT(2)) + return 0; + + a4l_dbg(1, drv_dbg, dev, "ai_cmdtest ERR 2 \n"); + return -EINVAL; + } + + /* Step 3: check if arguments are trivially valid */ if (cmd->start_src == TRIG_EXT) { /* external trigger */ unsigned int tmp = CR_CHAN(cmd->start_arg); - if (tmp > 16) tmp = 16; tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE)); - if (cmd->start_arg != tmp) { - cmd->start_arg = tmp; - return -EINVAL; - } + err |= cfc_check_trigger_arg_is(&cmd->start_arg, tmp); + } else { - if (cmd->start_arg != 0) { - /* true for both TRIG_NOW and TRIG_INT */ - cmd->start_arg = 0; - return -EINVAL; - } + /* true for both TRIG_NOW and TRIG_INT */ + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); } - if (cmd->scan_begin_src == TRIG_TIMER) { - if (cmd->scan_begin_arg < ni_min_ai_scan_period_ns(dev, - cmd->nb_chan)) { - cmd->scan_begin_arg = - ni_min_ai_scan_period_ns(dev, cmd->nb_chan); - - if (cmd->scan_begin_arg > devpriv->clock_ns * 0xffffff) - cmd->scan_begin_arg = devpriv->clock_ns * 0xffffff; - /* required for calibration */ - return 0; - } + if (cmd->scan_begin_src == TRIG_TIMER) { + err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, + ni_min_ai_scan_period_ns(dev, cmd->nb_chan)); + err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, + devpriv->clock_ns * 0xffffff); } else if (cmd->scan_begin_src == TRIG_EXT) { /* external trigger */ unsigned int tmp = CR_CHAN(cmd->scan_begin_arg); @@ -2082,32 +2175,23 @@ static int ni_ai_cmdtest(struct a4l_subdevice *subd, struct a4l_cmd_desc * cmd) if (tmp > 16) tmp = 16; tmp |= (cmd->scan_begin_arg & (CR_INVERT | CR_EDGE)); - if (cmd->scan_begin_arg != tmp) { - cmd->scan_begin_arg = tmp; - return -EINVAL; - } + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, tmp); + } else { /* TRIG_OTHER */ - if (cmd->scan_begin_arg) { - cmd->scan_begin_arg = 0; - return -EINVAL; - } + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + } + if (cmd->convert_src == TRIG_TIMER) { if ((boardtype.reg_type == ni_reg_611x) || (boardtype.reg_type == ni_reg_6143)) { - if (cmd->convert_arg != 0) { - cmd->convert_arg = 0; - return -EINVAL; - } + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + } else { - if (cmd->convert_arg < boardtype.ai_speed) { - cmd->convert_arg = boardtype.ai_speed; - return -EINVAL; - } - if (cmd->convert_arg > devpriv->clock_ns * 0xffff) { - cmd->convert_arg = devpriv->clock_ns * 0xffff; - return -EINVAL; - } + err |= cfc_check_trigger_arg_min(&cmd->convert_arg, + boardtype.ai_speed); + err |= cfc_check_trigger_arg_max(&cmd->convert_arg, + devpriv->clock_ns * 0xffff); } } else if (cmd->convert_src == TRIG_EXT) { /* external trigger */ @@ -2116,74 +2200,78 @@ static int ni_ai_cmdtest(struct a4l_subdevice *subd, struct a4l_cmd_desc * cmd) if (tmp > 16) tmp = 16; tmp |= (cmd->convert_arg & (CR_ALT_FILTER | CR_INVERT)); - if (cmd->convert_arg != tmp) { - cmd->convert_arg = tmp; - return -EINVAL; - } + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, tmp); } else if (cmd->convert_src == TRIG_NOW) { - if (cmd->convert_arg != 0) { - cmd->convert_arg = 0; - return -EINVAL; - } + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); } - if (cmd->scan_end_arg != cmd->nb_chan) { - cmd->scan_end_arg = cmd->nb_chan; - return -EINVAL; - } + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->nb_chan); + if (cmd->stop_src == TRIG_COUNT) { unsigned int max_count = 0x01000000; if (boardtype.reg_type == ni_reg_611x) max_count -= num_adc_stages_611x; - if (cmd->stop_arg > max_count) { - cmd->stop_arg = max_count; - return -EINVAL; - } - if (cmd->stop_arg < 1) { - cmd->stop_arg = 1; - return -EINVAL; - } + err |= cfc_check_trigger_arg_max(&cmd->stop_arg, max_count); + err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1); + } else { /* TRIG_NONE */ - if (cmd->stop_arg != 0) { - cmd->stop_arg = 0; - return -EINVAL; - } + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); } - /* step 4: fix up any arguments */ + if (err) { + if (cmd->valid_simul_stages & BIT(3)) + return 0; + a4l_dbg(1, drv_dbg, dev, "ai_cmdtest ERR 3 \n"); + return 3; + } + + /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { tmp = cmd->scan_begin_arg; cmd->scan_begin_arg = - ni_timer_to_ns(dev, ni_ns_to_timer(dev, - cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK)); + ni_timer_to_ns(dev, ni_ns_to_timer(dev, + cmd->scan_begin_arg, + cmd->flags & + TRIG_ROUND_MASK)); if (tmp != cmd->scan_begin_arg) - return -EINVAL; + err++; } if (cmd->convert_src == TRIG_TIMER) { if ((boardtype.reg_type != ni_reg_611x) && (boardtype.reg_type != ni_reg_6143)) { tmp = cmd->convert_arg; cmd->convert_arg = - ni_timer_to_ns(dev, ni_ns_to_timer(dev, - cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK)); + ni_timer_to_ns(dev, ni_ns_to_timer(dev, + cmd->convert_arg, + cmd-> + flags & + TRIG_ROUND_MASK)); if (tmp != cmd->convert_arg) - return -EINVAL; + err++; if (cmd->scan_begin_src == TRIG_TIMER && cmd->scan_begin_arg < cmd->convert_arg * cmd->scan_end_arg) { cmd->scan_begin_arg = - cmd->convert_arg * cmd->scan_end_arg; - return -EINVAL; + cmd->convert_arg * cmd->scan_end_arg; + err++; } } } + if (err) { + if (cmd->valid_simul_stages & BIT(4)) + return 0; + + a4l_dbg(1, drv_dbg, dev, "ai_cmdtest ERR 4 \n"); + return -EINVAL; + } + return 0; + + } static int ni_ai_cmd(struct a4l_subdevice *subd, struct a4l_cmd_desc *cmd) _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git