if_mcf5272.c
来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,887 行 · 第 1/5 页
C
1,887 行
buf_ptr = (u8_t*)ð_data->pkt_buf;
}
/* If there is a copy wrap error or the Rx packet filter */
/* rejected the packet, pass it to the upper layer. Otherwise, */
/* release the buffer descriptors. */
if (!eth_rx_pkt_filter(buf_ptr, len))
{
/* Inform the upper layer of a complete packet. */
(sc->funs->eth_drv->recv)(sc, len);
}
else
{
/* Release the buffer descriptors. */
nbuf_rx_release_good_pkt(p_buf_info);
/* Notify the FEC that there is at least a receive buffer */
/* descriptos available for the FEC. */
put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
}
}
}
else
{
/* Indicates that there are no more receive packets. */
return false;
}
return true;
}
/*******************************************************************************
MCF5272_fec_transmit_handler() - Transmit handler informs the upper
layer packet of a completion of a transmit packet.
*/
static
bool MCF5272_fec_transmit_handler(struct eth_drv_sc * sc)
/* If the FEC has successfull transmitted a packet, then realease the */
/* buffer used for the packet so that the buffer can be reused. */
{
/* Check to see which frame has completed sending so we can tell the */
/* upper layer to free up ts buffer. */
buf_info_t* p_buf_info = PBUF_INFO(sc);
MCF5272_fec_priv_data_t* eth_data = PMCF5272_FEC_DATA(sc);
NBUF* pNbd = NULL;
int_t index, i;
tx_keys_t key_entry;
bool result = true;
NBUF* next_bd;
/* Check wether there is any pending transmit buffer descriptors that */
/* are to deallocated. */
if ((index = nbuf_peek_tx_key(p_buf_info)) != -1)
{
/* Get the pointer to the buffer descriptor so that the flags in */
/* the status word in the buffer descriptor can be examined. */
NBUF* pNbuf = nbuf_tx_get(p_buf_info, index);
CYG_ASSERT(pNbuf->status & TX_BD_L, "Index to BD is not the last BD");
if (pNbuf->status & TX_BD_R)
{
/* Increment the number of times the device driver discovers */
/* that the buffer descriptor is still in use by the FEC and it */
/* has been skipped. */
if ((next_bd = nbuf_peek_bd_ahead(p_buf_info)))
{
if (!(next_bd->status & TX_BD_R) &&
pNbuf->status & TX_BD_R)
{
eth_data->diag_counters.tx_not_complete_cnt++;
goto RELEASE_BUF;
}
}
/* If the buffer not ready we return immediatly. */
return false;
}
RELEASE_BUF:
/* Dequeue the packet from the trasnmt packet queue to indicate */
/* that the packet is not being transmitted by the FEC. */
nbuf_deq_tx_key(p_buf_info, &key_entry);
/* Release the used buffers. */
for ( i = 0; i < key_entry.num_dbufs; i++)
{
/* Get the BD based on the index. */
pNbd = nbuf_tx_get(p_buf_info,
(key_entry.start_index + i) % NUM_TXBDS);
/* The last buffer descriptor of the packet. */
if (pNbd->status & TX_BD_L)
{
if (pNbd->status & TX_BD_RL)
{
/* Update the number of retries. */
eth_data->diag_counters.tx_retry_cnt += 16;
eth_data->diag_counters.tx_err_cnt++;
eth_data->diag_counters.tx_exes_retry_cnt++;
}
else
{
/* Check for error status. If there is an error */
/* proceed the increment the appropriate statistic */
/* counter. */
if (pNbd->status & (TX_BD_UN |
TX_BD_LC |
TX_BD_CSL |
TX_BD_HB))
{
if (pNbd->status & TX_BD_HB)
{
/* Heartbeat error count. */
eth_data->diag_counters.tx_hb_err_cnt++;
}
if (pNbd->status & TX_BD_UN)
{
/* Transmit underrun error count. */
eth_data->diag_counters.tx_underrun_cnt++;
}
if (pNbd->status & TX_BD_CSL)
{
/* Transmit carrier loss count. */
eth_data->diag_counters.tx_carrrier_loss_cnt++;
}
if (pNbd->status & TX_BD_LC)
{
/* Update the late collision counter. */
eth_data->diag_counters.tx_late_col_cnt++;
}
/* Update the number transmit error count. */
eth_data->diag_counters.tx_err_cnt++;
}
else
{
/* Update the diagnostic counters */
if (pNbd->status & TX_BD_DEF)
{
/* Defer indication count. */
eth_data->diag_counters.tx_def_cnt++;
}
/* Update the number of transmitted packets. */
eth_data->diag_counters.tx_pk_cnt++;
/* Update the transmitted packet size. If the */
/* size is less than the minimum size then take the */
/* minimum size as the actual frame length. This */
/* is because we take account of the pad bytes that */
/* the FEC appends when it sends out frames that */
/* has less than the minimum length. */
eth_data->diag_counters.tx_bytes_cnt +=
key_entry.pk_len < ETH_MIN_SIZE ? ETH_MIN_SIZE :
key_entry.pk_len;
}
/* Get the number of retries. */
eth_data->diag_counters.tx_retry_cnt +=
(pNbd->status >> 2) & 0xF;
}
}
/* Release the buffer descriptor so that it can be reused to */
/* transmit the next packet. */
nbuf_tx_release(pNbd);
/* If the start_index is the same as the index to the last */
/* buffer descriptor, then quit the loop. */
}
/* Decrement the number of busy descriptors. */
p_buf_info->num_busy_bd -= key_entry.num_dbufs;
switch(key_entry.key_type)
{
case TX_KEY_ECOS:
/* Inform the upper layer of a completion of the packet. */
(sc->funs->eth_drv->tx_done)(sc,
key_entry.tx_key,
0);
break;
case TX_KEY_USER:
/* Inform the application of the completion of the packet. */
eth_send_done(key_entry.tx_key);
break;
}
}
else
{
/* Retrun false to indicate that the transmit buffer is empty. */
result = false;
}
/* Indicate that the packet at the transmit buffer has been */
/* successfully handled. */
return result;
}
/* This routine informs the upper layer of a completion of a sent */
/* frame and a reception of a frame. */
static void
MCF5272_fec_deliver(struct eth_drv_sc * sc)
{
u32_t event;
/* Clear the event register. */
put_reg(MCF5272_SIM->enet.eir,
(event = (get_reg(MCF5272_SIM->enet.eir) &
MCF5272_FEC_INTERRUPT_MASK)));
while(event & MCF5272_FEC_INTERRUPT_MASK)
{
/* This flag will specifies whether we need to service the */
/* transmit or receive sides of the Ethernet controller. */
bool packet_status;
/* Keep count of any bus error that might occur when the FEC */
/* attempts while the FEC accessing the internal bus. */
if (event & MCF5272_FEC_EIR_EBERR)
{
PMCF5272_FEC_DATA(sc)->diag_counters.internal_bus_error_cnt++;
}
do
{
packet_status = false;
/* Call receive the handler to receive packets. */
packet_status |= MCF5252_fec_recv_handler(sc);
/* Call transit the handed to release the transmit buffers. */
packet_status |= MCF5272_fec_transmit_handler(sc);
/* Loop back up until all the receive and transmit buffers */
/* are empty. */
}while(packet_status);
/* Retrieve the next interrupt event. */
/* Clear the event register. */
put_reg(MCF5272_SIM->enet.eir,
event = (get_reg(MCF5272_SIM->enet.eir) &
MCF5272_FEC_INTERRUPT_MASK));
}
/* NOTE: If the a bit in the eir is set after clearing the bit in the */
/* eir, unmasking the bit in the imr will generate an interrupt. This */
/* assumption is true only if the interrupt line to the microprocessor */
/* core is level sensitive. */
/* Allow interrupts by setting IMR register. */
put_reg(MCF5272_SIM->enet.eimr, get_reg(MCF5272_SIM->enet.eimr) |
MCF5272_FEC_INTERRUPT_MASK
);
}
/* Generic Interrupt Service Routine. This routine wakes up the DSR */
/* for further processing. */
static int
MCF5272_fec_isr(cyg_vector_t vector, cyg_addrword_t data,
HAL_SavedRegisters *regs)
{
/* Mask the FEC's interrupts so that it won't generate these */
/* interrupts anymore as the driver reads the packets or acknowledges */
/* packets. */
put_reg(MCF5272_SIM->enet.eimr, get_reg(MCF5272_SIM->enet.eimr) &
~(MCF5272_FEC_INTERRUPT_MASK));
return CYG_ISR_CALL_DSR;
}
/* Call MCF5272_fec_deliver() to poll the FEC. */
static void
MCF5272_fec_int(struct eth_drv_sc *sc)
{
MCF5272_fec_deliver(sc);
}
static int
MCF5272_fec_int_vector(struct eth_drv_sc *sc)
{
/* How do you return multiple interrupt vector? */
return CYGNUM_HAL_VECTOR_ERX;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?