?? qmcsw.c
字號:
#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*/
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -