Webserver+3d print
Diff: cyclone_tcp/drivers/mcf5225x_eth.c
- Revision:
- 0:8918a71cdbe9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cyclone_tcp/drivers/mcf5225x_eth.c Sat Feb 04 18:15:49 2017 +0000 @@ -0,0 +1,782 @@ +/** + * @file mcf5225x_eth.c + * @brief Coldfire V2 MCF5225x Ethernet MAC controller + * + * @section License + * + * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneTCP Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 1.7.6 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL NIC_TRACE_LEVEL + +//Dependencies +#include "mcf52259.h" +#include "core/net.h" +#include "drivers/mcf5225x_eth.h" +#include "debug.h" + +//Underlying network interface +static NetInterface *nicDriverInterface; + +//TX buffer +static uint8_t txBuffer[MCF5225X_ETH_TX_BUFFER_COUNT][MCF5225X_ETH_TX_BUFFER_SIZE]; +//RX buffer +static uint8_t rxBuffer[MCF5225X_ETH_RX_BUFFER_COUNT][MCF5225X_ETH_RX_BUFFER_SIZE]; +//TX buffer descriptors +static Mcf5225xTxBufferDesc txBufferDesc[MCF5225X_ETH_TX_BUFFER_COUNT]; +//RX buffer descriptors +static Mcf5225xRxBufferDesc rxBufferDesc[MCF5225X_ETH_RX_BUFFER_COUNT]; + +//TX buffer index +static uint_t txBufferIndex; +//RX buffer index +static uint_t rxBufferIndex; + + +/** + * @brief MCF5225x Ethernet MAC driver + **/ + +const NicDriver mcf5225xEthDriver = +{ + NIC_TYPE_ETHERNET, + ETH_MTU, + mcf5225xEthInit, + mcf5225xEthTick, + mcf5225xEthEnableIrq, + mcf5225xEthDisableIrq, + mcf5225xEthEventHandler, + mcf5225xEthSendPacket, + mcf5225xEthSetMulticastFilter, + mcf5225xEthUpdateMacConfig, + mcf5225xEthWritePhyReg, + mcf5225xEthReadPhyReg, + TRUE, + TRUE, + TRUE, + FALSE +}; + + +/** + * @brief MCF5225x Ethernet MAC initialization + * @param[in] interface Underlying network interface + * @return Error code + **/ + +error_t mcf5225xEthInit(NetInterface *interface) +{ + error_t error; + uint_t i; + uint32_t value; + + //Debug message + TRACE_INFO("Initializing MCF5225x Ethernet MAC...\r\n"); + + //Save underlying network interface + nicDriverInterface = interface; + + //GPIO configuration + mcf5225xEthInitGpio(interface); + + //Reset FEC module + MCF_FEC_ECR = MCF_FEC_ECR_RESET; + //Wait for the reset to complete + while(MCF_FEC_ECR & MCF_FEC_ECR_RESET); + + //Reveive control register + MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL(1518) | MCF_FEC_RCR_MII_MODE; + //Transmit control register + MCF_FEC_TCR = 0; + //Configure MDC clock frequency + MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED(19); + + //PHY transceiver initialization + error = interface->phyDriver->init(interface); + //Failed to initialize PHY transceiver? + if(error) + return error; + + //Set the MAC address (upper 16 bits) + value = interface->macAddr.b[5]; + value |= (interface->macAddr.b[4] << 8); + MCF_FEC_PAUR = MCF_FEC_PAUR_PADDR2(value) | MCF_FEC_PAUR_TYPE(0x8808); + + //Set the MAC address (lower 32 bits) + value = interface->macAddr.b[3]; + value |= (interface->macAddr.b[2] << 8); + value |= (interface->macAddr.b[1] << 16); + value |= (interface->macAddr.b[0] << 24); + MCF_FEC_PALR = MCF_FEC_PALR_PADDR1(value); + + //Hash table for unicast address filtering + MCF_FEC_IALR = 0; + MCF_FEC_IAUR = 0; + //Hash table for multicast address filtering + MCF_FEC_GALR = 0; + MCF_FEC_GAUR = 0; + + //Initialize buffer descriptors + mcf5225xEthInitBufferDesc(interface); + + //Clear any pending interrupts + MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL; + + //Enable desired interrupts + MCF_FEC_EIMR = MCF_FEC_EIMR_TXF | MCF_FEC_EIMR_TXB | + MCF_FEC_EIMR_RXF | MCF_FEC_EIMR_RXB | MCF_FEC_EIMR_EBERR; + + //Set the priority of FEC interrupts + for(i = 23; i <= 35; i++) + { + MCF_INTC0_ICR(i) = MCF_INTC_ICR_IL(MCF5225X_ETH_IRQ_LEVEL) | + MCF_INTC_ICR_IP(MCF5225X_ETH_IRQ_PRIORITY); + } + + //Enable Ethernet MAC + MCF_FEC_ECR |= MCF_FEC_ECR_ETHER_EN; + //Instruct the DMA to poll the receive descriptor list + MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE; + + //Accept any packets from the upper layer + osSetEvent(&interface->nicTxEvent); + + //Successful initialization + return NO_ERROR; +} + + +//TWR-MCF5225X evaluation board? +#if defined(USE_TWR_MCF5225X) + +/** + * @brief GPIO configuration + * @param[in] interface Underlying network interface + **/ + +void mcf5225xEthInitGpio(NetInterface *interface) +{ + uint8_t temp; + + //Configure FEC_COL (PTI0), FEC_CRS (PTI1), FEC_RXCLK (PTI2), FEC_RXD0 (PTI3), + //FEC_RXD1 (PTI4), FEC_RXD2 (PTI5), FEC_RXD3 (PTI6) and FEC_RXDV (PTI7) + MCF_GPIO_PTIPAR |= MCF_GPIO_PTIPAR_FEC_COL_FEC_COL | MCF_GPIO_PTIPAR_FEC_CRS_FEC_CRS | + MCF_GPIO_PTIPAR_FEC_RXCLK_FEC_RXCLK | MCF_GPIO_PTIPAR_FEC_RXD0_FEC_RXD0 | + MCF_GPIO_PTIPAR_FEC_RXD1_FEC_RXD1 | MCF_GPIO_PTIPAR_FEC_RXD2_FEC_RXD2 | + MCF_GPIO_PTIPAR_FEC_RXD3_FEC_RXD3 | MCF_GPIO_PTIPAR_FEC_RXDV_FEC_RXDV; + + //Configure FEC_RXER (PTJ0), FEC_TXCLK (PTJ1), FEC_TXD0 (PTJ2), FEC_TXD1 (PTJ3) + //FEC_TXD2 (PTJ4), FEC_TXD3 (PTJ5), FEC_TXEN (PTJ6) and FEC_TXER (PTJ7) + MCF_GPIO_PTJPAR |= MCF_GPIO_PTJPAR_FEC_RXER_FEC_RXER | MCF_GPIO_PTJPAR_FEC_TXCLK_FEC_TXCLK | + MCF_GPIO_PTJPAR_FEC_TXD0_FEC_TXD0 | MCF_GPIO_PTJPAR_FEC_TXD1_FEC_TXD1 | + MCF_GPIO_PTJPAR_FEC_TXD2_FEC_TXD2 | MCF_GPIO_PTJPAR_FEC_TXD3_FEC_TXD3 | + MCF_GPIO_PTJPAR_FEC_TXEN_FEC_TXEN | MCF_GPIO_PTJPAR_FEC_TXER_FEC_TXER; + + //Configure FEC_MDIO (PNQ3) + temp = MCF_GPIO_PNQPAR & ~MCF_GPIO_PNQPAR_PNQPAR3(3); + MCF_GPIO_PNQPAR = temp | MCF_GPIO_PNQPAR_IRQ3_FEC_MDIO; + + //Configure FEC_MDC (PNQ5) + temp = MCF_GPIO_PNQPAR & ~MCF_GPIO_PNQPAR_PNQPAR5(3); + MCF_GPIO_PNQPAR = temp | MCF_GPIO_PNQPAR_IRQ5_FEC_MDC; + + //Reset PHY transceiver + MCF_RCM_RCR |= MCF_RCM_RCR_FRCRSTOUT; + sleep(10); + + //Take the PHY transceiver out of reset + MCF_RCM_RCR &= ~MCF_RCM_RCR_FRCRSTOUT; + sleep(10); +} + +#endif + + +/** + * @brief Initialize buffer descriptors + * @param[in] interface Underlying network interface + **/ + +void mcf5225xEthInitBufferDesc(NetInterface *interface) +{ + uint_t i; + + //Initialize TX buffer descriptors + for(i = 0; i < MCF5225X_ETH_TX_BUFFER_COUNT; i++) + { + //The descriptor is initially owned by the software + txBufferDesc[i].status = 0; + //Transmit buffer length + txBufferDesc[i].length = 0; + //Transmit buffer address + txBufferDesc[i].address = (uint32_t) FEC_ALIGN16(txBuffer[i]); + } + + //Mark the last descriptor entry with the wrap flag + txBufferDesc[i - 1].status |= FEC_TX_BD_W; + //Initialize TX buffer index + txBufferIndex = 0; + + //Initialize RX buffer descriptors + for(i = 0; i < MCF5225X_ETH_RX_BUFFER_COUNT; i++) + { + //The descriptor is initially owned by the DMA + rxBufferDesc[i].status = FEC_RX_BD_E; + //Receive buffer length + rxBufferDesc[i].length = 0; + //Receive buffer address + rxBufferDesc[i].address = (uint32_t) FEC_ALIGN16(rxBuffer[i]); + } + + //Mark the last descriptor entry with the wrap flag + rxBufferDesc[i - 1].status |= FEC_RX_BD_W; + //Initialize RX buffer index + rxBufferIndex = 0; + + //Start location of the TX descriptor list + MCF_FEC_ETSDR = (uint32_t) txBufferDesc; + //Start location of the RX descriptor list + MCF_FEC_ERDSR = (uint32_t) rxBufferDesc; + //Maximum receive buffer size + MCF_FEC_EMRBR = MCF5225X_ETH_RX_BUFFER_SIZE; +} + + +/** + * @brief MCF5225x Ethernet MAC timer handler + * + * This routine is periodically called by the TCP/IP stack to + * handle periodic operations such as polling the link state + * + * @param[in] interface Underlying network interface + **/ + +void mcf5225xEthTick(NetInterface *interface) +{ + //Handle periodic operations + interface->phyDriver->tick(interface); +} + + +/** + * @brief Enable interrupts + * @param[in] interface Underlying network interface + **/ + +void mcf5225xEthEnableIrq(NetInterface *interface) +{ + //Enable Ethernet MAC interrupts + MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT_MASK23 | + MCF_INTC_IMRL_INT_MASK24 | MCF_INTC_IMRL_INT_MASK25 | + MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27 | + MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | + MCF_INTC_IMRL_INT_MASK30 | MCF_INTC_IMRL_INT_MASK31); + + MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK33 | + MCF_INTC_IMRH_INT_MASK34| MCF_INTC_IMRH_INT_MASK35); + + //Enable Ethernet PHY interrupts + interface->phyDriver->enableIrq(interface); +} + + +/** + * @brief Disable interrupts + * @param[in] interface Underlying network interface + **/ + +void mcf5225xEthDisableIrq(NetInterface *interface) +{ + //Disable Ethernet MAC interrupts + MCF_INTC0_IMRL |= MCF_INTC_IMRL_INT_MASK23 | + MCF_INTC_IMRL_INT_MASK24 | MCF_INTC_IMRL_INT_MASK25 | + MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27 | + MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | + MCF_INTC_IMRL_INT_MASK30 | MCF_INTC_IMRL_INT_MASK31; + + MCF_INTC0_IMRH |= MCF_INTC_IMRH_INT_MASK33 | + MCF_INTC_IMRH_INT_MASK34| MCF_INTC_IMRH_INT_MASK35; + + //Disable Ethernet PHY interrupts + interface->phyDriver->disableIrq(interface); +} + + +/** + * @brief Ethernet MAC interrupt + **/ + +__declspec(interrupt) void mcf5225xEthIrqHandler(void) +{ + bool_t flag; + uint32_t events; + + //Enter interrupt service routine + osEnterIsr(); + + //This flag will be set if a higher priority task must be woken + flag = FALSE; + //Read interrupt event register + events = MCF_FEC_EIR; + + //A packet has been transmitted? + if(events & (MCF_FEC_EIR_TXF | MCF_FEC_EIR_TXB)) + { + //Clear TXF and TXB interrupt flags + MCF_FEC_EIR = MCF_FEC_EIR_TXF | MCF_FEC_EIR_TXB; + + //Check whether the TX buffer is available for writing + if(!(txBufferDesc[txBufferIndex].status & FEC_TX_BD_R)) + { + //Notify the TCP/IP stack that the transmitter is ready to send + flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); + } + + //Instruct the DMA to poll the transmit descriptor list + MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE; + } + + //A packet has been received? + if(events & (MCF_FEC_EIR_RXF | MCF_FEC_EIR_RXB)) + { + //Disable RXF and RXB interrupts + MCF_FEC_EIMR &= ~(MCF_FEC_EIMR_RXF | MCF_FEC_EIMR_RXB); + + //Set event flag + nicDriverInterface->nicEvent = TRUE; + //Notify the TCP/IP stack of the event + flag |= osSetEventFromIsr(&netEvent); + } + + //System bus error? + if(events & MCF_FEC_EIR_EBERR) + { + //Disable EBERR interrupt + MCF_FEC_EIMR &= ~MCF_FEC_EIMR_EBERR; + + //Set event flag + nicDriverInterface->nicEvent = TRUE; + //Notify the TCP/IP stack of the event + flag |= osSetEventFromIsr(&netEvent); + } + + //Any other event? + if(events & (MCF_FEC_EIR_HBERR | MCF_FEC_EIR_BABR | MCF_FEC_EIR_BABT | MCF_FEC_EIR_GRA | + MCF_FEC_EIR_MII | MCF_FEC_EIR_LC | MCF_FEC_EIR_RL | MCF_FEC_EIR_UN)) + { + //Clear interrupt flags + MCF_FEC_EIR = MCF_FEC_EIR_HBERR | MCF_FEC_EIR_BABR | MCF_FEC_EIR_BABT | MCF_FEC_EIR_GRA | + MCF_FEC_EIR_MII | MCF_FEC_EIR_LC | MCF_FEC_EIR_RL | MCF_FEC_EIR_UN; + } + + //Leave interrupt service routine + osExitIsr(flag); +} + + +/** + * @brief MCF5225x Ethernet MAC event handler + * @param[in] interface Underlying network interface + **/ + +void mcf5225xEthEventHandler(NetInterface *interface) +{ + error_t error; + uint32_t status; + + //Read interrupt event register + status = MCF_FEC_EIR; + + //Packet received? + if(status & (MCF_FEC_EIR_RXF | MCF_FEC_EIR_RXB)) + { + //Clear RXF and RXB interrupt flag + MCF_FEC_EIR = MCF_FEC_EIR_RXF | MCF_FEC_EIR_RXB; + + //Process all pending packets + do + { + //Read incoming packet + error = mcf5225xEthReceivePacket(interface); + + //No more data in the receive buffer? + } while(error != ERROR_BUFFER_EMPTY); + } + + //System bus error? + if(status & MCF_FEC_EIR_EBERR) + { + //Clear EBERR interrupt flag + MCF_FEC_EIR = MCF_FEC_EIR_EBERR; + + //Disable Ethernet MAC + MCF_FEC_ECR &= ~MCF_FEC_ECR_ETHER_EN; + //Reset buffer descriptors + mcf5225xEthInitBufferDesc(interface); + //Resume normal operation + MCF_FEC_ECR |= MCF_FEC_ECR_ETHER_EN; + //Instruct the DMA to poll the receive descriptor list + MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE; + } + + //Re-enable Ethernet MAC interrupts + MCF_FEC_EIMR = MCF_FEC_EIMR_TXF | MCF_FEC_EIMR_TXB | + MCF_FEC_EIMR_RXF | MCF_FEC_EIMR_RXB | MCF_FEC_EIMR_EBERR; +} + + +/** + * @brief Send a packet + * @param[in] interface Underlying network interface + * @param[in] buffer Multi-part buffer containing the data to send + * @param[in] offset Offset to the first data byte + * @return Error code + **/ + +error_t mcf5225xEthSendPacket(NetInterface *interface, + const NetBuffer *buffer, size_t offset) +{ + size_t length; + + //Retrieve the length of the packet + length = netBufferGetLength(buffer) - offset; + + //Check the frame length + if(length > MCF5225X_ETH_TX_BUFFER_SIZE) + { + //The transmitter can accept another packet + osSetEvent(&interface->nicTxEvent); + //Report an error + return ERROR_INVALID_LENGTH; + } + + //Make sure the current buffer is available for writing + if(txBufferDesc[txBufferIndex].status & FEC_TX_BD_R) + return ERROR_FAILURE; + + //Copy user data to the transmit buffer + netBufferRead(FEC_ALIGN16(txBuffer[txBufferIndex]), buffer, offset, length); + + //Set frame length + txBufferDesc[txBufferIndex].length = length; + + //Check current index + if(txBufferIndex < (MCF5225X_ETH_TX_BUFFER_COUNT - 1)) + { + //Give the ownership of the descriptor to the DMA engine + txBufferDesc[txBufferIndex].status = FEC_TX_BD_R | + FEC_TX_BD_L | FEC_TX_BD_TC; + + //Point to the next buffer + txBufferIndex++; + } + else + { + //Give the ownership of the descriptor to the DMA engine + txBufferDesc[txBufferIndex].status = FEC_TX_BD_R | + FEC_TX_BD_W | FEC_TX_BD_L | FEC_TX_BD_TC; + + //Wrap around + txBufferIndex = 0; + } + + //Instruct the DMA to poll the transmit descriptor list + MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE; + + //Check whether the next buffer is available for writing + if(!(txBufferDesc[txBufferIndex].status & FEC_TX_BD_R)) + { + //The transmitter can accept another packet + osSetEvent(&interface->nicTxEvent); + } + + //Successful processing + return NO_ERROR; +} + + +/** + * @brief Receive a packet + * @param[in] interface Underlying network interface + * @return Error code + **/ + +error_t mcf5225xEthReceivePacket(NetInterface *interface) +{ + error_t error; + size_t n; + + //Make sure the current buffer is available for reading + if(!(rxBufferDesc[rxBufferIndex].status & FEC_RX_BD_E)) + { + //The frame should not span multiple buffers + if(rxBufferDesc[rxBufferIndex].status & FEC_RX_BD_L) + { + //Check whether an error occurred + if(!(rxBufferDesc[rxBufferIndex].status & (FEC_RX_BD_LG | + FEC_RX_BD_NO | FEC_RX_BD_CR | FEC_RX_BD_OV | FEC_RX_BD_TR))) + { + //Retrieve the length of the frame + n = rxBufferDesc[rxBufferIndex].length; + //Limit the number of data to read + n = MIN(n, MCF5225X_ETH_RX_BUFFER_SIZE); + + //Pass the packet to the upper layer + nicProcessPacket(interface, FEC_ALIGN16(rxBuffer[rxBufferIndex]), n); + + //Valid packet received + error = NO_ERROR; + } + else + { + //The received packet contains an error + error = ERROR_INVALID_PACKET; + } + } + else + { + //The packet is not valid + error = ERROR_INVALID_PACKET; + } + + //Check current index + if(rxBufferIndex < (MCF5225X_ETH_RX_BUFFER_COUNT - 1)) + { + //Give the ownership of the descriptor back to the DMA engine + rxBufferDesc[rxBufferIndex].status = FEC_RX_BD_E; + //Point to the next buffer + rxBufferIndex++; + } + else + { + //Give the ownership of the descriptor back to the DMA engine + rxBufferDesc[rxBufferIndex].status = FEC_RX_BD_E | FEC_RX_BD_W; + //Wrap around + rxBufferIndex = 0; + } + + //Instruct the DMA to poll the receive descriptor list + MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE; + } + else + { + //No more data in the receive buffer + error = ERROR_BUFFER_EMPTY; + } + + //Return status code + return error; +} + + +/** + * @brief Configure multicast MAC address filtering + * @param[in] interface Underlying network interface + * @return Error code + **/ + +error_t mcf5225xEthSetMulticastFilter(NetInterface *interface) +{ + uint_t i; + uint_t k; + uint32_t crc; + uint32_t hashTable[2]; + MacFilterEntry *entry; + + //Debug message + TRACE_DEBUG("Updating MCF5225x hash table...\r\n"); + + //Clear hash table + hashTable[0] = 0; + hashTable[1] = 0; + + //The MAC filter table contains the multicast MAC addresses + //to accept when receiving an Ethernet frame + for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) + { + //Point to the current entry + entry = &interface->macMulticastFilter[i]; + + //Valid entry? + if(entry->refCount > 0) + { + //Compute CRC over the current MAC address + crc = mcf5225xEthCalcCrc(&entry->addr, sizeof(MacAddr)); + + //The upper 6 bits in the CRC register are used to index the + //contents of the hash table + k = (crc >> 26) & 0x3F; + + //Update hash table contents + hashTable[k / 32] |= (1 << (k % 32)); + } + } + + //Write the hash table + MCF_FEC_GALR = hashTable[0]; + MCF_FEC_GAUR = hashTable[1]; + + //Debug message + TRACE_DEBUG(" GALR = %08" PRIX32 "\r\n", MCF_FEC_GALR); + TRACE_DEBUG(" GAUR = %08" PRIX32 "\r\n", MCF_FEC_GAUR); + + //Successful processing + return NO_ERROR; +} + + +/** + * @brief Adjust MAC configuration parameters for proper operation + * @param[in] interface Underlying network interface + * @return Error code + **/ + +error_t mcf5225xEthUpdateMacConfig(NetInterface *interface) +{ + //Disable Ethernet MAC while modifying configuration registers + MCF_FEC_ECR &= ~MCF_FEC_ECR_ETHER_EN; + + //Half-duplex or full-duplex mode? + if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) + { + //Full-duplex mode + MCF_FEC_TCR |= MCF_FEC_TCR_FDEN; + //Receive path operates independently of transmit + MCF_FEC_RCR &= ~MCF_FEC_RCR_DRT; + } + else + { + //Half-duplex mode + MCF_FEC_TCR &= ~MCF_FEC_TCR_FDEN; + //Disable reception of frames while transmitting + MCF_FEC_RCR |= MCF_FEC_RCR_DRT; + } + + //Reset buffer descriptors + mcf5225xEthInitBufferDesc(interface); + + //Re-enable Ethernet MAC + MCF_FEC_ECR |= MCF_FEC_ECR_ETHER_EN; + //Instruct the DMA to poll the receive descriptor list + MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE; + + //Successful processing + return NO_ERROR; +} + + +/** + * @brief Write PHY register + * @param[in] phyAddr PHY address + * @param[in] regAddr Register address + * @param[in] data Register value + **/ + +void mcf5225xEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) +{ + uint32_t value; + + //Set up a write operation + value = MCF_FEC_MMFR_ST(1) | MCF_FEC_MMFR_OP(1) | MCF_FEC_MMFR_TA(2); + //PHY address + value |= MCF_FEC_MMFR_PA(phyAddr); + //Register address + value |= MCF_FEC_MMFR_RA(regAddr); + //Register value + value |= MCF_FEC_MMFR_DATA(data); + + //Clear MII interrupt flag + MCF_FEC_EIR = MCF_FEC_EIR_MII; + //Start a write operation + MCF_FEC_MMFR = value; + //Wait for the write to complete + while(!(MCF_FEC_EIR & MCF_FEC_EIR_MII)); +} + + +/** + * @brief Read PHY register + * @param[in] phyAddr PHY address + * @param[in] regAddr Register address + * @return Register value + **/ + +uint16_t mcf5225xEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) +{ + uint32_t value; + + //Set up a read operation + value = MCF_FEC_MMFR_ST(1) | MCF_FEC_MMFR_OP(2) | MCF_FEC_MMFR_TA(2); + //PHY address + value |= MCF_FEC_MMFR_PA(phyAddr); + //Register address + value |= MCF_FEC_MMFR_RA(regAddr); + + //Clear MII interrupt flag + MCF_FEC_EIR = MCF_FEC_EIR_MII; + //Start a read operation + MCF_FEC_MMFR = value; + //Wait for the read to complete + while(!(MCF_FEC_EIR & MCF_FEC_EIR_MII)); + + //Return PHY register contents + return MCF_FEC_MMFR; +} + + +/** + * @brief CRC calculation + * @param[in] data Pointer to the data over which to calculate the CRC + * @param[in] length Number of bytes to process + * @return Resulting CRC value + **/ + +uint32_t mcf5225xEthCalcCrc(const void *data, size_t length) +{ + uint_t i; + uint_t j; + + //Point to the data over which to calculate the CRC + const uint8_t *p = (uint8_t *) data; + //CRC preset value + uint32_t crc = 0xFFFFFFFF; + + //Loop through data + for(i = 0; i < length; i++) + { + //Update CRC value + crc ^= p[i]; + //The message is processed bit by bit + for(j = 0; j < 8; j++) + { + if(crc & 0x00000001) + crc = (crc >> 1) ^ 0xEDB88320; + else + crc = crc >> 1; + } + } + + //Return CRC value + return crc; +} +