/*****************************************************************************
* voicesync_pci_main.c	Amfeltec VoiceSync (PCI)- PCI Voice Sync Timer Interface
*
*
* Copyright:	(c) 2010 Amfeltec Corp.
*
* ============================================================================
* June 10, 2008		Initial version.
*****************************************************************************/

/***************************************************************************
****		I N C L U D E  		F I L E S			****
***************************************************************************/


#include "os/os_abstr_includes.h"
#include "os/os_abstr_defines.h"
#include "os/os_abstr_debug.h"
#include "os/os_abstr_basic.h"
#include "os/os_abstr_time.h"
#include "os/os_abstr_bus.h"
#include "os/os_abstr_pci.h"

#include "voicesync.h"

/***************************************************************************
****		   	  M A C R O S / D E F I N E S			****
***************************************************************************/
#define VS_MOD_NAME		"voicesync"
#define VS_MOD_DESC		"Amfeltec VoiceSync"

#define VS_CLOCK_SRC		"voicesync"

#define VS_FLAG_READY		1

/***************************************************************************
****		     S T R U C T U R E S / T Y P E D E F S		****
***************************************************************************/

/***************************************************************************
****			F U N C T I O N  P R O T O T Y P E S		****
***************************************************************************/
int voicesync_init(void* arg);
/*int voicesync_shutdown(void *arg);*/
/*int voicesync_ready_unload(void *arg);*/
int voicesync_exit (void *arg);


/***************************************************************************
****		       G L O B A L  V A R I A B L E S			****
***************************************************************************/
static unsigned long	voicesync_flag;

#if defined(__Linux__) || defined(__FreeBSD__)
OS_MODULE_DEFINE(
		voicesync, "voicesync",
		"Support Team <support@amfeltec.com>",
		VS_MOD_DESC,
		"GPL",
		voicesync_init, voicesync_exit,
		NULL);
OS_MODULE_VERSION(hvt, VS_MAJOR_VERSION);
#endif

#if DAHDI_VERSION >= 24
static const struct dahdi_span_ops voicesync_ops = {
	.owner = THIS_MODULE,
};
#endif

/***************************************************************************
****			 F U N C T I O N  D E F I N I T I O N		****
***************************************************************************/

/*===========================================================================*/
/*================= Kernel module entry functions ===========================*/
int voicesync_init(void* arg)
{

	DEBUG_EVENT("Loading %s Driver v%s.%s (Verbose %d)\n",
			VS_MOD_DESC,
			VS_MAJOR_VERSION, VS_MINOR_VERSION,
			VS_VERBOSE);

#if defined(CONFIG_VOICESYNC_PCIE)
	voicesync_pcie_register();
#endif
#if defined(CONFIG_VOICESYNC_PCI)
	voicesync_pci_register();
	voicesync_pci152_register();
#endif
#if defined(CONFIG_VOICESYNC_USB)
	voicesync_usb_register();
#endif
	return 0;
}

#if 0
int voicesync_shutdown(void *arg)
{
	DEBUG_EVENT("%s: Shutting down %s \n",
			VS_MOD_NAME, VS_MOD_DESC);
	return 0;
}

int voicesync_ready_unload(void *arg)
{
	DEBUG_EVENT("%s: Is %s ready to unload \n",
			VS_MOD_NAME, VS_MOD_DESC);
	return 0;
}
#endif

/*============================================================================
 * Module deinit point.
 * o release all remaining system resources
 */
int voicesync_exit (void *arg)
{

#if defined(CONFIG_VOICESYNC_USB)
	voicesync_usb_unregister();
#endif
#if defined(CONFIG_VOICESYNC_PCI)
	voicesync_pci_unregister();
	voicesync_pci152_unregister();
#endif
#if defined(CONFIG_VOICESYNC_PCIE)
	voicesync_pcie_unregister();
#endif
	DEBUG_EVENT("%s Driver Unloaded\n",
			VS_MOD_DESC);

	return 0;
}

/*============================================================================
 * Register pci/usb voice timer interface
 * 
 */
int voicesync_register(void)
{
	if (os_test_and_set_bit(VS_FLAG_READY, &voicesync_flag)){
		DEBUG_EVENT("ERROR: Another interface is already registered!\n");
		return -EINVAL;
	}
	return 0;
}

/*============================================================================
 * Unregister pci/usb voice timer interface
 * 
 */
int voicesync_unregister(void)
{
	os_clear_bit(VS_FLAG_READY, &voicesync_flag);
	return 0;
}

/*============================================================================
 * Register interface into Dahdi/Zaptel.
 * 
 */
int voicesync_initialize(voicesync_dahdi_t *dahdi)
{
	/* Zapata stuff */
	dahdi->chan = &dahdi->_chan;
	dahdi->chan_ptrs[0] = &dahdi->_chan; 

	sprintf(dahdi->span.name, "VOICESYNC/1");
	snprintf(	dahdi->span.desc, 
			sizeof(dahdi->span.desc) - 1, 
			"%s (source: " VS_CLOCK_SRC ") %d", 
			dahdi->span.name, 1);
	sprintf(dahdi->chan->name, "VOICESYNC/%d/%d", 1, 0);
	dahdi->chan->chanpos 	= 1;
#if DAHDI_VERSION == 23
	dahdi->span.owner	= THIS_MODULE;
#endif
#if defined(__DAHDI__)    
	dahdi->span.chans 	= dahdi->chan_ptrs;
#else
	dahdi->span.chans 	= dahdi->chan;
#endif
	dahdi->span.channels 	= 0;		/* no channels on our span */
	dahdi->span.deflaw 	= ZT_LAW_MULAW;
#if DAHDI_VERSION < 25
	init_waitqueue_head(&dahdi->span.maintq);
#endif
#if DAHDI_VERSION < 24
	dahdi->span.pvt 		= dahdi;
#endif
	dahdi->chan->pvt 	= dahdi;
#if DAHDI_VERSION >= 24
	dahdi->span.ops		= &voicesync_ops;
#endif
	if (zt_register(&dahdi->span, 0)) {
		return -1;
	}
	return 0;
}

#if !(ZT_CHUNKSIZE==8 || ZT_CHUNKSIZE==16 || ZT_CHUNKSIZE==40 || ZT_CHUNKSIZE==80)
# error Sorry, chunksize must be 8/16/40/80
#endif
