diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index ce2e40f258c2b1..ed5085a70807bc 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -521,13 +521,14 @@ static int chanToInterval(int nChannels) return 8; } -static int usbdux_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd) +static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { - struct usbduxsigma_private *this_usbduxsub = dev->private; - int err = 0, i; - unsigned int tmpTimer; + struct usbduxsigma_private *devpriv = dev->private; + int high_speed = devpriv->high_speed; + int interval = chanToInterval(cmd->chanlist_len); + int err = 0; /* Step 1 : check if triggers are trivially valid */ @@ -558,34 +559,28 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); if (cmd->scan_begin_src == TRIG_TIMER) { - if (this_usbduxsub->high_speed) { + unsigned int tmp; + + if (high_speed) { /* * In high speed mode microframes are possible. * However, during one microframe we can roughly * sample two channels. Thus, the more channels * are in the channel list the more time we need. */ - i = chanToInterval(cmd->chanlist_len); err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, - (1000000 / 8 * i)); - /* now calc the real sampling rate with all the - * rounding errors */ - tmpTimer = - ((unsigned int)(cmd->scan_begin_arg / 125000)) * - 125000; + (1000000 / 8 * interval)); + + tmp = (cmd->scan_begin_arg / 125000) * 125000; } else { /* full speed */ /* 1kHz scans every USB frame */ err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 1000000); - /* - * calc the real sampling rate with the rounding errors - */ - tmpTimer = ((unsigned int)(cmd->scan_begin_arg / - 1000000)) * 1000000; + + tmp = (cmd->scan_begin_arg / 1000000) * 1000000; } - err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, - tmpTimer); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, tmp); } err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); @@ -600,6 +595,37 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, if (err) return 3; + /* Step 4: fix up any arguments */ + + if (high_speed) { + /* + * every 2 channels get a time window of 125us. Thus, if we + * sample all 16 channels we need 1ms. If we sample only one + * channel we need only 125us + */ + devpriv->ai_interval = interval; + devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval); + } else { + /* interval always 1ms */ + devpriv->ai_interval = 1; + devpriv->ai_timer = cmd->scan_begin_arg / 1000000; + } + if (devpriv->ai_timer < 1) + err |= -EINVAL; + + if (cmd->stop_src == TRIG_COUNT) { + /* data arrives as one packet */ + devpriv->ai_sample_count = cmd->stop_arg; + devpriv->ai_continuous = 0; + } else { + /* continuous acquisition */ + devpriv->ai_continuous = 1; + devpriv->ai_sample_count = 0; + } + + if (err) + return 4; + return 0; } @@ -692,102 +718,61 @@ static int usbduxsigma_ai_inttrig(struct comedi_device *dev, return 1; } -static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +static int usbduxsigma_ai_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) { - struct usbduxsigma_private *this_usbduxsub = dev->private; + struct usbduxsigma_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int chan; - int i, ret; - int result; + unsigned int len = cmd->chanlist_len; uint8_t muxsg0 = 0; uint8_t muxsg1 = 0; uint8_t sysred = 0; + int ret; + int i; + + down(&devpriv->sem); - /* block other CPUs from starting an ai_cmd */ - down(&this_usbduxsub->sem); - if (this_usbduxsub->ai_cmd_running) { - up(&this_usbduxsub->sem); - return -EBUSY; - } /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; + for (i = 0; i < len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); - /* first the number of channels per time step */ - this_usbduxsub->dux_commands[1] = cmd->chanlist_len; - - /* CONFIG0 */ - this_usbduxsub->dux_commands[2] = 0x12; - - /* CONFIG1: 23kHz sampling rate, delay = 0us, */ - this_usbduxsub->dux_commands[3] = 0x03; - - /* CONFIG3: differential channels off */ - this_usbduxsub->dux_commands[4] = 0x00; - - for (i = 0; i < cmd->chanlist_len; i++) { - chan = CR_CHAN(cmd->chanlist[i]); create_adc_command(chan, &muxsg0, &muxsg1); } - this_usbduxsub->dux_commands[5] = muxsg0; - this_usbduxsub->dux_commands[6] = muxsg1; - this_usbduxsub->dux_commands[7] = sysred; - - result = send_dux_commands(dev, SENDADCOMMANDS); - if (result < 0) { - up(&this_usbduxsub->sem); - return result; - } - if (this_usbduxsub->high_speed) { - /* - * every 2 channels get a time window of 125us. Thus, if we - * sample all 16 channels we need 1ms. If we sample only one - * channel we need only 125us - */ - this_usbduxsub->ai_interval = - chanToInterval(cmd->chanlist_len); - this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 * - (this_usbduxsub-> - ai_interval)); - } else { - /* interval always 1ms */ - this_usbduxsub->ai_interval = 1; - this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000; - } - if (this_usbduxsub->ai_timer < 1) { - up(&this_usbduxsub->sem); - return -EINVAL; - } - this_usbduxsub->ai_counter = this_usbduxsub->ai_timer; + devpriv->dux_commands[1] = len; /* num channels per time step */ + devpriv->dux_commands[2] = 0x12; /* CONFIG0 */ + devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */ + devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */ + devpriv->dux_commands[5] = muxsg0; + devpriv->dux_commands[6] = muxsg1; + devpriv->dux_commands[7] = sysred; - if (cmd->stop_src == TRIG_COUNT) { - /* data arrives as one packet */ - this_usbduxsub->ai_sample_count = cmd->stop_arg; - this_usbduxsub->ai_continuous = 0; - } else { - /* continuous acquisition */ - this_usbduxsub->ai_continuous = 1; - this_usbduxsub->ai_sample_count = 0; + ret = send_dux_commands(dev, SENDADCOMMANDS); + if (ret < 0) { + up(&devpriv->sem); + return ret; } + devpriv->ai_counter = devpriv->ai_timer; + if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ - ret = usbduxsigma_submit_urbs(dev, this_usbduxsub->urbIn, - this_usbduxsub->numOfInBuffers, - 1); + ret = usbduxsigma_submit_urbs(dev, devpriv->urbIn, + devpriv->numOfInBuffers, 1); if (ret < 0) { - up(&this_usbduxsub->sem); + up(&devpriv->sem); return ret; } - this_usbduxsub->ai_cmd_running = 1; s->async->inttrig = NULL; - } else { - /* TRIG_INT */ - /* don't enable the acquision operation */ - /* wait for an internal signal */ + devpriv->ai_cmd_running = 1; + } else { /* TRIG_INT */ + /* wait for an internal signal and submit the urbs later */ s->async->inttrig = usbduxsigma_ai_inttrig; } - up(&this_usbduxsub->sem); + + up(&devpriv->sem); + return 0; } @@ -1448,8 +1433,8 @@ static int usbduxsigma_attach_common(struct comedi_device *dev) s->maxdata = 0x00ffffff; s->range_table = &range_usbdux_ai_range; s->insn_read = usbduxsigma_ai_insn_read; - s->do_cmdtest = usbdux_ai_cmdtest; - s->do_cmd = usbdux_ai_cmd; + s->do_cmdtest = usbduxsigma_ai_cmdtest; + s->do_cmd = usbduxsigma_ai_cmd; s->cancel = usbdux_ai_cancel; /* Analog Output subdevice */