fec.c

来自「opentcp_mcf5282原代码」· C语言 代码 · 共 196 行

C
196
字号
/*
 * File:		fec.c
 * Purpose:		Device driver for the MCF5282 FEC
 *
 *
 */

#include "src/common/m5282evb.h"
#include "src/ethernet/nif.h"
#include "src/ethernet/fec.h"

/********************************************************************/
static int
fec_reset(NIF *nif)
{
	/* Reset the FEC - equivalent to a hard reset */
	MCF5282_FEC_ECR = MCF5282_FEC_ECR_RESET;
	/* Wait for the reset sequence to complete */
	while (MCF5282_FEC_ECR & MCF5282_FEC_ECR_RESET)
		;
	/* Disable all FEC interrupts by clearing the EIMR register */
	MCF5282_FEC_EIMR = 0;
	/* Clear any interrupts by setting all bits in the EIR register */
	MCF5282_FEC_EIR = 0xFFFFFFFF;

	/* Set the source address for the controller */
	MCF5282_FEC_PALR = (0
		| (nif->hwa[0] <<24)
		| (nif->hwa[1] <<16)
		| (nif->hwa[2] <<8)
		| (nif->hwa[3] <<0));
	MCF5282_FEC_PAUR = (0
		| (nif->hwa[4] <<24)
		| (nif->hwa[5] <<16));

	/* Initialize the hash table registers */
	MCF5282_FEC_IAUR = 0;
	MCF5282_FEC_IALR = 0;

	/* Set Receive Buffer Size */
	MCF5282_FEC_EMRBR = (uint16)RX_BUFFER_SIZE;

	/* Point to the start of the circular Rx buffer descriptor queue */
	MCF5282_FEC_ERDSR = nbuf_get_start(Rx);

	/* Point to the start of the circular Tx buffer descriptor queue */
	MCF5282_FEC_ETDSR = nbuf_get_start(Tx);

	/* Set the tranceiver interface to MII mode */
	MCF5282_FEC_RCR = (0
		| MCF5282_FEC_RCR_MII_MODE);
	/*	| MCF5282_FEC_RCR_DRT); */	/* half duplex */

	/* Only operate in half-duplex, no heart beat control */
	MCF5282_FEC_TCR = 0;

	return TRUE;
}

/********************************************************************/
static void
fec_start(NIF *nif)
{
	(void) nif;

	/* Enable FEC */
	MCF5282_FEC_ECR = MCF5282_FEC_ECR_ETHER_EN;

	/* Allow interrupts by setting IMR register */
	MCF5282_FEC_EIMR = MCF5282_FEC_EIMR_RXF;

	/* Indicate that there have been empty receive buffers produced */
	MCF5282_FEC_RDAR = 1;
}

/********************************************************************/
static void
fec_stop (NIF *nif)
{
	(void) nif;

	/* Set the Graceful Transmit Stop bit */
	MCF5282_FEC_TCR = (MCF5282_FEC_TCR
		| MCF5282_FEC_TCR_GTS);

	/* Wait for the current transmission to complete */
	while ( !(MCF5282_FEC_EIR & MCF5282_FEC_EIR_GRA))
		;

	/* Clear the GRA event */
	MCF5282_FEC_EIR = MCF5282_FEC_EIR_GRA;

	/* Disable the FEC */
	MCF5282_FEC_ECR = 0;

	/* Disable all FEC interrupts by clearing the IMR register */
	MCF5282_FEC_EIMR = 0;

	/* Clear the GTS bit so frames can be tranmitted when restarted */
	MCF5282_FEC_TCR = (MCF5282_FEC_TCR
		& ~MCF5282_FEC_TCR_GTS);
}

/********************************************************************/
static int
fec_send (NIF *nif, NBUF *pNbuf)
{
	/* If data length of the frame is too long or short, reject */
	if ((pNbuf->length > nif->mtu) || (pNbuf->length <= 0))
		return FALSE;

	/* Adjust the length by the ethernet header size */
	//pNbuf->length += ETH_HDR_SIZE;

	/* Set Frame ready for transmit */
	pNbuf->status |= TX_BD_R;

	/* Mark the buffer as not in use */
	nif->tx_free(pNbuf);

	/* Indicate that there has been a transmit buffer produced */
	MCF5282_FEC_TDAR = 1;

	/* The hardware will mark the buffer as empty once it's transmitted */

	nif->f_tx++;
	return TRUE;
}

/********************************************************************/
static void
fec_receive(NIF *nif)
{

	nif_protocol_handler(nif);

			return;

}

/********************************************************************/
void
fec_rx_release(NBUF* pNbuf)
{
	/* Mark the buffer as empty */
	nbuf_rx_release(pNbuf);

	/* Tell the HW that there has been an empty Rx buffer produced */
	MCF5282_FEC_RDAR = 1;
}

/********************************************************************/
int
fec_handler (NIF *nif)
{	/* This is the Interrupt Service Routine for the FEC receiver */

	int old_ipl = asm_set_ipl(6);

	/* Clear FEC RX Event from the Event Register (by writing 1) */
	if (MCF5282_FEC_EIR & (MCF5282_FEC_EIR_RXB | MCF5282_FEC_EIR_RXF))
	{

		/* Clear interrupt from EIR register immediately */
		MCF5282_FEC_EIR = (MCF5282_FEC_EIR_RXB | MCF5282_FEC_EIR_RXF);

		fec_receive(nif);
				
	}

	asm_set_ipl(old_ipl);

	return TRUE;
}

/********************************************************************/
int
fec_init (NIF *nif)
{
	nif_init(nif, "mcf5282_fec");
	nif->hwa_size = 6;
	nif->mtu = ETH_MAX_SIZE;
	nif->reset = fec_reset;
	nif->start = fec_start;
	nif->stop = fec_stop;
	nif->send = fec_send;
	nif->receive = (void *)&fec_receive;
	nif->rx_alloc = nbuf_rx_allocate;
	nif->tx_alloc = nbuf_tx_allocate;
	nif->rx_free = fec_rx_release;
	nif->tx_free = nbuf_tx_release;

	return TRUE;
}

/********************************************************************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?