/** @file scan.c

Contains analog inputs scan functions, to initialize and read analog values on the APCI-3200.

@par CREATION
@author Krauth Julien
@date   16.11.05

@par VERSION
@verbatim
$LastChangedRevision$
$LastChangedDate$
@endverbatim

@par COMPILER
@verbatim
Compiler	: gcc
Version	: gcc (GCC) 3.3.6 (Debian 1:3.3.6-5)
kernel	: 2.4.26
@endverbatim

@par UPDATES
@verbatim
Date			:
Author		:
Description	:
@endverbatim

@par LICENCE
@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
*/


#include "apci3200-private.h"
#include "iomap.h"

EXPORT_SYMBOL(i_APCI3200_InitScanModuleAcquisitionSensor);
EXPORT_SYMBOL(i_APCI3200_InitScanModuleAcquisition);
EXPORT_SYMBOL(i_APCI3200_StartScanModuleAcquisition);
EXPORT_SYMBOL(i_APCI3200_StopScanModuleAcquisition);

/**@def EXPORT_NO_SYMBOLS
* Function in this file are not exported.
*/
EXPORT_NO_SYMBOLS;

//------------------------------------------------------------------------------

/** Initialize one analog input.
*
* @param [in] pdev			: The device to initialize.
* @param [in] w_Module		: The module to use (0 to 3).
* @param [in] b_Channel	: The channel to initialize (0 to 3).
* @param [in] w_Gain		: Must be one (1) in all cases.
*
* @retval 0: No error.
* @retval 1: The handle parameter of the board is wrong.
* @retval 2: The module parameter is wrong.
* @retval -EIO Board access time out
*/
static int i_APCI3200_PrimaryInitAnalogInputChannel (struct pci_dev *pdev, WORD module, WORD w_Channel, WORD w_Gain)
{
	BYTE   b_Polarity      = 0;
	register unsigned long module_address = module_to_address(pdev,module);

	if (!pdev)
		return 1;

	//TODO: check parameters

	/* Checks if the module is valid */
	if (module >= APCI3200_PRIVDATA(pdev)->w_NbHardwareComponent) return 2;

	/* Test input type of module */
	if (GET_MODULE_DATA(pdev,module)->b_SensorType == ADDIDATA_THERMOCOUPLE)
	{
		/* Bipolar / Gain 1 / Single */
		b_Polarity = 0;
		w_Gain = 1;
	}
	else if (GET_MODULE_DATA(pdev,module)->b_SensorType == ADDIDATA_RTD)
	{
		/* Unipolar / Gain 1 / Differential */
		b_Polarity = 1;
		w_Gain = 1;
	}

	/* Prepare the configuration to write */
	{
		uint32_t dw_Configuration = 	 w_Gain | ((DWORD) b_Polarity << 6) | ( ( (DWORD) GET_MODULE_DATA(pdev,module)->b_DiffSingSelected ) << 7);

		/* Write the channel to configure */
		if( outl_module(module_address, APCI3200_REG_ACQUISITION_CONFIG, w_Channel) )
			return -EIO;

		/* Reset the configuration */
		if( outl_module(module_address, APCI3200_REG_CHANNEL_CONFIG, 0 ) )
			return -EIO;

		/* Write the configuration */
		if( outl_module(module_address, APCI3200_REG_CHANNEL_CONFIG, dw_Configuration) )
			return -EIO;
	}
	/* Reset the calibration bit (D18 and D17) */
	{
		uint32_t dw_Configuration = inl(module_address + APCI3200_REG_READYBIT);
		if( outl_module(module_address, APCI3200_REG_READYBIT, (dw_Configuration & 0xFFF8FFFF) ) )
			return -EIO;
	}
	return 0;
}

//------------------------------------------------------------------------------

/** Initialise the scan.
*
* Scan works on a complete module and not on single channels.
*
* @param [in] pdev			: The device to initialize.
* @param [in] module		: The module to use (0 to 3).
*
* @retval 0: No error.
* @retval 1: The handle parameter of the board is wrong.
* @retval 2: The module parameter is wrong.
* @retval -EIO Board access time out
*/
static int i_APCI3200_PrimaryInitAnalogInputSCAN (struct pci_dev *pdev, uint16_t module)
{
	BYTE   b_CurrentSource = 0;
	DWORD dw_Configuration = 0;
	BYTE   b_ChannelCpt    = 0;
	INT    i_ErrorCode     = 0;
	register unsigned long module_address = module_to_address(pdev,module);
	if (!pdev)
		return 1;

	/* Checks if the module is valid */
	if (module >= APCI3200_PRIVDATA(pdev)->w_NbHardwareComponent) return 2;

	for (b_ChannelCpt = 0; b_ChannelCpt < GET_MODULE_DATA(pdev,module)->w_NbChannel; b_ChannelCpt++)
	{
		/* Init the configuration of the channel */
		if ( (i_ErrorCode = i_APCI3200_PrimaryInitAnalogInputChannel (pdev ,module, b_ChannelCpt, 1)) != 0)
			return (i_ErrorCode);

		/* Test if the current source are used */
		if (GET_MODULE_DATA(pdev,module)->b_SensorType == ADDIDATA_RTD )
		{
			/* Activated the current source */
			b_CurrentSource = b_CurrentSource & (1 << b_ChannelCpt);

			/* Write the configuration of the current source */
			/* ?? */
			if( outl_module(module_address, APCI3200_REG_READYBIT, (b_CurrentSource << 22) ) )
				return -EIO;
		}
	}

	/* Set the new configuration */
	dw_Configuration =	0 | (3 << 8) | 0x00100000 |
	GET_MODULE_DATA(pdev,module)->b_SCANExternTriggerSelected << 24 |
	GET_MODULE_DATA(pdev,module)->b_SCANExternTriggerFrontSelected << 25 | 0x8 << 27 |
	GET_MODULE_DATA(pdev,module)->b_SCANDelayModeSelected << 18 |
	GET_MODULE_DATA(pdev,module)->b_SCANModeSelected << 16;

	/* Write the Configuration */
	if( outl_module(module_address, APCI3200_REG_ACQUISITION_CONTROL, dw_Configuration ) )
		return -EIO;

	/* following code is not needed! */
	// Write the counter value */
	//if( outl_module(module_address, 48, 0 ) )
	//	return -EIO;

	/* Write the Delay value */
	if( outl_module(module_address, APCI3200_REG_DELAY_VALUE, GET_MODULE_DATA(pdev,module)->dw_SCANDelayReloadValueSelected ) )
		return -EIO;

	/* Write the Delay time base */
	if( outl_module(module_address, APCI3200_REG_DELAY_BASE, GET_MODULE_DATA(pdev,module)->b_SCANDelayTimeBaseSelected ) )
		return -EIO;

	/* Write the conversion time value */
	if( outl_module(module_address, APCI3200_REG_CONVERSION_VALUE, GET_MODULE_DATA(pdev,module)->dw_SCANConversionReloadValueSelected ) )
		return -EIO;

	/* Write the conversion time base */
	if( outl_module(module_address, APCI3200_REG_CONVERSION_BASE, 2 ) )
		return -EIO;

	/* Set the SCAN bit */
	dw_Configuration = inl(module_address + APCI3200_REG_ACQUISITION_CONFIG);
	if( outl_module(module_address, APCI3200_REG_ACQUISITION_CONFIG, ((dw_Configuration & 0xFFFE1F00) | 0x00002000) ) )
		return -EIO;
	return 0;
}

//------------------------------------------------------------------------------

/** Start a scan.
*
* @param [in] pdev			: The device to initialize.
* @param [in] module		: The module to use (0 to 3).
*
* @retval 0: No error.
* @retval 1: The handle parameter of the board is wrong.
* @retval 2: The module parameter is wrong.
* @retval -EIO Board access time out
*/
static int i_APCI3200_PrimaryStartAnalogInputSCAN (struct pci_dev *pdev, uint16_t module)
{
	register unsigned long module_address = module_to_address(pdev,module);
	DWORD dw_Configuration = 0;

	if (!pdev) return 1;

	/* Checks if the module is valid */
	if (module >= APCI3200_PRIVDATA(pdev)->w_NbHardwareComponent) return 2;

	/* Set the START bit */
	dw_Configuration = inl(module_address + APCI3200_REG_ACQUISITION_CONTROL);

	/* Start */
	if( outl_module(module_address, APCI3200_REG_ACQUISITION_CONTROL, (dw_Configuration | 0x00080000) ) )
		return -EIO;

	return 0;
}

//------------------------------------------------------------------------------

/** Stop a scan.
*
* @param [in] pdev			: The device to initialize.
* @param [in] module		: The module to use (0 to 3).
*
* @retval 0: No error.
* @retval 1: The handle parameter of the board is wrong.
* @retval 2: The module parameter is wrong.
* @retval -EIO Board access time out
*/
static int i_APCI3200_PrimaryStopAnalogInputSCAN (struct pci_dev *pdev, uint16_t module)
{
	register unsigned long module_address = module_to_address(pdev,module);
	uint32_t dw_Configuration = 0;

	/* Checks if the module is valid */
	if (module >= APCI3200_PRIVDATA(pdev)->w_NbHardwareComponent)
		return 2;

	/* Reset the START and IRQ bit */

	dw_Configuration = inl(module_address + APCI3200_REG_ACQUISITION_CONTROL);
	if( outl_module(module_address, APCI3200_REG_ACQUISITION_CONTROL, (dw_Configuration & 0xFFE7FFFF) ) )
		return -EIO;

	return 0;
}

//------------------------------------------------------------------------------

/** Initialise scan module sensor type.
*
* @param [in] pdev				: The device to initialize.
* @param [in] module			: The module to use (0 to 3).
* @param [in] b_SensorType		: ADDIDATA_THERMOCOUPLE or ADDIDATA_RTD.
* @param [in] *b_SensorValue	: Thermocouple types: <br>
* 									ADDIDATA_THERMOCOUPLE_TYPE_B <br>
* 									ADDIDATA_THERMOCOUPLE_TYPE_E <br>
* 									ADDIDATA_THERMOCOUPLE_TYPE_J <br>
* 									ADDIDATA_THERMOCOUPLE_TYPE_K <br>
* 									ADDIDATA_THERMOCOUPLE_TYPE_N <br>
* 									ADDIDATA_THERMOCOUPLE_TYPE_R <br>
*									ADDIDATA_THERMOCOUPLE_TYPE_S <br>
*									ADDIDATA_THERMOCOUPLE_TYPE_T <br>
*
* 								 RTD types: <br>
* 									ADDIDATA_RTD_TYPE_PT <br>
* 									ADDIDATA_RTD_TYPE_Ni
*
* @param [in] b_DiffSingSelected	:  Connection type:<br>
* 									   if ADDIDATA_THERMOCOUPLE:
*                                          - APCI3200_CONNECTION_TYPE_SINGLE<br>
*                                          - APCI3200_CONNECTION_TYPE_DIFFERENTIAL
* 									   if ADDIDATA_RTD:
* 											- APCI3200_CONNECTION_TYPE_DIFFERENTIAL
*
* @retval 0: No error.
* @retval 1: The handle parameter of the board is wrong.
* @retval 2: The module parameter is wrong.
* @retval 3: The sensor parameter is wrong.
* @retval 4: The b_DiffSingSelected parameter is wrong.
*/
int i_APCI3200_InitScanModuleAcquisitionSensor (struct pci_dev *pdev, WORD module, BYTE b_SensorType, BYTE b_SensorValue[4], BYTE b_DiffSingSelected)
{
	unsigned int i_ChannelCounter = 0;

	if (!pdev)
		return 1;

	/* Checks if the module is valid */
	if (module >= APCI3200_PRIVDATA(pdev)->w_NbHardwareComponent)
		return 2;

	/* Checks if the sensor type and sensor value are valid. */
	switch (b_SensorType)
	{
	case ADDIDATA_THERMOCOUPLE:

		/*
		 * Values to read with thermocouple are:
		 * 1) Channel 0
		 * 2) Channel 1
		 * 3) Channel 2
		 * 4) Channel 3
		 * 5) CJC
		 * 6) Calibration offset
		 * 7) Calibration gain
		 */
		GET_MODULE_DATA(pdev,module)->ui_NbDataToRead = 7;
		GET_MODULE_DATA(pdev,module)->b_SensorType = ADDIDATA_THERMOCOUPLE;


		switch(b_DiffSingSelected)
		{
		case APCI3200_CONNECTION_TYPE_SINGLE:
			/*
			 * Values to read with thermocouple are:
			 * 1) Channel 0
			 * 2) Channel 1
			 * 3) Channel 2
			 * 4) Channel 3
			 * 5) CJC
			 * 6) Calibration offset
			 * 7) Calibration gain
			 */
			GET_MODULE_DATA(pdev,module)->ui_NbDataToRead = 7;
			GET_MODULE_DATA(pdev,module)->b_DiffSingSelected = b_DiffSingSelected;
			GET_MODULE_DATA(pdev,module)->w_NbChannel = 4; /* in single mode => 4 channels */
			break;
		case APCI3200_CONNECTION_TYPE_DIFFERENTIAL:
			/*
			 * Values to read with thermocouple are:
			 * 1) Channel 0
			 * 2) Channel 1
			 * 5) CJC
			 * 6) Calibration offset
			 * 7) Calibration gain
			 */
			GET_MODULE_DATA(pdev,module)->ui_NbDataToRead = 5;
			GET_MODULE_DATA(pdev,module)->b_DiffSingSelected = b_DiffSingSelected;
			GET_MODULE_DATA(pdev,module)->w_NbChannel = 2; /* in differential mode => 2 channels */
			break;
		default:
			return 4;
		}
		//TODO: parameter checking

		for (i_ChannelCounter = 0; i_ChannelCounter < GET_MODULE_DATA(pdev,module)->w_NbChannel; i_ChannelCounter++)
		{
			switch (b_SensorValue[i_ChannelCounter])
			{
			case ADDIDATA_THERMOCOUPLE_TYPE_B :
				GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_THERMOCOUPLE_TYPE_B;
				break;

			case ADDIDATA_THERMOCOUPLE_TYPE_E :
				GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_THERMOCOUPLE_TYPE_E;
				break;

			case ADDIDATA_THERMOCOUPLE_TYPE_J :
				GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_THERMOCOUPLE_TYPE_J;
				break;

			case ADDIDATA_THERMOCOUPLE_TYPE_K :
				GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_THERMOCOUPLE_TYPE_K;
				break;

			case ADDIDATA_THERMOCOUPLE_TYPE_N :
				GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_THERMOCOUPLE_TYPE_N;
				break;

			case ADDIDATA_THERMOCOUPLE_TYPE_R :
				GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_THERMOCOUPLE_TYPE_R;
				break;

			case ADDIDATA_THERMOCOUPLE_TYPE_S :
				GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_THERMOCOUPLE_TYPE_S;
				break;

			case ADDIDATA_THERMOCOUPLE_TYPE_T :
				GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_THERMOCOUPLE_TYPE_T;
				break;

			default:
				return 3;
				break;
			}
		}

		break;

		case ADDIDATA_RTD :

			/*
			 * Values to read with thermocouple are:
			 * 1) Channel 0
			 * 2) Channel 1
			 * 3) CJC
			 * 4) Calibration offset
			 * 5) Calibration gain
			 */
			GET_MODULE_DATA(pdev,module)->ui_NbDataToRead = 5;
			GET_MODULE_DATA(pdev,module)->b_SensorType = ADDIDATA_RTD;
			GET_MODULE_DATA(pdev,module)->w_NbChannel = 2;

			switch (b_DiffSingSelected)
			{
			case ADDIDATA_RTD:
				GET_MODULE_DATA(pdev,module)->b_DiffSingSelected = APCI3200_CONNECTION_TYPE_DIFFERENTIAL;
				break;
			default:
				return 4;
			}

			for (i_ChannelCounter = 0; i_ChannelCounter < GET_MODULE_DATA(pdev,module)->w_NbChannel; i_ChannelCounter++)
			{
				switch (b_SensorValue[i_ChannelCounter])
				{
				case ADDIDATA_RTD_TYPE_PT :
					GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_RTD_TYPE_PT;
					break;

				case ADDIDATA_RTD_TYPE_Ni :
					GET_MODULE_DATA(pdev,module)->b_SensorValue[i_ChannelCounter] = ADDIDATA_RTD_TYPE_Ni;
					break;

				default:
					return 3;
					break;
				}
			}

			break;

			default:
				return 4;
				break;
	}

	GET_MODULE_DATA(pdev,module)->b_ModuleInitialised = 1;

	return 0;
}

//------------------------------------------------------------------------------

/** Start scan module.
*
* @param [in] pdev				: The device to initialize.
* @param [in] module			: The module to use (0 to 3).
*
* @retval 0: No error.
* @retval 1: The handle parameter of the board is wrong.
* @retval 2: The module parameter is wrong.
* @retval 3: Scan not initialized.
* @retval 4: Scan already started.
* @retval 5: Scan can't be started.
*/
int i_APCI3200_StartScanModuleAcquisition (struct pci_dev *pdev, WORD module)
{
	if (!pdev) return 1;

	/* Checks if the module is valid */
	if (module >= APCI3200_PRIVDATA(pdev)->w_NbHardwareComponent)
		return 2;

	/* Test if the SCAN is initialised */
	if (!GET_MODULE_DATA(pdev,module)->b_SCANInitialised)
		return 3;

	/* Test if the SCAN is not started */
	if (GET_MODULE_DATA(pdev,module)->b_SCANStarted)
		return 4;

	/* Init the SCAN */
	if (i_APCI3200_PrimaryInitAnalogInputSCAN (pdev, module) != 0)
		return 5;

	/* Start the SCAN */
	if (i_APCI3200_PrimaryStartAnalogInputSCAN (pdev, module) != 0)
		return 5;

	GET_MODULE_DATA(pdev,module)->b_SCANStarted = 1;

	return 0;
}

//------------------------------------------------------------------------------

/** Stop scan module.
*
* @param [in] pdev				: The device to initialize.
* @param [in] module			: The module to use (0 to 3).
*
* @retval 0: No error.
* @retval 1: The handle parameter of the board is wrong.
* @retval 2: The module parameter is wrong.
* @retval 3: Scan not initialized.
* @retval 4: Scan not started.
* @retval 5: Scan can't be stopped.
*/
INT i_APCI3200_StopScanModuleAcquisition (struct pci_dev *pdev, WORD module)
{
	if (!pdev) return 1;

	/* Checks if the module is valid */
	if (module >= APCI3200_PRIVDATA(pdev)->w_NbHardwareComponent)
		return 2;

	/* Test if the SCAN is initialised */
	if (!GET_MODULE_DATA(pdev,module)->b_SCANInitialised)
		return 3;

	/* Test if the SCAN is not started */
	if (!GET_MODULE_DATA(pdev,module)->b_SCANStarted)
		return 4;

	/* Stop the SCAN */
	if (i_APCI3200_PrimaryStopAnalogInputSCAN (pdev, module) != 0)
		return 5;

	GET_MODULE_DATA(pdev,module)->b_SCANStarted = 0;

	return 0;
}

//------------------------------------------------------------------------------

/** Initialise the scan.
*
* @param [in] pdev					: The device to initialize.
* @param [in] module				: The module to use (0 to 3).
* @param [in] dw_ConversionTime	: Conversion time for each channels: <br>
* 									  in Hz : 20 - 40 - 80 - 160
*
* @param [in] b_SCANTimeMode		: Define the mode of the delay: <br>
* 										ADDIDATA_DELAY_NOT_USED: The delay between two SCANs is not used <br>
* 										ADDIDATA_DELAY_MODE1_USED: The delay between two SCANs is used. <br>
* 										The conversion is started at once, and the delay is used after the first SCAN.
* @param [in] dw_SCANTime			: Total time of the SCAN (including delay).
*
* @param [in] b_SCANTimeUnit		: APCI3200_MS (millisecond) or APCI3200_S (second)
*
* @param [in] b_SCANMode			: ADDIDATA_SINGLE_SCAN or ADDIDATA_CONTINUOUS_SCAN.
*
* @param [in] b_ExternTriggerMode	: External Trigger action: <br>
* 			 						  APCI3200_DISABLE <br>
* 									  APCI3200_FIRST_LOW_EDGE_START_ALL_SCAN <br>
* 									  APCI3200_FIRST_HIGH_EDGE_START_ALL_SCAN <br>
* 									  APCI3200_FIRST_EDGE_START_ALL_SCAN
*
* @retval 0: No error.
* @retval 1: The handle parameter of the board is wrong.
* @retval 2: The module parameter is wrong.
* @retval 3: Scan not initialized.
* @retval 4: Wrong conversion time value.
* @retval 5: Wrong sacn time mode.
* @retval 6: Wrong sacn time unit value.
* @retval 7: Wrong sacn time value.
* @retval 8: Wrong trigger mode.
*/
INT i_APCI3200_InitScanModuleAcquisition (struct pci_dev *pdev,
		WORD module,
		DWORD dw_ConversionTime,
		BYTE b_SCANTimeMode,
		DWORD dw_SCANTime,
		BYTE b_SCANTimeUnit,
		BYTE b_SCANMode,
		BYTE b_ExternTriggerMode)
{
	DWORD dw_ConversionTimeUs = 0;
	DWORD dw_SCANTimeUs = 0;

	if (!pdev) return 1;

	/* Checks if the module is valid */
	if (module >= APCI3200_PRIVDATA(pdev)->w_NbHardwareComponent) return 2;

	/* Test if the module is initialized */
	if (!GET_MODULE_DATA(pdev,module)->b_ModuleInitialised) return 3;

	/* Test the conversion time value */
	if ((dw_ConversionTime != 20) && (dw_ConversionTime != 40) && (dw_ConversionTime != 80) && (dw_ConversionTime != 160)) return 4;

	/* Get the convert time in micro second */
	switch (dw_ConversionTime)
	{
	case 20 : dw_ConversionTimeUs = 50000;
	break;

	case 40 : dw_ConversionTimeUs = 25000;
	break;

	case 80 : dw_ConversionTimeUs = 12500;
	break;

	case 160 : dw_ConversionTimeUs = 6500;
	break;
	}

	/* Test the scan time mode value */
	if ((b_SCANTimeMode != APCI3200_DELAY_NOT_USED) && (b_SCANTimeMode != APCI3200_DELAY_MODE1_USED)) return 5;

	if (b_SCANTimeMode == APCI3200_DELAY_MODE1_USED)
	{
		/* Test the scan time unit value */
		if ((b_SCANTimeUnit != APCI3200_UNIT_MS) && (b_SCANTimeUnit != APCI3200_UNIT_S)) return 6;

		/* Test the scan time value */
		if (dw_SCANTime <= 1023)
		{
			if (b_SCANTimeUnit == APCI3200_UNIT_MS)
				dw_SCANTimeUs=dw_SCANTime*1000;

			if (b_SCANTimeUnit == APCI3200_UNIT_S)
				dw_SCANTimeUs=dw_SCANTime*1000000;

			if ((GET_MODULE_DATA(pdev,module)->w_NbChannel)*dw_ConversionTimeUs > dw_SCANTimeUs) return 7;
		}
		else
			return 7;
	}

	/* Test the extern trigger mode value */
	if ((b_ExternTriggerMode == APCI3200_DISABLE)
			||(b_ExternTriggerMode == APCI3200_FIRST_LOW_EDGE_START_ALL_SCAN)
			||(b_ExternTriggerMode == APCI3200_FIRST_HIGH_EDGE_START_ALL_SCAN)
			||(b_ExternTriggerMode == APCI3200_FIRST_EDGE_START_ALL_SCAN))
	{
		GET_MODULE_DATA(pdev,module)->b_SCANInitialised = 1;
		GET_MODULE_DATA(pdev,module)->dw_SCANConversionReloadValueSelected = dw_ConversionTime;
		GET_MODULE_DATA(pdev,module)->b_SCANDelayModeSelected = b_SCANTimeMode;
		GET_MODULE_DATA(pdev,module)->dw_SCANDelayReloadValueSelected = dw_SCANTime;
		GET_MODULE_DATA(pdev,module)->b_SCANDelayTimeBaseSelected = b_SCANTimeUnit;
		GET_MODULE_DATA(pdev,module)->b_SCANModeSelected = b_SCANMode;

		if (b_ExternTriggerMode == APCI3200_DISABLE)
		{
			GET_MODULE_DATA(pdev,module)->b_SCANExternTriggerSelected = 0;
			GET_MODULE_DATA(pdev,module)->b_SCANExternTriggerFrontSelected = 0;
		}
		else
		{
			GET_MODULE_DATA(pdev,module)->b_SCANExternTriggerSelected = 1;
			if (b_ExternTriggerMode == APCI3200_FIRST_HIGH_EDGE_START_ALL_SCAN )
				GET_MODULE_DATA(pdev,module)->b_SCANExternTriggerFrontSelected = 1;

			if (b_ExternTriggerMode == APCI3200_FIRST_LOW_EDGE_START_ALL_SCAN)
				GET_MODULE_DATA(pdev,module)->b_SCANExternTriggerFrontSelected = 2;

			if (b_ExternTriggerMode == APCI3200_FIRST_EDGE_START_ALL_SCAN)
				GET_MODULE_DATA(pdev,module)->b_SCANExternTriggerFrontSelected = 3;
		}
	}
	else
		return 8;

	return 0;
}


