📄 mutlihdlc.c
字号:
/* includes */
#include "copyright_wrs.h"
#include "vxWorks.h"
#include "stdio.h"
#include "ioLib.h"
#include "intLib.h"
#include "errno.h"
#include "ifLib.h"
#include "sysLib.h"
#include "taskLib.h"
#include "msgQLib.h"
#include "iv.h"
#include "drv/intrCtl/ppc860Intr.h"
#include "drv/multi/ppc860Siu.h"
#include "drv/multi/ppc860Cpm.h"
#include "drv/sio/ppc860Sio.h"
#include "mutlichannel.h"
#include "arch/ppc/vxPpcLib.h"
#include "iosLib.h"
#include "sysLib.h"
#include "MAILBOX.h"
#define MAX_MSG_NUM 32
#define MAX_MSG_LENGTH 600
#define DPRAM_PORT_OFFSET 0x0002 /*右口邮箱偏移量*/
extern SEM_ID MboxPrcTaskSemId; /*mailboxDs21354_Isr释放的信号量,通知DPRAM里有新邮件*/
#define M_HDLC_PASS 0x17
u_char mhdlcTxBuffer[]=" i one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen";
u_char multibuf[1024] = {0};
UINT16 multilen = 0;
/*#include "ds21354.c"*/
UINT8 totTs ;
UINT16 dl, hdlcTxLen ;
UINT32 chReset[32] = {0};
extern UINT32 rxCorrectTotal[32] ;
/*HDLC收消息队列*/
extern MSG_Q_ID mutliChannelHdlcMsgQId;
extern MSG_Q_ID mutliChannelHdlcMsgQId1;
#define PURE_HDLC_FRAME
/* defines */
int mutliHdlcOpen (PPC860SCCHDLC_CHAN *, u_char*,int);
int mutliHdlcRead (PPC860SCCHDLC_CHAN *, u_char*, int) ;
int mutliHdlcWrite (PPC860SCCHDLC_CHAN *, u_char*, int) ;
LOCAL STATUS mutliHdlcIoctl (PPC860SCCHDLC_CHAN *, int, int) ;
void mutliHdlcStartup(void);
/*************************************************************************
* mutli_channel HDLC Interrupt - interrupt service routine
*
* Most drivers have routines that handle interrupts from the devices
* serviced by the driver. These routines are connected to the interrupts
* by calling intConnect (usually in xxDrv above). They can receive a
* single argument, specified in the call to intConnect (see intLib).
*/
void mutliHdlcInterrupt (PPC860SCCHDLC_CHAN *);
STATUS mutliHdlcDrv(void);
STATUS mutliHdlcDevCreate(PPC860SCCHDLC_CHAN *,u_char*,FAST int);
void QMC_GlobalInit(void);
void QMC_ChannelInit(void);
void QMC_InitBDs(void);
void mutliChannelHdlcInit(void);
void sccMutliHdlcInit(void);
void mutliChannelHdlcStartup(void);
int mutliChannelHdlcWrite(u_char*,int);
UINT16 *IntCQ=(UINT16*)(0x01ff8000); /* interrupt circle queue for QMC*/
int mutliHdlcDrvNum=0;
PPC860SCCHDLC_CHAN mutliHdlcChan; /*mutli-channel hdlc struct*/
UINT8 *qmcTxBuffer=(UINT8*)(0x1fe0000);/*32k*/
UINT8 *qmcRxBuffer=(UINT8*)(0x1fe8000);/*32k*/
BDRINGS *bdbase=(BDRINGS*)(0x01ff0000);/**/
R_HDLC_FRAME *rHdlcFrame=(R_HDLC_FRAME*)(0x01ffa000);
/* forward declarations */
/* driver function table */
/* 打开一个多通道HDLC设备 */
/*
参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
的调用都要通过此结构体来完成用户需要。
2、char * remainder:保留参数,没有使用,因此必须为0
3、 int mode:打开模式,没有使用,必须为0
返回值:设备数据结构的值
*/
int mutliHdlcOpen
(
PPC860SCCHDLC_CHAN *pSioChan,
u_char * remainder,
int mode
)
{
/* serial devices should have no file name part */
if (remainder[0] != 0)
return (ERROR);
else
return ((int) pSioChan);
}
/*
多通道HDLC设备写函数(指定通道号)
参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
的调用都要通过此结构体来完成用户需要。
2、char *buffer: 等待写如入的数据指针,因为程序需要区分该数据是写往哪一路HDLC,所以上层程序需要指
明要写入的HDLC链路号,从0到31,buffer[0]被指定为链路号标识。
3、int dataLen: 写数据长度,每次写入的数据长度不能超过HDLC链路规定的最大帧长度,因为一次写操作只
能写入一个HDLC帧,我们规定的最大帧长度为1500个字节,因此该参数必须小于1496,4个字
节CRC校验空间保留。
注意:长度大小不包括buffer[0]在内
返回值:1、OK,数据发送成功
2、EAGAIN,数据发送失败
*/
int mutliHdlcWrite( PPC860SCCHDLC_CHAN *pSioChan, u_char *buffer, int dataLen )
{
PPC860SCCHDLC_CHAN * pChan = pSioChan;
int i,j;
int channelNum;
int activeTxBd;
UINT16 *tempAddr;
channelNum=buffer[0];
activeTxBd=pChan->hdlc.txBdNext[channelNum];
tempAddr=(UINT16*)(0xff002000+0x02+channelNum*64);
i=0;
while((i<=20000)&&(bdbase[channelNum].TxBd[activeTxBd].bd_cstatus&BD_TX_READY_BIT))
{
i++;
}
/*如果该通道有未发送的帧,等待1000个循环*/
if (bdbase[channelNum].TxBd[activeTxBd].bd_cstatus &BD_TX_READY_BIT)
{
return(EAGAIN);
}
/*如果还有未发送的帧,返回错误*/
if(dataLen>MAX_HDLC_FRAME)
{
return(EAGAIN);
}
/*太大的帧,不发送*/
for( i=1,j=1; i<=dataLen; i++,j++ )
{
bdbase[channelNum].TxBd[activeTxBd].bd_addr[j-1] =(u_char)buffer[i];
}
bdbase[channelNum].TxBd[activeTxBd].bd_length =dataLen;
/*数据长度*/
bdbase[channelNum].TxBd[activeTxBd].bd_cstatus|=BD_TX_READY_BIT|0x0800;
/*打开发送位,开始发送*/
*tempAddr|=0x0100;
pChan->hdlc.txBdNext[channelNum]= (activeTxBd + 1) % pChan->hdlc.txBdNum;
/*指向下一个BD*/
return(OK);
}
/*
多通道HDLC设备读函数(向指定通道读)
参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
的调用都要通过此结构体来完成用户需要。
2、char *buffer: 等待读入的数据指针,因为程序需要区分该数据是写往哪一路HDLC,所以上层
程序需要指明要写入的HDLC链路号,从0到31,buffer[0]被指定为链路号标
识。
3、int dataLen: 读数据长度,每次读入的数据长度不能超过HDLC链路规定的最大帧长度,因为
一次读操作只能读入一个HDLC帧,我们规定的最大帧长度为1500个字节,因此
该参数必须小于1496,4个字节的CRC校验空间保留。
注意:长度大小不包括buffer[0]在内
返回值:OK,数据读取成功
EAGAIN,数据读取失败
*/
int mutliHdlcRead
(
PPC860SCCHDLC_CHAN *pChan ,
u_char *buffer ,
int dataLen
)
{
int i=0,j=0, activeRxBd,lastFrameBd;
int channelNum;
channelNum=buffer[0];
if((channelNum>=MAXLOGCHAN)|(channelNum<0))
return(EAGAIN);
activeRxBd=pChan->hdlc.rxBdNext[channelNum];
lastFrameBd=activeRxBd;
if (bdbase[channelNum].RxBd[activeRxBd].bd_cstatus &BD_RX_EMPTY_BIT)
return(EAGAIN);
/*接收缓冲为空,返回错误*/
if (bdbase[channelNum].RxBd[activeRxBd].bd_cstatus &0x003c)
return(EAGAIN);
/*有出现LG,NO,AB,CR错误,返回*/
while(!(bdbase[channelNum].RxBd[lastFrameBd].bd_cstatus&0x0800))
{
lastFrameBd=(lastFrameBd+1)%(pChan->hdlc.rxBdNum);
if ( (bdbase[channelNum].RxBd[lastFrameBd].bd_cstatus & 0x803c)|(i>1000) )
{
while(activeRxBd==lastFrameBd)
{
bdbase[channelNum].RxBd[activeRxBd].bd_cstatus |= BD_RX_EMPTY_BIT;
activeRxBd=(activeRxBd+1)%(pChan->hdlc.rxBdNum);
}/*将上面的缓冲区置空标志*/
return(EAGAIN);
}
i++;
/*循环1000次,找不到一帧的最后缓冲区标志,返回错误*/
}
dataLen = bdbase[channelNum].RxBd[lastFrameBd].bd_length;
if(dataLen>MAX_HDLC_FRAME)
{
dataLen=0;
while(activeRxBd==lastFrameBd)
{
bdbase[channelNum].RxBd[activeRxBd].bd_cstatus|=
BD_RX_EMPTY_BIT;
activeRxBd=(activeRxBd+1)%(pChan->hdlc.rxBdNum);
}/*将上面的缓冲区置空标志*/
return(EAGAIN);
}
/*太大的帧,不接受,置dataLen=0*/
for(i=1,j=1;i<dataLen;i++,j++)
{
buffer[i]=(u_char)bdbase[channelNum].RxBd[activeRxBd].bd_addr[j-1];
if(j>bdbase[channelNum].RxBd[activeRxBd].bd_length) /*缓冲区读完*/
{
bdbase[channelNum].RxBd[activeRxBd].bd_cstatus|=BD_RX_EMPTY_BIT;
/*置缓冲区为空*/
activeRxBd=(activeRxBd+1)%(pChan->hdlc.rxBdNum);
/*下一个BD*/
j=1;
}
}
bdbase[channelNum].RxBd[activeRxBd].bd_cstatus|=BD_RX_EMPTY_BIT;
/*置缓冲区为空*/
if(activeRxBd==lastFrameBd)
{
pChan->hdlc.rxBdNext[channelNum] = (activeRxBd + 1) % pChan->hdlc.rxBdNum;
}
else
{
pChan->hdlc.rxBdNext[channelNum] = (lastFrameBd + 1) % pChan->hdlc.rxBdNum;
}
return(OK);
}
/*I/O控制函数,目前暂时没有功能可以使用,可以根据需要增加*/
/*
参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
的调用都要通过此结构体来完成用户需要。
2、int request:要求代码
3、int arg: 参数
返回值:多通道HDLC工作模式改变
1、正确
2、出错:返回系统错误代码
*/
LOCAL STATUS mutliHdlcIoctl
(
PPC860SCCHDLC_CHAN * pChan, /* device to control */
int request, /* request code */
int arg /* some argument */
)
{
STATUS status = OK;
switch(request)
{
case(SIO_MODE_SET):
return(ENOSYS);
break;
default:
status = ENOSYS;
}
return(status);
}
/*
多通道中断处理函数,本函数只处理多通道HDLC的某一路收到一个完整的HDLC帧,将收到的帧保存在缓冲区里
然后向消息队列中发送一条消息,通知上层应用程序处理
参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
的调用都要通过此结构体来完成用户需要。
返回值:无
*/
//UINT32 rxChReset[32] = {0} ;
void mutliHdlcInterrupt
(
PPC860SCCHDLC_CHAN * pSioChan
)
{
PPC860SCCHDLC_CHAN * pChan = pSioChan;
UINT16 *curIntCQPtr;
int exitFlag,lastBdFlag;
UINT16 scceReg;
UINT16 channelNum;
UINT16 i,j, rxLen, temp;
int activeRxBd, lastFrameBd;
exitFlag=0;
lastBdFlag=OK;
scceReg=*(UINT16*)MPC860_SCCE2(vxImmrGet());
*MPC860_SCCE2(vxImmrGet())=0x000f;
curIntCQPtr=IntCQ;
i=0;
j=0;
if(!scceReg&0x0004)
{
*MPC860_CISR(vxImmrGet())|=CISR_SCC2;
/*清中断*/
return;
/*没有GINT中断,退出*/
/*几乎屏蔽其他所有的中断*/
}
while(!exitFlag)
{
if((*curIntCQPtr)&QMC_ITE_V) /*V有效?*/
{
channelNum=((*curIntCQPtr)&QMC_ITE_CN);
channelNum=(channelNum>>6);
/*获得通道号*/
activeRxBd=pChan->hdlc.rxBdNext[channelNum];
lastFrameBd=activeRxBd;
if((*curIntCQPtr)&QMC_ITE_RXF) /*收到一个帧*/
{
rHdlcFrame->frameLen=
bdbase[channelNum].RxBd[lastFrameBd].bd_length;
/*帧的长度*/
rHdlcFrame->channelNum=channelNum;
rHdlcFrame->buffer[0]=channelNum;
/*通道号*/
/* 读取帧的内容 */
for(i=1,j=0;i<=rHdlcFrame->frameLen;i++,j++)
{
rHdlcFrame->buffer[i]=
(u_char)bdbase[channelNum].RxBd[activeRxBd].bd_addr[j];
}
rHdlcFrame->frameLen=rHdlcFrame->frameLen-2;
bdbase[channelNum].RxBd[activeRxBd].bd_cstatus |= BD_RX_EMPTY_BIT;
/*置缓冲区为空*/
pChan->hdlc.rxBdNext[channelNum] = (activeRxBd + 1) % pChan->hdlc.rxBdNum;
rxLen = (UINT)rHdlcFrame->frameLen ;
for( i=1; i<rxLen; i++ )
{
if( rHdlcFrame->buffer[i] != i )
{
for( j=0; j<rxLen; j++ )
{
if( j%20 == 0 )
logMsg( "\n",0,0,0,0,0,0 ) ;
logMsg( "%2x ", rHdlcFrame->buffer[j],0,0,0,0,0 ) ;
}
i = 0x1000 ;
}
}
if(( i < 0x1000 ) && ( rxLen == hdlcTxLen ))
rxCorrectTotal[rHdlcFrame->buffer[0]] = rxCorrectTotal[rHdlcFrame->buffer[0]] + 1 ;
/* msgQSend(mutliChannelHdlcMsgQId1,
rHdlcFrame->buffer,
(UINT)rHdlcFrame->frameLen,
0, MSG_PRI_NORMAL); */
/*向上层队列发送消息*/
} /*(*curIntCQPtr)&QMC_ITE_RXF*/
}/* if((*curIntCQPtr)&QMC_ITE_V)*/
if((*curIntCQPtr)&QMC_ITE_W) /*中断表最后一个??*/
{
exitFlag=1;
/*最后一个,退出*/
(*curIntCQPtr)&=(QMC_ITE_CLEAR | QMC_ITE_W);
/*清*/
curIntCQPtr=IntCQ;
}
else
{
(*curIntCQPtr)&=QMC_ITE_CLEAR;
curIntCQPtr++; /*中断表下一个*/
}
}
*MPC860_CISR(vxImmrGet())|=CISR_SCC2;
/*清中断*/
/*读取32通道RxBD状态*/
// for( i=0; i<MAXLOGCHAN; i++ )
// {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -