| /* Digital Input IRQ Function Selection */ |
| #define APCI1564_DI_INT_OR (0 << 1) |
| #define APCI1564_DI_INT_AND (1 << 1) |
| |
| /* Digital Input Interrupt Enable Disable. */ |
| #define APCI1564_DI_INT_ENABLE 0x4 |
| #define APCI1564_DI_INT_DISABLE 0xfffffffb |
| |
| /* Digital Output Interrupt Enable Disable. */ |
| #define APCI1564_DO_VCC_INT_ENABLE 0x1 |
| #define APCI1564_DO_VCC_INT_DISABLE 0xfffffffe |
| #define APCI1564_DO_CC_INT_ENABLE 0x2 |
| #define APCI1564_DO_CC_INT_DISABLE 0xfffffffd |
| |
| /* TIMER COUNTER WATCHDOG DEFINES */ |
| #define ADDIDATA_TIMER 0 |
| #define ADDIDATA_COUNTER 1 |
| #define ADDIDATA_WATCHDOG 2 |
| |
| 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; |
| |
| /* First Stop The Timer */ |
| ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG); |
| ctrl &= 0xfffff9fe; |
| /* Stop The Timer */ |
| outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG); |
| |
| if (data[1] == 1) { |
| /* Enable timer int & disable all the other int sources */ |
| outl(0x02, 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 &= 0xfff719e2; |
| ctrl |= (2 << 13) | 0x10; |
| /* mode 2 */ |
| 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); |
| switch (data[1]) { |
| case 0: /* Stop The Timer */ |
| ctrl &= 0xfffff9fe; |
| break; |
| case 1: /* Enable the Timer */ |
| ctrl &= 0xfffff9ff; |
| ctrl |= 0x1; |
| 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) & 0x1; |
| |
| /* 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; |
| |
| /* First Stop The Counter */ |
| ctrl = inl(iobase + ADDI_TCW_CTRL_REG); |
| ctrl &= 0xfffff9fe; |
| /* Stop The Timer */ |
| outl(ctrl, iobase + ADDI_TCW_CTRL_REG); |
| |
| /* Set the reload value */ |
| outl(data[3], iobase + ADDI_TCW_RELOAD_REG); |
| |
| /* Set the mode : */ |
| /* - Disable the hardware */ |
| /* - Disable the counter mode */ |
| /* - Disable the warning */ |
| /* - Disable the reset */ |
| /* - Disable the timer mode */ |
| /* - Enable the counter mode */ |
| |
| ctrl &= 0xfffc19e2; |
| ctrl |= 0x80000 | (data[4] << 16); |
| outl(ctrl, iobase + ADDI_TCW_CTRL_REG); |
| |
| /* Enable or Disable Interrupt */ |
| ctrl &= 0xfffff9fd; |
| ctrl |= (data[1] << 1); |
| outl(ctrl, iobase + ADDI_TCW_CTRL_REG); |
| |
| /* Set the Up/Down selection */ |
| ctrl &= 0xfffbf9ff; |
| ctrl |= (data[6] << 18); |
| 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); |
| switch (data[1]) { |
| case 0: /* Stops the Counter subdevice */ |
| ctrl = 0; |
| break; |
| case 1: /* Start the Counter subdevice */ |
| ctrl &= 0xfffff9ff; |
| ctrl |= 0x1; |
| break; |
| case 2: /* Clears the Counter subdevice */ |
| ctrl &= 0xfffff9ff; |
| ctrl |= 0x400; |
| 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 >> 1) & 1; /* software trigger status */ |
| data[2] = (status >> 2) & 1; /* hardware trigger status */ |
| data[3] = (status >> 3) & 1; /* software clear status */ |
| data[4] = (status >> 0) & 1; /* overflow status */ |
| |
| return insn->n; |
| } |