📄 bdihdlc.c
字号:
/* initialize each transmit buffer descriptor */
for (frame = 0; frame < sccChan.hdlc.txBdNum; frame++) {
sccChan.hdlc.txBdBase[frame].statusMode = SCC_HDLC_TX_BD_L | SCC_HDLC_TX_BD_TC;
sccChan.hdlc.txBdBase[frame].dataLength = 0;
sccChan.hdlc.txBdBase[frame].dataPointer = sccChan.hdlc.txBufBase + (frame * SCC_TX_BUFF_SIZE);
} /* for */
/* set the last BD to wrap to the first */
sccChan.hdlc.txBdBase[(frame - 1)].statusMode |= SCC_HDLC_TX_BD_WRAP;
/* set up receive buffer descriptors */
sccChan.hdlc.rxBdNum = SCC_RBD_NUM;
sccChan.hdlc.rxBdBase = (SCC_HDLC_BD*)(immrVal + SCC_RBD_OFF);
sccChan.hdlc.rxBufBase = (u_char*)(SCC_RX_BUFF_ADDR);
sccChan.hdlc.rxBdNext = 0;
/* initialize each receive buffer descriptor */
for (frame = 0; frame < sccChan.hdlc.rxBdNum; frame++) {
sccChan.hdlc.rxBdBase[frame].statusMode = SCC_HDLC_RX_BD_EMPTY | SCC_HDLC_RX_BD_INT;
sccChan.hdlc.rxBdBase[frame].dataLength = SCC_RX_BUFF_SIZE;
sccChan.hdlc.rxBdBase[frame].dataPointer = sccChan.hdlc.rxBufBase + (frame * SCC_RX_BUFF_SIZE);
} /* for */
/* set the last BD to wrap to the first */
sccChan.hdlc.rxBdBase[(frame - 1)].statusMode |= SCC_HDLC_RX_BD_WRAP;
/* initialize parameter RAM area for this SCC */
*pRBASE = SCC_RBD_OFF;
*pTBASE = SCC_TBD_OFF;
*pRFCR = 0x18; /* supervisor data access */
*pTFCR = 0x18; /* supervisor data access */
*pMRBLR = SCC_RX_BUFF_SIZE;
*pCMASK = 0x0000F0B8;
*pCPRES = 0x0000FFFF;
*pDISFC = 0;
*pCRCEC = 0;
*pABTSC = 0;
*pNMARC = 0;
*pRETRC = 0;
*pMFLR = SCC_RX_BUFF_SIZE;
*pRFTHR = 1;
*pHMASK = 0x0000;
*pHADDR1 = 0x0000;
*pHADDR2 = 0x0000;
*pHADDR3 = 0x0000;
*pHADDR4 = 0x0000;
/* program the three SCC mode registers: gsmrl, gsmrh, and psmr */
*pGSMR_L = M8260_SCC_GSMRL_TPL_16
| M8260_SCC_GSMRL_TPP_01
| M8260_SCC_GSMRL_TDCR_X16
| M8260_SCC_GSMRL_RDCR_X16
| (4L<<11) | (4L<<8) /* Manchester encoding */
| M8260_SCC_GSMRL_HDLC;;
*pGSMR_H = 0;
*pPSMR = SCC_HDLC_PSMR_NOF_0 | SCC_HDLC_PSMR_CRC16;
/* wait until the CP is clear */
do {
M8260_SCC_32_RD((M8260_CPCR (immrVal)), cpcrVal);
} while (cpcrVal & M8260_CPCR_FLG) ;
/* Tell CP to initialize tx and rx parameters for SCC */
cpcrVal = ( M8260_CPCR_OP (M8260_CPCR_RT_INIT)
| M8260_CPCR_SBC (M8260_CPCR_SBC_SCC1 | (scc * 0x1))
| M8260_CPCR_PAGE (M8260_CPCR_PAGE_SCC1 | (scc * 0x1))
| M8260_CPCR_FLG);
M8260_SCC_32_WR (M8260_CPCR (immrVal), cpcrVal);
/* clear all events */
*pSCCE = 0xFFFF;
/* enables the transmitter and receiver */
*pGSMR_L |= (M8260_SCC_GSMRL_ENT | M8260_SCC_GSMRL_ENR);
/* unmask interrupt */
*pSCCM |= SCC_HDLC_SCCX_RXF;
/* enable SCC interrupts at the SIU Interrupt Controller */
if (SCC_NUM == 1) m8260IntEnable(INUM_SCC1);
else if (SCC_NUM == 2) m8260IntEnable(INUM_SCC2);
else if (SCC_NUM == 3) m8260IntEnable(INUM_SCC3);
else if (SCC_NUM == 4) m8260IntEnable(INUM_SCC4);
intUnlock (oldlevel); /* UNLOCK INTERRUPTS */
} /* sccInit */
/*******************************************************************************
*
* sccInterrupt - handle an SCC interrupt
*
* This routine is called to handle SCC interrupts.
*/
static void sccInterrupt(WDB_HDLC_PKT_DEV *pPktDev)
{
UINT16 sccEvent;
UINT16 rxCount;
FAST char* pChar;
FAST char rxChar;
SCC_HDLC_BD* pBD;
/* read and clear events */
sccEvent = *sccChan.pSCCE;
*sccChan.pSCCE = sccEvent;
/* handle receive event */
if (sccEvent & SCC_HDLC_SCCX_RXF) {
/* process all filled receive buffers */
pBD = sccChan.hdlc.rxBdBase + sccChan.hdlc.rxBdNext;
while ( ((pBD->statusMode & SCC_HDLC_RX_BD_EMPTY) == 0)
&& ((pBD->statusMode & SCC_HDLC_RX_BD_INT) != 0)
) {
/* a valid receive frame */
if ((pBD->statusMode & HDLC_RX_ERRORS) == 0) {
struct mbuf* pMbuf = wdbMbufAlloc();;
if (pMbuf) {
pBD->statusMode &= ~SCC_HDLC_RX_BD_INT;
pPktDev->pBD = (void*)pBD;
wdbMbufClusterInit (pMbuf,
pBD->dataPointer,
(pBD->dataLength - 2), /* discard CRC */
(int (*)())wdbPktFree,
(int)pPktDev);
(*pPktDev->wdbDrvIf.stackRcv) (pMbuf); /* invoke callback */
} /* if */
} /* if */
/* discard frame and release buffer */
if (pBD->statusMode & SCC_HDLC_RX_BD_INT) {
pBD->dataLength = 0;
pBD->statusMode &= SCC_HDLC_RX_BD_WRAP;
pBD->statusMode |= (SCC_HDLC_RX_BD_EMPTY | SCC_HDLC_RX_BD_INT);
} /* else */
/* switch to next buffer */
pBD->statusMode |= SCC_HDLC_RX_BD_EMPTY;
sccChan.hdlc.rxBdNext = (sccChan.hdlc.rxBdNext + 1) % sccChan.hdlc.rxBdNum;
pBD = sccChan.hdlc.rxBdBase + sccChan.hdlc.rxBdNext;
} /* while */
} /* if */
} /* sccInterrupt */
/*******************************************************************************
*
* wdbHdlcPktDevInit - init the fast SLIP paket driver
*
* This routine init the WDB agents paket driver.
*
* RETURNS: initialized WDB_SLIP_PKT_DEV structure
*
*/
void wdbHdlcPktDevInit
(
WDB_HDLC_PKT_DEV *pPktDev,
void (*stackRcv)()
)
{
VOIDFUNCPTR* ivec;
/* setup driver interface structure */
pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_INT;
pPktDev->wdbDrvIf.mtu = WDB_HDLC_PKT_MTU;
pPktDev->wdbDrvIf.stackRcv = stackRcv;
pPktDev->wdbDrvIf.devId = (WDB_HDLC_PKT_DEV *)pPktDev;
pPktDev->wdbDrvIf.pollRtn = wdbPktPoll;
pPktDev->wdbDrvIf.pktTxRtn = wdbPktTx;
pPktDev->wdbDrvIf.modeSetRtn = wdbPktModeSet;
/* init SCC channel in CPM */
sccInit();
/* connect interrupt service */
if (SCC_NUM == 1) ivec = INUM_TO_IVEC(INUM_SCC1);
else if (SCC_NUM == 2) ivec = INUM_TO_IVEC(INUM_SCC2);
else if (SCC_NUM == 3) ivec = INUM_TO_IVEC(INUM_SCC3);
else if (SCC_NUM == 4) ivec = INUM_TO_IVEC(INUM_SCC4);
(void)intConnect (ivec, (VOIDFUNCPTR) sccInterrupt, (int)pPktDev);
} /* wdbHdlcPktDevInit */
/******************************************************************************
*
* wdbPktTx - transmit a packet
*
* This routine can only be called by the WDB agent.
*
* RETURNS: OK, or ERROR if a packet is currently being transmitted, or
* the packet is too large to send.
*/
static STATUS wdbPktTx
(
void * pDev,
struct mbuf * pMbuf
)
{
int pktSize;
u_char txChar;
SCC_HDLC_BD* pTxBD;
/* copy transmit data to local buffer */
pTxBD = sccChan.hdlc.txBdBase + sccChan.hdlc.txBdNext;
if (pTxBD->statusMode & SCC_HDLC_TX_BD_READY) return (ERROR);
wdbMbufDataGet(pMbuf, pTxBD->dataPointer, WDB_HDLC_PKT_MTU, &pktSize);
wdbMbufChainFree(pMbuf);
/* start transmitting */
pTxBD->dataLength = pktSize;
sccChan.hdlc.txBdNext = (sccChan.hdlc.txBdNext + 1) % sccChan.hdlc.txBdNum;
pTxBD->statusMode |= SCC_HDLC_TX_BD_READY;
return (OK);
} /* wdbPktTx */
/******************************************************************************
*
* wdbPktFree - free the input buffer
*
* This is the callback used to let us know the agent is done with the
* input buffer we loaded it.
*
* RETURNS: N/A
*/
static void wdbPktFree
(
void * pDev
)
{
SCC_HDLC_BD * pBD = ((WDB_HDLC_PKT_DEV*)pDev)->pBD;
pBD->dataLength = 0;
pBD->statusMode &= SCC_HDLC_RX_BD_WRAP;
pBD->statusMode |= (SCC_HDLC_RX_BD_EMPTY | SCC_HDLC_RX_BD_INT);
}
/******************************************************************************
*
* wdbPktModeSet - switch driver modes
*
* RETURNS: OK for a supported mode, else ERROR
*/
static STATUS wdbPktModeSet
(
void * pDev,
uint_t newMode
)
{
WDB_HDLC_PKT_DEV * pPktDev = pDev;
if (newMode == WDB_COMM_MODE_INT)
pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_INT;
else if (newMode == WDB_COMM_MODE_POLL)
pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_POLL;
else
return (ERROR);
return (OK);
}
/******************************************************************************
*
* wdbPktPoll - poll for a packet
*
* This routine polls for a packet. If a packet has arrived it invokes
* the agents callback.
*
* RETURNS: OK if a packet has arrived, else ERROR.
*/
static STATUS wdbPktPoll
(
void * pDev
)
{
WDB_HDLC_PKT_DEV * pPktDev = pDev;
struct mbuf * pMbuf;
return (ERROR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -