 /* @file privadata.h
  * 
  * @brief Holds definition for driver's private data and its manipulation functions. 
  * 
  * 
  * 
  */

/** @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 library is free software; you can redistribute it and/or modify it under 
 the terms of the GNU Lesser General Public License as published by the 
 Free Software Foundation; either version 2.1 of the License, 
 or (at your option) any later version.
 
 This library 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 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public License 
 along with this library; if not, write to the Free Software Foundation, 
 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 
 You also shoud find the complete LGPL in the LGPL.txt file accompanying 
 this source code.
 
 @endverbatim
**/

#ifndef __APCI1696_PRIVDATA_H_
#define __APCI1696_PRIVDATA_H_

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)		
	#include <asm/semaphore.h>
#else
	#include <linux/semaphore.h>
#endif

/**@union OneDigitalIORegister_t
 * One register of the board is of 32 bits.
 * In one register are defined 4 ports of 8 bits.
 * This union permit to access directly the 32 bits or each single port.
 */
union OneDigitalIORegister_t
{
	uint8_t  SinglePort[4];
	uint32_t AllPorts; /**< Includes 32 channels */
};

/**@struct DigitalIORegister_t
 * This structure is used to map the digital input/output register of the APCI-1696.
 */
struct DigitalIORegister_t
{
	union OneDigitalIORegister_t Register1;
	union OneDigitalIORegister_t Register2;
	union OneDigitalIORegister_t Register3;
};

/* internal driver data */
struct apci1696_str_BoardInformations
{
	struct semaphore sem; /**< semaphore protect the board data */
	
	unsigned char OutputMemoryStatus;					/**< Digital Output Memory Status (0: not active, 1: active) */     
	struct DigitalIORegister_t RegisterSetting;			/**< Map the setting register */	
	struct DigitalIORegister_t RegisterDigitalInput;	/**< Map the digital input register */		
	struct DigitalIORegister_t RegisterDigitalOutput;	/**< Map the digital output register */				
};

/** initialise board's private data - fill it when adding new members and ioctl handlers */
static __inline__ void apci1696_init_priv_data(struct apci1696_str_BoardInformations * data)
{
	/* Initialize the board structure */
	memset (data, 0, sizeof (struct apci1696_str_BoardInformations));
		
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
	init_MUTEX( &(data->sem) );	
#else
	sema_init( &(data->sem), 1 );
#endif
}


/** typed cast (safer to use) */
static __inline__ struct apci1696_str_BoardInformations * APCI1696_PRIVDATA(struct pci_dev * pdev)
{	
	return (struct apci1696_str_BoardInformations *) pci_get_drvdata(pdev);	
}

/** used to lock the board - 
 * may be interrupted : check return value 
 * like that:
 * if (APCI1696_DOWN(pdev))
 * 	return -ERESTARTSYS;
 * 
 * */
static inline int APCI1696_LOCK(struct pci_dev * pdev, unsigned long * flags)
{
	return down_interruptible(&(APCI1696_PRIVDATA(pdev)->sem));
}

/** release the semaphore */
static inline void APCI1696_UNLOCK(struct pci_dev * pdev,unsigned long flags)
{
	up(&(APCI1696_PRIVDATA(pdev)->sem));
}
#endif // __APCI1696_PRIVDATA_H_
