The DAQ700Card has an 8254 counter/timer that provides 3 counters. Counter 0 controls the onboard data acquisition timing, and all three counters are available for general-purpose timing functions. Add a subdevice to allow the user to use the counters. Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx> Cc: Ian Abbott <abbotti@xxxxxxxxx> Cc: Greg Kroah-Hartman <gregk@xxxxxxxxxxxxxxxxxxx> --- drivers/staging/comedi/comedi.h | 9 ++ drivers/staging/comedi/drivers/ni_daq_700.c | 125 +++++++++++++++++++++++++++- 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index dbaeba7..c722748 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -987,4 +987,13 @@ enum ke_counter_clock_source { KE_CLK_EXT /* external clock on pin 21 of D-Sub */ }; +/* + * Values for setting the counter 1 clock source with INSN_CONFIG_SET_CLOCK_SRC + * for the counter subdevice on the NI PCMCIA DAQCard-700 (ni_daq_700 driver). + */ +enum ni_daq700_counter_clock_source { + DAQ700_CLK_EXT, /* external CLK1 signal (default) */ + DAQ700_CLK_1MHZ, /* internal 1MHz */ +}; + #endif /* _COMEDI_H */ diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index e1e7ba7..4ff3556 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -589,6 +589,112 @@ static int daq700_ai_cmdtest(struct comedi_device *dev, return 0; } +static int daq700_counter_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned long timer_base = dev->iobase + DAQ700_TIMER_BASE; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; + + for (i = 0; i < insn->n; i++) + data[i] = i8254_read(timer_base, 0, chan); + + return insn->n; +} + +static int daq700_counter_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned long timer_base = dev->iobase + DAQ700_TIMER_BASE; + unsigned int chan = CR_CHAN(insn->chanspec); + + /* only write the final value to the counter */ + if (insn->n) + i8254_write(timer_base, 0, chan, data[insn->n - 1]); + + return insn->n; +} + +static int daq700_counter_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct daq700_private *devpriv = dev->private; + unsigned long timer_base = dev->iobase + DAQ700_TIMER_BASE; + unsigned int chan = CR_CHAN(insn->chanspec); + + switch (data[0]) { + case INSN_CONFIG_SET_CLOCK_SRC: + switch (chan) { + case 1: + switch (data[1]) { + case DAQ700_CLK_EXT: + /* CLK1 signal from I/O connector */ + devpriv->cmd3 &= ~DAQ700_CMD3_CLK1SRC; + break; + case DAQ700_CLK_1MHZ: + /* CLK1 from internal 1MHz */ + devpriv->cmd3 |= DAQ700_CMD3_CLK1SRC; + break; + default: + return -EINVAL; + } + outb(devpriv->cmd3, dev->iobase + DAQ700_CMD3_REG); + break; + default: + /* + * The clock source cannot be changed for all + * other channels. + */ + return -EINVAL; + } + break; + case INSN_CONFIG_GET_CLOCK_SRC: + switch (chan) { + case 0: + /* counter 0 is connected to the 1MHz internal clock */ + data[1] = DAQ700_CLK_1MHZ; + data[2] = I8254_OSC_BASE_1MHZ; + break; + case 1: + /* + * Counter 1 can use the 1MHz internal clock or an + * external clock. + */ + if (devpriv->cmd3 & DAQ700_CMD3_CLK1SRC) { + data[1] = DAQ700_CLK_1MHZ; + data[2] = I8254_OSC_BASE_1MHZ; + } else { + data[1] = DAQ700_CLK_EXT; + data[2] = 0; /* unknown */ + } + break; + case 2: + /* counter 2 uses an external clock */ + data[1] = DAQ700_CLK_EXT; + data[2] = 0; /* unknown */ + break; + default: + return -EINVAL; + } + break; + case INSN_CONFIG_SET_COUNTER_MODE: + i8254_set_mode(timer_base, 0, chan, data[1]); + break; + case INSN_CONFIG_8254_READ_STATUS: + data[1] = i8254_status(timer_base, 0, chan); + break; + default: + return -EINVAL; + } + return insn->n; +} + /* * Data acquisition is enabled. * The counter 0 output is high. @@ -640,7 +746,7 @@ static int daq700_auto_attach(struct comedi_device *dev, if (ret == 0) dev->irq = link->irq; - ret = comedi_alloc_subdevices(dev, 2); + ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; @@ -672,6 +778,23 @@ static int daq700_auto_attach(struct comedi_device *dev, s->cancel = daq700_ai_cancel; } + /* + * Counter/Timer subdevice + * + * The 8254 has three counters - 0, 1, and 2. Counter 0 controls + * the onboard data acquisition timing, and all three counters + * are available for general-purpose timing functions. + */ + s = &dev->subdevices[2]; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 3; + s->maxdata = 0xffff; + s->range_table = &range_unknown; + s->insn_config = daq700_counter_insn_config; + s->insn_write = daq700_counter_insn_write; + s->insn_read = daq700_counter_insn_read; + return 0; } -- 1.9.3 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel