📄 sndshdlcend.c
字号:
pDrvCtrl->baudRate = atoi (tok);
/*Baud Rate */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->dataFormat = atoi (tok);
ENDLOGMSG (("Processed all arugments\n", 1, 2, 3, 4, 5, 6));
return OK;
}
/*******************************************************************************
*
* sndsHdlcEndMemInit - initialize memory for the chip
*
* This routine is highly specific to the device.
*
* RETURNS: OK or ERROR.
*/
STATUS sndsHdlcEndMemInit
(
HDLC_END_DEVICE * pDrvCtrl /* device to be initialized */
)
{
/*allocate and initialized any shared memory areas */
/*
* This is how we would set up and END netPool using netBufLib(1).
* This code is pretty generic.
*/
if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
return (ERROR);
pDrvCtrl->hdlcEndMclConfig.mBlkNum = END_MBLK_NUM;
pDrvCtrl->hdlcEndClDescTbl[0].clSize = SNDS_CL_SIZE;
pDrvCtrl->hdlcEndClDescTbl[0].clNum = END_CL_NUM;
pDrvCtrl->hdlcEndMclConfig.clBlkNum = pDrvCtrl->hdlcEndClDescTbl[0].clNum;
/* Calculate the total memory for all the M-Blks and CL-Blks. */
pDrvCtrl->hdlcEndMclConfig.memSize = (pDrvCtrl->hdlcEndMclConfig.mBlkNum * (MSIZE + sizeof (long))) +
(pDrvCtrl->hdlcEndMclConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)));
if ((pDrvCtrl->hdlcEndMclConfig.memArea = (char *) memalign (sizeof(long),
pDrvCtrl->hdlcEndMclConfig.memSize)) == NULL)
return (ERROR);
/* Calculate the memory size of all the clusters. */
pDrvCtrl->hdlcEndClDescTbl[0].memSize = (pDrvCtrl->hdlcEndClDescTbl[0].clNum *
(pDrvCtrl->hdlcEndClDescTbl[0].clSize + 8)) + sizeof(int);
/* Allocate the memory for the clusters from cache safe memory. */
pDrvCtrl->hdlcEndClDescTbl[0].memArea =
(char *) malloc (pDrvCtrl->hdlcEndClDescTbl[0].memSize);
if ((int)pDrvCtrl->hdlcEndClDescTbl[0].memArea == NULL)
{
return (ERROR);
}
/* Initialize the memory pool. */
if (netPoolInit(pDrvCtrl->end.pNetPool, &(pDrvCtrl->hdlcEndMclConfig),
&(pDrvCtrl->hdlcEndClDescTbl[0]), CLDESCTBL_NUM_ENT, NULL) == ERROR)
{
return (ERROR);
}
return OK;
}
/*******************************************************************************
*
* sndsHdlcEndStart - start the device
*
* This function calls BSP functions to connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or ERROR
*
*/
LOCAL STATUS sndsHdlcEndStart
(
HDLC_END_DEVICE *pDrvCtrl /* device to be started */
)
{
HDLC_HCON hdlchcon;
/*Connect Tx and Rx Interrupts*/
intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(pDrvCtrl->hdlcVecTx), sndsHdlcTxInt, (UINT32)pDrvCtrl);
intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(pDrvCtrl->hdlcVecRx), sndsHdlcRxInt, (UINT32)pDrvCtrl);
/* Enable the Interrupts */
intEnable(pDrvCtrl->hdlcVecTx);
intEnable(pDrvCtrl->hdlcVecRx);
/* Enable to Rx Data*/
SNDS_HDLC_REG_READ (pDrvCtrl, SNDS_HCON, hdlchcon.hcon_resetval);
hdlchcon.hcon_reg.rxen = 1;
hdlchcon.hcon_reg.drxen = 1;
hdlchcon.hcon_reg.txen = 1;
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HCON, hdlchcon.hcon_resetval);
END_FLAGS_SET(&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
return (OK);
}
/*******************************************************************************
*
* sndsHdlcEndHandleRcvInt - task level interrupt service for input packets
*
* This routine is called at task level indirectly by the interrupt
* service routine to do any message received processing.
*
* RETURNS: N/A.
*/
LOCAL void sndsHdlcEndHandleRcvInt
(
HDLC_END_DEVICE *pDrvCtrl, /* interrupting device */
UINT32 status /* Receive status */
)
{
HDLC_HSTAT hdlchstat;
SNDSHDLCBD *pRxBD;
UINT32 * pFrameData;
UINT32 frameLength;
SNDS_HDLC_REG_READ (pDrvCtrl, SNDS_HDMARXPTR, *(UINT32 *)(&pRxBD));
hdlchstat.hstat_resetval = status;
if((*(UINT32*)(&(pDrvCtrl->gpRxBDStart->StatusLength))) == 0)
return;
do
{
if(hdlchstat.hstat_reg.drxnl == 1)
return;
frameLength = (pDrvCtrl->gpRxBDStart->StatusLength) & 0xffff;
if(hdlchstat.hstat_reg.drxfd == 1)
{
pFrameData = (UINT32 *)(pDrvCtrl->gpRxBDStart->BufferDataPtr);
sndsHdlcEndRecv (pDrvCtrl, (char *)pFrameData, frameLength);
}
pDrvCtrl->gpRxBDStart->BufferDataPtr |= BOWNERSHIP_DMA ;
*(UINT32*)(&(pDrvCtrl->gpRxBDStart->StatusLength)) = 0;
pDrvCtrl->gpRxBDStart = pDrvCtrl->gpRxBDStart->NextBD;
} while(pDrvCtrl->gpRxBDStart != pRxBD);
}
/*******************************************************************************
*
* sndsHdlcEndRecv - process the next incoming packet
*
* Handle one incoming packet. The packet is checked for errors.
*
* RETURNS: N/A.
*/
LOCAL STATUS sndsHdlcEndRecv
(
HDLC_END_DEVICE *pDrvCtrl, /* device structure */
char* pData, /* packet to process */
UINT32 len /* Length of received data */
)
{
M_BLK_ID pMblk;
char* pNewCluster;
CL_BLK_ID pClBlk;
/* Add one to our unicast data. */
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
/*
* We implicitly are loaning here, if copying is necessary this
* step may be skipped, but the data must be copied before being
* passed up to the protocols.
*/
pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->end.pNetPool->clTbl[0]);
if (pNewCluster == NULL)
{
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
bcopy (pData, pNewCluster, len); /* Copy received data to net buffer */
/* Grab a cluster block to marry to the cluster we received. */
if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
{
netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
/*
* OK we've got a spare, let's get an M_BLK_ID and marry it to the
* one in the ring.
*/
if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
{
netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);
netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
/* Join the cluster to the MBlock */
netClBlkJoin (pClBlk, pNewCluster, SNDS_CL_SIZE, NULL, 0, 0, 0);
netMblkClJoin (pMblk, pClBlk);
pMblk->mBlkHdr.mData += 0;
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = len;
/* Call the upper layer's receive routine. */
END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
cleanRXD:
return (OK);
}
/*******************************************************************************
*
* sndsHdlcEndSend - the driver send routine
*
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it. This is done by a higher layer. The last arguments are a free
* routine to be called when the device is done with the buffer and a pointer
* to the argument to pass to the free routine.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sndsHdlcEndSend
(
HDLC_END_DEVICE *pDrvCtrl, /* device ptr */
M_BLK_ID pNBuff /* data to send */
)
{
int len=0;
int oldLevel;
BOOL freeNow = TRUE;
SNDSHDLCBD *pTxBD;
HDLC_HCON hdlchcon;
pTxBD = pDrvCtrl->gpTxBDStart;
if (pTxBD->BufferDataPtr & BOWNERSHIP_DMA)
return ERROR;
len = pNBuff->mBlkPktHdr.len;
/*
* Obtain exclusive access to transmitter. This is necessary because
* we might have more than one stack transmitting at once.
*/
END_TX_SEM_TAKE(&pDrvCtrl->end, WAIT_FOREVER);
/*set pointers in Local Structures to point to data */
if (netMblkToBufCopy(pNBuff, (void *)pTxBD->BufferDataPtr, NULL) == ERROR)
return(ERROR);
pTxBD->StatusLength = len;
pTxBD->BufferDataPtr |= BOWNERSHIP_DMA;
pTxBD->Reserved = (LITTLE | LASTBF); /* Little endian mode, last buffer in frame */
oldLevel=intLock();
/*Initiate Device Transmit*/
SNDS_HDLC_REG_READ (pDrvCtrl, SNDS_HCON, hdlchcon.hcon_resetval);
hdlchcon.hcon_reg.dtxen = 1;
SNDS_HDLC_REG_WRITE (pDrvCtrl, SNDS_HCON, hdlchcon.hcon_resetval);
intUnlock(oldLevel);
pDrvCtrl->gpTxBDStart = pDrvCtrl->gpTxBDStart->NextBD;
END_TX_SEM_GIVE(&pDrvCtrl->end);
/* Bump the statistic counter. */
END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
/*
* Cleanup. The driver must either free the packet now or
* set up a structure so it can be freed later after a transmit
* interrupt occurs.
*/
if (freeNow)
netMblkClChainFree (pNBuff);
return (OK);
}
/*******************************************************************************
*
* sndsHdlcEndIoctl - the driver I/O control routine
*
* Process an ioctl request.
*
* RETURNS: A command specific response, usually OK or ERROR.
*/
LOCAL int sndsHdlcEndIoctl
(
HDLC_END_DEVICE *pDrvCtrl, /* device receiving command */
int cmd, /* ioctl command code */
caddr_t data /* command argument */
)
{
int error = 0;
long value;
switch (cmd)
{
case EIOCSADDR:
if (data == NULL)
return (EINVAL);
bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
END_HADDR_LEN(&pDrvCtrl->end));
break;
case EIOCGADDR:
if (data == NULL)
return (EINVAL);
bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
END_HADDR_LEN(&pDrvCtrl->end));
break;
case EIOCSFLAGS:
value = (long)data;
if (value < 0)
{
value = -(--value);
END_FLAGS_CLR (&pDrvCtrl->end, value);
}
else
{
END_FLAGS_SET (&pDrvCtrl->end, value);
}
sndsHdlcEndConfig (pDrvCtrl);
break;
case EIOCGFLAGS:
*(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
break;
case EIOCGMIB2:
if (data == NULL)
return (EINVAL);
bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
sizeof(pDrvCtrl->end.mib2Tbl));
break;
case EIOCGFBUF:
if (data == NULL)
return (EINVAL);
*(int *)data = 0; /*END_MIN_FBUF;*/
break;
default:
error = EINVAL;
}
return (error);
}
/******************************************************************************
*
* sndsHdlcEndConfig - reconfigure the interface under us.
*
* Reconfigure the interface setting promiscuous mode, and changing the
* multicast interface list.
*
* RETURNS: N/A.
*/
LOCAL void sndsHdlcEndConfig
(
HDLC_END_DEVICE *pDrvCtrl /* device to be re-configured */
)
{
}
/******************************************************************************
*
* sndsHdlcEndAddrFilterSet - set the address filter for multicast addresses
*
* This routine goes through all of the multicast addresses on the list
* of addresses (added with the endAddrAdd() routine) and sets the
* device's filter correctly.
*
* RETURNS: N/A.
*/
LOCAL void sndsHdlcEndAddrFilterSet
(
HDLC_END_DEVICE *pDrvCtrl /* device to be updated */
)
{
}
/*******************************************************************************
*
* sndsHdlcEndPollRcv - routine to receive a packet in polled mode.
*
* This routine is called by a user to try and get a packet from the
* device.
*
* RETURNS: OK upon success. EAGAIN is returned when no packet is available.
*/
LOCAL STATUS sndsHdlcEndPollRcv
(
HDLC_END_DEVICE *pDrvCtrl, /* device to be polled */
M_BLK_ID* pMblk /* ptr to buffer */
)
{
return (OK);
}
/*******************************************************************************
*
* sndsHdlcEndPollSend - routine to send a packet in polled mode.
*
* This routine is called by a user to try and send a packet on the
* device.
*
* RETURNS: OK upon success. EAGAIN if device is busy.
*/
LOCAL STATUS sndsHdlcEndPollSend
(
HDLC_END_DEVICE* pDrvCtrl, /* device to be polled */
M_BLK_ID* pMblk /* packet to send */
)
{
return (OK);
}
/*****************************************************************************
*
* sndsHdlcEndMCastAdd - add a multicast address for the device
*
* This routine adds a multicast address to whatever the driver
* is already listening for. It then resets the address filter.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sndsHdlcEndMCastAdd
(
HDLC_END_DEVICE *pDrvCtrl, /* device pointer */
char* pAddress /* new address to add */
)
{
int error;
if ((error = etherMultiAdd (&pDrvCtrl->end.multiList,
pAddress)) == ENETRESET)
sndsHdlcEndConfig (pDrvCtrl);
return (OK);
}
/*****************************************************************************
*
* sndsHdlcEndMCastDel - delete a multicast address for the device
*
* This routine removes a multicast address from whatever the driver
* is listening for. It then resets the address filter.
*
* RETURNS: OK or ERROR.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -