*/
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/interrupt.h>
#include "../comedidev.h"
#include "8255.h"
-#include "8253.h"
+#include "comedi_8254.h"
#include "comedi_fc.h"
#define DAS16M1_SIZE2 8
#define Q_RANGE(x) (((x) & 0xf) << 4)
#define UNIPOLAR 0x40
#define DAS16M1_8254_FIRST 0x8
-#define DAS16M1_8254_FIRST_CNTRL 0xb
-#define TOTAL_CLEAR 0x30
#define DAS16M1_8254_SECOND 0xc
#define DAS16M1_82C55 0x400
#define DAS16M1_8254_THIRD 0x404
};
struct das16m1_private_struct {
+ struct comedi_8254 *counter;
unsigned int control_state;
unsigned int adc_count; /* number of samples completed */
/* initial value in lower half of hardware conversion counter,
* counter yet (loaded by first sample conversion) */
u16 initial_hw_count;
unsigned short ai_buffer[FIFO_SIZE];
- unsigned int divisor1; /* divides master clock to obtain conversion speed */
- unsigned int divisor2; /* divides master clock to obtain conversion speed */
unsigned long extra_iobase;
};
static int das16m1_cmd_test(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
- struct das16m1_private_struct *devpriv = dev->private;
int err = 0;
- unsigned int arg;
/* Step 1 : check if triggers are trivially valid */
/* step 4: fix up arguments */
if (cmd->convert_src == TRIG_TIMER) {
- arg = cmd->convert_arg;
- i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
- &devpriv->divisor1,
- &devpriv->divisor2,
- &arg, cmd->flags);
+ unsigned int arg = cmd->convert_arg;
+
+ comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
}
return 0;
}
-static void das16m1_set_pacer(struct comedi_device *dev)
-{
- struct das16m1_private_struct *devpriv = dev->private;
- unsigned long timer_base = dev->iobase + DAS16M1_8254_SECOND;
-
- i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
- i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-
- i8254_write(timer_base, 0, 1, devpriv->divisor1);
- i8254_write(timer_base, 0, 2, devpriv->divisor2);
-}
-
static int das16m1_cmd_exec(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct das16m1_private_struct *devpriv = dev->private;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- unsigned long timer_base = dev->iobase + DAS16M1_8254_FIRST;
unsigned int byte, i;
/* disable interrupts and internal pacer */
/* set software count */
devpriv->adc_count = 0;
- /* Initialize lower half of hardware counter, used to determine how
+
+ /*
+ * Initialize lower half of hardware counter, used to determine how
* many samples are in fifo. Value doesn't actually load into counter
- * until counter's next clock (the next a/d conversion) */
- i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
- i8254_write(timer_base, 0, 1, 0);
- /* remember current reading of counter so we know when counter has
- * actually been loaded */
- devpriv->initial_hw_count = i8254_read(timer_base, 0, 1);
+ * until counter's next clock (the next a/d conversion).
+ */
+ comedi_8254_set_mode(devpriv->counter, 1, I8254_MODE2 | I8254_BINARY);
+ comedi_8254_write(devpriv->counter, 1, 0);
+
+ /*
+ * Remember current reading of counter so we know when counter has
+ * actually been loaded.
+ */
+ devpriv->initial_hw_count = comedi_8254_read(devpriv->counter, 1);
+
/* setup channel/gain queue */
for (i = 0; i < cmd->chanlist_len; i++) {
outb(i, dev->iobase + DAS16M1_QUEUE_ADDR);
/* enable interrupts and set internal pacer counter mode and counts */
devpriv->control_state &= ~PACER_MASK;
if (cmd->convert_src == TRIG_TIMER) {
- das16m1_set_pacer(dev);
+ comedi_8254_update_divisors(dev->pacer);
+ comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
devpriv->control_state |= INT_PACER;
} else { /* TRIG_EXT */
devpriv->control_state |= EXT_PACER;
async = s->async;
cmd = &async->cmd;
- /* figure out how many samples are in fifo */
- hw_counter = i8254_read(dev->iobase + DAS16M1_8254_FIRST, 0, 1);
+ /* figure out how many samples are in fifo */
+ hw_counter = comedi_8254_read(devpriv->counter, 1);
/* make sure hardware counter reading is not bogus due to initial value
* not having been loaded yet */
if (devpriv->adc_count == 0 && hw_counter == devpriv->initial_hw_count) {
dev->irq = it->options[1];
}
+ dev->pacer = comedi_8254_init(dev->iobase + DAS16M1_8254_SECOND,
+ I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+ if (!dev->pacer)
+ return -ENOMEM;
+
+ devpriv->counter = comedi_8254_init(dev->iobase + DAS16M1_8254_FIRST,
+ 0, I8254_IO8, 0);
+ if (!devpriv->counter)
+ return -ENOMEM;
+
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
if (ret)
return ret;
- /* disable upper half of hardware conversion counter so it doesn't mess with us */
- outb(TOTAL_CLEAR, dev->iobase + DAS16M1_8254_FIRST_CNTRL);
-
/* initialize digital output lines */
outb(0, dev->iobase + DAS16M1_DIO);
{
struct das16m1_private_struct *devpriv = dev->private;
- if (devpriv && devpriv->extra_iobase)
- release_region(devpriv->extra_iobase, DAS16M1_SIZE2);
+ if (devpriv) {
+ if (devpriv->extra_iobase)
+ release_region(devpriv->extra_iobase, DAS16M1_SIZE2);
+ kfree(devpriv->counter);
+ }
comedi_legacy_detach(dev);
}