📄 sndshdlcend.c
字号:
LOCAL STATUS sndsHdlcEndMCastDel
(
HDLC_END_DEVICE* pDrvCtrl, /* device pointer */
char* pAddress /* address to be deleted */
)
{
int error;
if ((error = etherMultiDel (&pDrvCtrl->end.multiList,
(char *)pAddress)) == ENETRESET)
sndsHdlcEndConfig (pDrvCtrl);
return (OK);
}
/*****************************************************************************
*
* sndsHdlcEndMCastGet - get the multicast address list for the device
*
* This routine gets the multicast list of whatever the driver
* is already listening for.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sndsHdlcEndMCastGet
(
HDLC_END_DEVICE* pDrvCtrl, /* device pointer */
MULTI_TABLE* pTable /* address table to be filled in */
)
{
return (etherMultiGet (&pDrvCtrl->end.multiList, pTable));
}
/*******************************************************************************
*
* sndsHdlcEndStop - stop the device
*
* This function calls BSP functions to disconnect interrupts and stop
* the device from operating in interrupt mode.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sndsHdlcEndStop
(
HDLC_END_DEVICE *pDrvCtrl /* device to be stopped */
)
{
STATUS result = OK;
HDLC_HCON hdlchcon;
/* TODO - stop/disable the device. */
*(UINT32*)(&hdlchcon) = 0;
SNDS_HDLC_REG_READ (pDrvCtrl, SNDS_HCON, hdlchcon.hcon_resetval);
hdlchcon.hcon_reg.txen = 0;
hdlchcon.hcon_reg.rxen = 0;
hdlchcon.hcon_reg.dtxen = 0;
hdlchcon.hcon_reg.drxen = 0;
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HCON, hdlchcon.hcon_resetval);
intDisable(pDrvCtrl->hdlcVecTx);
intDisable(pDrvCtrl->hdlcVecRx);
END_FLAGS_CLR(&pDrvCtrl->end,IFF_UP | IFF_RUNNING);
return (result);
}
/******************************************************************************
*
* sndsHdlcEndUnload - unload a driver from the system
*
* This function first brings down the device, and then frees any
* stuff that was allocated by the driver in the load function.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sndsHdlcEndUnload
(
HDLC_END_DEVICE* pDrvCtrl /* device to be unloaded */
)
{
END_OBJECT_UNLOAD (&pDrvCtrl->end);
sndsHdlcEndStop (pDrvCtrl);
sndsHdlcEndReset (pDrvCtrl);
sndsHdlcEndFree (pDrvCtrl);
/* Free any shared DMA memory */
if (pDrvCtrl->end.pNetPool)
{
netPoolDelete (pDrvCtrl->end.pNetPool);
free (pDrvCtrl->end.pNetPool);
}
if (pDrvCtrl->hdlcEndClDescTbl[0].memArea)
free (pDrvCtrl->hdlcEndClDescTbl[0].memArea);
if (pDrvCtrl->hdlcEndMclConfig.memArea)
free (pDrvCtrl->hdlcEndMclConfig.memArea);
if (pDrvCtrl)
free (pDrvCtrl);
return (OK);
}
/*******************************************************************************
*
* sndsHdlcEndPollStart - start polled mode operations
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sndsHdlcEndPollStart
(
HDLC_END_DEVICE* pDrvCtrl /* device to be polled */
)
{
return (OK);
}
/*******************************************************************************
*
* sndsHdlcEndPollStop - stop polled mode operations
*
* This function terminates polled mode operation. The device returns to
* interrupt mode.
*
* The device interrupts are enabled, the current mode flag is switched
* to indicate interrupt mode and the device is then reconfigured for
* interrupt operation.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sndsHdlcEndPollStop
(
HDLC_END_DEVICE* pDrvCtrl /* device to be changed */
)
{
return (OK);
}
/*******************************************************************************
*
* sndsHdlcEndReset- Reset the HDLC
*
*/
LOCAL void sndsHdlcEndReset
(
HDLC_END_DEVICE *pDrvCtrl /* Pointer to the device */
)
{
HDLC_HCON hdlchcon;
*(UINT32 *)(&hdlchcon) = 0;
/*reset the frame length and receive buffer registers*/
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HMFLR, 0);
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HRBSR, 0);
/*reset the tx,rx,dmatx,dmarx registers */
hdlchcon.hcon_reg.txrs = 1;
hdlchcon.hcon_reg.rxrs = 1;
hdlchcon.hcon_reg.dtxrs = 1;
hdlchcon.hcon_reg.drxrs = 1;
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HCON, hdlchcon.hcon_resetval);
}
/********************************************************************************
*
* sndsHdlcEndInitialize - Initialize the HDLC driver.
*
*/
LOCAL void sndsHdlcEndInitialize
(
HDLC_END_DEVICE* pDevice
)
{
HDLC_HMODE hdlchmode;
HDLC_HCON hdlchcon;
HDLC_HINTEN hdlchinten;
HDLC_HBRGTC hdlchbrgtc;
/*Hmode Initialization*/
*(UINT32*)(&hdlchmode) = 0;
hdlchmode.hmode_reg.dformat = pDevice->dataFormat; /*Data format */
hdlchmode.hmode_reg.brgclock = 1; /*BRG clock-MCLK2*/
hdlchmode.hmode_reg.txclock = 4; /*TX clock-BRGOUT2*/
hdlchmode.hmode_reg.rxclock = 4; /*Rx clock-BRGOUT2*/
hdlchmode.hmode_reg.txoutput = 0; /* Tx Output-Tx clocl*/
hdlchmode.hmode_reg.rxlittle = 1; /* Rx data in bus is little mode*/
hdlchmode.hmode_reg.txlittle = 1; /* Tx data in bus is little mode*/
SNDS_HDLC_REG_WRITE (pDevice, SNDS_HMODE, hdlchmode.hmode_resetval);
/*Hcon Initialization*/
*(UINT32*)(&hdlchcon) = 0;
hdlchcon.hcon_reg.brgen = 1; /* BRG Counter Enabled*/
hdlchcon.hcon_reg.txwd = 0; /* TXWD-1 word mode selected*/
hdlchcon.hcon_reg.rxwd = 0; /* TXWD-1 word mode selected*/
hdlchcon.hcon_reg.rxwa = 0; /* No Invaled Bytes*/
hdlchcon.hcon_reg.dtxstsk = 1; /* DMA Tx Stops when not owner*/
hdlchcon.hcon_reg.drxstsk = 1; /* DMA Rx Stops when not owner*/
hdlchcon.hcon_reg.txdtr = 1; /* Tx Data Terminal Ready -Low*/
SNDS_HDLC_REG_WRITE (pDevice, SNDS_HCON, hdlchcon.hcon_resetval);
/*Hinten Initialization*/
*(UINT32*)(&hdlchinten) = 0;
hdlchinten.hinten_reg.rxmovie = 1; /* Rx Memory Overflow Interrupt Enb*/
hdlchinten.hinten_reg.drxfdie = 1; /* DMA Rx Frame Done Interrupt Enb*/
hdlchinten.hinten_reg.dtxfdie = 1; /* DMA Tx Frame Done Interrupt Enb*/
hdlchinten.hinten_reg.drxnlie = 1; /* DMA Rx Null List Interrupt Enable*/
hdlchinten.hinten_reg.drxnoie = 1; /* DMA Rx Not owner Interrupt Enable*/
SNDS_HDLC_REG_WRITE (pDevice, SNDS_HINTEN, hdlchinten.hinten_resetval);
/*Baud Rate Set*/
*(UINT32 *)(&hdlchbrgtc)=0;
hdlchbrgtc.hbrgtc_reg.cnt_2 = 1; /* CNT2 value =1*/
hdlchbrgtc.hbrgtc_reg.cnt_1 = 0; /* CNT1 value =0*/
switch (pDevice->baudRate)
{
case 1200:
hdlchbrgtc.hbrgtc_reg.cnt_0 = 1301; /* CNT0 value =1301*/
break;
case 2400:
hdlchbrgtc.hbrgtc_reg.cnt_0 = 650; /* CNT0 value =650*/
break;
case 4800:
hdlchbrgtc.hbrgtc_reg.cnt_0 = 324; /* CNT0 value =324*/
break;
case 9600:
hdlchbrgtc.hbrgtc_reg.cnt_0 = 162; /* CNT0 value =162*/
break;
case 19200:
hdlchbrgtc.hbrgtc_reg.cnt_0 = 80; /* CNT0 value =80*/
break;
case 38400:
hdlchbrgtc.hbrgtc_reg.cnt_0 = 40; /* CNT0 value =40*/
break;
}
SNDS_HDLC_REG_WRITE (pDevice, SNDS_HBRGTC, hdlchbrgtc.hbrgtc_resetval);
/*Station Address Register */
SNDS_HDLC_REG_WRITE (pDevice, SNDS_HSAR0, pDevice->hdlcAddr);
SNDS_HDLC_REG_WRITE (pDevice, SNDS_HMASK, pDevice->hdlcHmask);
/*Maximum Frame Length Register */
SNDS_HDLC_REG_WRITE (pDevice, SNDS_HMFLR, MAXFRAMELENGTH);
/* Receive Buffer Size Register */
SNDS_HDLC_REG_WRITE (pDevice, SNDS_HRBSR, MAXFRAMEDATA);
/* Preamble register */
SNDS_HDLC_REG_WRITE (pDevice, SNDS_HPRMB, PREAMBLE_NRZ);
/* Initialize Buffer Descriptor*/
sndsHdlcTxBuffInitialize(pDevice);
sndsHdlcRxBuffInitialize(pDevice);
}
/********************************************************************************
*
* sndsHdlcTxBuffInitialize - Initialize the Transmit Buffer Descriptor
*
*/
LOCAL void sndsHdlcTxBuffInitialize
(
HDLC_END_DEVICE *pDrvCtrl /* Pointer to the device being initialized */
)
{
SNDSHDLCBD *CurrentTxBD;
SNDSHDLCBD *PrevTxBD=NULL;
int count;
for(count = 0; count < MAXTXBDCOUNT; count++)
{
if ((CurrentTxBD = (SNDSHDLCBD *)calloc(sizeof(SNDSHDLCBD), 1)) == NULL)
return;
(UINT32)CurrentTxBD += NON_CACHE_REGION;
(UINT32)(CurrentTxBD->BufferDataPtr) = (SNDSHDLCFRAME *)calloc(sizeof(SNDSHDLCFRAME), 1);
CurrentTxBD->BufferDataPtr += NON_CACHE_REGION;
CurrentTxBD->BufferDataPtr &= BOWNERSHIP_CPU;
CurrentTxBD->StatusLength = 0;
CurrentTxBD->NextBD = NULL;
if (count == 0)
{
pDrvCtrl->gpTxBDStart = CurrentTxBD;
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HDMATXPTR, *(UINT32*)(&CurrentTxBD));
}
else
{
PrevTxBD->NextBD = CurrentTxBD;
}
if (count == (MAXTXBDCOUNT - 1))
{
CurrentTxBD->NextBD = pDrvCtrl->gpTxBDStart;
}
PrevTxBD = CurrentTxBD;
}
}
/********************************************************************************
*
*sndsHdlcRxBuffInitialize - Initialize the Receive Buffer Descriptor
*
*/
LOCAL void sndsHdlcRxBuffInitialize
(
HDLC_END_DEVICE *pDrvCtrl /* Pointer to the device being initialized */
)
{
SNDSHDLCBD *CurrentRxBD;
SNDSHDLCBD *PrevRxBD=NULL;
int count;
for(count = 0; count < MAXRXBDCOUNT; count++)
{
if ((CurrentRxBD = (SNDSHDLCBD *)calloc(sizeof(SNDSHDLCBD), 1)) == NULL)
return;
(UINT32)CurrentRxBD += NON_CACHE_REGION;
(UINT32)CurrentRxBD->BufferDataPtr = (SNDSHDLCFRAME *)calloc(sizeof(SNDSHDLCFRAME), 1);
CurrentRxBD->BufferDataPtr += NON_CACHE_REGION;
CurrentRxBD->BufferDataPtr |= BOWNERSHIP_DMA;
CurrentRxBD->StatusLength = 0;
CurrentRxBD->NextBD = NULL;
if (count == 0)
{
pDrvCtrl->gpRxBDStart = CurrentRxBD;
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HDMARXPTR, *(UINT32 *)(&CurrentRxBD));
}
else
{
PrevRxBD->NextBD = CurrentRxBD;
}
if (count == (MAXRXBDCOUNT - 1))
{
CurrentRxBD->NextBD = pDrvCtrl->gpRxBDStart;
}
PrevRxBD = CurrentRxBD;
}
}
/************************************************************************************
*
* sndsHdlcTxInt- Transmitter Handle Interrupt Controller
*
*/
LOCAL void sndsHdlcTxInt
(
HDLC_END_DEVICE *pDrvCtrl /* Pointer to the device causing interrupt */
)
{
HDLC_HSTAT hdlchstat;
SNDS_HDLC_REG_READ (pDrvCtrl, SNDS_HSTAT, hdlchstat.hstat_resetval);
if(hdlchstat.hstat_reg.dtxfd == 1)
pDrvCtrl->gHTxStatus.DMATxFD++;
if(hdlchstat.hstat_reg.dtxabt == 1)
pDrvCtrl->gHTxStatus.DMATxABT++;
if(hdlchstat.hstat_reg.dtxnl == 1)
pDrvCtrl->gHTxStatus.DMATxNL++;
if(hdlchstat.hstat_reg.dtxno == 1)
pDrvCtrl->gHTxStatus.DMATxNO++;
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HSTAT, hdlchstat.hstat_resetval);
}
/*******************************************************************************
*
* sndsHdlcRxInt- Receive Interrupt Controller
*
*/
LOCAL void sndsHdlcRxInt
(
HDLC_END_DEVICE *pDrvCtrl /* Pointer to the device causing interrupt */
)
{
HDLC_HSTAT hdlchstat;
BOOL rxErr = FALSE;
SNDS_HDLC_REG_READ (pDrvCtrl, SNDS_HSTAT, hdlchstat.hstat_resetval);
if(hdlchstat.hstat_reg.drxfd == 1)
{
pDrvCtrl->gHRxStatus.DMARxFD++;
if(hdlchstat.hstat_reg.rxcrce == 1)
{
pDrvCtrl->gHRxStatus.RxCRCErr++;
rxErr = TRUE;
}
}
if(hdlchstat.hstat_reg.rxmov == 1)
{
pDrvCtrl->gHRxStatus.DMARxMOV++;
rxErr = TRUE;
}
if(hdlchstat.hstat_reg.drxnl == 1)
{
pDrvCtrl->gHRxStatus.DMARxNL++;
rxErr = TRUE;
}
if(hdlchstat.hstat_reg.drxno == 1)
{
pDrvCtrl->gHRxStatus.DMARxNO++;
rxErr = TRUE;
}
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HSTAT, hdlchstat.hstat_resetval);
if (rxErr == FALSE)
netJobAdd ((FUNCPTR)sndsHdlcEndHandleRcvInt, (int)pDrvCtrl, hdlchstat.hstat_resetval, 0,0,0);
}
/******************************************************************************
* sndsHdlcEndFree - Free the allocated TX and RX FD lists and buffers
* This function frees all the allocated TX and RX FDs and the associated buffers
*/
LOCAL void sndsHdlcEndFree
(
HDLC_END_DEVICE *pDrvCtrl /* Pointer to the device being freed */
)
{
SNDSHDLCBD *pRxBD;
SNDSHDLCBD *pTxBD;
UINT32 count;
for (count = 0; (count < MAXTXBDCOUNT) && pDrvCtrl->gpTxBDStart; count++)
{
pTxBD = pDrvCtrl->gpTxBDStart;
if (pDrvCtrl->gpTxBDStart->BufferDataPtr)
{
pDrvCtrl->gpTxBDStart->BufferDataPtr &= ~NON_CACHE_REGION;
free ((UINT32 *)pDrvCtrl->gpTxBDStart->BufferDataPtr);
}
pDrvCtrl->gpTxBDStart = pDrvCtrl->gpTxBDStart->NextBD;
(UINT32)pTxBD -= NON_CACHE_REGION;
free (pTxBD);
}
for (count = 0; (count < MAXRXBDCOUNT) && pDrvCtrl->gpRxBDStart; count++)
{
pRxBD = pDrvCtrl->gpRxBDStart;
if (pDrvCtrl->gpRxBDStart->BufferDataPtr)
{
pDrvCtrl->gpRxBDStart->BufferDataPtr &= ~NON_CACHE_REGION;
free ((UINT32 *)(pDrvCtrl->gpRxBDStart->BufferDataPtr));
}
pDrvCtrl->gpRxBDStart = pDrvCtrl->gpRxBDStart->NextBD;
(UINT32)pRxBD -= NON_CACHE_REGION;
free (pRxBD);
}
*(UINT32 *)(&(pDrvCtrl->gpRxBDStart)) = *(UINT32 *)(&(pDrvCtrl->gpTxBDStart)) = 0;
}
#endif /* INCLUDE_SNDS_HDLC_END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -