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

📄 templeend.c

📁 VxWorks中网络驱动开发中的END驱动程序模版 VxWorks 、BSP、END、网络、模版
💻 C
📖 第 1 页 / 共 2 页
字号:
/*包含头文件×/

#include "vxWorks.h"
#include "stdlib.h"
#include "cacheLib.h"
#include "intLib.h"
#include "end.h"
#include "endLib.h"
#include "lstLib.h"
#include "wdLib.h"
#include "iv.h"
#include "semLib.h"
#include "etherLib.h"
#include "logLib.h"
#include "netLib.h"
#include "stdio.h"
#include "sysLib.h"
#include "errno.h"
#include "errnoLib.h"
#include "memLib.h"
#include "iosLib.h"

#undef ETHER_MAP_IP_MULTICAST
#include "etherMultiLib.h"

#include "net/mbuf.h"
#include "net/unixLib.h"
#include "net/protosw.h"
#include "net/systm.h"
#include "net/if_subr.h"
#include "net/route.h"

#include "sys/socket.h"
#include "sys/ioctl.h"
#include "sys/times.h"

IMPORT int endMultiListCnt(END_OBJ* pEnd);

/*宏定义*/

/*配置项目的宏定义*/

#define END_BUFSIZ  (ETHERMTU + ENET_HDR_REAL_SIZ + 6)
#define EH_SIZE     (14)
#define END_SPEED_10M  10000000    /*速率为10Mbps*/
#define END_SPEED_100M 100000000   /*速率为100Mbps*/
#define END_SPEED      END_SPEED_10M

/*高速缓存的宏定义*/


#define END_CACHE_INVALIDATE(address,len)\
         CACHE_DRV_INVALIDATE(&pDrvCtrl->cacheFuncs,(address),(len))
     
#define END_CACHE_PHYS_TO_VIRT(address)\
         CACHE_DRV_PHYS_TO_VIRT(&pDrvCtrl->cacheFuncs,(address))
         
#define END_CACHE_VIRT_TO_PHYS(address)\
         CACHE_DRV_VIRT_TO_PHYS(&pDrvCtrl->cacheFuncs,(address))
         
/***************************************************************************/
/*以下是BSP接口的默认宏定义。这些宏定义可以在其他文件再次定义成用户自己的值*/
/*                                                                         */
/***************************************************************************/

/*将中断处理程序连接到中断向量的宏定义*/

#ifndef SYS_INT_CONNECT
#define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)\
        {\
        IMPORT STATUS sysIntConnect();\
        *pResult = intConnect((VOIDFUNCPTR*)INUM_TO_IVEC(pDrvCtrl->ivec),rtn,(int)arg);\
      }
#endif

/*清除中断处理程序与中断向量表连接的宏定义*/

LOCAL void dummyIsr(void){};

#ifndef SYS_INT_DISCONNECT
#define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)\
        {\
        IMPORT STATUS intConnect();\
        *pResult = intConnect((VOIDFUNCPTR*)INUM_TO_IVEC(pDrvCtrl->ivec),dummyIsr,(int)arg);\
        }
#endif

/*启动中断级别的宏定义*/

#ifndef SYS_INT_ENABLE
#define SYS_INT_ENABLE(pDrvCtrl)\
        {\
        IMPORT void sysLanIntEnable();\
        sysLanIntEnable(pDrvCtrl->ilevel);\
        }
#endif

/*从BSP获得以太网地址的宏定义*/

#ifndef SYS_ENET_ADDR_GET
#define SYS_ENET_ADDR_GET(pDevice)\
        {\
        IMPORT unsigned char sysTemplateEnetAddr[];\
        bcopy((char*)sysTemplateEnetAddr,(char*)(&pDevice->enetAddr),6);\
        }
#endif

/*快速访问内存芯片的宏定义*/

#ifndef TEMPLATE_OUT_SHOT
#define TEMPLATE_OUT_SHOT(pDrvCtrl,addr,value)\
        (*(USHORT*)addr = value)
#endif

#ifndef TEMPLATE_IN_SHORT
#define TEMPLATE_IN_SHORT(pDrvCtrl,addr,pData)\
        (*pData = *addr)
#endif

/*从MIB II快速获取硬件地址的宏定义*/

#define END_HADDR(pEnd)\
         ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
         
#define END_HADDR_LEN(pEnd)\
         ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
         

/*数据结构类型定义*/

typedef struct
    {
    	int len;
    	char * pData;
    }PKT;      /*一个简单的DMA数据包*/
    
#define TEMPLATE_PKT_LEN_GET(pPkt)(((PKT*)pKt)->len)

typedef struct rfd
    {
    	PKT* pPkt;
    	struct rfd* next;
    }RFD  /*简单的接收帧描述符*/
    
typedef struct free_args
    {
    	void* arg1;
    	void* arg2;
    }FREE_ARGS
    
/*驱动程序控制结构的定义*/

typedef struct end_device
    {
    	END_OBJ END;  /*现有的end结构的重用*/
    	int unit;/*单元号*/
    	int ivec;  /*中断向量*/
    	int ilevel;  /*中断级别*/
    	char* pShMem;   /*指向共享内存的指针*/
    	long flag;
    	UCHAR enetAddr[6];   /*以太网地址*/
    	CACHE_FUNCS cacheFuncs;  /高速缓存函数指针*/
    	FUNCPTR freeRtn[128];
    	struct free_args freeData[128];
    	CL_POOL_ID pClPoolId;    /*资源池*/
    	bool rxHandling;   /*调度的接收任务*/    	
    }END_DEVICE;    
    
    
M_CL_CONFIG templateMclBlkConfig = /*网络mbuf配置表*/
    {
    	0,0,NULL,0
    };
    
CL_DESC templateClDescTabl[] = /*网络资源池配置表*/
    {
    	{ETHERMTU+EH_SIZE+2,0,NULL,0}
    };
    
int templateClDescTblNumEnt = (NELEMENTS(templateClDescTbl));

NET_POOL templateCmpNetPool;

/*标志字段的定义*/

#define TEMPLATE_PROMISCUOUS 0x1
#define TEMPLATE_POLLING     0X2

/*状态寄存器的位定义*/

#define TEMPLATE_RINT  0x1  /*rx 中断挂起*/
#define TEMPLATE_TINT  0X2  /*TX 中断挂起*/
#define TEMPLATE_RXON  0X4  /*RX 使能*/
#define TEMPLATE_VALID_INT  0X3  /*有一个中断挂起*/

#defien TEMPLATE_MIN_FBUF (1536)   /*第一个缓冲区的大小*/

/*用于调试的宏定义*/

#ifdef DEBUG
#define LOGMSG(x,a,b,c,d,e,f)\
         if(endDebug)\
         	{\
         		logMsg(x,a,b,c,d,e,f);\
         	}    
#else
#define LOGMSG(x,a,b,c,d,e,f)
#endif

#undef DRV_DEBUG

#ifdef DRV_DEBUG
#define DRV_DEBUG_OFF 0X0000
#define DRV_DEBUG_RX 0X0001
#define DRV_DEBUG_TX 0X0002
#define DRV_DEBUG_INT 0X0004
#define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
#define DRV_DEBUG_POLL_RX 0X0008
#define DRV_DEBUG_POLL_TX 0X0010
#define DRV_DEBUG_LOAD 0X0020
#define DRV_DEBUG_IOCTL 0X0040
#define DRV_DEBUG_POLL_REDIR 0X10000
#define DRV_DEBUG_LOG_NVRAM 0X20000

int templateDebug = 0x00;
int templateTxInts = 0;

#define DRV_LOG(FLG,X0,X1,X2,X3,X4,X5,X6) \
         if (templateDebug & FLG) \
         	   logMsg(X0,X1,X2,X3,X4,X5,X6);
         	   
#define DRV_PRINT(FLG,X) \
          if (templateDebug & FLG) printf X;

#else

#define DRV_LOG(DBG_SW,X1,X2,X3,X4,X5,X6)
#define DRV_PRINT(DBG_SW,X)

#endif

/*本地使用的函数定义*/

/*静态函数声明*/

LOCAL void templateReset (END_DEVICE* pDrvCtrl);
LOCAL void templateInt (END_DEVICE* pDrvCtrl);
LOCAL void templateHandleRcvInt (END_DEVICE* pDrvCtrl);
LOCAL STATUS templateRecv (END_DEVICE* pDrvCtrl,char* pData);
LOCAL void templateConfig (END_DEVICE* pDrvCtrl);
LOCAL UINT templateStatusRead(END_DEVICE* pDrvCtrl);

/*END特定的接口定义*/

/*这些接口只对外部程序可见*/

END_OBJ* templateLoad(char* initString);

LOCAL STATUS templateStart (END_OBJ* pDrvCtrl);
LOCAL STATUS templateStop (END_OBJ* pDrvCtrl);
LOCAL int    templateIoctl (END_OBJ* pDrvCtrl);
LOCAL STATUS templateUnload (END_OBJ* pDrvCtrl);
LOCAL STATUS templateSend (END_OBJ* pDrvCtrl,M_BLK_ID pBuf);

LOCAL STATUS templateMCastAdd(END_OBJ* pDrvCtrl,char* pAddress);
LOCAL STATUS templateMCastDel(END_OBJ* pDrvCtrl,char* pAddress);
LOCAL STATUS templateMCastGet(END_OBJ* pDrvCtrl,MULTI_TABLE* pTable);
LOCAL STATUS templatePollStart(ENG_DEVICE* pDrvCtrl);
LOCAL STATUS templatePollStop (END_DEVICE* pDrvCtrl);
LOCAL STATUS templatePollSend(END_OBJ* pDrvCtrl,M_BLK_ID pBuf);
LOCAL STATUS templatePollRcv(END_OBJ* pDrvCtrl,M_BLK_ID pBuf);
LOCAL void  templateSddrFilterSet(END_DEVICE* pDrvCtrl);

LOCAL STATUS templateParse();
LOCAL STATUS templateMemInit();

/*声明功能函数表*/

LOCAL NET_FUNCS templateFuncTable =
{
	(FUNCPTR)templateStart,  /*用于启动设备的函数*/
	(FUNCPTR)templateStop,   /*用于停止设备的函数*/
	(FUNCPTR)templateUnload, /*驱动程序的卸载函数*/
	(FUNCPTR)templateIoctl,  /*驱动程序的Ioctl函数*/
	(FUNCPTR)templateSend,   /*驱动程序的发送函数*/
	(FUNCPTR)templateMCastAdd,/*驱动程序的增加多播的函数*/
	(FUNCPTR)temlateMCastDel, /*驱动程序的禁用多播的函数*/
	(FUNCPTR)templateMCastGet,
	(FUNCPTR)templatePollSend,
	(FUNCPTR)templatePollRcv,
	endEtherAddressForm,
	endEtherPacketDataGet,
	endEtherPacketAddrGet     /*获得分组地址的函数*/   
};

/**************************************************/
/*templateLoad函数用于初始化驱动程序和物理设备。  
initString用于传递与设备有关的所有信息。
返回值end对象指针*/
END_OBJ* templateLoad(char* initString)
{
	END_DEVICE  *pDrvCtrl;
	DRV_LOG(DRV_DEBUG_LOAD,"Loading template...\n",1,2,3,4,5,6);
	
	/*申请设备描述结构*/
	
	pDrvCtrl = (END_DEVICE*)calloc(sizeof(END_DEVICE),1);
	if(pDrvCtrl == NULL)
		goto errorExit;
		
	/*解析初始化字符串,同时填充设备描述结构*/
	
	if(templateParse(pDrvCtrl,initString) == ERROR)
		goto errorExit;
		
  /*从BSP获取以太网地址*/
  
  SYS_ENET_ADDR_GET(pDrvCtrl);
  
  /*初始化结构中的END和MIB2部分*/
  
  /*The M2 element must come from m2Lib.h This template is set up for a DIX type ethernet device.*/
  
  if(END_OBJ_INIT(&pDrvCtrl->end,(DEV_OBJ*)pDrvCtrl,"template",
  	              pDrvCtrl-unit,&templateFuncTable,
  	              "END Template Driver.") == ERROR
  	 ||END_MIB_INIT(&pDrvCtrl->end,M2_ifType_ethernet_csmacd,
  	                &pDrvCtrl->enetAddr[0],6,END_BUFSIZ.
  	                END_SPEED) == ERROR
  	 )
  	 goto errorExit;
  	 
  /*执行内存分配*/
  
  if(templateMemInit(pDrvCtrl) == ERROR)
  	goto errorExit;
  	
  /*重置和重配设备*/
  
  templateReset(pDrvCtrl);
  templateConfig(pDrvCtrl);
  
  /*设置可读标志*/
  
  END_OBJ_READY(&pDrvCtrl->end,
         IFF_UP|IFF_RUNNING|IFF_NOTRAILERS|IFF_BROADCAST
         |IFF_MULTICAST);
  
  DRV_LOG(DRV_DEBUG_LOAD,"Done loading Template...",1,2,3,4,5,6);
  
  return(&pDrvCtrl);
  
errorExit:
	if (pDrvCtrl != NULL)
		free((char*)pDrvCtrl);
	
	return NULL;
	  	                             
}    
  
  
  
  
/*****************************************
templateParse函数用来拆分和解析初始化字符串。
此函数拆分输入的字符串,然后将值填入到设备驱动程序的控制结构中。
vxworks系统的muxLib。o 模块会自动地通过BSP(configNet。h)
将单元号(unit number)传递给用户地初始化字符串中。

******************************************/

STATUS templateParse(END_DEVOICE* pDrvCtrl,char* initString)
{
	char* tok;
	char* pHolder = NULL;
	
	/*下面开始拆分输入地字符串*/
	
	/*来自muxLib.o的单元号*/
	
	tok = rtrtok_r(initString,":",&pHolder);
	if(tok == NULL)
		return ERROR;
	pDrvCtrl->unit = atoi(tok);
	
	/*中断向量*/
	
	iok = strtok_r(NULL,":",&pHolder);
	if(iok == NULL)
		return ERROR;
		pDrvCtrl->ivec = atoi(tok);
		
	/*中断级别*/
	tok = strtok_r(NULL,":",&pHolder);
	if(tok == NULL)
		return ERROR;
	pDrvCtrl->ilevel = atoi(tok);
		
	DRV_LOG(DRV_DEBUG_LOAD,"Processed all aruguments\n",1,2,3,4,5,6);
	
	return OK;
}  

/*************************************************
templateMemInit 此函数用于初始化内存。
此函数用来为网络设备初始化内存,它与设备密切相关。

*************************************************/

STATUS templateMemInit(END_DEVICE* pDrvCtrl)
{
	int count;
	/*如果需要可以首先申请和初始化所有共享内存区域*/
	
	/*下面将设置一个END网络内存池*/
	
	if((pDrvCtrl->end.pNetPool = malloc(sizeof(NET_POOL))) == NULL)
		return ERROR;
		
	templateMclBlkConfig.mBlkNum = 16;
	templateClDescTbl[0].clNum = 16;
	templateMclBlkConfig.clBlkNum = templateClDescTbl[0].clNum;
	
	/*计算所有M-Blks (内存大块)和Cl-Blks(内存小段)所占用的总内存*/
	
	templateMclBlkConfig.memSize = (templateMclBlkConfig.mBlkNum*
	             (MSIZE + sizeof(long))) + 
	             (templateMclBlkConfig.clBlkNum*
	             (CL_BLK_SZ + sizeof(long)));
	             
	if(templateMclBlkConfig.memArea = (char*)memalign(sizeof(long),templateMckBlkConfig.memSize)) == NULL)
		return ERROR;
		
	/*计算所有内存的大小*/
	
	templateClDescTbl[0].memSize = (templateClDescTbl[0].clNum* (END_BUFSIZ + 8)) + sizeof(int);
	
	/*在高速缓存安全内存中为所有内存段申请内存*/
	
	templateClDescTbl[0].memArea = 
	    (char*)cacheDmaMalloc(templateClDescTbl[0].memSize);
	    
	if((int)templateClDescTbl[0].memArea == NULL)
		{
			DRV_LOG(DRV_DEBUG_LOAD,"system memory unavailable\m",1,2,3,4,5,6);
			return (ERROR);
		}
	
	/*初始化内存池*/
	
	if(netPoolInit(pDrvCtrl->end.pNetPool,&templateMclBlkConfig,&templateClDescTbl[0],templateClDescTblNumEnt,NULL) == ERROR)
		{
			DRV_LOG(DRV_DEBUG_LOAD,"Could not init buffering\n",1,2,3,4,5,6);
			return(ERROR);
		}
	/*如果需要使用内存段存储接收到的分组,那么事先在此申请。*/
	
	if((pDrvCtrl-pClPoolId	= netClPoolIdGet(pDrvCtrl->end.pNetPool,sizeof(RFD),false)) == NULL)
		return(ERROR);
		
	while(count < templateClDescTbl[0].clNum)
		{
			char* pTempBuf;
			
			if((pTempBuf = (char*)netClusterGet(pDrvCtrl->end.pNetPool,pDrvCtrl->pClPoolId)) == NULL)
				{
					DRV_LOG(DRV_DEBUG_LOAD,"Could not get a buffer\n",1,2,3,4,5,6);
					return(ERROR);
				}
			
			/*可以在这里将指针保存到一个结构体中*/
			
				
		}
		
	DRV_LOG(DRV_DEBUG_LOAD,"Memory setup complete\n",1,2,3,4,5,6);
	
	return OK;
}

/***************************************************************
templateStart 此函数用于启动一个设备
这个函数调用BSP函数为设备连接并启动中断,保证设备运行在中断模式。
***************************************************************/

LOCAL STATUS templateStart (END_OBJ* pDrvCtrl)
{
	END_DEVICE STATUS result;
	
	SYS_INT_CONNECT(pDrvCtrl,templateInt,(int)pDrvCtrl,&result);
	if(result == ERROR)
		return ERROR;
	
	DRV_LOG(DRV_DEBUG_LOAD,"Interrupt connected.\n",1,2,3,4,5,6);
	
	SYS_INT_ENABLE(pDrvCtrl);
	
	DRV_LOG(DRV_DEBUG_LOAD,"interrupt enabled.\n",1,2,3,4,5,6);
	
	/*在这里可以启用中断并打开设备*/
	
	return OK;
}

/*************************************************************
templateInt 此函数用于处理控制器中断。
当控制器中断到来时,这个函数将在对应的中断级别上调用。
***************************************************************/

LOCAL void templateInt(END_DEVICE* pDrvCtrl)
{
	UCHAR stat;
	
	DRV_LOG(DRV_DEBUG_INT,"Got an interrupt!\n",1,2,3,4,5,6);
	
	/*读取设备状态寄存器*/
	
	stat = templateStatusRead(pDrvCtrl);
	
	/*如果检测中断失败直接返回*/
	
	if(!(stat & TEMPLATE_VALID_INT))/*检测是否是有效的中断*/
		return ;
		
	/*下面可以启用中断,清除发送或接收中断同时清除所有出错标志*/
	
	/*这里可以增加出错处理的代码*/
	
	/*对于接收到的任何分组都由一个网络任务处理*/
	
	if((stat & TEMPLATE_RINT)&&(stat & TEMPLATE_RXON))
		{
			if(!(pDrvCtrl->rxHandling))
				{

⌨️ 快捷键说明

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