📄 ethernet.c
字号:
//! otherwise.
//
//*****************************************************************************
tBoolean
EthernetPacketAvail(unsigned long ulBase)
{
//
// Check the arguments.
//
ASSERT(ulBase == ETH_BASE);
//
// Return the availability of packets.
//
return((HWREG(ulBase + MAC_O_NP) & MAC_NP_NPR_M) ? true : false);
}
//*****************************************************************************
//
//! Checks for packet space available in the Ethernet controller.
//!
//! \param ulBase is the base address of the controller.
//!
//! The Ethernet controller's transmit FIFO is designed to support a single
//! packet at a time. After the packet has been written into the FIFO, the
//! transmit request bit must be set to enable the transmission of the packet.
//! Only after the packet has been transmitted can a new packet be written
//! into the FIFO. This function will simply check to see if a packet is
//! in progress. If so, there is no space available in the transmit FIFO.
//!
//! \return Returns \b true if a space is available in the transmit FIFO, and
//! \b false otherwise.
//
//*****************************************************************************
tBoolean
EthernetSpaceAvail(unsigned long ulBase)
{
//
// Check the arguments.
//
ASSERT(ulBase == ETH_BASE);
//
// Return the availability of space.
//
return((HWREG(ulBase + MAC_O_TR) & MAC_TR_NEWTX) ? false : true);
}
//*****************************************************************************
//
//! \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 Returns the negated packet length \b -n if the packet is too large
//! for \e pucBuf, and returns the packet length \b n otherwise.
//
//*****************************************************************************
static long
EthernetPacketGetInternal(unsigned long ulBase, unsigned char *pucBuf,
long lBufLen)
{
unsigned long ulTemp;
long lFrameLen, lTempLen;
long i = 0;
//
// 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++] = (unsigned char) ((ulTemp >> 16) & 0xff);
pucBuf[i++] = (unsigned char) ((ulTemp >> 24) & 0xff);
//
// Read all but the last WORD into the receive buffer.
//
lTempLen = (lBufLen < (lFrameLen - 6)) ? lBufLen : (lFrameLen - 6);
while(i <= (lTempLen - 4))
{
*(unsigned long *)&pucBuf[i] = HWREG(ulBase + MAC_O_DATA);
i += 4;
}
//
// 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++] = ((ulTemp >> 0) & 0xff);
pucBuf[i++] = ((ulTemp >> 8) & 0xff);
pucBuf[i++] = ((ulTemp >> 16) & 0xff);
i += 1;
}
else if(i == lTempLen - 2)
{
pucBuf[i++] = ((ulTemp >> 0) & 0xff);
pucBuf[i++] = ((ulTemp >> 8) & 0xff);
i += 2;
}
else if(i == lTempLen - 1)
{
pucBuf[i++] = ((ulTemp >> 0) & 0xff);
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);
}
//*****************************************************************************
//
//! Receives 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.
//!
//! This function reads a packet from the receive FIFO of the controller and
//! places it into \e pucBuf. If no packet is available the function will
//! return immediately. Otherwise, the function will read the entire packet
//! from the receive FIFO. If there are more bytes in the packet than will fit
//! into \e pucBuf (as specified by \e lBufLen), the function will return the
//! negated length of the packet and the buffer will contain \e lBufLen bytes
//! of the packet. Otherwise, the function will return the length of the
//! packet that was read and \e pucBuf will contain the entire packet
//! (excluding the frame check sequence bytes).
//!
//! This function replaces the original EthernetPacketNonBlockingGet() API and
//! performs the same actions. A macro is provided in <tt>ethernet.h</tt> to
//! map the original API to this API.
//!
//! \note This function will return immediately if no packet is available.
//!
//! \return Returns \b 0 if no packet is available, the negated packet length
//! \b -n if the packet is too large for \e pucBuf, and the packet length \b n
//! otherwise.
//
//*****************************************************************************
long
EthernetPacketGetNonBlocking(unsigned long ulBase, unsigned char *pucBuf,
long lBufLen)
{
//
// Check the arguments.
//
ASSERT(ulBase == ETH_BASE);
ASSERT(pucBuf != 0);
ASSERT(lBufLen > 0);
//
// Check to see if any packets are available.
//
if((HWREG(ulBase + MAC_O_NP) & MAC_NP_NPR_M) == 0)
{
return(0);
}
//
// Read the packet, and return.
//
return(EthernetPacketGetInternal(ulBase, pucBuf, lBufLen));
}
//*****************************************************************************
//
//! Waits for 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.
//!
//! This function reads a packet from the receive FIFO of the controller and
//! places it into \e pucBuf. The function will wait until a packet is
//! available in the FIFO. Then the function will read the entire packet
//! from the receive FIFO. If there are more bytes in the packet than will
//! fit into \e pucBuf (as specified by \e lBufLen), the function will return
//! the negated length of the packet and the buffer will contain \e lBufLen
//! bytes of the packet. Otherwise, the function will return the length of
//! the packet that was read and \e pucBuf will contain the entire packet
//! (excluding the frame check sequence bytes).
//!
//! \note This function is blocking and will not return until a packet arrives.
//!
//! \return Returns the negated packet length \b -n if the packet is too large
//! for \e pucBuf, and returns the packet length \b n otherwise.
//
//*****************************************************************************
long
EthernetPacketGet(unsigned long ulBase, unsigned char *pucBuf,
long lBufLen)
{
//
// Check the arguments.
//
ASSERT(ulBase == ETH_BASE);
ASSERT(pucBuf != 0);
ASSERT(lBufLen > 0);
//
// Wait for a packet to become available
//
while((HWREG(ulBase + MAC_O_NP) & MAC_NP_NPR_M) == 0)
{
}
//
// Read the packet
//
return(EthernetPacketGetInternal(ulBase, pucBuf, lBufLen));
}
//*****************************************************************************
//
//! \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 Returns the negated packet length \b -lBufLen if the packet is too
//! large for FIFO, and the packet length \b lBufLen otherwise.
//
//*****************************************************************************
static long
EthernetPacketPutInternal(unsigned long ulBase, unsigned char *pucBuf,
long lBufLen)
{
unsigned long ulTemp;
long i = 0;
//
// 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);
ulTemp |= (pucBuf[i++] << 16);
ulTemp |= (pucBuf[i++] << 24);
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))
{
HWREG(ulBase + MAC_O_DATA) = *(unsigned long *)&pucBuf[i];
i += 4;
}
//
// Build the last word of the remaining 1, 2, or 3 bytes, and store
// the WORD into the transmit FIFO.
//
if(i != lBufLen)
{
if(i == (lBufLen - 3))
{
ulTemp = (pucBuf[i++] << 0);
ulTemp |= (pucBuf[i++] << 8);
ulTemp |= (pucBuf[i++] << 16);
HWREG(ulBase + MAC_O_DATA) = ulTemp;
}
else if(i == (lBufLen - 2))
{
ulTemp = (pucBuf[i++] << 0);
ulTemp |= (pucBuf[i++] << 8);
HWREG(ulBase + MAC_O_DATA) = ulTemp;
}
else if(i == (lBufLen - 1))
{
ulTemp = (pucBuf[i++] << 0);
HWREG(ulBase + MAC_O_DATA) = ulTemp;
}
}
//
// Activate the transmitter
//
HWREG(ulBase + MAC_O_TR) = MAC_TR_NEWTX;
//
// Return the Buffer Length transmitted.
//
return(lBufLen);
}
//*****************************************************************************
//
//! Sends 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.
//!
//! This function writes \e lBufLen bytes of the packet contained in \e pucBuf
//! into the transmit FIFO of the controller and then activates the
//! transmitter for this packet. If no space is available in the FIFO, the
//! function will return immediately. If space is available, the
//! function will return once \e lBufLen bytes of the packet have been placed
//! into the FIFO and the transmitter has been started. The function will not
//! wait for the transmission to complete. The function will return the
//! negated \e lBufLen if the length is larger than the space available in
//! the transmit FIFO.
//!
//! This function replaces the original EthernetPacketNonBlockingPut() API and
//! performs the same actions. A macro is provided in <tt>ethernet.h</tt> to
//! map the original API to this API.
//!
//! \note This function does not block and will return immediately if no space
//! is available for the transmit packet.
//!
//! \return Returns \b 0 if no space is available in the transmit FIFO, the
//! negated packet length \b -lBufLen if the packet is too large for FIFO, and
//! the packet length \b lBufLen otherwise.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -