if_mcf5272.c
来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,887 行 · 第 1/5 页
C
1,887 行
}while(1);
/* Set the R bit in the first buffer descriptor to indicate that the */
/* buffer is ready for transmission if there are more than one buffer */
/* descriptors. */
if (sg_len > 1)
first_bd->status |= TX_BD_R;
/* Indicate that there is a transmit buffer ready. */
put_reg(MCF5272_SIM->enet.tdar, 1);
}
/* This function is called as a result of the "eth_drv_recv()" call */
/* above. It's job is to actually fetch data for a packet from the */
/* hardware once memory buffers have been allocated for the packet. Note */
/* that the buffers may come in pieces, using a scatter-gather list. This */
/* allows for more efficient processing in the upper layers of the stack. */
/* Note that the total buffer allocated for the scatter-gather list */
/* can be smaller than the packet or the buffer that in the scatter gather */
/* list is invalid. This happens when the upper layer driver runs out of */
/* buffers for the scatter-gather list. */
static void
MCF5272_fec_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
{
uint_t fill_count = 0, buf_count;
uint_t frame_length = 0, buf_len;
NBUF *pNbuf = NULL;
cyg_uint8* buf = NULL;
cyg_bool_t done = false;
uint_t sg_index = 0;
/* If the scatter-gather list is zero, set buf to NULL so that this */
/* routine would not copy the buffer to the scatter-gatther buffer. */
if (sg_len > 0)
{
buf = (cyg_uint8*)sg_list[0].buf;
}
do
{
/* Get the next buffer descriptor (bd). */
pNbuf = nbuf_rx_get_next(PBUF_INFO(sc));
CYG_ASSERT(pNbuf != NULL, "Cannot get the next bd");
if (pNbuf->status & TX_BD_L)
{
/* Calculate the remaining numer of bytes in the packet that */
/* needed to be copied out since the the length of the in the */
/* last BD contains the total length of the packet and not the */
/* length of the buffer. */
buf_len = (uint_t)pNbuf->length - frame_length;
/* Since the last bd, set done to true in order to exit the */
/* loop. */
done = true;
}
else
{
buf_len = RX_BUFFER_SIZE;
/* Update the frame length. */
frame_length += RX_BUFFER_SIZE;
}
/* Copy the packet to the scatter gather list if there is a buffer */
/* to copy the packet to. */
for (buf_count = 0; buf_count < buf_len && buf != NULL;)
{
uint_t copy_len;
/* Retrieve the minimum copy length. We basically copy based */
/* on the smaller size: the buffer from the scatther list or the */
/* from the buffer descriptor. */
copy_len = (((uint_t)sg_list[sg_index].len - fill_count) <
(buf_len - buf_count) ?
(uint_t)sg_list[sg_index].len - fill_count :
(buf_len - buf_count));
/* Copy the buffer to the upper layer driver buffer. */
memcpy(&buf[fill_count],
&pNbuf->data[buf_count],
copy_len);
/* Update the counts to reflect the number of bytes copied. */
fill_count += copy_len;
buf_count += copy_len;
/* If the buffer in the scatter-gather list is full, we */
/* attempt to retrieve the next buffer in the list. */
if (fill_count >= sg_list[sg_index].len)
{
/* If there is no more buffer, set the buf to NULL and */
/* exit the loop. */
if (++sg_index >= sg_len)
{
buf = NULL;
break;
}
else
{
buf = (cyg_uint8*)sg_list[sg_index].buf;
fill_count = 0;
}
}
}
/* Release the buffer scriotor so it cab be used to receive other */
/* packets. */
nbuf_rx_release(pNbuf);
}while(done == false);
/* Notify the FEC that there are receive buffer descriptors available */
/* for the FEC. */
put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
}
/*******************************************************************************
MCF5252_fec_recv_handler() - Receive handler to read the received
buffer descriptors and inform the upper layer driver of the arrival
of the packet.
*/
inline static
bool MCF5252_fec_recv_handler(struct eth_drv_sc * sc)
{
/* Receive interrupt has occurred informing driver that a frame has */
/* been written to the buffer. */
NBUF* pNBuf;
buf_info_t* p_buf_info = PBUF_INFO(sc);
MCF5272_fec_priv_data_t* eth_data = PMCF5272_FEC_DATA(sc);
uint_t len;
/* Pointer to the first buffer descriptor. */
NBUF* p_first_bd;
/* Check to see if the buffer descrpitor is not busy. */
if (nbuf_rx_next_ready(p_buf_info))
{
/* Flag that indicates whether the buffer is wrapped. */
cyg_bool_t wrap = false;
/* Get the index of the buffer desrciptor of the next frame. */
uint_t index = nbuf_rx_get_index(p_buf_info);
cyg_bool_t error = false;
len = 0;
/* Get the pointer to the first buffer descriptor. */
p_first_bd = nbuf_rx_get(p_buf_info, index);
do
{
pNBuf = nbuf_rx_get(p_buf_info, index);
if (pNBuf->status & RX_BD_E)
{
/* The buffer is empty or the FEC is stll writing to the */
/* buffer. then exit. */
return false;
}
/* Advance the index to the next buffer descriptor in the */
/* ring buffer. */
index = (index + 1) % NUM_RXBDS;
if ((pNBuf->status & (RX_BD_L | RX_BD_W)) == RX_BD_W)
{
/* If the buffer descriptor wraps, set the wrap flag and */
/* initalize the index pointer to the first buffer */
/* descriptor in the ring. */
wrap = true;
}
if (pNBuf->status & RX_BD_TR)
{
/* Packet truncate count. */
eth_data->diag_counters.rx_trunc_error_cnt++;
/* Release the bds. */
nbuf_rx_release_pkt(p_buf_info);
/* Update the receive error count. */
eth_data->diag_counters.rx_err_cnt++;
/* Notify the FEC that there are receive buffer */
/* descriptors available from the FEC. */
put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
error = true;
break;
}
if (pNBuf->status & RX_BD_L)
{
/* Get the length of frame contain in the buffers. */
len = pNBuf->length;
/* If there is an error in receiving the packet, we */
/* proceed to update the counters. Otherwise, we just fall */
/* through. */
if (pNBuf->status & (RX_BD_LG | RX_BD_SH | RX_BD_CR |
RX_BD_OV))
{
/* Update the diagnostic counters. */
if (pNBuf->status & RX_BD_LG)
{
/* Larget frame error count. */
eth_data->diag_counters.rx_long_frm_err_cnt++;
}
if (pNBuf->status & RX_BD_SH)
{
/* Short frame error count. */
eth_data->diag_counters.rx_short_frm_err_cnt++;
}
if (pNBuf->status & RX_BD_CR)
{
/* CRC error count. */
eth_data->diag_counters.rx_crc_err_cnt++;
}
if (pNBuf->status & RX_BD_OV)
{
/* Overrun error count. */
eth_data->diag_counters.rx_overrun_err_cnt++;
}
/* Release the packet. */
nbuf_rx_release_pkt(p_buf_info);
/* Update the receive error count. */
eth_data->diag_counters.rx_err_cnt++;
/* Notify the FEC that there are receive buffer */
/* descriptors available for the FEC */
put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
/* Set the error flag to true to indicate that there */
/* is an error. */
error = true;
}
}
}while(!(pNBuf->status & RX_BD_L));
if (error == false)
{
cyg_uint8* buf_ptr = p_first_bd->data;
/* Since there is no error, we update the good statistic */
/* counters. */
/* Update the number of frames received. */
eth_data->diag_counters.rx_pk_cnt++;
/* Update the number of bytes in the frame received. */
/* Subract 4 bytes from the length because the packet */
/* includes the 4-byte FCS. */
eth_data->diag_counters.rx_bytes_cnt += (len - 4);
/* If the packet wraps then copy the packet to the a */
/* temporary buffer in order to make the packet contigous */
/* packet in memory. */
if (wrap)
{
uint_t count_len = 0;
uint_t pk_len;
/* Set p_buf the pointer to temporary packet biffer which */
/* we will use to copy the packet. */
u8_t* p_buf = (u8_t*)ð_data->pkt_buf;
/* Get the index of the buffer desrcitor of the next frame. */
uint_t index = nbuf_rx_get_index(p_buf_info);
do
{
/* Get the buffer descriptor. */
pNBuf = nbuf_rx_get(p_buf_info, index);
/* Calculate the length of the data in the buffer */
/* descriptor. If we reach the last buffer descriptor, */
/* the the actual data size in the last buffer */
/* descriptor is the number of bytes we have copied */
/* less from the value of the length field of the last */
/* buffer descriptor. */
if (pNBuf->status & RX_BD_L)
{
pk_len = len - count_len;
}
else
{
pk_len = RX_BUFFER_SIZE;
}
/* Copy the content of the buffer to the temporary */
/* packet buffer. */
memcpy(&p_buf[count_len], pNBuf->data, pk_len);
/* Keep count of the number of bytes read from the */
/* buffer descriptor. */
count_len += pk_len;
/* Advance to the to next buffer descriptor. */
index = (index + 1) % NUM_RXBDS;
}while(!(pNBuf->status & RX_BD_L));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?