📄 mcf5xxx_fecx.c
字号:
* src Source MAC Address
* type Ethernet Frame Type
* length Number of bytes to be transmitted (doesn't include type,
* src, or dest byte count)
* pkt Pointer packet network buffer
*
* Return Value:
* 1 success
* 0 otherwise
*/
int
fec_send (NIF *nif, uint8 *dst, uint8 *src, uint16 type, NBUF *nbuf)
{
FECBD *pTxBD;
uint8 ch = (uint8)nif->ch;
(void) nif;
#if (FEC_NUM_CH == 1)
ch = 0;
#else
ASSERT(ch < FEC_NUM_CH);
#endif
/* Check the length */
if ((nbuf->length + ETH_HDR_LEN) > ETH_MTU)
return 0;
/*
* Copy the destination address, source address, and Ethernet
* type into the packet
*/
memcpy(&nbuf->data[0], dst, 6);
memcpy(&nbuf->data[6], src, 6);
memcpy(&nbuf->data[12], &type, 2);
/*
* Grab the next available Tx Buffer Descriptor
*/
if ((pTxBD = fecbd_tx_alloc()) == NULL)
return 0;
/*
* Put the network buffer into the Tx waiting queue
*/
nbuf_add(NBUF_TX_RING, nbuf);
/*
* Setup the buffer descriptor for transmission
*/
pTxBD->data = nbuf->data;
pTxBD->length = nbuf->length + ETH_HDR_LEN;
pTxBD->status |= (TX_BD_R | TX_BD_L | TX_BD_TC);
/*
* Continue the Tx DMA task (in case it was waiting for a new
* TxBD to be ready)
*/
fec_tx_continue(ch);
return 1;
}
/********************************************************************/
/*
* Resend the last packet that was already prepared and sent
*
* Parameters:
* ch FEC channel
*/
void
fec_resend (uint8 ch)
{
FECBD *pTxBD;
NBUF *pNbuf;
#if (FEC_NUM_CH == 1)
ch = 0;
#else
ASSERT(ch < FEC_NUM_CH);
#endif
/*
* Grab the most recently sent TxBD
*/
pTxBD = fecbd_tx_free();
ASSERT(pTxBD != NULL);
/*
* Grab the network buffer associated with this buffer descriptor
*/
pNbuf = nbuf_remove(NBUF_TX_RING);
ASSERT(pNbuf);
ASSERT(pNbuf->data == pTxBD->data);
/*
* Grab the next available Tx Buffer Descriptor
*/
while ((pTxBD = fecbd_tx_alloc()) == NULL)
;
/*
* Put the network buffer back into the Tx waiting queue
*/
nbuf_add(NBUF_TX_RING, pNbuf);
/*
* Reset the TxBD status flags
*/
pTxBD->data = pNbuf->data;
pTxBD->length = pNbuf->length + ETH_HDR_LEN;
pTxBD->status |= (TX_BD_R | TX_BD_L | TX_BD_TC);
/*
* Continue the Tx DMA task (in case it was waiting for a new
* TxBD to be ready)
*/
fec_tx_continue(ch);
}
/********************************************************************/
/*
* Enable interrupts from the FEC
*
* Parameters:
* ch FEC channel
*/
void
fec_irq_enable(uint8 ch)
{
#if (FEC_NUM_CH == 1)
ch = 0;
#else
ASSERT(ch < FEC_NUM_CH);
#endif
/*
* Clear any pending FEC interrupt events
*/
MCF_FEC_EIR(ch) = MCF_FEC_EIR_CLEAR_ALL;
/*
* Unmask all FEC interrupts
*/
MCF_FEC_EIMR(ch) = MCF_FEC_EIMR_UNMASK_ALL;
}
/********************************************************************/
/*
* Disable interrupts from the FEC
*
* Parameters:
* ch FEC channel
*/
void
fec_irq_disable(uint8 ch)
{
#if (FEC_NUM_CH == 1)
ch = 0;
#else
ASSERT(ch < FEC_NUM_CH);
#endif
/*
* Mask all FEC interrupts
*/
MCF_FEC_EIMR(ch) = MCF_FEC_EIMR_MASK_ALL;
}
/********************************************************************/
/*
* FEC interrupt handler
*
* Parameters:
* arg1 NIF structure
* arg2 NULL
*
* Return Value:
* Always TRUE (1)
*/
int
fec_irq_handler(void* arg1, void* arg2)
{
uint32 event, eir;
uint8 ch = (uint8)((NIF *)arg1)->ch;
(void) arg2;
/*
* Determine which interrupt(s) asserted by AND'ing the
* pending interrupts with those that aren't masked.
*/
eir = MCF_FEC_EIR(ch);
event = eir & MCF_FEC_EIMR(ch);
#ifdef DEBUG
if (event != eir)
printf("Pending but not enabled: 0x%08X\n",(event ^ eir));
#endif
/*
* Clear the event(s) in the EIR immediately
*/
MCF_FEC_EIR(ch) = event;
if (event & MCF_FEC_EIR_UN)
{
fec_log[ch].errors++;
fec_log[ch].un++;
#ifdef DEBUG
printf("FEC Tx FIFO Underflow\n");
#endif
}
if (event & MCF_FEC_EIR_RL)
{
fec_log[ch].errors++;
fec_log[ch].rl++;
#ifdef DEBUG
printf("FEC Collision Retry Limit\n");
#endif
fec_resend(ch);
}
if (event & MCF_FEC_EIR_LC)
{
fec_log[ch].errors++;
fec_log[ch].lc++;
#ifdef DEBUG
printf("FEC Late Collision\n");
#endif
fec_resend(ch);
}
if (event & MCF_FEC_EIR_EBERR)
{
fec_log[ch].errors++;
fec_log[ch].eberr++;
#ifdef DEBUG
printf("FEC/DMA fatal bus error!\n");
#endif
fec_eth_stop(ch);
}
if (event & MCF_FEC_EIR_MII)
{
fec_log[ch].mii++;
}
if (event & MCF_FEC_EIR_RXB || event & MCF_FEC_EIR_RXF)
{
fec_rx_handler((NIF *)arg1);
}
if (event & MCF_FEC_EIR_TXB || event & MCF_FEC_EIR_TXF)
{
fec_tx_handler((NIF *)arg1);
}
if (event & MCF_FEC_EIR_GRA)
{
fec_log[ch].gra++;
}
if (event & MCF_FEC_EIR_BABT)
{
fec_log[ch].errors++;
fec_log[ch].babt++;
#ifdef DEBUG
printf("FEC Babbling transmit error\n");
#endif
}
if (event & MCF_FEC_EIR_BABR)
{
fec_log[ch].errors++;
fec_log[ch].babr++;
#ifdef DEBUG
printf("FEC Babbling receive error\n");
#endif
}
if (event & MCF_FEC_EIR_HBERR)
{
fec_log[ch].errors++;
fec_log[ch].hberr++;
#ifdef DEBUG
printf("HBERR\n");
#endif
}
return TRUE;
}
/********************************************************************/
/*
* Configure the selected Ethernet port and enable all operations
*
* Parameters:
* ch FEC channel
* trcvr Transceiver mode (MII, 7-Wire or internal loopback)
* mac Physical (MAC) Address
*/
void
fec_eth_setup(uint8 ch, uint8 trcvr, const uint8 *mac)
{
#if (FEC_NUM_CH == 1)
ch = 0;
#else
ASSERT(ch < FEC_NUM_CH);
#endif
/*
* Disable FEC interrupts
*/
fec_irq_disable(ch);
/*
* Initialize the event log
*/
fec_log_init(ch);
/*
* Initialize the network buffers and fec buffer descriptors
*/
nbuf_init();
fecbd_init();
/*
* Initialize the FEC
*/
fec_reset(ch);
fec_init(ch,trcvr,mac);
if (trcvr == FEC_MODE_MII)
{
/*
* Initialize the MII interface
*/
fec_mii_init(ch, SYSTEM_CLOCK);
}
/*
* Initialize and enable FEC interrupts
*/
fec_irq_enable(ch);
/*
* Enable the FEC channel
*/
MCF_FEC_ECR(ch) |= MCF_FEC_ECR_ETHER_EN;
/*
* Start the Rx FEC DMA
*/
fec_rx_continue(ch);
}
/********************************************************************/
/*
* Reset the Ethernet port
*
* Parameters:
* ch FEC channel
*/
void
fec_eth_reset(uint8 ch)
{
#if (FEC_NUM_CH == 1)
ch = 0;
#else
ASSERT(ch < FEC_NUM_CH);
#endif
fec_reset(ch);
}
/********************************************************************/
/*
* Stop the selected Ethernet port
*
* Parameters:
* ch FEC channel
*/
void
fec_eth_stop(uint8 ch)
{
int level;
#if (FEC_NUM_CH == 1)
ch = 0;
#else
ASSERT(ch < FEC_NUM_CH);
#endif
/*
* Disable interrupts
*/
level = asm_set_ipl(7);
/*
* Gracefully disable the transmitter
*/
fec_tx_stop(ch);
/*
* Disable FEC interrupts
*/
fec_irq_disable(ch);
/*
* Disable the FEC channel
*/
MCF_FEC_ECR(ch) &= ~MCF_FEC_ECR_ETHER_EN;
#ifdef DEBUG
nbuf_debug_dump();
fecbd_dump();
fec_log_dump(ch);
#endif
/*
* Flush the network buffers
*/
nbuf_flush();
/*
* Restore interrupt level
*/
asm_set_ipl(level);
}
/********************************************************************/
#endif /* #ifdef DBUG_NETWORK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -