📄 templeend.c
字号:
/*包含头文件×/
#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 + -