/** @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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA You shoud also find the complete GPL in the COPYING file accompanying this source code. @endverbatim */ /* +-----------------------------------------------------------------------+ | (C) ADDI-DATA GmbH Dieselstrasse 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-3XXX | Compiler : GCC | | Module name : hwdrv_apci3xxx.c| Version : 2.96 | +-------------------------------+---------------------------------------+ | Project manager: S. Weber | Date : 15/09/2005 | +-----------------------------------------------------------------------+ | Description :APCI3XXX Module. Hardware abstraction Layer for APCI3XXX| +-----------------------------------------------------------------------+ | UPDATE'S | +-----------------------------------------------------------------------+ | Date | Author | Description of updates | +----------+-----------+------------------------------------------------+ | | | | | | | | +----------+-----------+------------------------------------------------+ */ #include "hwdrv_apci3xxx.h" /* +----------------------------------------------------------------------------+ | ANALOG INPUT FUNCTIONS | +----------------------------------------------------------------------------+ */ /* +----------------------------------------------------------------------------+ | Function Name : INT i_APCI3XXX_TestConversionStarted | | (struct comedi_device *dev) | +----------------------------------------------------------------------------+ | Task Test if any conversion started | +----------------------------------------------------------------------------+ | Input Parameters : - | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value : 0 : Conversion not started | | 1 : Conversion started | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev) { if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL) { return (1); } else { return (0); } } /* +----------------------------------------------------------------------------+ | Function Name : INT i_APCI3XXX_AnalogInputConfigOperatingMode | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task Converting mode and convert time selection | +----------------------------------------------------------------------------+ | Input Parameters : b_SingleDiff = (BYTE) data[1]; | | b_TimeBase = (BYTE) data[2]; (0: ns, 1:micros 2:ms)| | dw_ReloadValue = (DWORD) data[3]; | | ........ | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value :>0 : No error | | -1 : Single/Diff selection error | | -2 : Convert time base unity selection error | | -3 : Convert time value selection error | | -10: Any conversion started | | .... | | -100 : Config command error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; BYTE b_TimeBase = 0; BYTE b_SingleDiff = 0; DWORD dw_ReloadValue = 0; DWORD dw_TestReloadValue = 0; /************************/ /* Test the buffer size */ /************************/ if (insn->n == 4) { /****************************/ /* Get the Singel/Diff flag */ /****************************/ b_SingleDiff = (BYTE) data[1]; /****************************/ /* Get the time base unitiy */ /****************************/ b_TimeBase = (BYTE) data[2]; /*************************************/ /* Get the convert time reload value */ /*************************************/ dw_ReloadValue = (DWORD) data[3]; /**********************/ /* Test the time base */ /**********************/ if ((devpriv->ps_BoardInfo-> b_AvailableConvertUnit & (1 << b_TimeBase)) != 0) { /*******************************/ /* Test the convert time value */ /*******************************/ if ((dw_ReloadValue >= 0) && (dw_ReloadValue <= 65535)) { dw_TestReloadValue = dw_ReloadValue; if (b_TimeBase == 1) { dw_TestReloadValue = dw_TestReloadValue * 1000UL; } if (b_TimeBase == 2) { dw_TestReloadValue = dw_TestReloadValue * 1000000UL; } /*******************************/ /* Test the convert time value */ /*******************************/ if (dw_TestReloadValue >= devpriv->ps_BoardInfo-> ui_MinAcquisitiontimeNs) { if ((b_SingleDiff == APCI3XXX_SINGLE) || (b_SingleDiff == APCI3XXX_DIFF)) { if (((b_SingleDiff == APCI3XXX_SINGLE) && (devpriv->ps_BoardInfo->i_NbrAiChannel == 0)) || ((b_SingleDiff == APCI3XXX_DIFF) && (devpriv->ps_BoardInfo->i_NbrAiChannelDiff == 0))) { /*******************************/ /* Single/Diff selection error */ /*******************************/ printk("Single/Diff selection error\n"); i_ReturnValue = -1; } else { /**********************************/ /* Test if conversion not started */ /**********************************/ if (i_APCI3XXX_TestConversionStarted(dev) == 0) { devpriv-> ui_EocEosConversionTime = (UINT) dw_ReloadValue; devpriv-> b_EocEosConversionTimeBase = b_TimeBase; devpriv-> b_SingelDiff = b_SingleDiff; devpriv-> b_AiInitialisation = 1; /*******************************/ /* Set the convert timing unit */ /*******************************/ writel((DWORD) b_TimeBase, (void *) (devpriv-> dw_AiBase + 36)); /**************************/ /* Set the convert timing */ /*************************/ writel(dw_ReloadValue, (void *)(devpriv->dw_AiBase + 32)); } else { /**************************/ /* Any conversion started */ /**************************/ printk("Any conversion started\n"); i_ReturnValue = -10; } } } else { /*******************************/ /* Single/Diff selection error */ /*******************************/ printk("Single/Diff selection error\n"); i_ReturnValue = -1; } } else { /************************/ /* Time selection error */ /************************/ printk("Convert time value selection error\n"); i_ReturnValue = -3; } } else { /************************/ /* Time selection error */ /************************/ printk("Convert time value selection error\n"); i_ReturnValue = -3; } } else { /*****************************/ /* Time base selection error */ /*****************************/ printk("Convert time base unity selection error\n"); i_ReturnValue = -2; } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | Function Name : INT i_APCI3XXX_InsnConfigAnalogInput | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task Converting mode and convert time selection | +----------------------------------------------------------------------------+ | Input Parameters : b_ConvertMode = (BYTE) data[0]; | | b_TimeBase = (BYTE) data[1]; (0: ns, 1:micros 2:ms)| | dw_ReloadValue = (DWORD) data[2]; | | ........ | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value :>0: No error | | .... | | -100 : Config command error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 1) { switch ((BYTE) data[0]) { case APCI3XXX_CONFIGURATION: i_ReturnValue = i_APCI3XXX_AnalogInputConfigOperatingMode(dev, s, insn, data); break; default: i_ReturnValue = -100; printk("Config command error %d\n", data[0]); break; } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | Function Name : INT i_APCI3XXX_InsnReadAnalogInput | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task Read 1 analog input | +----------------------------------------------------------------------------+ | Input Parameters : b_Range = CR_RANGE(insn->chanspec); | | b_Channel = CR_CHAN(insn->chanspec); | | dw_NbrOfAcquisition = insn->n; | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value :>0: No error | | -3 : Channel selection error | | -4 : Configuration selelection error | | -10: Any conversion started | | .... | | -100 : Config command error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; BYTE b_Configuration = (BYTE) CR_RANGE(insn->chanspec); BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); DWORD dw_Temp = 0; DWORD dw_Configuration = 0; DWORD dw_AcquisitionCpt = 0; BYTE b_Interrupt = 0; /*************************************/ /* Test if operating mode configured */ /*************************************/ if (devpriv->b_AiInitialisation) { /***************************/ /* Test the channel number */ /***************************/ if (((b_Channel < devpriv->ps_BoardInfo->i_NbrAiChannel) && (devpriv->b_SingelDiff == APCI3XXX_SINGLE)) || ((b_Channel < devpriv->ps_BoardInfo-> i_NbrAiChannelDiff) && (devpriv->b_SingelDiff == APCI3XXX_DIFF))) { /**********************************/ /* Test the channel configuration */ /**********************************/ if (b_Configuration > 7) { /***************************/ /* Channel not initialised */ /***************************/ i_ReturnValue = -4; printk("Channel %d range %d selection error\n", b_Channel, b_Configuration); } } else { /***************************/ /* Channel selection error */ /***************************/ i_ReturnValue = -3; printk("Channel %d selection error\n", b_Channel); } /**************************/ /* Test if no error occur */ /**************************/ if (i_ReturnValue >= 0) { /************************/ /* Test the buffer size */ /************************/ if ((b_Interrupt != 0) || ((b_Interrupt == 0) && (insn->n >= 1))) { /**********************************/ /* Test if conversion not started */ /**********************************/ if (i_APCI3XXX_TestConversionStarted(dev) == 0) { /******************/ /* Clear the FIFO */ /******************/ writel(0x10000UL, (void *)(devpriv->dw_AiBase + 12)); /*******************************/ /* Get and save the delay mode */ /*******************************/ dw_Temp = readl((void *)(devpriv-> dw_AiBase + 4)); dw_Temp = dw_Temp & 0xFFFFFEF0UL; /***********************************/ /* Channel configuration selection */ /***********************************/ writel(dw_Temp, (void *)(devpriv->dw_AiBase + 4)); /**************************/ /* Make the configuration */ /**************************/ dw_Configuration = (b_Configuration & 3) | ((DWORD) (b_Configuration >> 2) << 6) | ((DWORD) devpriv-> b_SingelDiff << 7); /***************************/ /* Write the configuration */ /***************************/ writel(dw_Configuration, (void *)(devpriv->dw_AiBase + 0)); /*********************/ /* Channel selection */ /*********************/ writel(dw_Temp | 0x100UL, (void *)(devpriv->dw_AiBase + 4)); writel((DWORD) b_Channel, (void *)(devpriv->dw_AiBase + 0)); /***********************/ /* Restaure delay mode */ /***********************/ writel(dw_Temp, (void *)(devpriv->dw_AiBase + 4)); /***********************************/ /* Set the number of sequence to 1 */ /***********************************/ writel(1, (void *)(devpriv->dw_AiBase + 48)); /***************************/ /* Save the interrupt flag */ /***************************/ devpriv->b_EocEosInterrupt = b_Interrupt; /*******************************/ /* Save the number of channels */ /*******************************/ devpriv->ui_AiNbrofChannels = 1; /******************************/ /* Test if interrupt not used */ /******************************/ if (b_Interrupt == 0) { for (dw_AcquisitionCpt = 0; dw_AcquisitionCpt < insn->n; dw_AcquisitionCpt++) { /************************/ /* Start the conversion */ /************************/ writel(0x80000UL, (void *) (devpriv-> dw_AiBase + 8)); /****************/ /* Wait the EOS */ /****************/ do { dw_Temp = readl( (void *) (devpriv-> dw_AiBase + 20)); dw_Temp = dw_Temp & 1; } while (dw_Temp != 1); /*************************/ /* Read the analog value */ /*************************/ data[dw_AcquisitionCpt] = (unsigned int) readl((void *) (devpriv-> dw_AiBase + 28)); } } else { /************************/ /* Start the conversion */ /************************/ writel(0x180000UL, (void *)(devpriv-> dw_AiBase + 8)); } } else { /**************************/ /* Any conversion started */ /**************************/ printk("Any conversion started\n"); i_ReturnValue = -10; } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } } } else { /***************************/ /* Channel selection error */ /***************************/ printk("Operating mode not configured\n"); i_ReturnValue = -1; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | Function name : void v_APCI3XXX_Interrupt (int irq, | | void *d) | +----------------------------------------------------------------------------+ | Task :Interrupt handler for APCI3XXX | | When interrupt occurs this gets called. | | First it finds which interrupt has been generated and | | handles corresponding interrupt | +----------------------------------------------------------------------------+ | Input Parameters : - | +----------------------------------------------------------------------------+ | Return Value : - | +----------------------------------------------------------------------------+ */ void v_APCI3XXX_Interrupt(int irq, void *d) { struct comedi_device *dev = d; BYTE b_CopyCpt = 0; DWORD dw_Status = 0; /***************************/ /* Test if interrupt occur */ /***************************/ if (((dw_Status = readl((void *)(devpriv->dw_AiBase + 16))) & 0x2UL) == 0x2UL) { /***********************/ /* Reset the interrupt */ /***********************/ writel(dw_Status, (void *)(devpriv->dw_AiBase + 16)); /*****************************/ /* Test if interrupt enabled */ /*****************************/ if (devpriv->b_EocEosInterrupt == 1) { /********************************/ /* Read all analog inputs value */ /********************************/ for (b_CopyCpt = 0; b_CopyCpt < devpriv->ui_AiNbrofChannels; b_CopyCpt++) { devpriv->ui_AiReadData[b_CopyCpt] = (UINT) readl((void *)(devpriv-> dw_AiBase + 28)); } /**************************/ /* Set the interrupt flag */ /**************************/ devpriv->b_EocEosInterrupt = 2; /**********************************************/ /* Send a signal to from kernel to user space */ /**********************************************/ send_sig(SIGIO, devpriv->tsk_Current, 0); } } } /* +----------------------------------------------------------------------------+ | ANALOG OUTPUT SUBDEVICE | +----------------------------------------------------------------------------+ */ /* +----------------------------------------------------------------------------+ | Function Name : INT i_APCI3XXX_InsnWriteAnalogOutput | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task Read 1 analog input | +----------------------------------------------------------------------------+ | Input Parameters : b_Range = CR_RANGE(insn->chanspec); | | b_Channel = CR_CHAN(insn->chanspec); | | data[0] = analog value; | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value :>0: No error | | -3 : Channel selection error | | -4 : Configuration selelection error | | .... | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec); BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); DWORD dw_Status = 0; INT i_ReturnValue = insn->n; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 1) { /***************************/ /* Test the channel number */ /***************************/ if (b_Channel < devpriv->ps_BoardInfo->i_NbrAoChannel) { /**********************************/ /* Test the channel configuration */ /**********************************/ if (b_Range < 2) { /***************************/ /* Set the range selection */ /***************************/ writel(b_Range, (void *)(devpriv->dw_AiBase + 96)); /**************************************************/ /* Write the analog value to the selected channel */ /**************************************************/ writel((data[0] << 8) | b_Channel, (void *)(devpriv->dw_AiBase + 100)); /****************************/ /* Wait the end of transfer */ /****************************/ do { dw_Status = readl((void *)(devpriv-> dw_AiBase + 96)); } while ((dw_Status & 0x100) != 0x100); } else { /***************************/ /* Channel not initialised */ /***************************/ i_ReturnValue = -4; printk("Channel %d range %d selection error\n", b_Channel, b_Range); } } else { /***************************/ /* Channel selection error */ /***************************/ i_ReturnValue = -3; printk("Channel %d selection error\n", b_Channel); } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | TTL FUNCTIONS | +----------------------------------------------------------------------------+ */ /* +----------------------------------------------------------------------------+ | Function Name : INT i_APCI3XXX_InsnConfigInitTTLIO | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task You must calling this function be | | for you call any other function witch access of TTL. | | APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)| +----------------------------------------------------------------------------+ | Input Parameters : b_InitType = (BYTE) data[0]; | | b_Port2Mode = (BYTE) data[1]; | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value :>0: No error | | -1: Port 2 mode selection is wrong | | .... | | -100 : Config command error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; BYTE b_Command = 0; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 1) { /*******************/ /* Get the command */ /* **************** */ b_Command = (BYTE) data[0]; /********************/ /* Test the command */ /********************/ if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) { /***************************************/ /* Test the initialisation buffer size */ /***************************************/ if ((b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) && (insn->n != 2)) { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } } else { /************************/ /* Config command error */ /************************/ printk("Command selection error\n"); i_ReturnValue = -100; } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } /*********************************************************************************/ /* Test if no error occur and APCI3XXX_TTL_INIT_DIRECTION_PORT2 command selected */ /*********************************************************************************/ if ((i_ReturnValue >= 0) && (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)) { /**********************/ /* Test the direction */ /**********************/ if ((data[1] == 0) || (data[1] == 0xFF)) { /**************************/ /* Save the configuration */ /**************************/ devpriv->ul_TTLPortConfiguration[0] = devpriv->ul_TTLPortConfiguration[0] | data[1]; } else { /************************/ /* Port direction error */ /************************/ printk("Port 2 direction selection error\n"); i_ReturnValue = -1; } } /**************************/ /* Test if no error occur */ /**************************/ if (i_ReturnValue >= 0) { /***********************************/ /* Test if TTL port initilaisation */ /***********************************/ if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) { /*************************/ /* Set the configuration */ /*************************/ outl(data[1], devpriv->iobase + 224); } } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | TTL INPUT FUNCTIONS | +----------------------------------------------------------------------------+ */ /* +----------------------------------------------------------------------------+ | Function Name : INT i_APCI3XXX_InsnBitsTTLIO | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Write the selected output mask and read the status from| | all TTL channles | +----------------------------------------------------------------------------+ | Input Parameters : dw_ChannelMask = data [0]; | | dw_BitMask = data [1]; | +----------------------------------------------------------------------------+ | Output Parameters : data[1] : All TTL channles states | +----------------------------------------------------------------------------+ | Return Value : >0 : No error | | -4 : Channel mask error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; BYTE b_ChannelCpt = 0; DWORD dw_ChannelMask = 0; DWORD dw_BitMask = 0; DWORD dw_Status = 0; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 2) { /*******************************/ /* Get the channe and bit mask */ /*******************************/ dw_ChannelMask = data[0]; dw_BitMask = data[1]; /*************************/ /* Test the channel mask */ /*************************/ if (((dw_ChannelMask & 0XFF00FF00) == 0) && (((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0xFF) || (((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) && ((dw_ChannelMask & 0XFF0000) == 0)))) { /*********************************/ /* Test if set/reset any channel */ /*********************************/ if (dw_ChannelMask) { /****************************************/ /* Test if set/rest any port 0 channels */ /****************************************/ if (dw_ChannelMask & 0xFF) { /*******************************************/ /* Read port 0 (first digital output port) */ /*******************************************/ dw_Status = inl(devpriv->iobase + 80); for (b_ChannelCpt = 0; b_ChannelCpt < 8; b_ChannelCpt++) { if ((dw_ChannelMask >> b_ChannelCpt) & 1) { dw_Status = (dw_Status & (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt)); } } outl(dw_Status, devpriv->iobase + 80); } /****************************************/ /* Test if set/rest any port 2 channels */ /****************************************/ if (dw_ChannelMask & 0xFF0000) { dw_BitMask = dw_BitMask >> 16; dw_ChannelMask = dw_ChannelMask >> 16; /********************************************/ /* Read port 2 (second digital output port) */ /********************************************/ dw_Status = inl(devpriv->iobase + 112); for (b_ChannelCpt = 0; b_ChannelCpt < 8; b_ChannelCpt++) { if ((dw_ChannelMask >> b_ChannelCpt) & 1) { dw_Status = (dw_Status & (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt)); } } outl(dw_Status, devpriv->iobase + 112); } } /*******************************************/ /* Read port 0 (first digital output port) */ /*******************************************/ data[1] = inl(devpriv->iobase + 80); /******************************************/ /* Read port 1 (first digital input port) */ /******************************************/ data[1] = data[1] | (inl(devpriv->iobase + 64) << 8); /************************/ /* Test if port 2 input */ /************************/ if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) { data[1] = data[1] | (inl(devpriv->iobase + 96) << 16); } else { data[1] = data[1] | (inl(devpriv->iobase + 112) << 16); } } else { /************************/ /* Config command error */ /************************/ printk("Channel mask error\n"); i_ReturnValue = -4; } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | Function Name : INT i_APCI3XXX_InsnReadTTLIO | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Read the status from selected channel | +----------------------------------------------------------------------------+ | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) | +----------------------------------------------------------------------------+ | Output Parameters : data[0] : Selected TTL channel state | +----------------------------------------------------------------------------+ | Return Value : 0 : No error | | -3 : Channel selection error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); INT i_ReturnValue = insn->n; unsigned int *pls_ReadData = data; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 1) { /***********************/ /* Test if read port 0 */ /***********************/ if (b_Channel < 8) { /*******************************************/ /* Read port 0 (first digital output port) */ /*******************************************/ pls_ReadData[0] = inl(devpriv->iobase + 80); pls_ReadData[0] = (pls_ReadData[0] >> b_Channel) & 1; } else { /***********************/ /* Test if read port 1 */ /***********************/ if ((b_Channel > 7) && (b_Channel < 16)) { /******************************************/ /* Read port 1 (first digital input port) */ /******************************************/ pls_ReadData[0] = inl(devpriv->iobase + 64); pls_ReadData[0] = (pls_ReadData[0] >> (b_Channel - 8)) & 1; } else { /***********************/ /* Test if read port 2 */ /***********************/ if ((b_Channel > 15) && (b_Channel < 24)) { /************************/ /* Test if port 2 input */ /************************/ if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) { pls_ReadData[0] = inl(devpriv->iobase + 96); pls_ReadData[0] = (pls_ReadData[0] >> (b_Channel - 16)) & 1; } else { pls_ReadData[0] = inl(devpriv->iobase + 112); pls_ReadData[0] = (pls_ReadData[0] >> (b_Channel - 16)) & 1; } } else { /***************************/ /* Channel selection error */ /***************************/ i_ReturnValue = -3; printk("Channel %d selection error\n", b_Channel); } } } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | TTL OUTPUT FUNCTIONS | +----------------------------------------------------------------------------+ */ /* +----------------------------------------------------------------------------+ | Function Name : INT i_APCI3XXX_InsnWriteTTLIO | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Set the state from TTL output channel | +----------------------------------------------------------------------------+ | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) | | b_State = data [0] | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value : 0 : No error | | -3 : Channel selection error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); BYTE b_State = 0; DWORD dw_Status = 0; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 1) { b_State = (BYTE) data[0]; /***********************/ /* Test if read port 0 */ /***********************/ if (b_Channel < 8) { /*****************************************************************************/ /* Read port 0 (first digital output port) and set/reset the selcted channel */ /*****************************************************************************/ dw_Status = inl(devpriv->iobase + 80); dw_Status = (dw_Status & (0xFF - (1 << b_Channel))) | ((b_State & 1) << b_Channel); outl(dw_Status, devpriv->iobase + 80); } else { /***********************/ /* Test if read port 2 */ /***********************/ if ((b_Channel > 15) && (b_Channel < 24)) { /*************************/ /* Test if port 2 output */ /*************************/ if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0xFF) { /*****************************************************************************/ /* Read port 2 (first digital output port) and set/reset the selcted channel */ /*****************************************************************************/ dw_Status = inl(devpriv->iobase + 112); dw_Status = (dw_Status & (0xFF - (1 << (b_Channel - 16)))) | ((b_State & 1) << (b_Channel - 16)); outl(dw_Status, devpriv->iobase + 112); } else { /***************************/ /* Channel selection error */ /***************************/ i_ReturnValue = -3; printk("Channel %d selection error\n", b_Channel); } } else { /***************************/ /* Channel selection error */ /***************************/ i_ReturnValue = -3; printk("Channel %d selection error\n", b_Channel); } } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | DIGITAL INPUT SUBDEVICE | +----------------------------------------------------------------------------+ */ /* +----------------------------------------------------------------------------+ | Function name :int i_APCI3XXX_InsnReadDigitalInput | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Reads the value of the specified Digital input channel | +----------------------------------------------------------------------------+ | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) (0 to 3) | +----------------------------------------------------------------------------+ | Output Parameters : data[0] : Channel value | +----------------------------------------------------------------------------+ | Return Value : 0 : No error | | -3 : Channel selection error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); DWORD dw_Temp = 0; /***************************/ /* Test the channel number */ /***************************/ if (b_Channel <= devpriv->ps_BoardInfo->i_NbrDiChannel) { /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 1) { dw_Temp = inl(devpriv->iobase + 32); *data = (dw_Temp >> b_Channel) & 1; } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } } else { /***************************/ /* Channel selection error */ /***************************/ printk("Channel selection error\n"); i_ReturnValue = -3; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | Function name :int i_APCI3XXX_InsnBitsDigitalInput | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Reads the value of the Digital input Port i.e.4channels| +----------------------------------------------------------------------------+ | Input Parameters : - | +----------------------------------------------------------------------------+ | Output Parameters : data[0] : Port value | +----------------------------------------------------------------------------+ | Return Value :>0: No error | | .... | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; DWORD dw_Temp = 0; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 1) { dw_Temp = inl(devpriv->iobase + 32); *data = dw_Temp & 0xf; } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | DIGITAL OUTPUT SUBDEVICE | +----------------------------------------------------------------------------+ */ /* +----------------------------------------------------------------------------+ | Function name :int i_APCI3XXX_InsnBitsDigitalOutput | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Write the selected output mask and read the status from| | all digital output channles | +----------------------------------------------------------------------------+ | Input Parameters : dw_ChannelMask = data [0]; | | dw_BitMask = data [1]; | +----------------------------------------------------------------------------+ | Output Parameters : data[1] : All digital output channles states | +----------------------------------------------------------------------------+ | Return Value : >0 : No error | | -4 : Channel mask error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; BYTE b_ChannelCpt = 0; DWORD dw_ChannelMask = 0; DWORD dw_BitMask = 0; DWORD dw_Status = 0; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 2) { /*******************************/ /* Get the channe and bit mask */ /*******************************/ dw_ChannelMask = data[0]; dw_BitMask = data[1]; /*************************/ /* Test the channel mask */ /*************************/ if ((dw_ChannelMask & 0XFFFFFFF0) == 0) { /*********************************/ /* Test if set/reset any channel */ /*********************************/ if (dw_ChannelMask & 0xF) { /********************************/ /* Read the digital output port */ /********************************/ dw_Status = inl(devpriv->iobase + 48); for (b_ChannelCpt = 0; b_ChannelCpt < 4; b_ChannelCpt++) { if ((dw_ChannelMask >> b_ChannelCpt) & 1) { dw_Status = (dw_Status & (0xF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt)); } } outl(dw_Status, devpriv->iobase + 48); } /********************************/ /* Read the digital output port */ /********************************/ data[1] = inl(devpriv->iobase + 48); } else { /************************/ /* Config command error */ /************************/ printk("Channel mask error\n"); i_ReturnValue = -4; } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | Function name :int i_APCI3XXX_InsnWriteDigitalOutput | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Set the state from digital output channel | +----------------------------------------------------------------------------+ | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) | | b_State = data [0] | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value : >0 : No error | | -3 : Channel selection error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; BYTE b_Channel = CR_CHAN(insn->chanspec); BYTE b_State = 0; DWORD dw_Status = 0; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 1) { /***************************/ /* Test the channel number */ /***************************/ if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) { /*******************/ /* Get the command */ /*******************/ b_State = (BYTE) data[0]; /********************************/ /* Read the digital output port */ /********************************/ dw_Status = inl(devpriv->iobase + 48); dw_Status = (dw_Status & (0xF - (1 << b_Channel))) | ((b_State & 1) << b_Channel); outl(dw_Status, devpriv->iobase + 48); } else { /***************************/ /* Channel selection error */ /***************************/ printk("Channel selection error\n"); i_ReturnValue = -3; } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | Function name :int i_APCI3XXX_InsnReadDigitalOutput | | (struct comedi_device *dev, | | struct comedi_subdevice *s, | | struct comedi_insn *insn, | | unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Read the state from digital output channel | +----------------------------------------------------------------------------+ | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) | +----------------------------------------------------------------------------+ | Output Parameters : b_State = data [0] | +----------------------------------------------------------------------------+ | Return Value : >0 : No error | | -3 : Channel selection error | | -101 : Data size error | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) { INT i_ReturnValue = insn->n; BYTE b_Channel = CR_CHAN(insn->chanspec); DWORD dw_Status = 0; /************************/ /* Test the buffer size */ /************************/ if (insn->n >= 1) { /***************************/ /* Test the channel number */ /***************************/ if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) { /********************************/ /* Read the digital output port */ /********************************/ dw_Status = inl(devpriv->iobase + 48); dw_Status = (dw_Status >> b_Channel) & 1; *data = dw_Status; } else { /***************************/ /* Channel selection error */ /***************************/ printk("Channel selection error\n"); i_ReturnValue = -3; } } else { /*******************/ /* Data size error */ /*******************/ printk("Buffer size error\n"); i_ReturnValue = -101; } return (i_ReturnValue); } /* +----------------------------------------------------------------------------+ | Function Name : int i_APCI3XXX_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+ | Task :resets all the registers | +----------------------------------------------------------------------------+ | Input Parameters : struct comedi_device *dev | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value : - | +----------------------------------------------------------------------------+ */ int i_APCI3XXX_Reset(struct comedi_device * dev) { unsigned char b_Cpt = 0; /*************************/ /* Disable the interrupt */ /*************************/ disable_irq(dev->irq); /****************************/ /* Reset the interrupt flag */ /****************************/ devpriv->b_EocEosInterrupt = 0; /***************************/ /* Clear the start command */ /***************************/ writel(0, (void *)(devpriv->dw_AiBase + 8)); /*****************************/ /* Reset the interrupt flags */ /*****************************/ writel(readl((void *)(devpriv->dw_AiBase + 16)), (void *)(devpriv->dw_AiBase + 16)); /*****************/ /* clear the EOS */ /*****************/ readl((void *)(devpriv->dw_AiBase + 20)); /******************/ /* Clear the FIFO */ /******************/ for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) { readl((void *)(devpriv->dw_AiBase + 28)); } /************************/ /* Enable the interrupt */ /************************/ enable_irq(dev->irq); return 0; }