/****************************************************************************
*
*	Name:			usbsndcm.c
*
*	Description:	Firmware command routine implemention file.
*
*	Copyright:		(c) 1999 Conexant Systems Inc.
*
*	Revision:	Date:		Author:				Description:
*
*	Linux-1.0	May 29 2002	Shen Wei Wang			Created.
*					shenwei.wang@conexant.com
*
*****************************************************************************
*	$Author:   Shen Wei Wang  $
*	$Revision:   1.0  $
*	$Modtime:   May 29 2002 11:09:58  $
****************************************************************************/

#include "hasbani.h"
//#include <linux/usb.h>

#include "ntdef.h"
#include "FwInit.h"
#include "usbsndcm.h"

//int udsl_print_packet (const unsigned char *data, int len);

extern void BlReadTransactionComplete(urb_t * urb);
extern void BlTransactionComplete(urb_t * urb);
extern int udsl_print_packet (const unsigned char *data, int len);

#if (DBG_ENABLED_DBG_CM_REQUEST_CODE)

#define DBG_CM_REQUEST_CODE(e)								\
(											\
	(										\
		((e) >= CM_REQUEST_UNDEFINED) &&					\
		((e) <= CM_REQUEST_MAX)							\
	) ? 										\
		(g_DbgCmRequestCode[(e) - CM_REQUEST_UNDEFINED]) :			\
		(DBG_ENUM_IS_OUT_OF_RANGE)						\
)															\

CHAR*	g_DbgCmRequestCode[] = 
{
/*	"CM_REQUEST_UNDEFINED", 

	"CM_REQUEST_TEST", 

	"CM_REQUEST_CHIP_GET_MAC_ADDRESS", 

	"CM_REQUEST_CHIP_GET_DP_VERSIONS", 

	"CM_REQUEST_CHIP_ADSL_LINE_START", 
	"CM_REQUEST_CHIP_ADSL_LINE_STOP", 

	"CM_REQUEST_CHIP_ADSL_LINE_GET_STATUS", 
	"CM_REQUEST_CHIP_ADSL_LINE_GET_SPEED", 

	"CM_REQUEST_CARD_INFO_GET", 

	"CM_REQUEST_CARD_DATA_GET", 

	"CM_REQUEST_CARD_DATA_SET", 

	"CM_REQUEST_COMMAND_HW_IO", 

	"CM_REQUEST_INTERFACE_HW_IO", 

	"CM_REQUEST_CARD_SERIAL_DATA_PATH_GET", 
	"CM_REQUEST_CARD_SERIAL_DATA_PATH_SET", 

	"CM_REQUEST_MAX"
*/
	"CM_REQUEST_UNDEFINED",

	"CM_REQUEST_TEST",

	"CM_REQUEST_CHIP_GET_MAC_ADDRESS",

	"CM_REQUEST_CHIP_GET_DP_VERSIONS",

	"CM_REQUEST_CHIP_ADSL_LINE_START",
	"CM_REQUEST_CHIP_ADSL_LINE_STOP", 

	"CM_REQUEST_CHIP_ADSL_LINE_GET_STATUS", 
	"CM_REQUEST_CHIP_ADSL_LINE_GET_SPEED", 

	"CM_REQUEST_CARD_INFO_GET", 
						    
	"CM_REQUEST_CARD_DATA_GET", 
						    
	"CM_REQUEST_CARD_DATA_SET", 
						    
	"CM_REQUEST_COMMAND_HW_IO", 

	"CM_REQUEST_INTERFACE_HW_IO", 

	"CM_REQUEST_CARD_SERIAL_DATA_PATH_GET", 
	"CM_REQUEST_CARD_SERIAL_DATA_PATH_SET", 

	"CM_REQUEST_CARD_CONTROLLER_VERSION_GET",
    
	"CM_REQUEST_CARD_GET_STATUS", 

	"CM_REQUEST_CARD_GET_MAC_ADDRESS", 

	"CM_REQUEST_CARD_GET_DATA_LINK_STATUS", 

    	"CM_REQUEST_BIT_ALLOC",
						    
    	"CM_REQUEST_SNR",
    	"CM_REQUEST_ERROR_DOWNLOAD_COMPLETE",
    	"CM_REQUEST_GET_LOCATION",
    	"CM_REQUEST_UPLOAD_BLOCK_COMPLETE",
    	"CM_REQUEST_READ_MEMORY_BLOCK",
    	"CM_REQUEST_PACKING_MODE",
    	"CM_REQUEST_USB_SUSPEND",
    	"CM_REQUEST_BEGIN_DOWNLOAD",

	"CM_REQUEST_MAX"
};

#else /* (DBG_ENABLED_DBG_CM_REQUEST_CODE) */ 

#define DBG_CM_REQUEST_CODE(pszName, pCardData)

#endif /* (DBG_ENABLED_DBG_CM_REQUEST_CODE) */ 





NTSTATUS USBADSL_ProcessMPXFR(
                               IN PDEVICE_OBJECT DeviceObject,
                               IN PCHAR buffer,
                               IN ULONG count,
                               IN MINIPORTCOMPLETIONROUTINE  CallBack,
                               IN PVOID MPContext,
                               IN ULONG pipeNumber,
                               IN BOOLEAN   IOFlag
                               );


BOOLEAN 
CmCommandRcv
(
	IN PDEVICE_OBJECT	DeviceObject,
	IN	CM_REQUEST_CODE	eCommand	
)
{
	CM_PACKET	UsbCommand;
	
	BOOLEAN		bResult		= FALSE;
	PDEBUG ("CmCommandRcv entered.\n");
	DBG_PRINT00("CmCommandRcv: ++{\n");

	DBG_PRINT00("CmCommandRcv: eCommand = %s\n", 
		DBG_CM_REQUEST_CODE(eCommand));
	DBG_PRINT00("CmCommandRcv: eCommand = 0x%0x\n",
		eCommand);
	if (!DeviceObject)
		return FALSE;
	{
		MEMSET(&UsbCommand, 0, sizeof(UsbCommand));
		UsbCommand.uRequest = (BYTE)eCommand;
		CmPacketSend ( DeviceObject, &UsbCommand );
//		BlDelay(1*10);

		MEMSET(&UsbCommand, 0, sizeof(CM_PACKET));

//		bResult = BlDatagramReceive(DeviceObject, 
//			&UsbCommand, sizeof(CM_PACKET));
		bResult = USBADSL_ProcessMPXFR(
                               DeviceObject,
                               (BYTE *)&UsbCommand,
                               sizeof(CM_PACKET),
                               (usb_complete_t)BlReadTransactionComplete,
                               DeviceObject,
                               1,
                               TRUE
                               );
                 sleep_on_timeout (&DeviceObject->iscomplete, 2*HZ);
                               
		if (bResult)
		{
			DBG_PRINT00("CmCommandRcv: (Receive == FALSE)\n");
		}
		else
		{
	//		DWORD	dwReceivedChecksum	= *(PDWORD)(&UsbCommand.USBData[eCommand - 0x80]);

			
	//		DBG_PRINT00("CmCommandRcv: value = 0x%08X\n", (unsigned int )dwReceivedChecksum);
		}
		udsl_print_packet ( (BYTE *) &UsbCommand, sizeof(CM_PACKET));
	}
	DBG_PRINT00("CmCommandRcv: bResult = 0x%08X\n", bResult);

	DBG_PRINT00("CmCommandRcv: }--\n");

	return bResult;
}


BOOLEAN 
CmCommandSend
(
	IN PDEVICE_OBJECT	DeviceObject,
	IN	CM_REQUEST_CODE	eCommand, 
	IN	DWORD		dwParam
//    IN MINIPORTCOMPLETIONROUTINE  CallBack,
//    IN PVOID MPContext
//    IN ULONG pipeNumber,
//    IN BOOLEAN   IOFlag
)
{
	CM_PACKET	CmRequest;

//	BOOLEAN		bResult		= FALSE;
	int		bResult = 0;
	PDEBUG ("CmCommandSend entered.\n");
	DBG_PRINT00("CmCommandSend: ++{\n");

	DBG_PRINT00("CmCommandSend: eCommand = %s\n", 
		DBG_CM_REQUEST_CODE(eCommand));
	DBG_PRINT00("CmCommandSend: eCommand = 0x%0x\n",
		eCommand);
	if (!DeviceObject)
		return FALSE;

	if ( DeviceObject->bDldError )
		return FALSE;	
			
	if (1)//CmCardIsInitialized(pUsbContext))
	{
#if (DBG_ENABLED_STATUS_SIMULATION)
		bResult = TRUE;
#else /* (DBG_ENABLED_STATUS_SIMULATION) */ 
	//	ZERO_OBJECT(&CmRequest);
		MEMSET(&CmRequest, 0, sizeof(CM_PACKET));

		CmRequest.uRequest = (BYTE)eCommand;
		((DWORD*)CmRequest.Data.Array)[0] = dwParam;

//		bResult = CmPacketSend(pUsbContext, &CmRequest);
		bResult = USBADSL_ProcessMPXFR(
                               DeviceObject,
                               (BYTE *)&CmRequest,
                               sizeof(CM_PACKET),
                               (usb_complete_t)BlTransactionComplete,
                               DeviceObject,
                               1,
                               FALSE
                               );
  		
  		if ( bResult != -911 )
		 	sleep_on_timeout (&DeviceObject->iscomplete, 2*HZ);
#endif /* (DBG_ENABLED_STATUS_SIMULATION) */ 
	}
/*	MEMSET(&CmRequest, 0, sizeof(CM_PACKET));
	CmRequest.uRequest = CM_REQUEST_CARD_INFO_GET;
	bResult = USBADSL_ProcessMPXFR(
					DeviceObject,
					(BYTE *)&CmRequest,
					sizeof(CM_PACKET),
					(usb_complete_t)CallBack,
					MPContext,
					pipeNumber,
					TRUE
					);
	 sleep_on_timeout (&DeviceObject->iscomplete, 2*HZ);
*/
	DBG_PRINT00("CmCommandSend: bResult = 0x%08X\n", bResult);

	DBG_PRINT00("CmCommandSend: }--\n");

	return NT_SUCCESS(bResult);
}

BOOLEAN 
CmPacketSend
(
	IN PDEVICE_OBJECT	DeviceObject,
//	IN	CM_REQUEST_CODE	eCommand, 
//	IN	DWORD			dwParam,
	IN  CM_PACKET	*	CmRequest
)
{
//	CM_PACKET	CmRequest;

//	BOOLEAN		bResult		= FALSE;
	int bResult = 0;
	PDEBUG ("CmPacketSend entered.\n");
	DBG_PRINT00("CmPacketSend: ++{\n");
	if (!DeviceObject)
		return FALSE;
		
	if ( DeviceObject->bDldError )
		return FALSE;	
			

	if (!CmRequest)
	{
		PDEBUG ("CmPacketSend: error CmRequest ==NULL.\n");
		return bResult;
	}
	DBG_PRINT00("CmPacketSend: eCommand = %s\n", 
		DBG_CM_REQUEST_CODE(CmRequest->uRequest));
	if (1)//CmCardIsInitialized(pUsbContext))
	{
#if (DBG_ENABLED_STATUS_SIMULATION)
		bResult = TRUE;
#else /* (DBG_ENABLED_STATUS_SIMULATION) */ 

		bResult = USBADSL_ProcessMPXFR(
                               DeviceObject,
                               (BYTE*)CmRequest,
                               sizeof(CM_PACKET),
                              (usb_complete_t)BlTransactionComplete,
                               DeviceObject,
                               1,
                               FALSE
                               );
		if ( bResult != -911 )
		 	sleep_on_timeout (&DeviceObject->iscomplete, 2*HZ);
#endif /* (DBG_ENABLED_STATUS_SIMULATION) */ 
	}

	DBG_PRINT00("CmPacketSend: bResult = 0x%08X\n", bResult);

	DBG_PRINT00("CmPacketSend: }--\n");

	return NT_SUCCESS(bResult);
}


BOOLEAN 
CmConfigParamSend
(
	IN PDEVICE_OBJECT	DeviceObject,
	IN	CM_REQUEST_CODE	eCommand, 
//	IN	DWORD			dwParam,
    IN MINIPORTCOMPLETIONROUTINE  CallBack,
    IN PVOID MPContext,
    IN ULONG pipeNumber,
    IN BOOLEAN   IOFlag
)
{

	int i, j, k;

	int ParamCount;
	CM_PACKET  * CmRequest;

	BOOLEAN		bResult		= FALSE;

	static DWORD data[] =
	{
		0x30,	0x00,	0x00,	0x01,	0x01,
		0x00,	0x00,	0x09,	0x10,	0x00,
		0x00,	0x00,	0x01,	0x02,	0x00,
		0xC8,	0x01,	0x00,	0x00,	0x00,
		0x01,	0x00,	0x00,	0x0E,	0x05,
		0x00,	0x00,	0x00,	0x00,	0x00,
		0x00,	0x00,	0x00,	0x00
	};
	PDEBUG ("CmConfigParamSend entered!\n");

	ParamCount = sizeof(data)/sizeof(DWORD);
	j = 0;
//	while(ParamCount > 0) 
	do
	{
	    CmRequest = kmalloc(sizeof(CM_PACKET), GFP_KERNEL);

		if (!CmRequest)
		{
			PDEBUG("CmConfigParamSend: No memory.\n");
			return FALSE;
		}
		PDEBUG ("CmConfigParamSend: CmRequest = 0x%p\n", CmRequest);
		MEMSET (CmRequest, 0, sizeof(CM_PACKET));
		for (i = 0; i< CARD_PARAM_MAX; i++)
		{

			if (i > ParamCount)
			{
				k = i;
				do
				{
					CmRequest->Data.CardData.Param[k].dwIndex = 0x0;//i + j*(CARD_PARAM_MAX);
					CmRequest->Data.CardData.Param[k].dwValue = 0x0;
					k ++;
				}while ( k < CARD_PARAM_MAX );
				break;
			}
			
			CmRequest->Data.CardData.Param[i].dwIndex = i+j*(CARD_PARAM_MAX);//data[i+j*CARD_PARAM_MAX];
			CmRequest->Data.CardData.Param[i].dwValue = data[i+j*(CARD_PARAM_MAX)];
		}
		ParamCount -=  CARD_PARAM_MAX;
//		if (ParamCount <= CARD_PARAM_MAX)
			PDEBUG ("CmConfigParamSend: it is the %d cycle. Attention!\n", j);
		CmRequest->Data.CardData.dwCount = i ;
		CmRequest->uRequest = eCommand;//CM_REQUEST_CARD_DATA_SET;
		PDEBUG("\n");
		for (k=0;k<CmRequest->Data.CardData.dwCount;k++)
		{
			 printk(KERN_DEBUG "(%d)0x%x, ",(int)CmRequest->Data.CardData.Param[k].dwIndex, (int)CmRequest->Data.CardData.Param[k].dwValue);
		}
		PDEBUG("\n");


		bResult |= CmPacketSend(DeviceObject, CmRequest);
		j ++;
		kfree (CmRequest);

	}while (ParamCount > 0 );//|| i==CARD_PARAM_MAX - 1);

	PDEBUG("CmConfigParamSend end. bResult = %d (0 = SUCCESS)\n", bResult);
	return bResult;
}

