⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fec.c

📁 motorola自己开发的针对coldfire 5272的Dbug bootloader程序
💻 C
字号:
/*
 * File:		fec.c
 * Purpose:		Device driver for the MCF5282 FEC
 *
 *      
 */

#include "src/include/dbug.h"
#include "src/uif/net/net.h"
#include "src/dev/MCF5282/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;
/* Initialize PEHLPAR to enable ethernet signals */
	MCF5282_GPIO_PEHLPAR = 0xC0;
	
	/* Enable FEC */
	MCF5282_FEC_ECR = MCF5282_FEC_ECR_ETHER_EN;

	/* Allow interrupts by setting EIMR 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_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 EIMR register */
	MCF5282_FEC_EIMR = 0;

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

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

	/* Write destination ethernet address */
	pNbuf->data[ETH_HDR_OFFSET + 0] = eth_dest[0];
	pNbuf->data[ETH_HDR_OFFSET + 1] = eth_dest[1];
	pNbuf->data[ETH_HDR_OFFSET + 2] = eth_dest[2];
	pNbuf->data[ETH_HDR_OFFSET + 3] = eth_dest[3];
	pNbuf->data[ETH_HDR_OFFSET + 4] = eth_dest[4];
	pNbuf->data[ETH_HDR_OFFSET + 5] = eth_dest[5];

	/* Write source ethernet address. */
	pNbuf->data[ETH_HDR_OFFSET + 6] = eth_src[0];
	pNbuf->data[ETH_HDR_OFFSET + 7] = eth_src[1];
	pNbuf->data[ETH_HDR_OFFSET + 8] = eth_src[2];
	pNbuf->data[ETH_HDR_OFFSET + 9] = eth_src[3];
	pNbuf->data[ETH_HDR_OFFSET + 10] = eth_src[4];
	pNbuf->data[ETH_HDR_OFFSET + 11] = eth_src[5];

	/* Write frame type */
	pNbuf->data[ETH_HDR_OFFSET + 12] = (uint8)((eth_type & 0xFF00) >> 8);
	pNbuf->data[ETH_HDR_OFFSET + 13] = (uint8)(eth_type & 0x00FF);

	/* 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 */
	return TRUE;
}

/********************************************************************/
static void 
fec_receive(NIF *nif)
{
	NBUF *pNbuf;
	eth_frame_hdr *ethframe;

	/* Clear interrupt from EIR register */
	MCF5282_FEC_EIR = MCF5282_FEC_EIR_RXF;

	while( nbuf_rx_next_ready() )	
	{
		/* Get the next buffer received by the FEC */
		pNbuf = nif->rx_alloc();
		if (pNbuf == NULL)
			return;

		/************************************************************
		 The size of the Rx Buffers is set so that every frame addressed
		 to me should fit in one buffer. Therefore, the L bit should be
		 set on every buffer received.
		*************************************************************/
		if (!(pNbuf->status & RX_BD_L))
		{
			do
			{	/* Free the current buffer */
				nif->rx_free(pNbuf);
				/* Get the next buffer of this frame */
				pNbuf = nif->rx_alloc();
				if (pNbuf == NULL)
					return;

				/* Keep going until we find the last one */
			} while (!(pNbuf->status & RX_BD_L));

			/* Free the last buffer of this frame */
			nif->rx_free(pNbuf);
			return;
		}

		/* Point to the ethernet header of this packet */
		ethframe = (eth_frame_hdr *)&pNbuf->data[ETH_HDR_OFFSET];

		/* Make sure the associated protocol is supported */
		if (!nif_protocol_exist(nif,ethframe->type))
		{
			nif->rx_free(pNbuf);
			return;
		}

		/* Adjust the length by the ethernet header size */
		pNbuf->length -= (4 + 6 + 6 + 2);

		/* Call the appriopriate handler */
		nif_protocol_handler(nif, ethframe->type, pNbuf);

		/************************************************************
		 Higher level protocols must save off the data if they need to 
		 keep it around for processing. The buffers are freed here to
		 ensure that the circular buffer descriptor ring is maintained
		 properly.
		*************************************************************/
		nif->rx_free(pNbuf);
	}
}

/********************************************************************/
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;
}

/********************************************************************/
/* 
 * This is the Interrupt Service Routine for the FEC receiver 
 */
int
fec_handler (void *not_used, NIF *nif)
{
	
	(void) not_used;
	
	board_irq_disable();

	if (MCF5282_FEC_EIR & MCF5282_FEC_EIR_RXF)
	{
		fec_receive(nif);
	}

	board_irq_enable();

	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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -