📄 ethernet.c
字号:
oldLevel = intLock (); /* disable ints during update */
intDisable (pDrvCtrl->ivecBdmaTx);
intDisable (pDrvCtrl->ivecBdmaRx);
intDisable (pDrvCtrl->ivecMacTx);
intDisable (pDrvCtrl->ivecMacRx);
pDrvCtrl->flags |= LS_POLLING;
intUnlock (oldLevel); /* now sndsEndInt won't get confused */
ENDLOGMSG (("STARTED\n", 1, 2, 3, 4, 5, 6));
sndsEndConfig (pDrvCtrl); /* reconfigure device */
/* Enable RX in BDMARXCON register */
*(UINT32 *) (&bdmaRxCon) = *(UINT32 *)SNDS_BDMARXCON;
bdmaRxCon.rxCon_reg.enable = 1 ;
*(UINT32 *)SNDS_BDMARXCON = bdmaRxCon.rxCon_resetval;
/* Enable RX in MACRXCON register */
*(UINT32 *)(&macRxCon) = *(UINT32 *)SNDS_MACRXCON;
macRxCon.macRxCon_reg.receiveEnable = 1;
*(UINT32 *)SNDS_MACRXCON = macRxCon.macRxCon_resetval;
/* Set the flags to indicate that the device is up */
END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
return (OK);
}
/*******************************************************************************
*
* sndsEndPollStop - 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 sndsEndPollStop
(
END_DEVICE* pDrvCtrl /* device to be changed */
)
{
BDMARXCON bdmaRxCon;
BDMATXCON bdmaTxCon;
MACCON macCon;
int oldLevel;
*(UINT32 *)(&bdmaRxCon) = *(UINT32 *)SNDS_BDMARXCON;
bdmaRxCon.rxCon_reg.enable = 0;
*(UINT32 *)SNDS_BDMARXCON = *(UINT32 *)(&bdmaRxCon);
*(UINT32 *)(&bdmaTxCon) = *(UINT32 *)SNDS_BDMATXCON;
bdmaTxCon.txCon_reg.enable = 0;
*(UINT32 *)SNDS_BDMATXCON = *(UINT32 *)(&bdmaTxCon);
*(UINT32 *)(&macCon) = *(UINT32 *)SNDS_MACCON;
macCon.macCon_reg.haltImm = 1;
*(UINT32 *)SNDS_MACCON = *(UINT32 *)(&macCon);
oldLevel = intLock (); /* disable ints during register updates */
pDrvCtrl->flags &= ~LS_POLLING;
intUnlock (oldLevel);
/*
* Restart in interrupt mode. Calling sndsEndConfig without clearing
* IFF_RUNNING flag will result in calling sndsEndStart automatically
*/
sndsEndConfig (pDrvCtrl);
ENDLOGMSG (("STOPPED\n", 1, 2, 3, 4, 5, 6));
return (OK);
}
/*******************************************************************************
*
* sndsEndPollRcv - 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 sndsEndPollRcv
(
END_DEVICE *pDrvCtrl, /* device to be polled */
M_BLK_ID pMblk /* ptr to buffer */
)
{
BDMASTAT bdmaStat;
char* pPacket;
int len;
STATUS retVal = EAGAIN;
#ifdef ENDDEBUG
if (endDebug)
nvLogMsg ("sndsEndPollRcv\n", 1, 2, 3, 4, 5, 6);
#endif /* ENDDEBUG */
bdmaStat.stat_resetval = *(UINT32 *)SNDS_BDMASTAT;
if (bdmaStat.stat_reg.bdmaRxDoneEveryRxFrame == 0)
return retVal;
/* Reset the status nit */
*(UINT32 *)SNDS_BDMASTAT = bdmaStat.stat_resetval;
if (gpReceiveFrameDescStart->rxStatusLength.good == 0)
goto pollRcvExit;
/* Upper layer must provide a valid buffer. */
len = gpReceiveFrameDescStart->rxStatusLength.frameLength;
if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
goto pollRcvExit;
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
pPacket = (char *)gpReceiveFrameDescStart->rxFrameData.frameDataPtr;
bcopy (pPacket, pMblk->m_data, len);
pMblk->m_len = len;
pMblk->mBlkHdr.mData += SNDS_DATA_OFFSET;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = len;
retVal = OK;
#ifdef ENDDEBUG
if (endDebug)
nvLogMsg ("sndsEndPollRcv OK\n", 1, 2, 3, 4, 5, 6);
#endif /* ENDDEBUG */
pollRcvExit:
gpReceiveFrameDescStart->rxFrameData.o_bit = 1; /* Ownership back to BDMA */
*(UINT32 *)(&gpReceiveFrameDescStart->rxStatusLength) = 0; /* Rx status length field */
gpReceiveFrameDescStart = gpReceiveFrameDescStart->nextRxFrameDesc;
return retVal;
}
/*******************************************************************************
*
* sndsEndPollSend - 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 sndsEndPollSend
(
END_DEVICE* pDrvCtrl, /* device to be polled */
M_BLK_ID pMblk /* packet to send */
)
{
TRANSMIT_FRAME_DESC *pTxFd;
BDMATXCON bdmaTxCon;
MACTXCON macTxCon;
int len;
#ifdef ENDDEBUG
if (endDebug)
nvLogMsg ("sndsEndPollSend\n", 1, 2, 3, 4, 5, 6);
#endif /* ENDDEBUG */
if (gpTransmitFrameDescStart->txFrameData.o_bit) /* Ownership with BDMA? */
return EAGAIN;
pTxFd = gpTransmitFrameDescStart;
len = pMblk->mBlkPktHdr.len;
/* Set pointers in local structures to point to data. */
netMblkToBufCopy(pMblk, (void *)pTxFd->txFrameData.frameDataPtr, NULL) ;
*(UINT32 *)(&pTxFd->txControl) = 0; /* Reset control word */
pTxFd->txControl.t_bit = 1;
pTxFd->txControl.a_bit = 1;
pTxFd->txControl.l_bit = 1;
pTxFd->txStatusLength.frameLength = len;
pTxFd->txFrameData.o_bit = 1;
/* initiate device transmit */
bdmaTxCon.txCon_resetval = *(UINT32 *)SNDS_BDMATXCON;
bdmaTxCon.txCon_reg.enable = 1;
*(UINT32 *)SNDS_BDMATXCON = bdmaTxCon.txCon_resetval;
macTxCon.macTxCon_resetval = *(UINT32 *)SNDS_MACTXCON;
macTxCon.macTxCon_reg.transmitEnable = 1;
*(UINT32 *)SNDS_MACTXCON = macTxCon.macTxCon_resetval;
/* Bump the statistic counter. */
END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
/* Advance our management index */
gpTransmitFrameDescStart = gpTransmitFrameDescStart->nextTxFrameDesc;
/*
* 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.
*/
netMblkClChainFree (pMblk);
#ifdef ENDDEBUG
if (endDebug)
nvLogMsg ("leaving sndsEndPollSend\n", 1, 2, 3, 4, 5, 6);
#endif /* ENDDEBUG */
return (OK);
}
/******************************************************************************
*
* sndsEndAddrFilterSet - 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 sndsEndAddrFilterSet
(
END_DEVICE *pDrvCtrl /* device to be updated */
)
{
ETHER_MULTI* pCurr;
UINT32 count;
UCHAR *pAddr;
for (count = 0; count < 32; count++)
pDrvCtrl->addrList[count] = 0; /* Zero the addresses */
pDrvCtrl->mcastAddrCount = 0; /* Init the multi count */
pAddr = (UCHAR *)(&pDrvCtrl->addrList[0]);
pAddr += 6; /* Leave first 6 bytes for our MAC address */
pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);
/*
* Now copy the addresses from ether_multi_list to our own array. In our
* array, the first 6 bytes are for our own MAC address. This array is
* an exact replica of the internal CAM registers of Ethernet controller.
* The CAM registers will be updated in sndsEndMacInitialize() function
*/
while (pCurr != NULL)
{
if (pDrvCtrl->mcastAddrCount > SNDS_MAX_MULTI)
break;
if (!(pDrvCtrl->mcastAddrCount & 0x01))
{
pAddr -= 2;
/* The address has to be stored in a swapped fashion! */
*(UINT16 *)pAddr = htons (*(UINT16 *)pCurr->addr);
pAddr += 4;
*(UINT16 *)pAddr = htons (*(UINT16 *)(pCurr->addr+4));
pAddr += 2;
*(UINT16 *)pAddr = htons (*(UINT16 *)(pCurr->addr+2));
}
else
{
pAddr += 2;
/* The address has to be stored in a swapped fashion! */
*(UINT16 *)pAddr = htons (*(UINT16 *)(pCurr->addr+2));
pAddr += 2;
*(UINT16 *)pAddr = htons (*(UINT16 *)pCurr->addr);
pAddr += 4;
*(UINT16 *)pAddr = htons (*(UINT16 *)(pCurr->addr+4));
}
pDrvCtrl->mcastAddrCount++; /* Bump the multicast address count */
pCurr = END_MULTI_LST_NEXT(pCurr); /* Get the next address in the list */
}
}
/*****************************************************************************
*
* sndsEndMCastAdd - 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 sndsEndMCastAdd
(
END_DEVICE *pDrvCtrl, /* device pointer */
char* pAddress /* new address to add */
)
{
int error;
if ((error = etherMultiAdd (&pDrvCtrl->end.multiList,
pAddress)) == ENETRESET)
sndsEndConfig (pDrvCtrl);
return (OK);
}
/*****************************************************************************
*
* sndsEndMCastDel - 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.
*/
LOCAL STATUS sndsEndMCastDel
(
END_DEVICE* pDrvCtrl, /* device pointer */
char* pAddress /* address to be deleted */
)
{
int error;
if ((error = etherMultiDel (&pDrvCtrl->end.multiList,
(char *)pAddress)) == ENETRESET)
sndsEndConfig (pDrvCtrl);
return (OK);
}
/*****************************************************************************
*
* sndsEndMCastGet - 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 sndsEndMCastGet
(
END_DEVICE* pDrvCtrl, /* device pointer */
MULTI_TABLE* pTable /* address table to be filled in */
)
{
int error;
error = etherMultiGet (&pDrvCtrl->end.multiList, pTable);
return (error);
}
/*******************************************************************************
*
* sndsEndStop - 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 sndsEndStop
(
END_DEVICE *pDrvCtrl /* device to be stopped */
)
{
STATUS result = OK;
BDMARXCON bdmaRxCon;
BDMATXCON bdmaTxCon;
MACCON macCon;
*(UINT32 *)(&bdmaRxCon) = *(UINT32 *)SNDS_BDMARXCON;
bdmaRxCon.rxCon_reg.enable = 0;
*(UINT32 *)SNDS_BDMARXCON = *(UINT32 *)(&bdmaRxCon);
*(UINT32 *)(&bdmaTxCon) = *(UINT32 *)SNDS_BDMATXCON;
bdmaTxCon.txCon_reg.enable = 0;
*(UINT32 *)SNDS_BDMATXCON = *(UINT32 *)(&bdmaTxCon);
*(UINT32 *)(&macCon) = *(UINT32 *)SNDS_MACCON;
macCon.macCon_reg.haltImm = 1;
*(UINT32 *)SNDS_MACCON = *(UINT32 *)(&macCon);
intDisable (pDrvCtrl->ivecBdmaTx);
intDisable (pDrvCtrl->ivecBdmaRx);
intDisable (pDrvCtrl->ivecMacTx);
intDisable (pDrvCtrl->ivecMacRx);
END_FLAGS_CLR (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
return (result);
}
/******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -