static int apci1564_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct apci1564_private *devpriv = dev->private; unsigned int ctrl; devpriv->tsk_current = current; /* Stop the timer */ ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG); ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_ENA); outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG); if (data[1] == 1) { /* Enable timer int & disable all the other int sources */ outl(ADDI_TCW_CTRL_IRQ_ENA, devpriv->timer + ADDI_TCW_CTRL_REG); outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG); outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG); outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG); if (devpriv->counters) { unsigned long iobase; iobase = devpriv->counters + ADDI_TCW_IRQ_REG; outl(0x0, iobase + APCI1564_COUNTER(0)); outl(0x0, iobase + APCI1564_COUNTER(1)); outl(0x0, iobase + APCI1564_COUNTER(2)); } } else { /* disable Timer interrupt */ outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG); } /* Loading Timebase */ outl(data[2], devpriv->timer + ADDI_TCW_TIMEBASE_REG); /* Loading the Reload value */ outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG); ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG); ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK | ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA | ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA); ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA; outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG); return insn->n; } static int apci1564_timer_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct apci1564_private *devpriv = dev->private; unsigned int ctrl; ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG); ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG); switch (data[1]) { case 0: /* Stop The Timer */ ctrl &= ~ADDI_TCW_CTRL_ENA; break; case 1: /* Enable the Timer */ ctrl |= ADDI_TCW_CTRL_ENA; break; } outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG); return insn->n; } static int apci1564_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct apci1564_private *devpriv = dev->private; /* Stores the status of the Timer */ data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) & ADDI_TCW_STATUS_OVERFLOW; /* Stores the Actual value of the Timer */ data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG); return insn->n; } static int apci1564_counter_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct apci1564_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan); unsigned int ctrl; devpriv->tsk_current = current; /* Stop The Timer */ ctrl = inl(iobase + ADDI_TCW_CTRL_REG); ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_ENA); outl(ctrl, iobase + ADDI_TCW_CTRL_REG); /* Set the reload value */ outl(data[3], iobase + ADDI_TCW_RELOAD_REG); /* Set the mode */ ctrl &= ~(ADDI_TCW_CTRL_EXT_CLK_MASK | ADDI_TCW_CTRL_MODE_MASK | ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA | ADDI_TCW_CTRL_WARN_ENA); ctrl |= ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE(data[4]); outl(ctrl, iobase + ADDI_TCW_CTRL_REG); /* Enable or Disable Interrupt */ if (data[1]) ctrl |= ADDI_TCW_CTRL_IRQ_ENA; else ctrl &= ~ADDI_TCW_CTRL_IRQ_ENA; outl(ctrl, iobase + ADDI_TCW_CTRL_REG); /* Set the Up/Down selection */ if (data[6]) ctrl |= ADDI_TCW_CTRL_CNT_UP; else ctrl &= ~ADDI_TCW_CTRL_CNT_UP; outl(ctrl, iobase + ADDI_TCW_CTRL_REG); return insn->n; } static int apci1564_counter_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct apci1564_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan); unsigned int ctrl; ctrl = inl(iobase + ADDI_TCW_CTRL_REG); ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG); switch (data[1]) { case 0: /* Stops the Counter subdevice */ ctrl = 0; break; case 1: /* Start the Counter subdevice */ ctrl |= ADDI_TCW_CTRL_ENA; break; case 2: /* Clears the Counter subdevice */ ctrl |= ADDI_TCW_CTRL_GATE; break; } outl(ctrl, iobase + ADDI_TCW_CTRL_REG); return insn->n; } static int apci1564_counter_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct apci1564_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan); unsigned int status; /* Read the Counter Actual Value. */ data[0] = inl(iobase + ADDI_TCW_VAL_REG); status = inl(iobase + ADDI_TCW_STATUS_REG); data[1] = (status & ADDI_TCW_STATUS_SOFT_TRIG) ? 1 : 0; data[2] = (status & ADDI_TCW_STATUS_HARDWARE_TRIG) ? 1 : 0; data[3] = (status & ADDI_TCW_STATUS_SOFT_CLR) ? 1 : 0; data[4] = (status & ADDI_TCW_STATUS_OVERFLOW) ? 1 : 0; return insn->n; }