📄 ethernet.c
字号:
//
// Check the arguments.
//
ASSERT(ulBase == ETH_BASE);
//
// Read the unmasked status.
//
ulStatus = HWREG(ulBase + MAC_O_IS);
//
// If masked status is requested, mask it off.
//
if(bMasked)
{
ulStatus &= HWREG(ulBase + MAC_O_IM);
}
//
// Return the interrupt status value.
//
return(ulStatus);
}
//*****************************************************************************
//
//! Clears Ethernet interrupt sources.
//!
//! \param ulBase is the base address of the controller.
//! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
//!
//! The specified Ethernet interrupt sources are cleared, so that they no
//! longer assert. This must be done in the interrupt handler to keep it from
//! being called again immediately upon exit.
//!
//! The parameter \e ulIntFlags has the same definition as the same parameter
//! to EthernetIntEnable().
//!
//! \return None.
//
//*****************************************************************************
void
EthernetIntClear(unsigned long ulBase, unsigned long ulIntFlags)
{
//
// Check the arguments.
//
ASSERT(ulBase == ETH_BASE);
ASSERT(ulIntFlags & ~(ETH_INT_PHY | ETH_INT_MDIO | ETH_INT_RXER |
ETH_INT_RXOF | ETH_INT_TX | ETH_INT_TXER | ETH_INT_RX));
//
// Clear the requested interrupt sources.
//
HWREG(ulBase + MAC_O_IACK) = ulIntFlags;
}
//*****************************************************************************
//
//! Write to the PHY register.
//!
//! \param ulBase is the base address of the controller.
//! \param ucRegAddr is the address of the PHY register to be accessed.
//! \param ulData is the data to be written to the PHY register.
//!
//! This function will write the \e ulData to the PHY register specified by
//! \e ucRegAddr.
//!
//! \return None.
//
//*****************************************************************************
void
EthernetPHYWrite(unsigned long ulBase, unsigned char ucRegAddr,
unsigned long ulData)
{
//
// Check the arguments.
//
ASSERT(ulBase == ETH_BASE);
//
// Wait for any pending transaction to complete.
//
while(HWREG(ulBase + MAC_O_MCTL) & MAC_MCTL_START)
{
}
//
// Program the DATA to be written.
//
HWREG(ulBase + MAC_O_MTXD) = ulData & MAC_MTXD_MDTX;
//
// Program the PHY register address and initiate the transaction.
//
HWREG(ulBase + MAC_O_MCTL) = ((ucRegAddr << 3) & MAC_MCTL_REGADR) |
MAC_MCTL_WRITE | MAC_MCTL_START;
//
// Wait for the write transaction to complete.
//
while(HWREG(ulBase + MAC_O_MCTL) & MAC_MCTL_START)
{
}
}
//*****************************************************************************
//
//! Read from a PHY register.
//!
//! \param ulBase is the base address of the controller.
//! \param ucRegAddr is the address of the PHY register to be accessed.
//!
//! This function will the contents of the PHY register specified by
//! \e ucRegAddr.
//!
//! \return The function will return the 16-bit value read from the PHY.
//
//*****************************************************************************
unsigned long
EthernetPHYRead(unsigned long ulBase, unsigned char ucRegAddr)
{
//
// Check the arguments.
//
ASSERT(ulBase == ETH_BASE);
//
// Wait for any pending transaction to complete.
//
while(HWREG(ulBase + MAC_O_MCTL) & MAC_MCTL_START)
{
}
//
// Program the PHY register address and initiate the transaction.
//
HWREG(ulBase + MAC_O_MCTL) = ((ucRegAddr << 3) & MAC_MCTL_REGADR) |
MAC_MCTL_START;
//
// Wait for the transaction to complete.
//
while(HWREG(ulBase + MAC_O_MCTL) & MAC_MCTL_START)
{
}
//
// Return the PHY data that was read.
//
return(HWREG(ulBase + MAC_O_MRXD) & MAC_MRXD_MDRX);
}
//*****************************************************************************
//
//! \internal
//!
//! Internal function for reading a packet from the Ethernet Controller.
//!
//! \param ulBase is the base address of the controller.
//! \param pucBuf is the pointer to the packet buffer.
//! \param lBufLen is the maximum number of bytes to be read into the buffer.
//!
//! Based on the following table of how the receive frame is stored in the
//! receive FIFO, this function will extract a packet from the FIFO and store
//! it in the packet buffer that was passed in.
//!
//! Format of the data in the RX FIFO is as follows:
//!
//! \verbatim
//! +---------+----------+----------+----------+----------+
//! | | 31:24 | 23:16 | 15:8 | 7:0 |
//! +---------+----------+----------+----------+----------+
//! | Word 0 | DA 2 | DA 1 | FL MSB | FL LSB |
//! +---------+----------+----------+----------+----------+
//! | Word 1 | DA 6 | DA 5 | DA 4 | DA 3 |
//! +---------+----------+----------+----------+----------+
//! | Word 2 | SA 4 | SA 3 | SA 2 | SA 1 |
//! +---------+----------+----------+----------+----------+
//! | Word 3 | FT LSB | FT MSB | SA 6 | SA 5 |
//! +---------+----------+----------+----------+----------+
//! | Word 4 | DATA 4 | DATA 3 | DATA 2 | DATA 1 |
//! +---------+----------+----------+----------+----------+
//! | Word 5 | DATA 8 | DATA 7 | DATA 6 | DATA 5 |
//! +---------+----------+----------+----------+----------+
//! | Word 6 | DATA 12 | DATA 11 | DATA 10 | DATA 9 |
//! +---------+----------+----------+----------+----------+
//! | ... | | | | |
//! +---------+----------+----------+----------+----------+
//! | Word X | DATA n | DATA n-1 | DATA n-2 | DATA n-3 |
//! +---------+----------+----------+----------+----------+
//! | Word Y | FCS 4 | FCS 3 | FCS 2 | FCS 1 |
//! +---------+----------+----------+----------+----------+
//! \endverbatim
//!
//! Where FL is Frame Length, (FL + DA + SA + FT + DATA + FCS) Bytes.
//! Where DA is Destination (MAC) Address.
//! Where SA is Source (MAC) Address.
//! Where FT is Frame Type (or Frame Length for Ethernet).
//! Where DATA is Payload Data for the Ethernet Frame.
//! Where FCS is the Frame Check Sequence.
//!
//! \return If the packet is too large for \e pucBuf, the function will return
//! the negated length \b -n. Otherwise, the function will return the length
//! \b n of the received packet.
//
//*****************************************************************************
static long
EthernetInternalGetPacket(unsigned long ulBase, unsigned char *pucBuf,
long lBufLen)
{
unsigned long ulTemp;
long lFrameLen, lTempLen;
short i = 0;
unsigned char *pucTemp = (unsigned char *)&ulTemp;
//
// Read WORD 0 (see format above) from the FIFO, set the receive
// Frame Length and store the first two bytes of the destination
// address in the receive buffer.
//
ulTemp = HWREG(ulBase + MAC_O_DATA);
lFrameLen = (long)(ulTemp & 0xFFFF);
pucBuf[i++] = pucTemp[2];
pucBuf[i++] = pucTemp[3];
//
// Read all but the last WORD into the receive buffer.
//
lTempLen = (lBufLen < (lFrameLen - 6)) ? lBufLen : (lFrameLen - 6) ;
while(i <= (lTempLen - 4))
{
ulTemp = HWREG(ulBase + MAC_O_DATA);
pucBuf[i++] = pucTemp[0];
pucBuf[i++] = pucTemp[1];
pucBuf[i++] = pucTemp[2];
pucBuf[i++] = pucTemp[3];
}
//
// Read the last 1, 2, or 3 BYTES into the buffer
//
if(i < lTempLen)
{
ulTemp = HWREG(ulBase + MAC_O_DATA);
if(i == lTempLen - 3)
{
pucBuf[i++] = pucTemp[0];
pucBuf[i++] = pucTemp[1];
pucBuf[i++] = pucTemp[2];
i += 1;
}
else if(i == lTempLen - 2)
{
pucBuf[i++] = pucTemp[0];
pucBuf[i++] = pucTemp[1];
i += 2;
}
else if(i == lTempLen - 1)
{
pucBuf[i++] = pucTemp[0];
i += 3;
}
}
//
// Read any remaining WORDS (that did not fit into the buffer).
//
while(i < (lFrameLen - 2))
{
ulTemp = HWREG(ulBase + MAC_O_DATA);
i += 4;
}
//
// If frame was larger than the buffer, return the "negative" frame length
//
lFrameLen -= 6;
if(lFrameLen > lBufLen)
{
return(-(lFrameLen));
}
//
// Return the Frame Length
//
return(lFrameLen);
}
//*****************************************************************************
//
//! \internal
//!
//! Internal function for sending a packet to the Ethernet Controller.
//
//! \param ulBase is the base address of the controller.
//! \param pucBuf is the pointer to the packet buffer.
//! \param lBufLen is number of bytes in the packet to be transmitted.
//!
//! Puts a packet into the transmit FIFO of the controller.
//!
//! Format of the data in the TX FIFO is as follows:
//!
//! \verbatim
//! +---------+----------+----------+----------+----------+
//! | | 31:24 | 23:16 | 15:8 | 7:0 |
//! +---------+----------+----------+----------+----------+
//! | Word 0 | DA 2 | DA 1 | PL MSB | PL LSB |
//! +---------+----------+----------+----------+----------+
//! | Word 1 | DA 6 | DA 5 | DA 4 | DA 3 |
//! +---------+----------+----------+----------+----------+
//! | Word 2 | SA 4 | SA 3 | SA 2 | SA 1 |
//! +---------+----------+----------+----------+----------+
//! | Word 3 | FT LSB | FT MSB | SA 6 | SA 5 |
//! +---------+----------+----------+----------+----------+
//! | Word 4 | DATA 4 | DATA 3 | DATA 2 | DATA 1 |
//! +---------+----------+----------+----------+----------+
//! | Word 5 | DATA 8 | DATA 7 | DATA 6 | DATA 5 |
//! +---------+----------+----------+----------+----------+
//! | Word 6 | DATA 12 | DATA 11 | DATA 10 | DATA 9 |
//! +---------+----------+----------+----------+----------+
//! | ... | | | | |
//! +---------+----------+----------+----------+----------+
//! | Word X | DATA n | DATA n-1 | DATA n-2 | DATA n-3 |
//! +---------+----------+----------+----------+----------+
//! \endverbatim
//!
//! Where PL is Payload Length, (DATA) only
//! Where DA is Destination (MAC) Address
//! Where SA is Source (MAC) Address
//! Where FT is Frame Type (or Frame Length for Ethernet)
//! Where DATA is Payload Data for the Ethernet Frame
//!
//! \return If the packet is too large for FIFO, the function will return the
//! negated length \b -lBufLen. Otherwise, the function will return the length
//! \b lBufLen of the transmitted packet.
//
//*****************************************************************************
static long
EthernetInternalPutPacket(unsigned long ulBase, unsigned char *pucBuf,
long lBufLen)
{
unsigned long ulTemp;
short i = 0;
unsigned char *pucTemp = (unsigned char *)&ulTemp;
//
// If the packet is too large, return the negative packet length as
// an error code.
//
if(lBufLen > (2048 - 2))
{
return(-lBufLen);
}
//
// Build and write WORD 0 (see format above) to the transmit FIFO.
//
ulTemp = (unsigned long)(lBufLen - 14);
pucTemp[2] = pucBuf[i++];
pucTemp[3] = pucBuf[i++];
HWREG(ulBase + MAC_O_DATA) = ulTemp;
//
// Write each subsequent WORD n to the transmit FIFO, except for the last
// WORD (if the word does not contain 4 bytes).
//
while(i <= (lBufLen - 4))
{
pucTemp[0] = pucBuf[i++];
pucTemp[1] = pucBuf[i++];
pucTemp[2] = pucBuf[i++];
pucTemp[3] = pucBuf[i++];
HWREG(ulBase + MAC_O_DATA) = ulTemp;
}
//
// Build the last word of the remaining 1, 2, or 3 bytes, and store
// the WORD into the transmit FIFO.
//
if (i != lBufLen)
{
ulTemp = 0;
if(i == (lBufLen - 3))
{
pucTemp[0] = pucBuf[i++];
pucTemp[1] = pucBuf[i++];
pucTemp[2] = pucBuf[i++];
HWREG(ulBase + MAC_O_DATA) = ulTemp;
}
else if(i == (lBufLen - 2))
{
pucTemp[0] = pucBuf[i++];
pucTemp[1] = pucBuf[i++];
HWREG(ulBase + MAC_O_DATA) = ulTemp;
}
else if(i == (lBufLen - 1))
{
pucTemp[0] = pucBuf[i++];
HWREG(ulBase + MAC_O_DATA) = ulTemp;
}
}
//
// Activate the transmitter
//
HWREG(ulBase + MAC_O_TR) = MAC_TR_NEWTX;
//
// Return the Buffer Length transmitted.
//
return(lBufLen);
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -