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

📄 qmcsw.c

📁 这是单板上DPRAM的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <psos.h>
#include "board.h"
#include "bspfuncs.h"
#include "sdev.h"
#include "hdlc.h"
#include "link.h"
#include "qmc.h"
#include "qmcsw.h"

#define QMCSW_BSP_LOOP_SEND_EV   1
#define QMCSW_BSP_LOOP_RECV_EV   2

static void QmcIsr(void);
static void QmcSwLimitInit(void);

static int CurSubChan;
static LinkStruct TxLink[32], FreeLink;
static QmcSwCfgStruct  *pGCfg;
static DataBufStruct   *gDataBuf[32];
static UCHAR   MapTable[32];

static void InitLink(void)
{
    int i;
   
    LinkInit(&FreeLink);
    for(i=0;i<pGCfg->MaxBufNum;i++)
    {  
        LinkBufStruct  *buf=(LinkBufStruct *)((ULONG)(pGCfg->UncachedBuffer)
                        +(sizeof(LinkBufStruct)-LINK_DATA_BUF_LEN
                        +pGCfg->MaxBufLen)*i);
        LinkAppendBuf(&FreeLink, buf);
    }
            
    for(i=0;i<32;i++)
        LinkInit(&TxLink[i]);
}

static void InitBD(void)
{
    int i,j;
    LinkBufStruct *pData;

    /* init the rxbd and txbd */
    for(i=0;i<pGCfg->MaxSubChanNum;i++)
    {
        for(j=0;j<pGCfg->MaxSendBD;j++)
        {
            pData=LinkGetBuf(&FreeLink);
            if(pData==NULL) continue; 
            (gDataBuf[i]->pBaseSendBD)[j].length=0;
            (gDataBuf[i]->pBaseSendBD)[j].address=pData->Data;
            (gDataBuf[i]->pBaseSendBD)[j].status=BD_INTR|BD_LAST|HDLC_TX_CRC;
           
        }
        if(j>0)(gDataBuf[i]->pBaseSendBD)[j-1].status|=BD_WRAP;
        for(j=0;j<pGCfg->MaxRecvBD;j++)
        {
            pData=LinkGetBuf(&FreeLink);
            if(pData==NULL) continue;
            (gDataBuf[i]->pBaseRecvBD)[j].length=0;
            (gDataBuf[i]->pBaseRecvBD)[j].address=pData->Data;
            (gDataBuf[i]->pBaseRecvBD)[j].status=BD_INTR|BD_EMPTY;
        }
        if(j>0) (gDataBuf[i]->pBaseRecvBD)[j-1].status|=BD_WRAP;
    }
}/*end of init BD */

static void StopTransmit(UCHAR Channel)
{
	CPM_CMD(((0x1F&Channel)<<2)|QMC_STOP_TX|QMC_RESERVE);
}

static void ReStartTransmit(UCHAR Channel)
{
    QmcSubChanParamStruct *ch=(QmcSubChanParamStruct*)((GetIMMR()&IO_MAP_MASK)
                               +0x2000+pGCfg->SubChParamOffset);
    QmcGlobalParamStruct *gmp=(QmcGlobalParamStruct *)((GetIMMR()&IO_MAP_MASK)
                               +0x3C00+0x100*pGCfg->ch);
    Channel&=0x1f;
    if(ch[Channel].chamr.ent==0) /*do if channel is deactive*/
    {
        ch[Channel].tstate=0x30000000;
        ch[Channel].zistate=0x100;
        gmp->tsatt[Channel].v=1;
        ch[Channel].chamr.ent=1;
    }
    ch[Channel].chamr.pol=1;
}

static void StopReceive(UCHAR Channel)
{
	CPM_CMD(((0x1F&Channel)<<2)|QMC_STOP_RX|QMC_RESERVE);
}

static void ReStartReceive(UCHAR Channel)
{
    QmcSubChanParamStruct *ch=(QmcSubChanParamStruct*)((GetIMMR()&IO_MAP_MASK)
                               +0x2000+pGCfg->SubChParamOffset);
    Channel&=0x1f;
    ch[Channel].zdstate=0x80;
    ch[Channel].rstate= 0x31000000;
}

static int QmcSwRead(void *pDataBuf,void *pBuf, int MaxLen)         
{   
    int ret;
    int imax; 
    
    if(pGCfg->FatalFlag==1)
        return SDE_QMCSW_FATAL;
    pGCfg->ReInUsing|=(1<<(CurSubChan-pGCfg->SubChParamOffset/64));    
    imax=splx(MAX_ILEV);
     _sync_io();                   
    ret=BDRead(gDataBuf[CurSubChan&0x1f],pBuf,MaxLen);
    splx(imax); 
    pGCfg->ReInUsing&=~(1<<(CurSubChan-pGCfg->SubChParamOffset/64));
    if(ret>2)return ret-2;    /* sub 2 bytes of CRC */
    else if(ret>0)return SDE_INVALID_PACKET;  
    else return ret;
}

static int QmcSwWrite(void *pDataBuf,void *pBuf, int MaxLen)         
{   
    int ret;
    int imax; 
    QmcSubChanParamStruct *ch=(QmcSubChanParamStruct*)((GetIMMR()&IO_MAP_MASK)
                               +0x2000+pGCfg->SubChParamOffset);
    if(pGCfg->FatalFlag==1) return SDE_QMCSW_FATAL;
    pGCfg->WrInUsing|=(1<<(CurSubChan-pGCfg->SubChParamOffset/64));
    imax=splx(MAX_ILEV);
    _sync_io(); 
    ret=BDWrite(gDataBuf[CurSubChan&0x1f],pBuf,MaxLen);
    splx(imax); 
    pGCfg->WrInUsing&=~(1<<(CurSubChan-pGCfg->SubChParamOffset/64));
    ch[CurSubChan&0x1f].chamr.pol=1;   
    return ret; 
}

static void InitScc(void)
{
    PDA  *pda=(PDA *)(GetIMMR() & IO_MAP_MASK);

    pda->Scc_regs[pGCfg->ch].scc_gsmrb=0x780;
    pda->Scc_regs[pGCfg->ch].scc_gsmra|=0x0a;  /* enable QMC*/
}

/* Init Global MutiChannel Params*/
static void InitGlobPrams(void)
{
    int i;
    QmcGlobalParamStruct *gmp=(QmcGlobalParamStruct *)((GetIMMR()&IO_MAP_MASK)
                              +0x3C00+0x100*pGCfg->ch);

    gmp->mcbase=(ULONG)pGCfg->BDTable;  /* pointer to the start of BD tab*/
    gmp->mrblr=pGCfg->MaxBufLen-8;        /* set the MAX buffer length*/
    gmp->intbase=(ULONG)pGCfg->IntTable;/* pointer to the start of int tab*/
    gmp->grfthr=1;                      /* 1 receive frame to interrupt*/
    gmp->grfcnt=1;                      /* 1 receive frame to interrupt*/
    gmp->cmask32=0x0debb20e3;           /* 32 bit crc constant */
    gmp->cmask16=0x0f0b8;               /* 16 bit crc constant  */
    gmp->intptr=gmp->intbase;
    for (i=0;i<pGCfg->MaxSubChanNum;i++)/* Init receive time slot table*/
    {
        gmp->tsatr[i].w=0;              /* Init one slot to one channel */
        gmp->tsatr[i].chp=i+pGCfg->SubChParamOffset; 
        gmp->tsatr[i].mask0_1 =0x3;     /* No subchannel */
        gmp->tsatr[i].mask2_7 =0x3f;
        gmp->tsatr[i].v=1;
    }
    gmp->tsatr[i-1].w=1;
    for (i=0;i<pGCfg->MaxSubChanNum;i++)/* init transmit time slot table */
    {
        gmp->tsatt[i].w=0;
        gmp->tsatt[i].chp=i+pGCfg->SubChParamOffset;
        gmp->tsatt[i].mask0_1 =0x3;
        gmp->tsatt[i].mask2_7 =0x3f;
        gmp->tsatt[i].v=1;
    }
    gmp->tsatt[i-1].w=1;
    gmp->rx_s_ptr=0x3C00+pGCfg->ch*0x100+0x20;  /* init pointer to tsatr */
    gmp->tx_s_ptr=0x3C00+pGCfg->ch*0x100+0x60;
    gmp->rxptr=gmp->rx_s_ptr;
    gmp->txptr=gmp->tx_s_ptr;
    gmp->qmcstate=0x8000;
} /* End of InitGlobPrams */

/* init channel specific params*/
static void InitChPrams(void)
{
    int i;
    QmcSubChanParamStruct *ch;

    ch=(QmcSubChanParamStruct*)((GetIMMR() & IO_MAP_MASK)
                                +0x2000+pGCfg->SubChParamOffset);
    for(i=0;i<pGCfg->MaxSubChanNum;i++)
    {
        DataBufStruct *pData=gDataBuf[i];
/*      memset(pData, 0, sizeof(DataBufStruct)); */
        pData->CurSendBD=0;
        pData->CurRecvBD=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);

        ch[i].tbase=i*(pGCfg->MaxSendBD+pGCfg->MaxRecvBD)*sizeof(BuffDescType);
        pData->pBaseSendBD=(BuffDescType *)(pGCfg->BDTable+ch[i].tbase);

        ch[i].rbase=ch[i].tbase+pGCfg->MaxSendBD*sizeof(BuffDescType);
        pData->pBaseRecvBD=(BuffDescType *)(pGCfg->BDTable+ch[i].rbase);

        ch[i].tstate=0x30000000;
        ch[i].rstate=0x31000000;
        ch[i].zistate=0x100;          /* HDLC mode */
        ch[i].zdstate=0x80;
        ch[i].intmask=0x0e;           /* enable RXF TXB and BSY interrupt*/
        ch[i].mflr=pGCfg->MaxBufLen-4;    /* maximum frame length */
        ch[i].tbptr=ch[i].tbase;
        ch[i].rbptr=ch[i].rbase;
        ch[i].chamr.mode=1;           /* HDLC mode */
        ch[i].chamr.idlm=0;           /* disable idle frame  */
        ch[i].chamr.ent=1;            /* enable channel xmit*/
        ch[i].chamr.crc=0;            /* 16 bit crc */
        ch[i].chamr.nof=0;            /* 1 flags  */
        ch[i].chamr.pol=0;            /* we enable polling later */
    }
} /* End of InitChPrams */
                  

/* Interrupt Init */
static void InitInterrupt(ULONG Vector, void *Handler, void * Arg)
{
    int i;
    PDA  *pda=(PDA *)(GetIMMR() & IO_MAP_MASK);

    for(i=0;i<pGCfg->MaxIntEty;i++)
       (pGCfg->IntTable)[i].Word16=0;
    (pGCfg->IntTable)[i-1].Bit.w=1;
    pGCfg->IntTablePtr=pGCfg->IntTable;  /* init the soft service pointer */
    pda->Scc_regs[pGCfg->ch].scc_scce=0xffff; /*clear the event register*/
    pda->Scc_regs[pGCfg->ch].scc_sccm=0x0f;
    SPLX(pda->cpmi_cimr|=(EN_SCC1 >> pGCfg->ch);)
    SPLX(pda->cpmi_cipr|=(CLR_SCC1 >> pGCfg->ch);)
    SPLX(pda->cpmi_cisr|=(CLR_SCC1 >> pGCfg->ch);)
    SPLX(CpmIsrAddHandler(Vector,Handler,Arg);)
    SPLX(pda->cpmi_cicr|=CPM_EN_INTS|0x1b0000;)
}/* end of init interrupt */

/* Qmc global init */
static void QmcSwGlobalInit(void)
{
    int i;
    PDA  *pda=(PDA *)(GetIMMR() & IO_MAP_MASK);
  
    for(i=0;i<32;i++)
      MapTable[i]=QMCSW_SUBCHAN_INVALID;
    
    /* we asume the last channel is for loop test*/  
    MapTable[pGCfg->MaxSubChanNum-1]=QMCSW_SUBCHAN_OPERATE;
  
    pGCfg->WrInUsing=0;
    pGCfg->ReInUsing=0;
   
    pda->Scc_regs[pGCfg->ch].scc_gsmra &= 0xffffffcf; /* Disable Rx,Tx */    
    pda->si_sicr &= (~( (0x000000ff)<<(pGCfg->ch*8)));/* Connect to TSA*/    
    pda->si_sicr |= ( (0x00000040)<<(pGCfg->ch*8) );
    InitScc();            /* Init general mode  register*/
    InitGlobPrams();      /* init Global MutiChannel Params*/
    InitChPrams();        /* init channel specific params*/
    InitLink();           /* init recyclebin or DataBuffer */
    InitBD();
    InitInterrupt(V_SCC1-pGCfg->ch,QmcIsr,NULL); /* init interrupt */
    pda->Scc_regs[pGCfg->ch].scc_gsmra|=0x00000030;   /* Enable Rx,Tx */
/* for(i=0;i<pGCfg->MaxSubChanNum;i++)  StopReceive(i); */ /*Stop Rx */
        
}/* end of global init*/

static int QmcSwCntrl(void *pDataBuf, int cmd, void *pParam, int maxlen)
{
    PDA *pda= (PDA *)(GetIMMR() & IO_MAP_MASK);
    ChanMapStruct *mp;
    int i,ret,imask;
      
    ret=BDCntrl(gDataBuf[CurSubChan&0x1f],cmd,pParam,maxlen);
    if(ret!=SDE_UNKNOW_CMD)return ret;
    switch(cmd)
    {
        
        case SDC_REINIT:
            for(i=0;i<pGCfg->MaxSubChanNum;i++)
            {
            	StopTransmit(i);
            	StopReceive(i);
            } 	 
            for(i=0;i<pGCfg->MaxSubChanNum;i++) /* clear the databuf struct */
               memset(gDataBuf[i],0,sizeof(DataBufStruct)); 
            QmcSwGlobalInit();     
            break;

        case SDC_SEL_SUBCHAN:
            if(maxlen!=sizeof(int))return SDE_INVALID_ARG;
            if(*(int *)pParam<0 || *(int *)pParam>=pGCfg->MaxSubChanNum)
                return SDE_INVALID_ARG;
            CurSubChan=*(int *)pParam;
            break;
        
        case SDC_SET_MAP_TABLE:
            if(maxlen!=sizeof(ChanMapStruct))return SDE_INVALID_ARG;   
            mp=(ChanMapStruct *)pParam;
            if( mp->ChanIn<0 || mp->ChanIn>=pGCfg->MaxSubChanNum )
                return SDE_INVALID_ARG;
            if((mp->ChanOut<0 || mp->ChanOut>=pGCfg->MaxSubChanNum) 
               &&(mp->ChanOut!=QMCSW_SUBCHAN_OPERATE)
               &&(mp->ChanOut!=QMCSW_SUBCHAN_INVALID))
                return SDE_INVALID_ARG;
            SPLX(MapTable[mp->ChanIn]=mp->ChanOut; )
       /*     ReStartReceive(mp->ChanIn); */
            break;  
        
        case SDC_SET_LOOPBACK_MODE:         
            for(i=0;i<pGCfg->MaxSubChanNum;i++)
            {
                StopReceive(i);
                StopTransmit(i);    
            }
            imask = splx(MAX_ILEV);/* mask interrupt*/

⌨️ 快捷键说明

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