/* Watchdog Related Defines */ #define ADDIDATA_TIMER 0 #define ADDIDATA_WATCHDOG 2 /* * (*insn_config) for the timer subdevice * * Configures The Timer, Counter or Watchdog * Data Pointer contains configuration parameters as below * data[0] : 0 Configure As Timer * 1 Configure As Counter * 2 Configure As Watchdog * data[1] : 1 Enable Interrupt * 0 Disable Interrupt * data[2] : Time Unit * data[3] : Reload Value */ static int apci3501_config_insn_timer(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct apci3501_private *devpriv = dev->private; unsigned int ctrl; if (data[0] != ADDIDATA_WATCHDOG && data[0] != ADDIDATA_TIMER) return -EINVAL; devpriv->tsk_Current = current; devpriv->timer_mode = data[0]; /* first, disable the watchdog or stop the timer */ if (devpriv->timer_mode == ADDIDATA_WATCHDOG) { ctrl = 0; } else { ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_ENA); } outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); /* enable/disable the timer interrupt */ ctrl = (data[1] == 1) ? ADDI_TCW_CTRL_IRQ_ENA : 0; outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); outl(data[2], devpriv->tcw + ADDI_TCW_TIMEBASE_REG); outl(data[3], devpriv->tcw + ADDI_TCW_RELOAD_REG); ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); if (devpriv->timer_mode == ADDIDATA_WATCHDOG) { /* Set the mode (e2->e0) NOTE: this doesn't look correct */ ctrl |= ~(ADDI_TCW_CTRL_CNT_UP | ADDI_TCW_CTRL_EXT_CLK_MASK | 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_IRQ_ENA | ADDI_TCW_CTRL_ENA); } else { /* mode 2 */ 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->tcw + ADDI_TCW_CTRL_REG); return insn->n; } /* * (*insn_write) for the timer subdevice * * Start / Stop The Selected Timer , Counter or Watchdog * Data Pointer contains configuration parameters as below * data[0] : 0 Timer * 1 Counter * 2 Watchdog * data[1] : 1 Start * 0 Stop * 2 Trigger */ static int apci3501_write_insn_timer(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct apci3501_private *devpriv = dev->private; unsigned int ctrl; if (devpriv->timer_mode == ADDIDATA_WATCHDOG || devpriv->timer_mode == ADDIDATA_TIMER) { ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG); if (data[1] == 1) { /* enable */ ctrl |= ADDI_TCW_CTRL_ENA; } else if (data[1] == 0) { /* stop */ if (devpriv->timer_mode == ADDIDATA_WATCHDOG) ctrl = 0; else ctrl &= ~ADDI_TCW_CTRL_ENA; } else if (data[1] == 2) { /* trigger */ ctrl |= ADDI_TCW_CTRL_TRIG; } outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); } inl(devpriv->tcw + ADDI_TCW_STATUS_REG); return insn->n; } /* * (*insn_read) for the timer subdevice * * Read The Selected Timer, Counter or Watchdog * Data Pointer contains configuration parameters as below * data[0] : 0 Timer * 1 Counter * 2 Watchdog * data[1] : Timer Counter Watchdog Number */ static int apci3501_read_insn_timer(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct apci3501_private *devpriv = dev->private; if (devpriv->timer_mode != ADDIDATA_TIMER && devpriv->timer_mode != ADDIDATA_WATCHDOG) return -EINVAL; data[0] = inl(devpriv->tcw + ADDI_TCW_STATUS_REG) & ADDI_TCW_STATUS_OVERFLOW; data[1] = inl(devpriv->tcw + ADDI_TCW_VAL_REG); return insn->n; }