| /** |
| @verbatim |
| |
| Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. |
| |
| ADDI-DATA GmbH |
| Dieselstrasse 3 |
| D-77833 Ottersweier |
| Tel: +19(0)7223/9493-0 |
| Fax: +49(0)7223/9493-92 |
| http://www.addi-data.com |
| info@addi-data.com |
| |
| This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| |
| @endverbatim |
| */ |
| /* |
| |
| +-----------------------------------------------------------------------+ |
| | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | |
| +-----------------------------------------------------------------------+ |
| | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | |
| | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | |
| +-------------------------------+---------------------------------------+ |
| | Project : APCI-1564 | Compiler : GCC | |
| | Module name : hwdrv_apci1564.c| Version : 2.96 | |
| +-------------------------------+---------------------------------------+ |
| | Project manager: Eric Stolz | Date : 02/12/2002 | |
| +-------------------------------+---------------------------------------+ |
| | Description : Hardware Layer Access For APCI-1564 | |
| +-----------------------------------------------------------------------+ |
| | UPDATES | |
| +----------+-----------+------------------------------------------------+ |
| | Date | Author | Description of updates | |
| +----------+-----------+------------------------------------------------+ |
| | | | | |
| | | | | |
| | | | | |
| +----------+-----------+------------------------------------------------+ |
| */ |
| |
| /********* Definitions for APCI-1564 card *****/ |
| |
| #define APCI1564_ADDRESS_RANGE 128 |
| |
| /* DIGITAL INPUT-OUTPUT DEFINE */ |
| /* Input defines */ |
| #define APCI1564_DIGITAL_IP 0x04 |
| #define APCI1564_DIGITAL_IP_INTERRUPT_MODE1 4 |
| #define APCI1564_DIGITAL_IP_INTERRUPT_MODE2 8 |
| #define APCI1564_DIGITAL_IP_IRQ 16 |
| |
| /* Output defines */ |
| #define APCI1564_DIGITAL_OP 0x18 |
| #define APCI1564_DIGITAL_OP_RW 0 |
| #define APCI1564_DIGITAL_OP_INTERRUPT 4 |
| #define APCI1564_DIGITAL_OP_IRQ 12 |
| |
| /* Digital Input IRQ Function Selection */ |
| #define ADDIDATA_OR 0 |
| #define ADDIDATA_AND 1 |
| |
| /* Digital Input Interrupt Status */ |
| #define APCI1564_DIGITAL_IP_INTERRUPT_STATUS 12 |
| |
| /* Digital Output Interrupt Status */ |
| #define APCI1564_DIGITAL_OP_INTERRUPT_STATUS 8 |
| |
| /* Digital Input Interrupt Enable Disable. */ |
| #define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE 0x4 |
| #define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE 0xfffffffb |
| |
| /* Digital Output Interrupt Enable Disable. */ |
| #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1 |
| #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xfffffffe |
| #define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2 |
| #define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xfffffffd |
| |
| /* TIMER COUNTER WATCHDOG DEFINES */ |
| |
| #define ADDIDATA_TIMER 0 |
| #define ADDIDATA_COUNTER 1 |
| #define ADDIDATA_WATCHDOG 2 |
| #define APCI1564_DIGITAL_OP_WATCHDOG 0x28 |
| #define APCI1564_TIMER 0x48 |
| #define APCI1564_COUNTER1 0x0 |
| #define APCI1564_COUNTER2 0x20 |
| #define APCI1564_COUNTER3 0x40 |
| #define APCI1564_COUNTER4 0x60 |
| #define APCI1564_TCW_SYNC_ENABLEDISABLE 0 |
| #define APCI1564_TCW_RELOAD_VALUE 4 |
| #define APCI1564_TCW_TIMEBASE 8 |
| #define APCI1564_TCW_PROG 12 |
| #define APCI1564_TCW_TRIG_STATUS 16 |
| #define APCI1564_TCW_IRQ 20 |
| #define APCI1564_TCW_WARN_TIMEVAL 24 |
| #define APCI1564_TCW_WARN_TIMEBASE 28 |
| |
| /* Global variables */ |
| static unsigned int ui_InterruptStatus_1564 = 0; |
| static unsigned int ui_InterruptData, ui_Type; |
| |
| /* |
| +----------------------------------------------------------------------------+ |
| | Function Name : int i_APCI1564_ConfigDigitalInput | |
| | (struct comedi_device *dev,struct comedi_subdevice *s, | |
| | struct comedi_insn *insn,unsigned int *data) | |
| +----------------------------------------------------------------------------+ |
| | Task : Configures the digital input Subdevice | |
| +----------------------------------------------------------------------------+ |
| | Input Parameters : struct comedi_device *dev : Driver handle | |
| | unsigned int *data : Data Pointer contains | |
| | configuration parameters as below | |
| | | |
| | data[0] : 1 Enable Digital Input Interrupt | |
| | 0 Disable Digital Input Interrupt | |
| | data[1] : 0 ADDIDATA Interrupt OR LOGIC | |
| | : 1 ADDIDATA Interrupt AND LOGIC | |
| | data[2] : Interrupt mask for the mode 1 | |
| | data[3] : Interrupt mask for the mode 2 | |
| | | |
| +----------------------------------------------------------------------------+ |
| | Output Parameters : -- | |
| +----------------------------------------------------------------------------+ |
| | Return Value : TRUE : No error occur | |
| | : FALSE : Error occur. Return the error | |
| | | |
| +----------------------------------------------------------------------------+ |
| */ |
| static int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
| { |
| struct addi_private *devpriv = dev->private; |
| |
| devpriv->tsk_Current = current; |
| /*******************************/ |
| /* Set the digital input logic */ |
| /*******************************/ |
| if (data[0] == ADDIDATA_ENABLE) { |
| data[2] = data[2] << 4; |
| data[3] = data[3] << 4; |
| outl(data[2], |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_INTERRUPT_MODE1); |
| outl(data[3], |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_INTERRUPT_MODE2); |
| if (data[1] == ADDIDATA_OR) { |
| outl(0x4, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_IRQ); |
| } /* if (data[1] == ADDIDATA_OR) */ |
| else { |
| outl(0x6, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_IRQ); |
| } /* else if (data[1] == ADDIDATA_OR) */ |
| } /* if (data[0] == ADDIDATA_ENABLE) */ |
| else { |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_INTERRUPT_MODE1); |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_INTERRUPT_MODE2); |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_IRQ); |
| } /* else if (data[0] == ADDIDATA_ENABLE) */ |
| |
| return insn->n; |
| } |
| |
| static int apci1564_di_insn_bits(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
| { |
| struct addi_private *devpriv = dev->private; |
| |
| data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP); |
| |
| return insn->n; |
| } |
| |
| /* |
| +----------------------------------------------------------------------------+ |
| | Function Name : int i_APCI1564_ConfigDigitalOutput | |
| | (struct comedi_device *dev,struct comedi_subdevice *s, | |
| | struct comedi_insn *insn,unsigned int *data) | |
| +----------------------------------------------------------------------------+ |
| | Task : Configures The Digital Output Subdevice. | |
| +----------------------------------------------------------------------------+ |
| | Input Parameters : struct comedi_device *dev : Driver handle | |
| | unsigned int *data : Data Pointer contains | |
| | configuration parameters as below | |
| | | |
| | data[1] : 1 Enable VCC Interrupt | |
| | 0 Disable VCC Interrupt | |
| | data[2] : 1 Enable CC Interrupt | |
| | 0 Disable CC Interrupt | |
| | | |
| +----------------------------------------------------------------------------+ |
| | Output Parameters : -- | |
| +----------------------------------------------------------------------------+ |
| | Return Value : TRUE : No error occur | |
| | : FALSE : Error occur. Return the error | |
| | | |
| +----------------------------------------------------------------------------+ |
| */ |
| static int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
| { |
| struct addi_private *devpriv = dev->private; |
| unsigned int ul_Command = 0; |
| |
| if ((data[0] != 0) && (data[0] != 1)) { |
| comedi_error(dev, |
| "Not a valid Data !!! ,Data should be 1 or 0\n"); |
| return -EINVAL; |
| } /* if ((data[0]!=0) && (data[0]!=1)) */ |
| if (data[0]) { |
| devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; |
| } /* if (data[0]) */ |
| else { |
| devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; |
| } /* else if (data[0]) */ |
| if (data[1] == ADDIDATA_ENABLE) { |
| ul_Command = ul_Command | 0x1; |
| } /* if (data[1] == ADDIDATA_ENABLE) */ |
| else { |
| ul_Command = ul_Command & 0xFFFFFFFE; |
| } /* else if (data[1] == ADDIDATA_ENABLE) */ |
| if (data[2] == ADDIDATA_ENABLE) { |
| ul_Command = ul_Command | 0x2; |
| } /* if (data[2] == ADDIDATA_ENABLE) */ |
| else { |
| ul_Command = ul_Command & 0xFFFFFFFD; |
| } /* else if (data[2] == ADDIDATA_ENABLE) */ |
| outl(ul_Command, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + |
| APCI1564_DIGITAL_OP_INTERRUPT); |
| ui_InterruptData = |
| inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + |
| APCI1564_DIGITAL_OP_INTERRUPT); |
| devpriv->tsk_Current = current; |
| return insn->n; |
| } |
| |
| static int apci1564_do_insn_bits(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
| { |
| struct addi_private *devpriv = dev->private; |
| unsigned int mask = data[0]; |
| unsigned int bits = data[1]; |
| |
| s->state = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + |
| APCI1564_DIGITAL_OP_RW); |
| if (mask) { |
| s->state &= ~mask; |
| s->state |= (bits & mask); |
| |
| outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + |
| APCI1564_DIGITAL_OP_RW); |
| } |
| |
| data[1] = s->state; |
| |
| return insn->n; |
| } |
| |
| /* |
| +----------------------------------------------------------------------------+ |
| | Function Name : int i_APCI1564_ConfigTimerCounterWatchdog | |
| | (struct comedi_device *dev,struct comedi_subdevice *s, | |
| | struct comedi_insn *insn,unsigned int *data) | |
| +----------------------------------------------------------------------------+ |
| | Task : Configures The Timer , Counter or Watchdog | |
| +----------------------------------------------------------------------------+ |
| | Input Parameters : struct comedi_device *dev : Driver handle | |
| | unsigned int *data : 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 | |
| | data[4] : Timer Mode | |
| | data[5] : Timer Counter Watchdog Number| |
| data[6] : Counter Direction |
| +----------------------------------------------------------------------------+ |
| | Output Parameters : -- | |
| +----------------------------------------------------------------------------+ |
| | Return Value : TRUE : No error occur | |
| | : FALSE : Error occur. Return the error | |
| | | |
| +----------------------------------------------------------------------------+ |
| */ |
| static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
| { |
| struct addi_private *devpriv = dev->private; |
| unsigned int ul_Command1 = 0; |
| |
| devpriv->tsk_Current = current; |
| if (data[0] == ADDIDATA_WATCHDOG) { |
| devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG; |
| |
| /* Disable the watchdog */ |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + |
| APCI1564_TCW_PROG); |
| /* Loading the Reload value */ |
| outl(data[3], |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + |
| APCI1564_TCW_RELOAD_VALUE); |
| } /* if (data[0]==ADDIDATA_WATCHDOG) */ |
| else if (data[0] == ADDIDATA_TIMER) { |
| /* First Stop The Timer */ |
| ul_Command1 = |
| inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_PROG); |
| ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; |
| outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Stop The Timer */ |
| |
| devpriv->b_TimerSelectMode = ADDIDATA_TIMER; |
| if (data[1] == 1) { |
| outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */ |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_IRQ); |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + |
| APCI1564_DIGITAL_OP_IRQ); |
| outl(0x0, |
| devpriv->i_IobaseAmcc + |
| APCI1564_DIGITAL_OP_WATCHDOG + |
| APCI1564_TCW_IRQ); |
| outl(0x0, |
| devpriv->iobase + APCI1564_COUNTER1 + |
| APCI1564_TCW_IRQ); |
| outl(0x0, |
| devpriv->iobase + APCI1564_COUNTER2 + |
| APCI1564_TCW_IRQ); |
| outl(0x0, |
| devpriv->iobase + APCI1564_COUNTER3 + |
| APCI1564_TCW_IRQ); |
| outl(0x0, |
| devpriv->iobase + APCI1564_COUNTER4 + |
| APCI1564_TCW_IRQ); |
| } /* if (data[1]==1) */ |
| else { |
| outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* disable Timer interrupt */ |
| } /* else if (data[1]==1) */ |
| |
| /* Loading Timebase */ |
| |
| outl(data[2], |
| devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_TIMEBASE); |
| |
| /* Loading the Reload value */ |
| outl(data[3], |
| devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_RELOAD_VALUE); |
| |
| ul_Command1 = |
| inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_PROG); |
| ul_Command1 = |
| (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL; |
| outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* mode 2 */ |
| } /* else if (data[0]==ADDIDATA_TIMER) */ |
| else if (data[0] == ADDIDATA_COUNTER) { |
| devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; |
| devpriv->b_ModeSelectRegister = data[5]; |
| |
| /* First Stop The Counter */ |
| ul_Command1 = |
| inl(devpriv->iobase + ((data[5] - 1) * 0x20) + |
| APCI1564_TCW_PROG); |
| ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; |
| outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG); /* Stop The Timer */ |
| |
| /************************/ |
| /* Set the reload value */ |
| /************************/ |
| outl(data[3], |
| devpriv->iobase + ((data[5] - 1) * 0x20) + |
| APCI1564_TCW_RELOAD_VALUE); |
| |
| /******************************/ |
| /* Set the mode : */ |
| /* - Disable the hardware */ |
| /* - Disable the counter mode */ |
| /* - Disable the warning */ |
| /* - Disable the reset */ |
| /* - Disable the timer mode */ |
| /* - Enable the counter mode */ |
| /******************************/ |
| ul_Command1 = |
| (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL | |
| (unsigned int) ((unsigned int) data[4] << 16UL); |
| outl(ul_Command1, |
| devpriv->iobase + ((data[5] - 1) * 0x20) + |
| APCI1564_TCW_PROG); |
| |
| /* Enable or Disable Interrupt */ |
| ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1); |
| outl(ul_Command1, |
| devpriv->iobase + ((data[5] - 1) * 0x20) + |
| APCI1564_TCW_PROG); |
| |
| /*****************************/ |
| /* Set the Up/Down selection */ |
| /*****************************/ |
| ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18); |
| outl(ul_Command1, |
| devpriv->iobase + ((data[5] - 1) * 0x20) + |
| APCI1564_TCW_PROG); |
| } /* else if (data[0]==ADDIDATA_COUNTER) */ |
| else { |
| printk(" Invalid subdevice."); |
| } /* else if (data[0]==ADDIDATA_WATCHDOG) */ |
| |
| return insn->n; |
| } |
| |
| /* |
| +----------------------------------------------------------------------------+ |
| | Function Name : int i_APCI1564_StartStopWriteTimerCounterWatchdog | |
| | (struct comedi_device *dev,struct comedi_subdevice *s, | |
| | struct comedi_insn *insn,unsigned int *data) | |
| +----------------------------------------------------------------------------+ |
| | Task : Start / Stop The Selected Timer , Counter or Watchdog | |
| +----------------------------------------------------------------------------+ |
| | Input Parameters : struct comedi_device *dev : Driver handle | |
| | unsigned int *data : Data Pointer contains | |
| | configuration parameters as below | |
| | | |
| | data[0] : 0 Timer | |
| | 1 Counter | |
| | 2 Watchdog | | data[1] : 1 Start | |
| | 0 Stop | |
| | 2 Trigger | |
| | Clear (Only Counter) | |
| +----------------------------------------------------------------------------+ |
| | Output Parameters : -- | |
| +----------------------------------------------------------------------------+ |
| | Return Value : TRUE : No error occur | |
| | : FALSE : Error occur. Return the error | |
| | | |
| +----------------------------------------------------------------------------+ |
| */ |
| static int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
| { |
| struct addi_private *devpriv = dev->private; |
| unsigned int ul_Command1 = 0; |
| |
| if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { |
| switch (data[1]) { |
| case 0: /* stop the watchdog */ |
| outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG); /* disable the watchdog */ |
| break; |
| case 1: /* start the watchdog */ |
| outl(0x0001, |
| devpriv->i_IobaseAmcc + |
| APCI1564_DIGITAL_OP_WATCHDOG + |
| APCI1564_TCW_PROG); |
| break; |
| case 2: /* Software trigger */ |
| outl(0x0201, |
| devpriv->i_IobaseAmcc + |
| APCI1564_DIGITAL_OP_WATCHDOG + |
| APCI1564_TCW_PROG); |
| break; |
| default: |
| printk("\nSpecified functionality does not exist\n"); |
| return -EINVAL; |
| } /* switch (data[1]) */ |
| } /* if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */ |
| if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { |
| if (data[1] == 1) { |
| ul_Command1 = |
| inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_PROG); |
| ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; |
| |
| /* Enable the Timer */ |
| outl(ul_Command1, |
| devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_PROG); |
| } /* if (data[1]==1) */ |
| else if (data[1] == 0) { |
| /* Stop The Timer */ |
| |
| ul_Command1 = |
| inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_PROG); |
| ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; |
| outl(ul_Command1, |
| devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_PROG); |
| } /* else if(data[1]==0) */ |
| } /* if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */ |
| if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { |
| ul_Command1 = |
| inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister - |
| 1) * 0x20) + APCI1564_TCW_PROG); |
| if (data[1] == 1) { |
| /* Start the Counter subdevice */ |
| ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; |
| } /* if (data[1] == 1) */ |
| else if (data[1] == 0) { |
| /* Stops the Counter subdevice */ |
| ul_Command1 = 0; |
| |
| } /* else if (data[1] == 0) */ |
| else if (data[1] == 2) { |
| /* Clears the Counter subdevice */ |
| ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400; |
| } /* else if (data[1] == 3) */ |
| outl(ul_Command1, |
| devpriv->iobase + ((devpriv->b_ModeSelectRegister - |
| 1) * 0x20) + APCI1564_TCW_PROG); |
| } /* if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */ |
| return insn->n; |
| } |
| |
| /* |
| +----------------------------------------------------------------------------+ |
| | Function Name : int i_APCI1564_ReadTimerCounterWatchdog | |
| | (struct comedi_device *dev,struct comedi_subdevice *s, | |
| | struct comedi_insn *insn,unsigned int *data) | |
| +----------------------------------------------------------------------------+ |
| | Task : Read The Selected Timer , Counter or Watchdog | |
| +----------------------------------------------------------------------------+ |
| | Input Parameters : struct comedi_device *dev : Driver handle | |
| | unsigned int *data : Data Pointer contains | |
| | configuration parameters as below | |
| | | |
| |
| +----------------------------------------------------------------------------+ |
| | Output Parameters : -- | |
| +----------------------------------------------------------------------------+ |
| | Return Value : TRUE : No error occur | |
| | : FALSE : Error occur. Return the error | |
| | | |
| +----------------------------------------------------------------------------+ |
| */ |
| static int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
| { |
| struct addi_private *devpriv = dev->private; |
| unsigned int ul_Command1 = 0; |
| |
| if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { |
| /* Stores the status of the Watchdog */ |
| data[0] = |
| inl(devpriv->i_IobaseAmcc + |
| APCI1564_DIGITAL_OP_WATCHDOG + |
| APCI1564_TCW_TRIG_STATUS) & 0x1; |
| data[1] = |
| inl(devpriv->i_IobaseAmcc + |
| APCI1564_DIGITAL_OP_WATCHDOG); |
| } /* if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */ |
| else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { |
| /* Stores the status of the Timer */ |
| data[0] = |
| inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_TRIG_STATUS) & 0x1; |
| |
| /* Stores the Actual value of the Timer */ |
| data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER); |
| } /* else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */ |
| else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { |
| /* Read the Counter Actual Value. */ |
| data[0] = |
| inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister - |
| 1) * 0x20) + |
| APCI1564_TCW_SYNC_ENABLEDISABLE); |
| ul_Command1 = |
| inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister - |
| 1) * 0x20) + APCI1564_TCW_TRIG_STATUS); |
| |
| /***********************************/ |
| /* Get the software trigger status */ |
| /***********************************/ |
| data[1] = (unsigned char) ((ul_Command1 >> 1) & 1); |
| |
| /***********************************/ |
| /* Get the hardware trigger status */ |
| /***********************************/ |
| data[2] = (unsigned char) ((ul_Command1 >> 2) & 1); |
| |
| /*********************************/ |
| /* Get the software clear status */ |
| /*********************************/ |
| data[3] = (unsigned char) ((ul_Command1 >> 3) & 1); |
| |
| /***************************/ |
| /* Get the overflow status */ |
| /***************************/ |
| data[4] = (unsigned char) ((ul_Command1 >> 0) & 1); |
| } /* else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */ |
| else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER) |
| && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG) |
| && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) { |
| printk("\n Invalid Subdevice !!!\n"); |
| } /* else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) */ |
| return insn->n; |
| } |
| |
| /* |
| +----------------------------------------------------------------------------+ |
| | Function Name : int i_APCI1564_ReadInterruptStatus | |
| | (struct comedi_device *dev,struct comedi_subdevice *s, | |
| | struct comedi_insn *insn,unsigned int *data) | |
| +----------------------------------------------------------------------------+ |
| | Task :Reads the interrupt status register | |
| +----------------------------------------------------------------------------+ |
| | Input Parameters : | |
| +----------------------------------------------------------------------------+ |
| | Output Parameters : -- | |
| +----------------------------------------------------------------------------+ |
| | Return Value : | |
| | | |
| +----------------------------------------------------------------------------+ |
| */ |
| |
| static int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
| { |
| *data = ui_Type; |
| return insn->n; |
| } |
| |
| /* |
| +----------------------------------------------------------------------------+ |
| | Function Name : static void v_APCI1564_Interrupt | |
| | (int irq , void *d) | |
| +----------------------------------------------------------------------------+ |
| | Task : Interrupt handler for the interruptible digital inputs | |
| +----------------------------------------------------------------------------+ |
| | Input Parameters : int irq : irq number | |
| | void *d : void pointer | |
| +----------------------------------------------------------------------------+ |
| | Output Parameters : -- | |
| +----------------------------------------------------------------------------+ |
| | Return Value : TRUE : No error occur | |
| | : FALSE : Error occur. Return the error | |
| | | |
| +----------------------------------------------------------------------------+ |
| */ |
| static void v_APCI1564_Interrupt(int irq, void *d) |
| { |
| struct comedi_device *dev = d; |
| struct addi_private *devpriv = dev->private; |
| unsigned int ui_DO, ui_DI; |
| unsigned int ui_Timer; |
| unsigned int ui_C1, ui_C2, ui_C3, ui_C4; |
| unsigned int ul_Command2 = 0; |
| |
| ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_IRQ) & 0x01; |
| ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + |
| APCI1564_DIGITAL_OP_IRQ) & 0x01; |
| ui_Timer = |
| inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_IRQ) & 0x01; |
| ui_C1 = inl(devpriv->iobase + APCI1564_COUNTER1 + |
| APCI1564_TCW_IRQ) & 0x1; |
| ui_C2 = inl(devpriv->iobase + APCI1564_COUNTER2 + |
| APCI1564_TCW_IRQ) & 0x1; |
| ui_C3 = inl(devpriv->iobase + APCI1564_COUNTER3 + |
| APCI1564_TCW_IRQ) & 0x1; |
| ui_C4 = inl(devpriv->iobase + APCI1564_COUNTER4 + |
| APCI1564_TCW_IRQ) & 0x1; |
| if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0 |
| && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) { |
| printk("\nInterrupt from unknown source\n"); |
| } /* if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) */ |
| |
| if (ui_DI == 1) { |
| ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_IRQ); |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_IRQ); |
| ui_InterruptStatus_1564 = |
| inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + |
| APCI1564_DIGITAL_IP_INTERRUPT_STATUS); |
| ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0; |
| send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ |
| outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); /* enable the interrupt */ |
| return; |
| } |
| |
| if (ui_DO == 1) { |
| /* Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. */ |
| ui_Type = |
| inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + |
| APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3; |
| /* Disable the Interrupt */ |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + |
| APCI1564_DIGITAL_OP_INTERRUPT); |
| |
| /* Sends signal to user space */ |
| send_sig(SIGIO, devpriv->tsk_Current, 0); |
| |
| } /* if (ui_DO) */ |
| |
| if (ui_Timer == 1) { |
| devpriv->b_TimerSelectMode = ADDIDATA_TIMER; |
| if (devpriv->b_TimerSelectMode) { |
| |
| /* Disable Timer Interrupt */ |
| ul_Command2 = |
| inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_PROG); |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_PROG); |
| |
| /* Send a signal to from kernel to user space */ |
| send_sig(SIGIO, devpriv->tsk_Current, 0); |
| |
| /* Enable Timer Interrupt */ |
| |
| outl(ul_Command2, |
| devpriv->i_IobaseAmcc + APCI1564_TIMER + |
| APCI1564_TCW_PROG); |
| } |
| }/* if (ui_Timer == 1) */ |
| |
| |
| if (ui_C1 == 1) { |
| devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; |
| if (devpriv->b_TimerSelectMode) { |
| |
| /* Disable Counter Interrupt */ |
| ul_Command2 = |
| inl(devpriv->iobase + APCI1564_COUNTER1 + |
| APCI1564_TCW_PROG); |
| outl(0x0, |
| devpriv->iobase + APCI1564_COUNTER1 + |
| APCI1564_TCW_PROG); |
| |
| /* Send a signal to from kernel to user space */ |
| send_sig(SIGIO, devpriv->tsk_Current, 0); |
| |
| /* Enable Counter Interrupt */ |
| outl(ul_Command2, |
| devpriv->iobase + APCI1564_COUNTER1 + |
| APCI1564_TCW_PROG); |
| } |
| } /* if (ui_C1 == 1) */ |
| |
| if (ui_C2 == 1) { |
| devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; |
| if (devpriv->b_TimerSelectMode) { |
| |
| /* Disable Counter Interrupt */ |
| ul_Command2 = |
| inl(devpriv->iobase + APCI1564_COUNTER2 + |
| APCI1564_TCW_PROG); |
| outl(0x0, |
| devpriv->iobase + APCI1564_COUNTER2 + |
| APCI1564_TCW_PROG); |
| |
| /* Send a signal to from kernel to user space */ |
| send_sig(SIGIO, devpriv->tsk_Current, 0); |
| |
| /* Enable Counter Interrupt */ |
| outl(ul_Command2, |
| devpriv->iobase + APCI1564_COUNTER2 + |
| APCI1564_TCW_PROG); |
| } |
| } /* if ((ui_C2 == 1) */ |
| |
| if (ui_C3 == 1) { |
| devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; |
| if (devpriv->b_TimerSelectMode) { |
| |
| /* Disable Counter Interrupt */ |
| ul_Command2 = |
| inl(devpriv->iobase + APCI1564_COUNTER3 + |
| APCI1564_TCW_PROG); |
| outl(0x0, |
| devpriv->iobase + APCI1564_COUNTER3 + |
| APCI1564_TCW_PROG); |
| |
| /* Send a signal to from kernel to user space */ |
| send_sig(SIGIO, devpriv->tsk_Current, 0); |
| |
| /* Enable Counter Interrupt */ |
| outl(ul_Command2, |
| devpriv->iobase + APCI1564_COUNTER3 + |
| APCI1564_TCW_PROG); |
| } |
| } /* if ((ui_C3 == 1) */ |
| |
| if (ui_C4 == 1) { |
| devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; |
| if (devpriv->b_TimerSelectMode) { |
| |
| /* Disable Counter Interrupt */ |
| ul_Command2 = |
| inl(devpriv->iobase + APCI1564_COUNTER4 + |
| APCI1564_TCW_PROG); |
| outl(0x0, |
| devpriv->iobase + APCI1564_COUNTER4 + |
| APCI1564_TCW_PROG); |
| |
| /* Send a signal to from kernel to user space */ |
| send_sig(SIGIO, devpriv->tsk_Current, 0); |
| |
| /* Enable Counter Interrupt */ |
| outl(ul_Command2, |
| devpriv->iobase + APCI1564_COUNTER4 + |
| APCI1564_TCW_PROG); |
| } |
| } /* if (ui_C4 == 1) */ |
| return; |
| } |
| |
| /* |
| +----------------------------------------------------------------------------+ |
| | Function Name : int i_APCI1564_Reset(struct comedi_device *dev) | | |
| +----------------------------------------------------------------------------+ |
| | Task :resets all the registers | |
| +----------------------------------------------------------------------------+ |
| | Input Parameters : struct comedi_device *dev |
| +----------------------------------------------------------------------------+ |
| | Output Parameters : -- | |
| +----------------------------------------------------------------------------+ |
| | Return Value : | |
| | | |
| +----------------------------------------------------------------------------+ |
| */ |
| |
| static int i_APCI1564_Reset(struct comedi_device *dev) |
| { |
| struct addi_private *devpriv = dev->private; |
| |
| outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ); /* disable the interrupts */ |
| inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS); /* Reset the interrupt status register */ |
| outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); /* Disable the and/or interrupt */ |
| outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2); |
| devpriv->b_DigitalOutputRegister = 0; |
| ui_Type = 0; |
| outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP); /* Resets the output channels */ |
| outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT); /* Disables the interrupt. */ |
| outl(0x0, |
| devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + |
| APCI1564_TCW_RELOAD_VALUE); |
| outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER); |
| outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); |
| |
| outl(0x0, devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG); |
| outl(0x0, devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG); |
| outl(0x0, devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG); |
| outl(0x0, devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG); |
| return 0; |
| } |