/* * File: fec.c * Purpose: Device driver for the MCF5282 FEC * * */ #include "rtxcapi.h" #include "enable.h" #include "m52xxevb.h" #include "mcf5xxx.h" #include "runtm.h" #include "nif.h" #include "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 = 0x00; /* 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); */ PPL_TYPE ppl; PUSHPPL(ppl); /* 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); */ POPPPL(ppl); 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; } /********************************************************************/