⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 go7007drv.c

📁 ARM嵌入式开发应用实例源代码下载控制器
💻 C
字号:
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/usb.h>
#include <linux/slab.h>

#include "usb-func.h"
#include "go7007drv.h"

#define MAXBLOCKSIZE		4096

/* Debug status */
static int debug = 0;

/* Redefine debug macro */
#undef	dbg
#define dbg(format, arg...) \
	do { if (debug) printk(KERN_DEBUG __FILE__ ": [" __FUNCTION__ "] " \
		format "\n" , ## arg); \
	} while (0)

#undef	err
#define err(format, arg...) printk(KERN_ERR __FILE__ ": [" __FUNCTION__ "] " \
		format "\n" , ## arg)

////////////////////////////////////////////////////////////////////////////////////////////
//
// SDK interacts with driver via send coomand to driver.
// All commands are sent accompanied by a "CMD_PACKET" structure , the "Type" field of
// the structure holds the command type which is defined as following enum. The other fields varies
// according to different command.

enum CMD
{
	CMD_BOOTUP,
	CMD_INITIALIZE,
	CMD_UNINITIALIZE,
	CMD_SENDPACKETS,
	CMD_SETBLOCKSIZE,

	// set interface mode
	//
	// CMD_PACKET::Param :	IM_HPI -- hpi mode, 
	//						IM_USB -- usb mode, 
	//						IM_STANDBY -- standby 

	CMD_SETINTERFACEMODE,

	// read cbus registers via firmware
	//
	// CMD_PACKET::Param : number of registers to read
	// CMD_PACKET::pBuf  : each unit of word holds an address
	// 
	// return buffer : each unit of word holds a read result data

	CMD_READCBUSREGFW,

	// write cbus registers via firmware
	//

	// CMD_PACKET::Param : number of registers to write
	// CMD_PACKET::pBuf  : each unit of word holds alternated address and data

	CMD_WRITECBUSREGFW,

	// read a hpi register
	//
	// CMD_PACKET::Param : address of hpi register
	// 
	// return buffer : a word that holds the read result data

	CMD_READHPIREGISTER,

	// write a hpi register
	//
	// CMD_PACKET::Param : address of hpi register
	// CMD_PACKET::pBuf	 : a word that holds data to write

	CMD_WRITEHPIREGISTER,

	// do a self test

	// CMD_PACKET::Param :	ST_HWMBIST -- hardware mbist
	// CMD_PACKET::pBuf  :
	
	// CMD_PACKET::Param :	ST_BASICHPICHECK -- basic hpi check
	// CMD_PACKET::pBuf  :  
	
	// CMD_PACKET::Param :	ST_IOCHECK -- io check
	// CMD_PACKET::pBuf  :  
	
	// CMD_PACKET::Param :	ST_SWMBIST -- software mbist
	// CMD_PACKET::pBuf  :
	
	// CMD_PACKET::Param :	ST_MEMSCAN -- memory scan
	// CMD_PACKET::pBuf  :  WORD[0] : memory size, 0 -- 4M, 1-- 8M

	CMD_SELFTEST,
	CMD_SENDPACKETSWITHRETURN,
	CMD_INITIALIZEI2C,
}; 

// DECLARE_WAIT_QUEUE_HEAD(delay_wq);

static void Delay()
{
	wait_queue_head_t wq_delay;

	init_waitqueue_head(&wq_delay);
	sleep_on_timeout(&wq_delay, 0.1*HZ);

	// sleep_on_timeout(&delay_wq, 0.1*HZ);
}

// 0 -- success
// -1 -- timeout
// -2 -- error interrupt type

int CheckInterruptPipe(pusb_t pdx, int InterruptType, int RepeatNum)
{
	int i;
	int r;
	USHORT IntRetVal, IntRetData;

	for(i=0;i<RepeatNum;i++)
	{
		r = ReadInterruptPipe(pdx, &IntRetVal, &IntRetData);

		if (r != 0)
		{
			if(IntRetVal == InterruptType)
				return 0;
			else
			{
				PrintMsg1(("<DRV> CheckInterruptPipe : Error Interrupt 0x%08X, required 0x%08X",IntRetVal, InterruptType));
				Delay();
				continue;//return IntRetVal;
			}
		}
		else
		{
			PrintMsg1(("<DRV> CheckInterruptPipe : Timeout"));
			return -1;
		}
	}

	return -2;
}

int CheckInterruptPipeWithReturn(pusb_t pdx, int InterruptType, int InterruptData, int RepeatNum)
{
	int i;
	int r;
	USHORT IntRetVal, IntRetData;

	r = ReadInterruptPipe(pdx, &IntRetVal, &IntRetData);

	if (r != 0)
	{
		if(IntRetVal==InterruptType || IntRetVal == 0x555b)
		{
			if(InterruptData<0) {
				err("IntRetData = 0x%x", IntRetData);
				return IntRetData;
			} else {
				err("IntRetVal==InterruptVal, InterruptData >= 0");
				return 0;
			}
		}
		else
		{
			err("<DRV> CheckInterruptPipe : Error Interrupt 0x%08X, required 0x%08X",IntRetVal, InterruptType);
			return IntRetVal;
		}
	}
	else
	{
		err("<DRV> CheckInterruptPipe : Timeout");
		return -1;
	}
}

// 0 -- success
// -1 -- timeout
// -2 -- error interrupt type

int CheckInterruptPipe2(pusb_t pdx, int InterruptType, int InterruptData, int RepeatNum)
{
	int i;
	int r;
	USHORT IntRetVal, IntRetData;

	for(i=0;i<RepeatNum;i++)
	{
		r = ReadInterruptPipe(pdx, &IntRetVal, &IntRetData);

		if (r != 0)
		{
			if((IntRetVal == InterruptType) && (IntRetData == InterruptData))
				return 0;
			else
			{
				dbg("Error Interrupt 0x%08x 0x%08x", IntRetVal,IntRetData);
				Delay();
				continue;//return IntRetVal;
			}
		}
		else
		{
			dbg("Timeout");
			return -1;
		}
	}

	return -2;
}

//////  return 0 -- success

int BootupChipWithFirmware(pusb_t pdx, unsigned char *pFirmware, int Firmlen)
{
	int r;

	PrintMsg1(("<DRV> BootupChipWithFirmware : Enter, FirmLen : %d",Firmlen));

	if(pdx->DeviceState != DS_OPENED && pdx->DeviceState != DS_BOOTUPED)
		return 1;

	WriteInterrupt(pdx,0x0001,0x0001);
	mdelay(50);

	WriteInterrupt(pdx,0x0001,0x0001);
	mdelay(50);

	if(CheckInterruptPipe(pdx, 0x55aa, 10)!=0)
	{
		PrintMsg(("<DRV> BootupChip : Bootup Fail 1"));
		PrintMsg1(("<DRV> BootupChip : Bootup Fail 1"));
		return 2;
	}

//	DownloadFirmware

	r = DownloadBuffer(pdx, pFirmware, Firmlen);
	if (r == 0)
		return 3;	

	if(CheckInterruptPipe(pdx, 0x5a5a, 10)!=0)
	{
		PrintMsg(("<DRV> BootupChip : Fail 2"));
		PrintMsg1(("<DRV> BootupChip : Fail 2"));
		return 3;
	}

	err("<DRV> BootupChip : Success");
	PrintMsg1(("<DRV> BootupChip : Success"));

	pdx->DeviceState = DS_BOOTUPED;
	return 0;
}

// DECLARE_WAIT_QUEUE_HEAD(wq_stop_stream_thread);

void StopStreamThread(void *arg)
{
	int rv;
	pusb_t pdx = (pusb_t)arg;

	pdx->StreamThreadState = 0;
	rv = sleep_on_timeout(&pdx->wq_stop_stream_thread, 5*HZ);

	dbg("StopStreamThread: rv = %d", rv);
}

DECLARE_MUTEX		(stream_thread_mutex);

int StreamThreadProc(void *arg)
{
	unsigned char	*pBlock;
	int	r;
	int ncount;

	pusb_t pdx = (pusb_t)arg;

	PrintMsg(("<DRV> StreamThreadProc : Enter"));

	if(pdx->bulk_in_buffer == NULL)
	{
		dbg("ERROR: bulk_in_buffer is NULL");
	}

	pBlock = pdx->bulk_in_buffer;

	ncount = 0;
	while(pdx->StreamThreadState == 1)
	{
		int BlockSize1 = BULK_IN_BUFSIZE;	//pdx->BlockSize;

		// down(&stream_thread_mutex);
		r = ReadStreamPipe(pdx, pBlock, BlockSize1);

		if(pdx->StreamThreadState == 1 && r != 0 ) {
			StreamBuffer_AddBlock(&(pdx->StreamBuffer),pBlock, BlockSize1);
		}

		// up(&stream_thread_mutex);
	#if 0
		while(ncount++ > 50) {
			schedule();
			ncount = 0;
		}
	#endif
	}

	PrintMsg1(("<DRV> StreamThreadProc : Need exit"));

	PrintMsg(("<DRV> StreamThreadProc : Exit"));
	wake_up(&pdx->wq_stop_stream_thread);
}

extern void begin_stream_input(pusb_t s);

// return 0: success
int InitializeDevice(pusb_t pdx, INT_PACKET *pInitPackets, int InitPacketsNum)
{
//	HANDLE InterruptThreadHandle;
//	HANDLE StreamThreadHandle;
//	NTSTATUS ntStatus;
	int r;

	PrintMsg(("<DRV> InitializeDevice : Enter"));

	if(pdx->DeviceState != DS_BOOTUPED)
		return 1;

	StreamBuffer_Reset(&(pdx->StreamBuffer));

//	pdx->IFrameNum = 0;
//	pdx->PFrameNum = 0;

//	pdx->TotalDelay = 0;
//	pdx->ChipDelay = 0;

	r = DownloadBuffer(pdx, (unsigned char *)pInitPackets, sizeof(INT_PACKET)*InitPacketsNum);
	if (r == 0)
		return 3;	

	if(CheckInterruptPipe(pdx, 0x0000, 10)!=0)
	{
		PrintMsg(("<DRV> Initialize : fail"));
		PrintMsg1(("<DRV> Initialize : fail"));
		return 3;	
	}

//	pdx->InterruptThreadState = 1;
//	ntStatus = PsCreateSystemThread( &InterruptThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL,
//								   InterruptThreadProc, (PVOID)fdo);

	pdx->StreamThreadState = 1;
	// kernel_thread(StreamThreadProc, (void *)pdx, 0);
	begin_stream_input(pdx);

	pdx->DeviceState = DS_RUNNING;

	err("<DRV> InitializeDevice : Completed SUCCESSFUL");
	return 0;
}



int UninitializeDevice(pusb_t pdx)
{
//	PDEVICE_EXTENSION pdx = fdo->DeviceExtension;
//	unsigned short *pBuffer;		
//	unsigned int i;

	PrintMsg(("<DRV> UninitializeDevice : Enter"));

	if(pdx->DeviceState != DS_RUNNING)
		return 1;

	// pdx->StreamThreadState = 0;		// stop stream thread
	StopStreamThread(pdx);


	WriteInterrupt(pdx,0x0001,0x0001);

	// send 0x0020 packet to make chip stop
/*	pBuffer = (unsigned short *)ExAllocatePool(NonPagedPool,64);
	RtlZeroMemory(pBuffer,64);
	pBuffer[0] = 0x0020;
	DownloadBuffer(fdo, (unsigned char *)pBuffer,64);
	ExFreePool(pBuffer);
*/
//	pdx->InterruptThreadState = 0;		// stop interrupt thread

//	for (i = 0; i < pdx->Interface->NumberOfPipes; i++)
//		AbortPipe(fdo,(USBD_PIPE_HANDLE) pdx->Interface->Pipes[i].PipeHandle);

//	for (i = 0; i < pdx->Interface->NumberOfPipes; i++)
//		ResetPipe(fdo,i);

	PrintMsg(("<DRV> Left"));

	pdx->DeviceState = DS_OPENED;

	return 0;
}

// return 0: success
int InitializeI2C(pusb_t pdx, INT_PACKET *pInitPackets, int InitPacketsNum)
{
	int r;

	PrintMsg1(("<DRV> InitializeI2C : Enter"));

	if(pdx->DeviceState != DS_BOOTUPED)
		return 1;

	r = DownloadBuffer(pdx, (unsigned char *)pInitPackets, sizeof(INT_PACKET)*InitPacketsNum);
	if (r == 0)
		return 3;	

	if(CheckInterruptPipe2(pdx, 0x555a, 0, 10)!=0)
	{
		PrintMsg(("<DRV> InitializeI2C : fail"));
		PrintMsg1(("<DRV> InitializeI2C : fail"));
		return 3;	
	}

	PrintMsg1(("<DRV> InitializeI2C : Completed"));
	return 0;
}

// return 0 : success
//        1 : fail

int	OnWriteProc(pusb_t pdx, const char *buf)
{
	int r = 0;
	CMD_PACKET *pCmd = (CMD_PACKET *)buf;

//	PrintMsg1(("<DRV> Write : %d %d",FrameSize,pCmd->Type));

	switch (pCmd->Type)
	{
	case CMD_BOOTUP:
		r = BootupChipWithFirmware(pdx, pCmd->pBuf, pCmd->Param);
		break;
	
	case CMD_INITIALIZE:
	{
		int PacketNum = pCmd->Param;
		INT_PACKET *p = (INT_PACKET *)(pCmd->pBuf);

//		DumpBuffer(pBuf,PacketNum*64+5);

		r = InitializeDevice(pdx, p, PacketNum);
		break;
	}

	case CMD_UNINITIALIZE:
	        err("CMD_UNINITIALIZE called");
		UninitializeDevice(pdx);
		break;
 
	case CMD_INITIALIZEI2C:
	{
		int PacketNum = pCmd->Param;
		INT_PACKET *p = (INT_PACKET *)(pCmd->pBuf);

//		DumpBuffer(pBuf,PacketNum*64+5);
		r = InitializeI2C(pdx, p, PacketNum);
		break;
	}

	case CMD_SENDPACKETS:
	{
		int PacketNum = pCmd->Param;
		INT_PACKET *p = (INT_PACKET *)(pCmd->pBuf);
		int rv;

//		PrintMsg1(("<DRV> Send Packet to chip : PacketNum(%d)",PacketNum));
//		DumpBuffer1(p,64);

		rv = DownloadBuffer(pdx,(UCHAR *)p,64*PacketNum);
		err("CMD_SENDPACKETS,rv = %i", rv);

		break;
	}

/*	case CMD_SETBLOCKSIZE:	
	{
		int BlockSize1 = pCmd->Param;
														    
		if(BlockSize1>0&&BlockSize1<=64)
			BlockSize1 = 64;
		else if(BlockSize1>64&&BlockSize1<=128)
			BlockSize1 = 128;
		else if(BlockSize1>128&&BlockSize1<=256)
			BlockSize1 = 256;
		else if(BlockSize1>256&&BlockSize1<=512)
			BlockSize1 = 512;
		else if(BlockSize1>512&&BlockSize1<=1024)
			BlockSize1 = 1024;
		else if(BlockSize1>1024&&BlockSize1<=2048)
			BlockSize1 = 2048;
		else if(BlockSize1>2048&&BlockSize1<=4096)
			BlockSize1 = 4096;
		else
			BlockSize1 = 8192;

		pdx->BlockSize = BlockSize1;
		
		PrintMsg1(("<DRV> BLOCKSIZE : %d",pdx->BlockSize));
		break;
	}

	case CMD_SETINTERFACEMODE:
	{
		int IfMode = pCmd->Param;
		UCHAR Data[1];

		if(IfMode == IM_HPI)
		{
			DoVendorRequest(fdo, VR_STARTHPI, 0, 0, Data, 1, DIR_IN); 
			if(Data[0] == 0xaa)
				r=0;
			else
				r=1;
		}
		else if(IfMode == IM_USB)
		{
			DoVendorRequest(fdo, VR_STARTUSB, 0, 0, Data, 1, DIR_IN); 
			if(Data[0] == 0x55)
				r=0;
			else
				r=1;
		}
		else if(IfMode == IM_STANDBY)
		{
			DoVendorRequest(fdo, VR_STANDBY, 0, 0, Data, 1, DIR_IN); 
			if(Data[0] == 0x88)
				r=0;
			else 
				r=1;
		}

		PrintMsg1(("<DRV> CMD_SETINTERFACEMODE %d, Return : 0x%02x",IfMode,Data[0]));
		break;
	}

	case CMD_WRITEHPIREGISTER:
		r = WriteHPIRegister(fdo, (USHORT)(pCmd->Param), *((USHORT *)(pCmd->pBuf)));
		break;

	case CMD_WRITECBUSREGFW:
		r = WriteCBusRegFW(fdo, pCmd->Param, (USHORT *)pCmd->pBuf);
		break;

	case CMD_SELFTEST:
	{
		int SelfTest = pCmd->Param;
		PrintMsg1(("<DRV> Self Test : %d",SelfTest)); 
		
		switch (SelfTest)
		{
		case ST_HWMBIST:
		{
			UCHAR Data[1];

			DoVendorRequest(fdo, VR_STARTBIST, 0, 0, Data, 1, DIR_IN); 
			if(Data[0] == 0)
				r=0;
			else
				r=1;
			PrintMsg1(("<DRV> Return val : %d",Data[0])); 
			break;
		}

		case ST_BASICHPICHECK:
			r = ST_BasicHPICheck(fdo, pCmd->pBuf);
			break;

		case ST_IOCHECK:
			r = ST_IOCheck(fdo, pCmd->pBuf);
			break;

		case ST_SWMBIST:
			r = ST_SwMBist(fdo, pCmd->pBuf);
			break;

//		case ST_REGSCAN:
//			r = ST_RegScan(fdo, pCmd->pBuf);
//			break;

		case ST_MEMSCAN:
			r = ST_MemoryScan(fdo, *((USHORT *)(pCmd->pBuf)));
			break;
		}
		break;
	}
*/
	default:
		break;
	}

	return r;
}

int OnIoctlProc(pusb_t pdx, unsigned long arg)
{
        int r = 0;
	CMD_PACKET *pCmd = (CMD_PACKET *)arg;

        err("OnIoctlProc : %d", pCmd->Type);
	
	switch (pCmd->Type)
	{
	case CMD_SENDPACKETSWITHRETURN:
	{	
		int PacketNum = pCmd->Param;
		INT_PACKET *p = (INT_PACKET *)(pCmd->pBuf);

                err("CMD_SENDPACKETSWITHRETURN,will downloadbuffer");
		DownloadBuffer(pdx,(UCHAR *)p, 64);
		err("[0x%x..0x%x..0x%x..0x%x..0x%x]", pCmd->pBuf[4], pCmd->pBuf[3], pCmd->pBuf[2], pCmd->pBuf[1], pCmd->pBuf[0]);
		
		r = CheckInterruptPipeWithReturn(pdx, 0x555a, -1, 10);

		if (r >= 0) {
			err("checkInterruptPipeWithReturn return 0x%x", r);
			put_user(r, (unsigned short *)arg);
			r = 0;
		} else {
			err("CMD_SENDPACKETSWITHRETURN, fail r = 0");
		}
		
		break;
	}
	
	default:
		break;
	}
	
	return r;
}


void dump_bin(char *Title,unsigned char *buf, int len)
{
	char s[256],s1[16];
	int i;
	
	PrintMsg1(("%s",Title));

	strcpy(s,"");	
	for(i=0;i<len;i++)
	{
		sprintf(s1, "%02X ", buf[i]);
		strcat(s,s1);
		if(i%16==15)
		{
			PrintMsg1(("%s",s));
			strcpy(s,"");
		}
	}
}  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -