📄 motcpmend.c
字号:
netMblkClChainFree(pMblk);
if(send5==1)
MOTCPMLOGMSG(("motCpmEndSend5 \n", 0, 0, 0, 0, 0, 0));
return (ERROR);
}
#endif
length = netMblkToBufCopy (pMblk, (char *)pBuf, NULL);
/* length = pMblk->mBlkPktHdr.len;*/
/* netMblkToBufCopy (pMblk, (u_char*)(pTxBd->dataPointer), NULL);*/
/* netMblkClChainFree(pMblk); */
pTxBd->dataPointer = (u_char *) pBuf;
/* padding mechanism in Rev A is buggy - do in software */
if (length < FRAME_MIN)
{
pad = pTxBd->dataPointer + length;
for (; length != FRAME_MIN; length++, pad++)
*pad = 0x88;
}
pTxBd->dataLength = length;
oldLevel = intLock (); /* disable ints during update */
if (pTxBd->statusMode & SCC_ETHER_TX_BD_W)
{
pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD |
SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC |
SCC_ETHER_TX_BD_W | SCC_ETHER_TX_BD_R;
}
else
{
pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD |
SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC |
SCC_ETHER_TX_BD_R;
}
pDrvCtrl->freeRtn[pDrvCtrl->ether.txBdNext] = (FUNCPTR) netClFree;
pDrvCtrl->freeData[pDrvCtrl->ether.txBdNext].arg1 =
pDrvCtrl->endObject.pNetPool;
pDrvCtrl->freeData[pDrvCtrl->ether.txBdNext].arg2 = pBuf;
/* incr BD count */
pDrvCtrl->ether.txBdNext = (pDrvCtrl->ether.txBdNext + 1) %
pDrvCtrl->ether.txBdNum;
/* Unlock interrupts */
intUnlock (oldLevel);
/* release semaphore */
END_TX_SEM_GIVE (&pDrvCtrl->endObject);
/* Bump the statistic counter. */
netMblkClChainFree(pMblk);
END_ERR_ADD (&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1);
if(send6==1)
MOTCPMLOGMSG(("motCpmEndSend_Over \n", 0, 0, 0, 0, 0, 0));
return (OK);
}
/*******************************************************************************
*
* motCpmEndIoctl - network interface control routine
*
* This routine implements the network interface control functions.
* It handles EIOCSIFADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS,
* EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2 and EIOCGFBUF commands.
*
* RETURNS: OK if successful, otherwise EINVAL.
*/
LOCAL int motCpmEndIoctl
(
END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */
int cmd, /* command to process */
caddr_t data /* pointer to data */
)
{
int error = 0; /* error value */
long value;
END_OBJ * pEndObj = &pDrvCtrl->endObject;
MOTCPMLOGMSG(("motCpmEndIoctl with command = 0x%x \n", cmd, 0, 0, 0, 0, 0));
switch (cmd)
{
case EIOCSADDR:
if (data == NULL)
error = EINVAL;
bcopy ((char *)data, (char *)END_HADDR(pEndObj),
END_HADDR_LEN(pEndObj));
break;
case EIOCGADDR:
if (data == NULL)
error = EINVAL;
else
bcopy ((char *)END_HADDR(pEndObj), (char *)data,
END_HADDR_LEN(pEndObj));
break;
case EIOCSFLAGS:
value = (long) data;
if (value < 0)
{
value = -value;
value--;
END_FLAGS_CLR (pEndObj, value);
}
else
END_FLAGS_SET (pEndObj, value);
/* set promisc bit off flags */
if (END_FLAGS_GET(pEndObj) & IFF_PROMISC)
pDrvCtrl->ether.pSccReg->psmr |= SCC_ETHER_PSMR_PRO;
else
pDrvCtrl->ether.pSccReg->psmr &= ~SCC_ETHER_PSMR_PRO;
break;
case EIOCGFLAGS:
if (data == NULL)
error = EINVAL;
else
*(int *)data = END_FLAGS_GET(pEndObj);
break;
case EIOCPOLLSTART:
error = motCpmEndPollStart (pDrvCtrl);
break;
case EIOCPOLLSTOP:
error = motCpmEndPollStop (pDrvCtrl);
break;
case EIOCGMIB2:
if (data == NULL)
error = EINVAL;
else
bcopy((char *)&pDrvCtrl->endObject.mib2Tbl, (char *)data,
sizeof(pDrvCtrl->endObject.mib2Tbl));
break;
case EIOCGFBUF:
if (data == NULL)
error = EINVAL;
else
*(int *)data = LENGTH_MIN_FBUF;
break;
default:
error = EINVAL;
}
return (error);
}
/*******************************************************************************
*
* motCpmEndMCastAddrAdd - add a multicast address for the device
*
* This routine adds a multicast address to whatever the driver
* is already listening for.
*
* To add an address in the processor group address hash filter, we use
* the SET GROUP ADDRESS command. This command can be executed at any
* time, regadless of whether the Ethernet channel is enabled.
*
* RETURNS : OK or ERROR
*/
LOCAL STATUS motCpmEndMCastAddrAdd
(
END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */
char * pAddr /* Address to add to the table. */
)
{
STATUS error;
MOTCPMLOGMSG(("motCpmEndMCastAddrAdd %x:%x:%x:%x:%x:%x \n",
pAddr[5], pAddr[4], pAddr[3],
pAddr[2], pAddr[1], pAddr[0]));
error = etherMultiAdd (&pDrvCtrl->endObject.multiList, pAddr);
if (error == ENETRESET)
{
pDrvCtrl->endObject.nMulti++;
/* Set the multicast address */
motCpmMCastFilterSet (pDrvCtrl, pAddr);
error = OK;
}
return ((error == OK) ? OK : ERROR);
}
/*******************************************************************************
*
* motCpmEndMCastAddrDel - delete a multicast address for the device
*
* This routine deletes a multicast address from the current list of
* multicast addresses.
*
* RETURNS : OK or ERROR
*/
LOCAL STATUS motCpmEndMCastAddrDel
(
END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */
char * pAddr /* Address to delete from the table. */
)
{
STATUS error;
MOTCPMLOGMSG(("motCpmEndMCastDel %x:%x:%x:%x:%x:%x \n",
pAddr[5], pAddr[4], pAddr[3],
pAddr[2], pAddr[1], pAddr[0]));
error = etherMultiDel (&pDrvCtrl->endObject.multiList, pAddr);
if (error == ENETRESET)
{
pDrvCtrl->endObject.nMulti--;
motCpmMCastConfig (pDrvCtrl);
error = OK;
}
return ((error == OK) ? OK : ERROR);
}
/*******************************************************************************
*
* motCpmEndMCastAddrGet - get the current multicast address list
*
* This routine returns the current multicast address list in <pTable>
*
*/
LOCAL STATUS motCpmEndMCastAddrGet
(
END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */
MULTI_TABLE *pTable /* table to fill in with addresses */
)
{
MOTCPMLOGMSG(("motCpmEndMCastAddrGet \n", 0, 0, 0, 0, 0, 0));
return (etherMultiGet (&pDrvCtrl->endObject.multiList, pTable));
}
/*******************************************************************************
*
* motCpmEndPollStart - start polling mode
*
* This routine starts polling mode by disabling ethernet interrupts and
* setting the polling flag in the END_CTRL stucture.
*
* It is necessary to empty transmit queue before entering polling mode
* because M_BLK_ID free routine used in interrupt mode could be unusable
* in this mode (could use kernel calls).
*
* RETURNS: OK or ERROR if already in polling mode.
*/
LOCAL STATUS motCpmEndPollStart
(
END_CTRL *pDrvCtrl /* pointer to END_CTRL structure */
)
{
int intLevel;
int txBdIndex;
SCC_BUF * pTxBd;
MOTCPMLOGMSG(("motCpmEndPollStart \n", 0, 0, 0, 0, 0, 0));
/* Lock interrupts */
intLevel = intLock();
/* clean transmit queue */
txBdIndex = pDrvCtrl->txBdIndexC;
while (txBdIndex != pDrvCtrl->ether.txBdNext)
{
pTxBd = & pDrvCtrl->ether.txBdBase[txBdIndex];
/* Spin until frame buffer is sent */
while (pTxBd->statusMode & SCC_ETHER_TX_BD_R)
;
/* Check for transmit errors */
if (pTxBd->statusMode & (SCC_ETHER_TX_BD_RL | SCC_ETHER_TX_BD_UN |
SCC_ETHER_TX_BD_CSL | SCC_ETHER_TX_BD_LC))
{
/* An error has occured, restart the transmitter */
pDrvCtrl->txStop = TRUE;
motCpmTxRestart (pDrvCtrl);
}
/* increment txBdIndex */
txBdIndex = (txBdIndex + 1) % pDrvCtrl->ether.txBdNum;
}
/* free all transmit buffer and update transmit queue */
motCpmCleanTxBdQueue (pDrvCtrl);
/* Now, transmit queue is empty. We can enter polling mode. */
/* mask off the receive and transmit interrupts */
pDrvCtrl->ether.pSccReg->sccm = 0;
/* Set the polling flag */
pDrvCtrl->polling = TRUE;
/* Unlock interrupts */
intUnlock (intLevel);
return (OK);
}
/*******************************************************************************
*
* motCpmEndPollStop - stop polling mode
*
* This routine stops polling mode by enabling ethernet interrupts and
* resetting the polling flag in the END_CTRL structure.
*
* RETURNS: OK always
*/
LOCAL STATUS motCpmEndPollStop
(
END_CTRL *pDrvCtrl /* pointer to END_CTRL structure */
)
{
int intLevel;
MOTCPMLOGMSG(("motCpmEndPollStop \n", 0, 0, 0, 0, 0, 0));
/* lock interrupt */
intLevel = intLock();
/* reset the SCC's interrupt status bit */
*CPM_CISR(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask;
/* enable this SCC's interrupt */
*CPM_CIMR(pDrvCtrl->regBase) |= pDrvCtrl->ether.intMask;
/* reset the status bits */
pDrvCtrl->ether.pSccReg->scce = 0xffff;
/* enables the receive and transmit interrupts */
pDrvCtrl->ether.pSccReg->sccm = SCC_ETHER_SCCX_RXF | SCC_ETHER_SCCX_TXE |
SCC_ETHER_SCCX_TXB;
/* reset the polling flag */
pDrvCtrl->polling = FALSE;
/* unlock interrupt */
intUnlock (intLevel);
return (OK);
}
/******************************************************************************
*
* motCpmEndPollSend - transmit a packet in polled mode
*
* This routine is called by a user to try and send a packet on the
* device. It sends a packet directly on the network from the caller without
* going through the normal processes of queuing a pacet on an output queue
* and the waiting for the device to decide to transmit it.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -