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

📄 cpcimultiint.c

📁 Vxworks下
💻 C
字号:
/**********************************************************************
 chengjy@felab, copyright 2002-2004
 cpciMultiInt.c
 函数:	
		void f9656Init();
		void f9656IntFunc(int intIndex);
		void f9656IntHandle(int boardNum);
		void f9656ShutDown();
 调用:			无
 被调用:		硬件响应底层函数,被命令通道调用
 说明:			本文件与硬件关联紧密,仅为中断响应的框架,
 				需要根据实际情况添加中断响应和处理代码才能使用
 **********************************************************************/
#include "vxWorks.h"
#include "logLib.h"
#include "arch/ppc/ivPpc.h"
#include "intLib.h"
#include "taskLib.h"
#include "semLib.h"
#include "string.h"

#include "cpciMultiInt.h"

#if 0	/*不打印9656中断信息*/
#define F9656LOG(a,b,c,d,e,f,g)	;			/*带6个参数的logMsg*/
#define F9656PRINT1(x)		;			/*没有参数的printf*/
#define F9656PRINT2(x,y)		;			/*带一个参数的printf*/
#else
#define F9656LOG(a,b,c,d,e,f,g)	;		/*logMsg((a),(b),(c),(d),(e),(f),(g))*/
#define F9656PRINT1(x)			printf(x)			
#define F9656PRINT2(x,y)		printf((x),(y))			
#endif

struct pciBoardIndex	pciBoard[MAX_BOARD_SUPPORT];
struct pciIntIndex		pciInt[MAX_INT_SUPPORT];
int pciBoardNum;				/*实际使用的pci板的数目,从0开始*/

void f9656Init();
void f9656IntFunc(int intIndex);
void f9656IntHandle(int boardNum);
void f9656ShutDown();

/**********************************************************************
 void f9656Init()
 函数描述: 	9656初始化,创建信号灯,发起服务任务,
               		计算基地址,挂接中断。
 参数:		无
 返回:		无
 调用:		void f9656IntFunc(int intIndex);
			void f9656IntHandle(int boardNum);
 被调用:	用户程序初始化部分
 			命令通道的命令
 **********************************************************************/
void f9656Init()
{
	int busNo,deviceNo,funcNo;
	int intIndex;
	int intNum;
	int i,j;
	STATUS state;
	
	char taskName[30];
	
	/*需要避免重入的控制*/

	/*初始化每块插板信息*/
	for(i=0;i<MAX_BOARD_SUPPORT;i++)
	{
		/*首先全部设置为0*/
		pciBoard[i].pcimem0		= 0;
		pciBoard[i].pcimem1		= 0;
		pciBoard[i].intNum		= 0xFF;
		pciBoard[i].intTimes	= 0;
	}

	/*初始化*/
	for(pciBoardNum=0;pciBoardNum<MAX_BOARD_SUPPORT;pciBoardNum++)
	{
		/*寻找9656*/
		if(pciFindDevice(PCI_F9656_VENDOR_ID,PCI_F9656_DEVICE_ID,pciBoardNum,&busNo,&deviceNo,&funcNo)!=OK)
		{
			break;
		}
		logMsg("f9656Init: pci device, vendor 0x%x,device 0x%x, index 0x%x\n",PCI_F9656_VENDOR_ID,PCI_F9656_DEVICE_ID,pciBoardNum,0,0,0);

		/*mem基地址*/
		pciConfigInLong(busNo,deviceNo,funcNo,0x10,&(pciBoard[pciBoardNum].pcimem0));
		pciBoard[pciBoardNum].pcimem0 = (UINT)PCIMEM2CPU(pciBoard[pciBoardNum].pcimem0&(~0xf));
		pciConfigInLong(busNo,deviceNo,funcNo,0x18,&(pciBoard[pciBoardNum].pcimem1));
		pciBoard[pciBoardNum].pcimem1 = (UINT)PCIMEM2CPU(pciBoard[pciBoardNum].pcimem1&(~0xf));

		/*中断号*/
		pciConfigInByte(busNo,deviceNo,funcNo,0x3C,&(pciBoard[pciBoardNum].intNum));
		pciBoard[pciBoardNum].intNum = CPCIINT2CPU(pciBoard[pciBoardNum].intNum);

		/*板号,可以通过9656的首部寄存器或者memory 1 某个地址的值不同来区分,
		这里为了简便直接赋值为pciBoardNum+1*/
		pciBoard[pciBoardNum].index = pciBoardNum+1;
		
		logMsg("f9656Init: memBase: 0x%8x,0x%8x,intNum 0x%x\n",
				pciBoard[pciBoardNum].pcimem0,pciBoard[pciBoardNum].pcimem1,pciBoard[pciBoardNum].intNum,0,0,0);			
	}	
		
	/*如果没有找到任何cpci 器件,退出*/
	if(pciBoardNum==0)
	{
		logMsg("f9656Init: no cpci board found, now exit\n",0,0,0,0,0,0);
		return;
	}

	/*没有找到cpci器件的中断index,对应的enable全部为0*/
	for(i=0;i<MAX_INT_SUPPORT;i++)
	{
		pciInt[i].enable = 0;
	}
	for(i=0;i<pciBoardNum;i++)
	{
		/*某个中断相应位上的1表示对应有插板使用此中断*/
		intIndex = INT_NUM2INDEX(pciBoard[pciBoardNum].intNum);
		pciInt[intIndex].enable = (pciInt[intIndex].enable | (0x01<<i));	
	}

	/*逐个使能中断*/
	for(intIndex=0;intIndex<MAX_INT_SUPPORT;intIndex++)
	{
		if(pciInt[intIndex].enable!=0)
		{
			intNum = INT_INDEX2NUM(intIndex);
			F9656LOG("f9656Init: int number: 0x%x connected\n",intNum,0,0,0,0,0);
			state = intConnect((INUM_TO_IVEC(intNum)),f9656IntFunc,intIndex);
			if(state!=OK)
				logMsg("f9656Init: error in intConnect\n",0,0,0,0,0,0);
			intEnable(intNum);
		}
	}

	/*逐个初始化插板*/
	for(i=0;i<pciBoardNum;i++)
	{
		/*创建信号灯*/
		pciBoard[i].semPci = semCCreate(SEM_Q_FIFO,SEM_EMPTY);
				
		if(pciBoard[i].semPci == NULL)
		{
			logMsg("f9656Init: unable to create semF9656\n",0,0,0,0,0,0);
			exit(-1);
		}

		/*发起相应的处理函数*/
		sprintf(taskName,TNAME_F9656INTHDL,"%d",i);
		taskSpawn(taskName,TPRI_F9656INTHDL,0,USER_STACK_SIZE,(FUNCPTR)f9656IntHandle,i,0,0,0,0,0,0,0,0,0);
	}
}

/**********************************************************************
 void f9656IntFunc(int intIndex)
 函数描述:	中断服务程序,挂接到9656中断,中断时自动被
 				调用。具体工作由f9656IntHandle() 完成,使用各板的
                 		semPci 同步。此函数中的清中断机制直接针对硬件,
                 		如果使用9656之外的其它pci桥片,请参阅芯片的datasheet.
 参数:		index,	产生的中断的index,取值范围从0 到3.
 返回:		无
 调用:		无
 被调用:	void f9656Init()
 **********************************************************************/
void f9656IntFunc(int intIndex)
{
	int  intNum;
	UINT regValue;
	int  pciIndex;

	intNum = INT_INDEX2NUM(intIndex);
	/*屏蔽中断*/
	intDisable(intNum);
		
	F9656LOG("f9656IntFunc: interrupt received\n",0,0,0,0,0,0);

	/*获取中断的板号*/
	for(pciIndex=0;pciIndex<MAX_BOARD_SUPPORT;pciIndex++)
	{
		if((pciInt[intIndex].enable&(0x01<<pciIndex))!=0)
		{
			/*逐个判断可能产生此中断的cpci 插板是否已经产生了中断*/
			regValue = *F9656MEM2CPU0(0x68,pciIndex);
			if((regValue&0x00002000)!=0)
			{
				/*清 单板的中断标志*/
				*F9656MEM2CPU0(0xA8,pciIndex)	= 0x18000000;
				/*释放信号灯,通知f9656IntHandle 开始处理*/
				semGive(pciBoard[pciIndex].semPci);
			}
		}
	}

	/*允许响应其它使用此中断号的插板的中断*/
	intEnable(intNum);
}

/**********************************************************************
 void f9656IntHandle(int boardNum)
 函数描述:	中断后的实际任务处理函数,中断服务程序
                		并不执行大量工作,只是通知此函数。
 参数:		boardNum,	产生中断的板的cpci 号,取值范围0~7
 返回:		无
 调用:		void f9656ShutDown()
 被调用:	void f9656Init()
 **********************************************************************/
void f9656IntHandle(int boardNum)
{
	while(1)
	{
		if(semTake(pciBoard[boardNum].semPci,WAIT_FOREVER)!=OK)
		{
			logMsg("f9656IntHandle: error in semTake %d\n",boardNum,0,0,0,0,0);
			break;
		}

		/*成功获取信号灯,说明该板产生了一次中断*/
		pciBoard[boardNum].intTimes++;

		/*防止过界*/
		if(pciBoard[boardNum].intTimes==0x1000000)
			pciBoard[boardNum].intTimes = 0;

		/*允许9656 再次传送数据到零槽*/
	}
	/*出错退出*/
	logMsg("f9656IntHandle: something wrong, now exit\n",0,0,0,0,0,0);
	f9656ShutDown();
}

/**********************************************************************
 void f9656ShutDown()
 函数描述:	关闭9656 的操作,主要是解决一些在SHELL 下重复
 				使用F9656Init()的信号灯没有删除的问题,在这里
                 		删除信号灯以及中断后的处理函数。
 参数:		无
 返回:		无
 调用:		无
 被调用:	void f9656IntHandle(int boardNum)
 			用户在shell下调用
 			命令通道的某个命令
 **********************************************************************/
void f9656ShutDown()
{
	int i;
	int intIndex;
	char taskName[30];

	/*需要添加避免重入的判断*/

	/*按中断index 0~3 关闭中断*/
	for(intIndex=0;intIndex<4;intIndex++)
	{
		intDisable(INT_INDEX2NUM(intIndex));
	}
	/*按插板index 0~7结束任务*/
	for(i=0;i<pciBoardNum;i++)
	{
		/*删除中断服务任务*/
		sprintf(taskName,TNAME_F9656INTHDL,"%d",i);
		/*如果是被f9656IntHandle()调用,自己会退出,否则必须删除任务*/
		if(taskNameToId(taskName)!=taskIdSelf())
		{
			taskDelete(taskNameToId(taskName));
			F9656LOG("f9656ShutDown:%d deleted\n",i,0,0,0,0,0);
		}
			
		/*删除信号灯*/
		semDelete(pciBoard[i].semPci);
	}
	logMsg("f9656ShutDown:9656 shut down now\n",0,0,0,0,0,0);
}

⌨️ 快捷键说明

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