/** @file kapi_utils.c
 
   Contains utilities kernel functions.
 
   @par CREATION  
   @author Krauth Julien
   @date   23.05.06
   
   @par VERSION
   @verbatim
   $LastChangedRevision:$
   $LastChangedDate:$
   @endverbatim   
   
   @par LICENCE
   @verbatim
    Copyright (C) 2009  ADDI-DATA GmbH for the source code of this module.
        
    ADDI-DATA GmbH
    Airpark Business Center
    Airport Boulevard B210
    77836 Rheinm�nster
    Germany
    Tel: +49(0)7229/1847-0
    Fax: +49(0)7229/1847-200
    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 "xpci3009-private.h"

EXPORT_SYMBOL(i_XPCI3009_GetModuleId);
EXPORT_SYMBOL(i_XPCI3009_GetFunctionality);
EXPORT_SYMBOL(i_XPCI3009_GetBoardType);

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

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

/** Read modules configuration.
 * 
 * @param [in] pdev          : The device to initialize.
 * 
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int   i_XPCI3009_ReadModulesConfiguration (struct pci_dev *pdev)
{
	uint8_t i = 0;
	uint8_t number_module = NUMBER_OF_MODULE(pdev);
    if (!pdev) 
    	return 1;

    for ( i = 0 ; i< number_module; i++ )
    {
    	INPDW_MEM(	GET_MEM_BAR3(pdev),
					APCI1710_FUNC_OFFSET + 60 + (XPCI3009_RANGE*i) ,
					&XPCI3009_PRIVDATA(pdev)->s_BoardInfos.dw_MolduleConfiguration [i] );
    }

    return 0;
}

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

/** Return the module functionality.
 *
 * @param [in] pdev          : The device to initialize.
 * @param [in] b_ModulNbr    : Module number to configure (0 to 3).
 *
 * @param [out] pui_Functionality : Module configuration.
 *
 * @retval 0: No error.
 * @retval 1: pdev is NULL.
 * @retval 2: b_ModuleNbr is incorrect.
 */
int   i_XPCI3009_GetFunctionality (struct pci_dev *pdev,
                                   uint8_t  b_ModuleNbr,
                                   uint32_t * pui_Functionality)
{
    if (!pdev)
    	return 1;

	/* Test the module number */
	if ( NOT_A_MODULE(pdev,b_ModuleNbr) )
		return 2;

	*pui_Functionality = XPCI3009_MODULE_FUNCTIONALITY(pdev, b_ModuleNbr);

	return 0;
}
//------------------------------------------------------------------------------
/** returns the content of the module configuration register (ID).
 *
 * This information helps to identify the type of module that is installed on the board.
 *
 * @param [in] argv                  : A pointer to an array of 4 unsigned long
 *
 * @retval 0: No error.
 * @retval 1: pdev is NULL.
 * @retval 2: b_ModuleNbr is incorrect
 *
 * The 2 first bytes identify the functionality ( see enumeration in apci1710.h )
 * the two last byte is the firmware version
 *
 */
int   i_XPCI3009_GetModuleId (struct pci_dev *pdev,uint8_t  b_ModuleNbr,uint32_t * pui_Id)
{
    if (!pdev)
    	return 1;

	/* Test the module number */
	if ( NOT_A_MODULE(pdev,b_ModuleNbr) )
		return 2;

	*pui_Id = XPCI3009_MODULE_ID(pdev, b_ModuleNbr);

	return 0;
}
//------------------------------------------------------------------------------
static const char * functionality_id_to_str(unsigned long Functionality)
{
	switch(Functionality)
	{
		case XPCI3009_INCREMENTAL_COUNTER:
			return "INCREMENTAL_COUNTER";
		case XPCI3009_SSI_COUNTER:
			return "SSI_COUNTER";
		case XPCI3009_TTL_IO:
			return "TTL_IO";
		case XPCI3009_DIGITAL_IO:
			return "DIGITAL_IO";
		case XPCI3009_82X54_TIMER:
			return "82X54_TIMER";
		case XPCI3009_CHRONOMETER:
			return "CHRONOMETER";
		case XPCI3009_PULSE_ENCODER:
			return "PULSE_ENCODER";
		case XPCI3009_TOR_COUNTER:
			return "TOR_COUNTER";
		case XPCI3009_PWM:
			return "PWM";
		case XPCI3009_ETM:
			return "ETM";
		case XPCI3009_CDA:
			return "CDA";
		case XPCI3009_BALISE:
			return "BALISE";
		default:
			return "UNKNOWN";
	}
}
//------------------------------------------------------------------------------
static inline int PRINTK_MODULE_INFO(struct pci_dev *pdev,uint8_t b_ModuleNbr)
{
	printk(KERN_INFO "module %d: ID is 0x%.8X (functionality: %s, version: 0x%.4X)\n",
			b_ModuleNbr,
			XPCI3009_MODULE_ID(pdev,b_ModuleNbr),
			functionality_id_to_str(XPCI3009_MODULE_FUNCTIONALITY(pdev,b_ModuleNbr)),
			XPCI3009_MODULE_VERSION(pdev,b_ModuleNbr)
			);
	return 0;
}

//------------------------------------------------------------------------------
int  i_XPCI3009_DumpModulesFunctionalities (struct pci_dev *pdev)
{
	uint8_t i = 0;
	uint8_t number_module;

    if (!pdev)
    	return 1;

    number_module = NUMBER_OF_MODULE(pdev);
    for ( i = 0 ; i < number_module ; i++ )
	{
    	PRINTK_MODULE_INFO(pdev,i);
	}

    return 0;
}

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

/** Get the board type.
 *
 * @param [in] pdev			: The device to use.
 *
 * @param [out] boardType	: Board hardware type:
 * 							  - APCI1710_10K10_BOARD_TYPE
 * 							  - APCI1710_10K20_BOARD_TYPE
 * 							  - APCIE1711_BOARD_TYPE
 * 							  - UNKNOWN_BOARD_TYPE
 *
 * @retval 0: No error.
 * @retval 1: pdev error.
 */
int i_XPCI3009_GetBoardType (struct pci_dev *pdev, uint32_t *boardType)
{
	// This driver is only make for xpci3009 boards
	*boardType = PCI3009_BOARD_TYPE;
	return 0;
}

