www.pudn.com > DMBDRV.rar > SianoSPI.c


#include  
//#include  
#include  
 
//#include "SianoSPI.h" 
#include "BusDrvIf.h" 
//#include "SpiHw.h" 
 
#include "SianoSPI.h" 
#include "smsspiphy.h" 
#include "memmap.h" 
 
 
/************************************************************************ 
*                                                                      * 
* FILE NAME:   SianoSPI.cpp	                                       * 
*                                                                      * 
* DESCRIPTION:														   * 
*									                                   * 
*                                                                      * 
* Copyright (C) 2006 Consonance Ltd.	                               * 
* All rights reserved                                                  * 
*                                                                      * 
************************************************************************/ 
 
 
DBGPARAM dpCurSettings = { 
    TEXT("BUILTINTEST"), { 
    TEXT("Errors"),    TEXT("Warnings"),  TEXT("Init"),        TEXT("Trace"), 
    TEXT("SPI_INIT"),  TEXT("SPI_READ"),  TEXT("SPI_WRITE"),   TEXT("SPI_IOCTL"), 
	TEXT("SPI_DEINIT"), TEXT("ZONE_FUNCTION"), TEXT("Undefined"), TEXT("Undefined") 
    }, 
     ZONE_ERROR_SET | ZONE_WARNING_SET | ZONE_INIT_SET | ZONE_INFO_SET //| ZONE_DETAILED_SET 
}; 
 
 
static CHAR preamble_pattern[] = { 0xa5, 0x5a, 0xe7, 0x7e }; 
 
#define RX_BUF_SIZE	0x1000 
#define TX_BUF_SIZE	0x200 
 
#define MAX_REG_PATH_SIZE 100 
#define MAX_REG_KEY_SIZE 100 
 
 
#define WAIT_FOR_DRIVER_LOADING_TIME 5000//waiting to be able to read from reg 
#ifdef USE_CONSO_DEFAULT  
//if we are on test mode use the SPI path if it is release use BuiltIn... 
#define REG_PATH L"Drivers\\SPI\\SianoSPI" 
#else 
#define REG_PATH L"Drivers\\BuiltIn\\SianoSPI" 
#endif 
 
 
#define MAX_MNPRT_NAME 64 
#define DRIVERLOADING 2000 
//RAN: for debug purpose 
extern DWORD gt_Freq;//frequency of the Performance Counter declared in SpiHw.cpp. 
DWORD gt_ClntST; 
DWORD gt_ClntET; 
LARGE_INTEGER Li_Clnt; 
//#define POSTDEBUGMSG 
 
 
static void MsgFound(void* context, void* buf, int len) 
{	 
	PSPIDEVICEEXTENSION pSpiDevExt = context; 
	//DBGMSG(ZONE_INFO, (TEXT("SmsSpi: MsgFound().\r\n"))); 
	if (pSpiDevExt->pBD_ReadCBFunc) 
	{ 
		//DBGMSG(ZONE_INFO, (TEXT("SmsSpi: Calling back with message.\r\n"))); 
		pSpiDevExt->pBD_ReadCBFunc(pSpiDevExt->hBDContext, buf, (DWORD)len); 
	} 
	//DBGMSG(ZONE_INFO, (TEXT("SmsSpi: MsgFound end.\r\n"))); 
	 
} 
 
 
static void smsspi_interruptHandler(PVOID pArg) 
{ 
	PSPIDEVICEEXTENSION pSpiDevExt  = (PSPIDEVICEEXTENSION)pArg; 
	//DBGMSG(ZONE_ERROR, (TEXT("SmsSpi: Interrupt().\r\n"))); 
	SetEventData(pSpiDevExt->transferMsgQueue, 0); 
	SetEvent(pSpiDevExt->transferMsgQueue); 
} 
 
 
static VOID SpiTransferThread(PVOID pArg) 
{ 
	PSPIDEVICEEXTENSION pSpiDevExt  = (PSPIDEVICEEXTENSION)pArg; 
	struct spi_msg *msg; 
 
	while (1) 
	{ 
		WaitForSingleObject(pSpiDevExt->transferMsgQueue, INFINITE); 
		//DBGMSG(ZONE_DETAILED, (TEXT("SmsSpi: Recieved xfer event.\r\n"))); 
		msg = (struct spi_msg *)GetEventData(pSpiDevExt->transferMsgQueue); 
		//if (msg) 
		//	DBGMSG(ZONE_INFO, (TEXT("SmsSpi: Transfering packet, buf=0x%x, len=%d.\r\n"), msg->buf, msg->len)); 
		smsspi_common_transfer_msg(&pSpiDevExt->dev, msg, pSpiDevExt->PaddingAllowed); 
        SetEvent(pSpiDevExt->WriteOperation); 
		DBGMSG(ZONE_DETAILED, (TEXT("SmsSpi: End xfer event.\r\n"))); 
    } 
 
} 
 
/************************************************************************************* 
FUNCTION NAME:	GetInstance 
 
DESCRIPTION:	getting the instancenum and name from the registry 
 
*************************************************************************************/ 
DWORD GetInstance(WCHAR *szName) 
{ 
	HKEY hSpikey; 
	LONG lRes; 
	DWORD dwType; 
	DWORD CurrInstancenum; 
	DWORD DataSize; 
	 
	lRes = RegOpenKeyEx(  
						HKEY_LOCAL_MACHINE,  
						REG_PATH,  
						0,//N\A  
						0,//N\A 
						 &hSpikey  
						); 
	if(lRes != ERROR_SUCCESS) 
		return (-1); 
 
	DataSize=sizeof(DWORD); 
	lRes = RegQueryValueEx(  
						  hSpikey,  
						  L"MiniPortInstance",  
						  0,  
						  &dwType,  
						  (LPBYTE)&CurrInstancenum,  
						  &DataSize  
						);  
	if(lRes!=ERROR_SUCCESS)	 
	{ 
		RegCloseKey(hSpikey); 
		return (-1); 
	} 
	 
	DataSize=MAX_MNPRT_NAME; 
	lRes = RegQueryValueEx(  
						  hSpikey,  
						  L"MiniportName",  
						  0,  
						  &dwType,  
						  (LPBYTE)szName,  
						  &DataSize  
						);  
	if(lRes!=ERROR_SUCCESS)	 
	{ 
		RegCloseKey(hSpikey); 
		return (-1); 
	} 
 
	RegCloseKey(hSpikey); 
	return CurrInstancenum; 
} 
 
 
 
 
/************************************************************************************* 
						Driver Actual Implementation  
				  -------------------------------------- 
*************************************************************************************/ 
/************************************************************************************* 
FUNCTION NAME:	DllEntry 
 
DESCRIPTION:	Standard DLLEntry point for a DLL 
 
PARAMETERS:		[IN]	HANDLE	hDllHandle	-	Instance to dll module  
				[IN]	DWORD	dwReasone	-	Reasone for the calling the routine  
				[IN]	LPVOID	lpReserved	-	Reserved	 
										    
RETURN VALUE:	None 
 
REMARKS			NONE 
*************************************************************************************/ 
BOOL WINAPI DllEntry( 
   HANDLE hDllHandle,  
   DWORD  dwReason,  
   LPVOID lpreserved 
   )  
{ 
    BOOL bRc = TRUE; 
     
    UNREFERENCED_PARAMETER(hDllHandle); 
    UNREFERENCED_PARAMETER(lpreserved); 
     
    switch (dwReason) { 
        case DLL_PROCESS_ATTACH:  
			{ 
            DEBUGREGISTER((HINSTANCE)hDllHandle); 
            DEBUGMSG(1,(_T("*** DLL_PROCESS_ATTACH - Current Process: 0x%x, ID: 0x%x ***\r\n"), 
                GetCurrentProcess(), GetCurrentProcessId())); 
	 
			 
			}  
			break; 
			 
        case DLL_PROCESS_DETACH:  
			{ 
            DEBUGMSG(1,(_T("*** DLL_PROCESS_DETACH - Current Process: 0x%x, ID: 0x%x ***\r\n"), 
                GetCurrentProcess(), GetCurrentProcessId())); 
 
 
			}  
			break; 
			 
        default: 
            break; 
    } 
	 
    return bRc; 
} 
 
 
static VOID FreeAllocatedResources(PSPIDEVICEEXTENSION pSpiDevExt) 
{ 
	DMA_ADAPTER_OBJECT adapter; 
 
	if (pSpiDevExt) 
	{ 
		if (pSpiDevExt->hSmsGenDrv != INVALID_HANDLE_VALUE) 
		{ 
			DeactivateDevice(pSpiDevExt->hSmsGenDrv); 
			pSpiDevExt->hSmsGenDrv = INVALID_HANDLE_VALUE; 
		} 
		if (pSpiDevExt->transferThread) 
		{ 
			TerminateThread(pSpiDevExt->transferThread, 0); 
			CloseHandle(pSpiDevExt->transferThread); 
		} 
		if (pSpiDevExt->transferMsgQueue) 
		{ 
			CloseHandle(pSpiDevExt->transferMsgQueue); 
		} 
		if (pSpiDevExt->WriteOperation) 
		{ 
			CloseHandle(pSpiDevExt->WriteOperation); 
		} 
 
		if (pSpiDevExt->dev.rxbuf) 
		{ 
			LocalFree(pSpiDevExt->dev.rxbuf); 
		} 
		if (pSpiDevExt->phyDrv) 
		{ 
			smsspiphy_deinit(pSpiDevExt->phyDrv); 
			pSpiDevExt->phyDrv = NULL; 
		} 
		if (pSpiDevExt->txbuf) 
		{ 
			PHYSICAL_ADDRESS phyAddr; 
			phyAddr.QuadPart = pSpiDevExt->txbuf_phy_addr; 
			HalFreeCommonBuffer(&adapter, TX_BUF_SIZE, phyAddr, pSpiDevExt->txbuf, FALSE); 
		} 
		LocalFree(pSpiDevExt); 
		pSpiDevExt = NULL; 
	} 
} 
 
 
 
static BOOL GetRegistrySettings(PVOID Context, PSPIDEVICEEXTENSION pSpiDevExt ) 
{ 
	TCHAR*	regKey; 
	BOOL	st; 
	HKEY	hKey; 
	DWORD	dataSize, type; 
	regKey = (TCHAR *)LocalAlloc (LPTR, MAX_REG_KEY_SIZE); 
	if (regKey == NULL) 
	{ 
		DBGMSG( ZONE_ERROR,(TEXT("Siano SPI - ERROR!! Allocating memory for registry reading failed.\r\n"))); 
		return FALSE; 
	} 
 
 
	st = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCWSTR)Context, 0, 0, &hKey);						 
	if(st != ERROR_SUCCESS) 
	{ 
		DBGMSG( ZONE_ERROR,(TEXT("Siano SPI - ERROR!! Could not open registry key.\r\n"))); 
		LocalFree(regKey); 
		return (FALSE); 
	} 
 
	dataSize=MAX_REG_KEY_SIZE; 
	st = RegQueryValueEx(	hKey,  
							TEXT("Key"),  
							NULL, 
							&type,  
							(LPBYTE)regKey,  
							&dataSize); 
	 
	RegCloseKey(hKey); 
	if(st!=ERROR_SUCCESS)	 
	{ 
		DBGMSG( ZONE_ERROR,(TEXT("Siano SPI - ERROR!! Could not get registry key name.\r\n"))); 
		LocalFree(regKey); 
		return (FALSE); 
	} 
	 
	// Now - read all the needed parameters for the driver from the registry. 
 
 
	st = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regKey, 0, 0, &hKey); 
	if(st != ERROR_SUCCESS) 
	{ 
		DBGMSG( ZONE_ERROR,(TEXT("Siano SPI - ERROR!! Could not open registry key.\r\n"))); 
		LocalFree(regKey); 
		return (FALSE); 
	} 
 
 
 
	dataSize = sizeof(pSpiDevExt->novaDevice); 
	st = RegQueryValueEx( hKey,  
					  L"novaDevice",  
					  0,  
					  &type,  
					  (LPBYTE)&pSpiDevExt->novaDevice,  
					  &dataSize); 
 
	if(st != ERROR_SUCCESS) 
	{ //Set default value if registry entry is not found. 
		pSpiDevExt->novaDevice = FALSE; 
	} 
 
	 
	st = RegCloseKey(hKey); 
	if(st!=ERROR_SUCCESS)	 
	{ 
		DBGMSG( ZONE_ERROR,(TEXT("Siano SPI - ERROR!! Could not get registry key name.\r\n"))); 
		LocalFree(regKey); 
		return (FALSE); 
	} 
 
	LocalFree(regKey); 
	return (TRUE); 
 
} 
 
 
/************************************************************************************* 
FUNCTION NAME:	SPI_Init 
 
DESCRIPTION:	Streame Driver Init entry point 
 
PARAMETERS:		[IN]	Context - pointer to the registry path for the device's parameters. 
										    
RETURN VALUE:	None 
 
REMARKS			NONE 
*************************************************************************************/ 
extern  PVOID    VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress); 
 
DWORD WINAPI SPI_Init(PVOID Context) 
{ 
 
	DWORD Res = 0; 
	//DMA_ADAPTER_OBJECT adapter; 
	MSGQUEUEOPTIONS	msgOptions; 
	//PHYSICAL_ADDRESS phyAddr; 
	PSPIDEVICEEXTENSION pSpiDevExt = (PSPIDEVICEEXTENSION)LocalAlloc(LPTR,sizeof(SPIDEVICEEXTENSION)); 
	 
	DBGMSG(ZONE_INIT, (TEXT("SmsSpi: SPI_Init() Start.\r\n"))); 
	if(pSpiDevExt == NULL) 
	{ 
		DBGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("SmsSpi: SPI_Init() failed to allocate memory for handle.\r\n"))); 
		return 0; 
	} 
	memset (pSpiDevExt, 0, sizeof(SPIDEVICEEXTENSION)); 
 
	//Init the hw: 
	 
	pSpiDevExt->txbuf = (char *)VirtualAllocCopy(0x2000, "I2C: v_pI2CReg", (PVOID)(IM_STORAGE_BASE_U_VIRTUAL + 0x4000)); 
	pSpiDevExt->txbuf_phy_addr = (unsigned long)(IM_STORAGE_BASE_PHYSICAL + 0x4000); 
 
	pSpiDevExt->rxbuf = (char *)(pSpiDevExt->txbuf + 0x1000); 
	pSpiDevExt->rxbuf_phy_addr = (unsigned long)pSpiDevExt->txbuf_phy_addr + 0x1000; 
/* 
	pSpiDevExt->txbuf = HalAllocateCommonBuffer(&adapter, TX_BUF_SIZE, &phyAddr, FALSE); 
	pSpiDevExt->txbuf_phy_addr = phyAddr.LowPart; 
	pSpiDevExt->rxbuf = HalAllocateCommonBuffer(&adapter, RX_BUF_SIZE, &phyAddr, FALSE); 
	pSpiDevExt->rxbuf_phy_addr = phyAddr.LowPart; 
*/ 
	pSpiDevExt->PaddingAllowed = 1; 
	pSpiDevExt->pBD_ReadCBFunc = NULL; 
 
	GetRegistrySettings(Context, pSpiDevExt); 
	pSpiDevExt->phyDrv = smsspiphy_init(Context, smsspi_interruptHandler, pSpiDevExt); 
	if (pSpiDevExt->phyDrv == NULL) 
	{ 
		DBGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("SmsSpi: SPI_Init() failed to initialize physical driver.\r\n"))); 
		FreeAllocatedResources(pSpiDevExt); 
		return 0; 
	} 
	pSpiDevExt->dev.rxbuf = LocalAlloc(LPTR, RX_BUF_SIZE); 
	if (pSpiDevExt->dev.rxbuf == NULL) 
	{ 
		DBGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("SmsSpi: SPI_Init() failed to allocate memory for RX buffer.\r\n"))); 
		FreeAllocatedResources(pSpiDevExt); 
		return 0; 
	} 
 
	smsspicommon_init(&pSpiDevExt->dev, (PVOID)pSpiDevExt->rxbuf, pSpiDevExt->rxbuf_phy_addr, pSpiDevExt, pSpiDevExt->phyDrv, smsspibus_xfer, MsgFound); 
	memcpy (pSpiDevExt->txbuf, preamble_pattern, sizeof(preamble_pattern)); 
	 
 
 
	pSpiDevExt->WriteOperation = CreateEvent(NULL, FALSE, FALSE, NULL); 
	if (pSpiDevExt->WriteOperation == NULL) 
	{ 
		DBGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("SmsSpi: SPI_Init() failed to create Write event.\r\n"))); 
		FreeAllocatedResources(pSpiDevExt); 
		return 0; 
	} 
 
	msgOptions.dwSize = sizeof(msgOptions); 
	msgOptions.dwFlags = 0; 
	msgOptions.dwMaxMessages = 5; 
	msgOptions.cbMaxMessage = sizeof(struct spi_msg); 
	msgOptions.bReadAccess = TRUE; 
 
	pSpiDevExt->transferMsgQueue = CreateEvent(NULL, FALSE, FALSE, NULL); 
	if (pSpiDevExt->transferMsgQueue == NULL) 
	{ 
		DBGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("SmsSpi: SPI_Init() failed to create transferMsgQueue.\r\n"))); 
		FreeAllocatedResources(pSpiDevExt); 
		return 0; 
	} 
 
	pSpiDevExt->transferThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)SpiTransferThread, pSpiDevExt, 0, NULL); 
	if (pSpiDevExt->transferThread == NULL) 
	{ 
		DBGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("SmsSpi: SPI_Init() failed to create transferThread thread.\r\n"))); 
		FreeAllocatedResources(pSpiDevExt); 
		return 0; 
	} 
	if (CeSetThreadPriority(pSpiDevExt->transferThread, 0) == FALSE) 
	{ 
		DBGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("SmsSpi: SPI_Init() failed to set transferThread thread priority.\r\n"))); 
		FreeAllocatedResources(pSpiDevExt); 
		return 0; 
	} 
 
	if (pSpiDevExt->novaDevice) 
	{ 
		DBGMSG(ZONE_INIT, (TEXT("SmsSpi: SPI_Init() Activating Gen driver with Nava device.\r\n"))); 
		pSpiDevExt->hSmsGenDrv = ActivateDevice(SMS_GEN_DRIVER_REGISTRY_PATH,BD_TYPE_SPI_NOVA); 
	} 
	else 
	{ 
		DBGMSG(ZONE_INIT, (TEXT("SmsSpi: SPI_Init() Activating Gen driver with Stellar device.\r\n"))); 
		pSpiDevExt->hSmsGenDrv = ActivateDevice(SMS_GEN_DRIVER_REGISTRY_PATH,BD_TYPE_SPI_STELLAR); 
	} 
	if (pSpiDevExt->hSmsGenDrv == NULL || pSpiDevExt->hSmsGenDrv == INVALID_HANDLE_VALUE) 
	{ 
		DBGMSG(ZONE_ERROR, (TEXT("SmsSpi: Failed to load SmsGenDrv. Error %d\r\n"),GetLastError())); 
		FreeAllocatedResources(pSpiDevExt); 
		return 0; 
	} 
	 
	DBGMSG(ZONE_INIT, (TEXT("SmsSpi: SPI_Init() End.\r\n"))); 
 
	return (DWORD)pSpiDevExt; 
} 
     
/************************************************************************************* 
FUNCTION NAME:	SPI_Deinit 
 
DESCRIPTION:	Streame Driver Deinit entry point 
 
PARAMETERS:		[IN]	Context - N/A 
										    
RETURN VALUE:	None 
 
REMARKS			NONE 
EXAMPLES		NONE 
*************************************************************************************/ 
BOOL WINAPI SPI_Deinit(DWORD dwContext) 
{ 
	PSPIDEVICEEXTENSION pSpiDevExt = (PSPIDEVICEEXTENSION)dwContext; 
 
	FreeAllocatedResources(pSpiDevExt); 
	return TRUE; 
} 
 
 
/************************************************************************************* 
FUNCTION NAME:	SPI_Open 
 
DESCRIPTION:	Streame Driver Open entry point 
 
PARAMETERS:		[IN]	Context   -  
				[IN]	Access	  -	N/A. 
				[IN]	ShareMode -  N/A. 
										    
RETURN VALUE:	None 
 
REMARKS			NONE 
*************************************************************************************/ 
DWORD WINAPI SPI_Open( 
						DWORD Context,  
						DWORD Access, 
						DWORD ShareMode) 
{ 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsSpi: SPI_Open()\r\n"))); 
	return (DWORD)Context; 
 
} 
 
 
/************************************************************************************* 
FUNCTION NAME:	SPI_Close 
 
DESCRIPTION:	Streame Driver Close entry point 
 
PARAMETERS:		[IN]	Context   -  
				[IN]	Access	  -	N/A. 
				[IN]	ShareMode -  N/A. 
										    
RETURN VALUE:	None 
 
REMARKS			NONE 
*************************************************************************************/ 
BOOL WINAPI SPI_Close(DWORD Context)  
{ 
	DBGMSG(ZONE_INFO, (TEXT("SmsSpi: SPI_Close()\r\n"))); 
	 
	return TRUE; 
} 
 
 
/************************************************************************************* 
FUNCTION NAME:	SPI_Read 
 
DESCRIPTION:	Streame Driver Read entry point 
 
PARAMETERS:		[IN]	DWORD  dwContext   -  
				[IN]	LPVOID pBuffer - User input buffer. 
				[IN]	DWORD  BufferLength 
										    
RETURN VALUE:	None 
 
REMARKS			NONE 
 
*************************************************************************************/ 
DWORD WINAPI SPI_Read(DWORD  dwContext, LPVOID pBuffer, DWORD  BufferLength)  
{ 
	DBGMSG(ZONE_ERROR, (TEXT("SmsSpi: SPI_Read() called, but not supported\r\n"))); 
	return (-1); 
} 
 
/************************************************************************************* 
FUNCTION NAME:	SPI_Write 
 
DESCRIPTION:	Streame Driver Write entry point 
 
PARAMETERS:		[IN]	DWORD  dwContext   
				[IN]	LPVOID pBuffer - User input buffer. 
				[IN]	DWORD  BufferLength 
										    
RETURN VALUE:	None 
 
REMARKS			NONE 
*************************************************************************************/ 
DWORD WINAPI SPI_Write(DWORD  dwContext, LPVOID pBuff, DWORD  BufferLength)  
{	 
	int 	Cnt; 
	int 	AddingPreamble, WrittenBytes; 
	static struct spi_msg   txmsg; 
	PSPIDEVICEEXTENSION pSpiDevExt  = (PSPIDEVICEEXTENSION)dwContext; 
	 
	//DBGMSG(ZONE_INFO, (TEXT("SmsSpi: SPI_Write() Writing %d bytes.\r\n"), BufferLength)); 
 
	AddingPreamble = 1; 
	if (BufferLength > 0x1000) 
	{ /* The FW is the only long message. Do not add preamble, and do not padd it*/ 
		pSpiDevExt->PaddingAllowed = 0; 
		AddingPreamble = 0; 
		BufferLength += 4; 
		smschipreset(pSpiDevExt->phyDrv);		 
	} 
	WrittenBytes = 0; 
		 
	while (BufferLength > 0) 
	{ 
		ResetEvent(pSpiDevExt->WriteOperation);	 
		txmsg.buf = pSpiDevExt->txbuf; 
		txmsg.buf_phy_addr = pSpiDevExt->txbuf_phy_addr; 
		if (AddingPreamble == 1) 
		{ 
			//DBGMSG(ZONE_INFO, (TEXT("SmsSpi: SPI_Write() Adding peamble.\r\n"))); 
			Cnt = min((int)(BufferLength + sizeof(preamble_pattern)), (int)TX_BUF_SIZE); 
			txmsg.len = Cnt; 
			memcpy (pSpiDevExt->txbuf, preamble_pattern, sizeof(preamble_pattern)); 
			memcpy(pSpiDevExt->txbuf+sizeof(preamble_pattern), pBuff, Cnt - sizeof(preamble_pattern)); 
			WrittenBytes += (Cnt - sizeof(preamble_pattern)); 
			BufferLength -= (Cnt - sizeof(preamble_pattern));		 
		} 
		else 
		{ 
			DBGMSG(ZONE_INFO, (TEXT("SmsSpi: SPI_Write() No preamble added.\r\n"))); 
			Cnt = min(BufferLength, TX_BUF_SIZE); 
			txmsg.len = Cnt; 
			memcpy(pSpiDevExt->txbuf, (CHAR*)pBuff, Cnt); 
			WrittenBytes += Cnt; 
			BufferLength -= Cnt;		 
		} 
		memset (pSpiDevExt->txbuf + Cnt, 0, TX_BUF_SIZE - Cnt); 
		//DBGMSG(ZONE_ERROR, (TEXT("SmsSpi: SPI_Write() Sending to transfer queue. buf = 0x%x, len=%d.\r\n"), txmsg.buf, txmsg.len)); 
		SetEventData(pSpiDevExt->transferMsgQueue, (DWORD)&txmsg); 
		//DBGMSG(ZONE_INFO, (TEXT("SmsSpi: SPI_Write() Sending to transfer queue. msg = 0x%x.\r\n"), (DWORD)&txmsg)); 
		SetEvent(pSpiDevExt->transferMsgQueue); 
		WaitForSingleObject(pSpiDevExt->WriteOperation, INFINITE); 
		memset (pSpiDevExt->txbuf, 0, Cnt); 
		(PCHAR)pBuff+=Cnt;		 
		AddingPreamble = 0; 
	} 
	pSpiDevExt->PaddingAllowed = 1; 
	//DBGMSG(ZONE_INFO, (TEXT("SmsSpi: SPI_Write() Write exits.\r\n"))); 
	return WrittenBytes; 
	 
} 
 
/************************************************************************************* 
FUNCTION NAME:	SPI_IOControl 
 
DESCRIPTION:	Streame Driver IOControl entry point 
 
PARAMETERS:		[IN]	DWORD  dwContext -  
				[IN]	DWORD  Ioctl - Command 
				[IN]	PUCHAR pInBuf - Input Buffer 
				[IN]	DWORD  InBufLen - Input Buffer Length  
				[IN]	PUCHAR pOutBuf - Output Buffer 
				[IN]	DWORD  OutBufLen - Output Buffer Length 
				[IN]	PDWORD pdwBytesTransferred - Bytes Transfferd. 
										    
RETURN VALUE:	None 
 
REMARKS			NONE 
*************************************************************************************/ 
BOOL WINAPI SPI_IOControl( 
    DWORD  dwContext, 
    DWORD  Ioctl, 
    PUCHAR pInBuf, 
    DWORD  InBufLen,  
    PUCHAR pOutBuf, 
    DWORD  OutBufLen, 
    PDWORD pdwBytesTransferred 
   ) 
{	 
	BOOL retVal; 
	PSPIDEVICEEXTENSION pSpiDevExt  = (PSPIDEVICEEXTENSION)dwContext; 
 
	retVal = FALSE; 
 
	switch(Ioctl) 
	{ 
		case SIANO_BD_IOCTL_REGISTER_READ_CB: 
			if ((pInBuf != NULL) && (InBufLen >= sizeof(BD_IOCTL_REGISTER_READ_PARAMS_ST))) 
			{ 
				pSpiDevExt->hBDContext = ((PBD_IOCTL_REGISTER_READ_PARAMS_ST)pInBuf)->hContext; 
				pSpiDevExt->pBD_ReadCBFunc = ((PBD_IOCTL_REGISTER_READ_PARAMS_ST)pInBuf)->pBD_ReadCBFunc; 
				retVal = TRUE; 
			} 
			break; 
 
		case SIANO_BD_IOCTL_WRITE_FW_BUFF_TO_DEVICE: 
			if (pInBuf != NULL) 
			{ 
				if (pSpiDevExt->novaDevice) 
					WriteFWtoNova(pSpiDevExt->phyDrv,pInBuf,InBufLen); 
				else 
					WriteFWtoStellar(pSpiDevExt->phyDrv,pInBuf,InBufLen); 
				retVal = TRUE; 
 
			} 
			break; 
		case IOCTL_POWER_CAPABILITIES: 
			DBGMSG(ZONE_INFO, (TEXT("SmsSpi: IOCTL_POWER_CAPABILITIES - supported power states are D0, D3 and D4\r\n"))); 
			if (pOutBuf != NULL && pdwBytesTransferred != NULL && OutBufLen >= sizeof(POWER_CAPABILITIES)) 
			{ 
				PPOWER_CAPABILITIES pCapabilities = (PPOWER_CAPABILITIES)pOutBuf; 
				memset(pCapabilities, 0, sizeof(POWER_CAPABILITIES)); 
				// support D0, D3, D4 
				pCapabilities->DeviceDx = DX_MASK(D0)|DX_MASK(D3)|DX_MASK(D4); 
				*pdwBytesTransferred = sizeof(POWER_CAPABILITIES); 
				retVal = TRUE; 
				break; 
			} 
			 
		case IOCTL_POWER_SET: 
			DBGMSG(ZONE_INFO, (TEXT("SmsSpi: IOCTL_POWER_SET - Changing power state to 0x%x \r\n"),*(CEDEVICE_POWER_STATE*)pOutBuf)); 
			/* Here we need to send the command of changing the power state to FW - not supported yet*/ 
			if (pSpiDevExt->powerState >= D3 && *(CEDEVICE_POWER_STATE*)pOutBuf == D0) 
			{ // When going back to D0 need to reset the FW in  order to make sure the device is ready for FW download. 
				Sleep(1000); 
			} 
			pSpiDevExt->powerState = *(CEDEVICE_POWER_STATE*)pOutBuf; 
			retVal = TRUE; 
			break; 
		case IOCTL_POWER_GET: 
			DBGMSG(ZONE_INFO, (TEXT("SmsSpi: IOCTL_POWER_GET - power state is 0x%x \r\n"),pSpiDevExt->powerState)); 
			*(CEDEVICE_POWER_STATE*)pOutBuf = pSpiDevExt->powerState; 
			retVal = TRUE; 
			break; 
		case IOCTL_REGISTER_POWER_RELATIONSHIP:			 
			DBGMSG(ZONE_WARNING, (TEXT("SmsSpi: Power manager command - not supported yet 0x%x \r\n"),Ioctl)); 
			break; 
		case IOCTL_POWER_QUERY: 
			DBGMSG(ZONE_INFO, (TEXT("SmsSpi: IOCTL_POWER_QUERY - not supported yet 0x%x \r\n"),Ioctl)); 
			if (*(CEDEVICE_POWER_STATE*)pOutBuf == D3) //D3 is not supported by SMS1000 
				*(CEDEVICE_POWER_STATE*)pOutBuf = PwrDeviceUnspecified; 
			retVal = TRUE; 
			break; 
 
        default: 
            break; 
	} 
 
	return retVal; 
 
} 
 
 
/************************************************************************************* 
FUNCTION NAME:	SPI_Seek 
 
DESCRIPTION:	Streame Driver Seek entry point 
 
PARAMETERS:		[IN]	DWORD  dwContext   -  
				[IN]	LONG Position. 
				[IN]	DWORD  Type 
										    
RETURN VALUE:	None 
 
REMARKS			Not implemented for this device 
*************************************************************************************/ 
ULONG SPI_Seek( 
   PVOID Context, 
   LONG  Position, 
   DWORD Type 
   ) 
{ 
    UNREFERENCED_PARAMETER(Context); 
    UNREFERENCED_PARAMETER(Position); 
    UNREFERENCED_PARAMETER(Type); 
     
    return (ULONG)-1; 
} 
 
 
/************************************************************************************* 
FUNCTION NAME:	SPI_PowerDown 
 
DESCRIPTION:	PowerDown entry point 
 
PARAMETERS:		[IN]	DWORD  dwContext   - pointer to a USBGEN_CONTEXT sructure. 
				 
										    
RETURN VALUE:	None 
 
REMARKS			Not implemented for this device 
*************************************************************************************/ 
VOID WINAPI SPI_PowerDown(DWORD dwContext) 
{ 
	UNREFERENCED_PARAMETER(dwContext); 
} 
 
 
/************************************************************************************* 
FUNCTION NAME:	SPI_PowerUp 
 
DESCRIPTION:	PowerUp entry point 
 
PARAMETERS:		[IN]	DWORD  dwContext   - pointer to a USBGEN_CONTEXT sructure. 
				 
										    
RETURN VALUE:	None 
 
REMARKS			Not implemented for this device 
*************************************************************************************/ 
VOID WINAPI SPI_PowerUp(DWORD dwContext) 
{ 
	UNREFERENCED_PARAMETER(dwContext); 
	 
}