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

📄 qmcen.c

📁 这是单板上DPRAM的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -