📄 qmcen.c
字号:
#include "board.h"
#include "bspfuncs.h"
#include "sdev.h"
#include "hdlc.h"
#include "qmcen.h"
#define regs(ch) pda->Scc_regs[ch]
/*---------Local functions-----------------------------*/
static void ReInitAllRecvCh(QmcGlobalCfgStruct *pGCfg);
static void ReInitAllSendCh(QmcGlobalCfgStruct *pGCfg);
static void QmcResetSubChan(DataBufStruct *pData,QmcSubChanCfgStruct *);
static void QmcStopOp(QmcSubChanCfgStruct *pCfg);
static void QmcStartOp(QmcSubChanCfgStruct *pCfg);
static void QmcSubChanIsr(void *pDataBuf,IntEntryStruct *pIES);
static void QmcIsr(void *pDataBuf);
static void QmcLimitReInit(QmcGlobalCfgStruct *pGCfg);
static void QmcResetSubChan(DataBufStruct *pData,QmcSubChanCfgStruct *pCfg)
{
int i;
/* QmcGlobalCfgStruct *pGCfg=pCfg->pGCfg;*/
QmcSubChanParamStruct* scpm=
(QmcSubChanParamStruct*)((GetIMMR() & IO_MAP_MASK)+0x2000);
scpm[pCfg->ch].tstate=0x30000000;
scpm[pCfg->ch].zistate=0x100;
scpm[pCfg->ch].tbptr=scpm[pCfg->ch].tbase;
scpm[pCfg->ch].rbptr=scpm[pCfg->ch].rbase;
pData->CurRecvBD=pData->CurSendBD=0;
for(i=0;i<pData->MaxRecvBD;i++)
pData->pBaseRecvBD[i].status = BD_EMPTY|BD_INTR;
if(i>0)pData->pBaseRecvBD[i-1].status |= BD_WRAP;
for(i=0;i<pData->MaxSendBD;i++)
pData->pBaseSendBD[i].status = BD_INTR|BD_LAST|HDLC_TX_CRC;
if(i>0)pData->pBaseSendBD[i-1].status |= BD_WRAP;
}
static void QmcStopOp(QmcSubChanCfgStruct *pCfg)
{
CPM_CMD(QMC_RESERVE|QMC_STOP_RX|((pCfg->ch)<<2));
CPM_CMD(QMC_RESERVE|QMC_STOP_TX|((pCfg->ch)<<2));
}
static void QmcStartOp(QmcSubChanCfgStruct *pCfg)
{
unsigned short k;
QmcGlobalParamStruct *gmp =(QmcGlobalParamStruct *)((GetIMMR()&IO_MAP_MASK)
+0x3C00+0x100*pCfg->pGCfg->ch);
QmcSubChanParamStruct* scpm=
(QmcSubChanParamStruct*)((GetIMMR() & IO_MAP_MASK)+0x2000);
k=pCfg->ch;
if(scpm[k].chamr.ent==0)/*do if channel is deactive*/
{
scpm[k].tstate=0x30000000;
scpm[k].zistate=0x100;
gmp->tsatt[k].v=1;
scpm[k].chamr.ent=1;
}
if(scpm[k].chamr.pol==0)
scpm[k].chamr.pol=1; /*start tx*/
scpm[k].rstate=0x31000000; /*start rev*/
scpm[k].zdstate=0x0000080;
}
int QmcRead(void *pDataBuf,void *pBuf, int MaxLen)
{
int ret;
DataBufStruct* pData=(DataBufStruct *)pDataBuf;
QmcSubChanCfgStruct* pCfg =(QmcSubChanCfgStruct *)(pData+1);
if(pCfg->subchatt==QMC_SUBCH_ATT_EXCHANG)
return QMC_SUBCHAN_IN_EXCHANG_MOD;
ret=BDRead(pDataBuf,pBuf,MaxLen);
if(ret>2)return ret-2; /* sub 2 bytes of CRC */
else if(ret>0)return SDE_INVALID_PACKET;
else return ret;
}
int QmcWrite(void *pDataBuf,void *pBuf, int MaxLen)
{
int ret,ilevel;
BuffDescType *bd;
LinkBufStruct *pBufLnk;
DataBufStruct* pDataDet=(DataBufStruct *)pDataBuf;
QmcSubChanCfgStruct* pCfg =(QmcSubChanCfgStruct *)(pDataDet+1);
QmcGlobalCfgStruct * pGCfg = pCfg->pGCfg;
QmcSubChanParamStruct* scpm=
(QmcSubChanParamStruct*)((GetIMMR() & IO_MAP_MASK)+0x2000);
if(MaxLen > pGCfg->MaxBufLen)return SDE_INVALID_PACKET;
SPLX(pDataDet->DrvInfo.SendTryNum++; /* statistic */);
SPLX(pBufLnk=(LinkBufStruct*)LinkGetBuf(&(pGCfg->FreeLink)););
if(pBufLnk==NULL)return SDE_DEV_BUSY;
pBufLnk->Length=MaxLen;
memmove(pBufLnk->Data,pBuf,MaxLen);
ilevel=splx(MAX_ILEV);
bd=&(pDataDet->pBaseSendBD[pDataDet->CurSendBD]);
if((bd->status&BD_READY)==BD_READY){
SPLX(LinkAppendBuf(&(pCfg->TxLink),pBufLnk););
splx(ilevel);
return MaxLen;
}
if(bd->address!=0 )
{
LinkBufStruct *p=(LinkBufStruct*)((ULONG)bd->address-8);
SPLX(LinkAppendBuf(&(pGCfg->FreeLink),p););
}
bd->address=pBufLnk->Data;
bd->length=pBufLnk->Length;
bd->status&=(~pDataDet->SendErrMask);
bd->status|=BD_READY;
pDataDet->DrvInfo.SendPerNum++; /*statistic*/
pDataDet->CurSendBD=(pDataDet->CurSendBD+1)%pDataDet->MaxSendBD;
splx(ilevel);
scpm[pCfg->ch].chamr.pol=1;
return MaxLen;
}
static void QmcSwSubIsrSend(DataBufStruct* pDataDet)
{
QmcSubChanCfgStruct* pCfgDet =(QmcSubChanCfgStruct *)(pDataDet+1);
QmcGlobalCfgStruct * pGCfg=pCfgDet->pGCfg;
QmcSubChanParamStruct *scpm=(QmcSubChanParamStruct*)((GetIMMR()&IO_MAP_MASK)
+0x2000);
LinkBufStruct *pBufLnk;
for(;;){
BuffDescType *bd=&(pDataDet->pBaseSendBD[pDataDet->CurSendBD]);
if((bd->status&BD_READY)==BD_READY) break;
if(LinkNumber(&(pCfgDet->TxLink))==0) break;
if(bd->address!=0 )
{
pBufLnk=(LinkBufStruct*)((ULONG)bd->address-8); /* adjust the addr*/
SPLX(LinkAppendBuf(&(pGCfg->FreeLink),pBufLnk););
}
SPLX(pBufLnk=LinkGetBuf(&(pCfgDet->TxLink)););
bd->address=pBufLnk->Data;
bd->length=pBufLnk->Length;
bd->status&=(~pDataDet->SendErrMask);
bd->status|=BD_READY;
pDataDet->DrvInfo.SendPerNum++; /*statistic*/
pDataDet->CurSendBD=(pDataDet->CurSendBD+1)%pDataDet->MaxSendBD;
}
scpm[pCfgDet->ch].chamr.pol=1;
}
static void ExchangBD(DataBufStruct* pDataSrc)
{
USHORT Status;
LinkBufStruct *pBufLnk;
QmcSubChanCfgStruct* pCfgSrc =(QmcSubChanCfgStruct *)(pDataSrc+1);
QmcGlobalCfgStruct * pGCfg=pCfgSrc->pGCfg;
DataBufStruct* pDataDet=(DataBufStruct*)(pGCfg->IsrParam[pCfgSrc->ExchangSubCh]);
QmcSubChanCfgStruct* pCfgDet =(QmcSubChanCfgStruct *)(pDataDet+1);
for(;;)
{
BuffDescType *bd=&(pDataSrc->pBaseRecvBD \
[pDataSrc->CurRecvBD]);
Status=bd->status;
if((Status&BD_EMPTY)==BD_EMPTY) break;
if(((Status&pDataSrc->RecvErrMask)==0)
&&(bd->length>2)
&&(pDataDet!=NULL)
&&(pCfgSrc->ExchangSubCh<64)
&&(pCfgSrc->ExchangSubCh>=0)
)
{
if(LinkNumber(&(pGCfg->FreeLink))==0) break;
pBufLnk=(LinkBufStruct*)((ULONG)bd->address-8);
pBufLnk->Length=bd->length-2;
SPLX(LinkAppendBuf(&(pCfgDet->TxLink),pBufLnk););
pDataDet->DrvInfo.SendTryNum++; /* statistic */
SPLX(pBufLnk=(LinkBufStruct*)LinkGetBuf(&(pGCfg->FreeLink)););
bd->address=pBufLnk->Data;
}
if((Status&pDataSrc->RecvErrMask)!=0)
{
char i;
pDataSrc->DrvInfo.RecvError++; /*statistic */
for(i=0;i<=15;i++)
if(Status&(0x8000L>>i))
pDataSrc->DrvInfo.RecvBDStat[i]++;
}
else
pDataSrc->DrvInfo.RecvNum++; /*statistic */
bd->status&=(~pDataSrc->RecvErrMask);
bd->status|=BD_EMPTY;
pDataSrc->CurRecvBD=(pDataSrc->CurRecvBD+1)
%pDataSrc->MaxRecvBD;
} /* end of recv */
QmcSwSubIsrSend(pDataDet);
}
static void QmcSubChanIsr(void *pDataBuf,IntEntryStruct *pIES)
{
IntEntryStruct ev=*pIES;
DataBufStruct* pData=(DataBufStruct *)pDataBuf;
PDA *pda = (PDA *)(GetIMMR() & IO_MAP_MASK);
QmcSubChanCfgStruct* pCfg=(QmcSubChanCfgStruct *)(pData+1);
QmcSubChanParamStruct *pSubChanParam
=(QmcSubChanParamStruct *)((char*)pda+0x2000);
if( ev.Bit.bsy==1 )
{
pSubChanParam[ev.Bit.chnum].rstate=0x31000000;
pSubChanParam[ev.Bit.chnum].zdstate=0x0000080;
}
if( ev.Bit.un==1 )
{
pSubChanParam[ev.Bit.chnum].chamr.pol=1;
return;
}
if( ev.Bit.rxf == 1 || ev.Bit.rxb == 1|| ev.Bit.bsy==1)
{
pData->DrvInfo.TotalRecvInt++;
if(pCfg->subchatt==QMC_SUBCH_ATT_EXCHANG)
ExchangBD(pData);
else{
if( (pData->RecvEv!=NULL) && (pData->RecvTid!=NULL) )
ev_send(pData->RecvTid,pData->RecvEv);
if( pData->RecvQID!=NULL )
q_send(pData->RecvQID,pData->RecvMessage);
}
}
if( ev.Bit.txb == 1 )
{
pData->DrvInfo.TotalSendInt++;
QmcSwSubIsrSend(pData);
if(pCfg->subchatt!=QMC_SUBCH_ATT_EXCHANG)
{
if( (pData->SendEv!=NULL) && (pData->SendTid!=NULL) )
ev_send(pData->SendTid,pData->SendEv);
if( pData->SendQID!=NULL )
q_send(pData->SendQID,pData->SendMessage);
}
}
}
static void ReInitAllRecvCh(QmcGlobalCfgStruct *pGCfg)
{
USHORT i;
PDA *pda = (PDA *)(GetIMMR() & IO_MAP_MASK);
QmcSubChanParamStruct *pSubChanParam
=(QmcSubChanParamStruct *)((char*)pda+0x2000);
DataBufStruct* pData;
QmcSubChanCfgStruct* pCfg;
for(i=0;i<pGCfg->MaxSubChanNum;i++)
{
pData=(DataBufStruct*)pGCfg->IsrParam[i+pGCfg->SubChParamOffset/64];
pCfg =(QmcSubChanCfgStruct *)(pData+1);
pSubChanParam[pCfg->ch].rstate=0x31000000;
pSubChanParam[pCfg->ch].zdstate=0x0000080;
}
pda->Scc_regs[pGCfg->ch].scc_gsmra|=0x00000020;/* Enable rx */
}
static void ReInitAllSendCh(QmcGlobalCfgStruct *pGCfg)
{
USHORT i;
PDA *pda = (PDA *)(GetIMMR() & IO_MAP_MASK);
QmcSubChanParamStruct *pSubChanParam
=(QmcSubChanParamStruct *)((char*)pda+0x2000);
DataBufStruct* pData;
QmcSubChanCfgStruct* pCfg;
for(i=0;i<pGCfg->MaxSubChanNum;i++)
{
pData=(DataBufStruct*)pGCfg->IsrParam[i+pGCfg->SubChParamOffset/64];
pCfg =(QmcSubChanCfgStruct *)(pData+1);
pSubChanParam[pCfg->ch].chamr.pol=1;
}
pda->Scc_regs[pGCfg->ch].scc_gsmra|=0x00000010;/* Enable tx */
}
static void QmcIsr(void *pDataBuf)
{
unsigned short Events;
QmcGlobalCfgStruct *pGCfg=(QmcGlobalCfgStruct *)pDataBuf;
PDA *pda = (PDA *)(GetIMMR() & IO_MAP_MASK);
Events = pda->Scc_regs[pGCfg->ch].scc_scce;
pda->Scc_regs[pGCfg->ch].scc_scce = Events; /* clear the event register */
if( (Events & QMC_GLOB_OV)==QMC_GLOB_OV )
{
ReInitAllRecvCh(pGCfg);
return;
}
if( ((Events & QMC_GLOB_UN)==QMC_GLOB_UN) )
{
ReInitAllSendCh(pGCfg);
return;
}
if( ((Events & QMC_GLOB_INT )==QMC_GLOB_INT) /* global interrupt */
|| ((Events & QMC_GLOB_IQOV)==QMC_GLOB_IQOV) )
{
while((pGCfg->IntTablePtr->Bit).v) /* search the interrupt table */
{
ULONG sub=pGCfg->IntTablePtr->Bit.chnum;
QmcSubChanIsr(pGCfg->IsrParam[sub],pGCfg->IntTablePtr);
pGCfg->IntTablePtr->Word16&=0x4000;
if(1 == pGCfg->IntTablePtr->Bit.w)
pGCfg->IntTablePtr=pGCfg->IntTable;
else
pGCfg->IntTablePtr++;
}
}/* end of if */
if((Events & QMC_GLOB_IQOV)==QMC_GLOB_IQOV )
{
ReInitAllRecvCh(pGCfg);/* end of if */
}
} /* end of QmcIsr */
void QmcSubChanInit(void *pDataBuf, QmcSubChanCfgStruct *cfg)
{
int i;
BuffDescType *temp_bufdes;
char *pRecvBuf,*pSendBuf;
DataBufStruct* pData=(DataBufStruct *)pDataBuf;
QmcSubChanCfgStruct* pCfg =(QmcSubChanCfgStruct *)(pData+1);
QmcGlobalCfgStruct * pGCfg=cfg->pGCfg;
QmcSubChanParamStruct* scpm=
(QmcSubChanParamStruct*)((GetIMMR() & IO_MAP_MASK)+0x2000);
LinkBufStruct *pFreeBuffLnk;
/*--------------------------<< Initial data >>-------------------------------*/
memmove(pCfg,cfg,sizeof(*cfg));
/* memset(pData, 0, sizeof(DataBufStruct));*/
/* memset(&pData->DrvInfo,0,sizeof(SDCGetDriverInfoStruct)); */
memset(scpm[pCfg->ch], 0, sizeof(QmcSubChanParamStruct));
pCfg->ch&=0x3F;
pData->CurRecvBD=0;
pData->CurSendBD=0;
pData->MaxRecvBD=pGCfg->MaxRecvBD;
pData->MaxSendBD=pGCfg->MaxSendBD;
pData->MaxBufLen=pGCfg->MaxBufLen;
pData->RecvErrMask=(HDLC_DPLL_ERR|HDLC_GREATER_LEN|HDLC_NOT_ALIGNED
|HDLC_ABORT_SEQ|HDLC_RX_CRC|HDLC_OVERRUN|HDLC_CD_LOST);
pData->SendErrMask=(HDLC_UNDERRUN|HDLC_CTS_LOST);
/*-------------------------<< stop SCCx operation >>----------------------*/
QmcStopOp(pCfg);
/*----------------------<< init SCCx >>-----------------------------------*/
scpm[pCfg->ch].tbase=(pGCfg->MaxRecvBD+pGCfg->MaxSendBD)*
(pCfg->ch-pGCfg->SubChParamOffset/64)*BD_LEN;
scpm[pCfg->ch].rbase=scpm[pCfg->ch].tbase+pGCfg->MaxSendBD*BD_LEN;
scpm[pCfg->ch].tstate=0x30000000;
/* scpm[pCfg->ch].rstate=0x31000000; we enable it later,in QmcStartOp() */
scpm[pCfg->ch].zistate=0x100; /* HDLC mode */
/* scpm[pCfg->ch].zdstate=0x80; we enable it later,in QmcStartOp() */
scpm[pCfg->ch].intmask=0x1e; /* enable UN,RXF TXB and BSY interrupt*/
scpm[pCfg->ch].mflr= pData->MaxBufLen-8; /* maximum frame length */
scpm[pCfg->ch].tbptr=scpm[pCfg->ch].tbase;
scpm[pCfg->ch].rbptr=scpm[pCfg->ch].rbase;
scpm[pCfg->ch].chamr.mode=1; /* HDLC mode */
scpm[pCfg->ch].chamr.idlm=0; /* disable idle frame */
scpm[pCfg->ch].chamr.ent=1; /* enable channel xmit*/
scpm[pCfg->ch].chamr.crc=0; /* 16 bit crc */
scpm[pCfg->ch].chamr.nof=0; /* 1 flags */
scpm[pCfg->ch].chamr.pol=0; /* enable polling later ,in QmcStartOp()*/
/* rx */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -