Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fm4_eth.c Source File

fm4_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file fm4_eth.c
00003  * @brief Spansion FM4 Ethernet MAC controller
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL NIC_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "s6e2cc.h"
00034 #include "core/net.h"
00035 #include "drivers/fm4_eth.h"
00036 #include "debug.h"
00037 
00038 //Underlying network interface
00039 static NetInterface *nicDriverInterface;
00040 
00041 //IAR EWARM compiler?
00042 #if defined(__ICCARM__)
00043 
00044 //Transmit buffer
00045 #pragma data_alignment = 4
00046 static uint8_t txBuffer[FM4_ETH_TX_BUFFER_COUNT][FM4_ETH_TX_BUFFER_SIZE];
00047 //Receive buffer
00048 #pragma data_alignment = 4
00049 static uint8_t rxBuffer[FM4_ETH_RX_BUFFER_COUNT][FM4_ETH_RX_BUFFER_SIZE];
00050 //Transmit DMA descriptors
00051 #pragma data_alignment = 4
00052 static Fm4TxDmaDesc txDmaDesc[FM4_ETH_TX_BUFFER_COUNT];
00053 //Receive DMA descriptors
00054 #pragma data_alignment = 4
00055 static Fm4RxDmaDesc rxDmaDesc[FM4_ETH_RX_BUFFER_COUNT];
00056 
00057 //Keil MDK-ARM or GCC compiler?
00058 #else
00059 
00060 //Transmit buffer
00061 static uint8_t txBuffer[FM4_ETH_TX_BUFFER_COUNT][FM4_ETH_TX_BUFFER_SIZE]
00062    __attribute__((aligned(4)));
00063 //Receive buffer
00064 static uint8_t rxBuffer[FM4_ETH_RX_BUFFER_COUNT][FM4_ETH_RX_BUFFER_SIZE]
00065    __attribute__((aligned(4)));
00066 //Transmit DMA descriptors
00067 static Fm4TxDmaDesc txDmaDesc[FM4_ETH_TX_BUFFER_COUNT]
00068    __attribute__((aligned(4)));
00069 //Receive DMA descriptors
00070 static Fm4RxDmaDesc rxDmaDesc[FM4_ETH_RX_BUFFER_COUNT]
00071    __attribute__((aligned(4)));
00072 
00073 #endif
00074 
00075 //Pointer to the current TX DMA descriptor
00076 static Fm4TxDmaDesc *txCurDmaDesc;
00077 //Pointer to the current RX DMA descriptor
00078 static Fm4RxDmaDesc *rxCurDmaDesc;
00079 
00080 
00081 /**
00082  * @brief Spansion FM4 Ethernet MAC driver
00083  **/
00084 
00085 const NicDriver fm4EthDriver =
00086 {
00087    NIC_TYPE_ETHERNET,
00088    ETH_MTU,
00089    fm4EthInit,
00090    fm4EthTick,
00091    fm4EthEnableIrq,
00092    fm4EthDisableIrq,
00093    fm4EthEventHandler,
00094    fm4EthSendPacket,
00095    fm4EthSetMulticastFilter,
00096    fm4EthUpdateMacConfig,
00097    fm4EthWritePhyReg,
00098    fm4EthReadPhyReg,
00099    TRUE,
00100    TRUE,
00101    TRUE,
00102    FALSE
00103 };
00104 
00105 
00106 /**
00107  * @brief Spansion FM4 Ethernet MAC initialization
00108  * @param[in] interface Underlying network interface
00109  * @return Error code
00110  **/
00111 
00112 error_t fm4EthInit(NetInterface *interface)
00113 {
00114    error_t error;
00115 
00116    //Debug message
00117    TRACE_INFO("Initializing Spansion FM4 Ethernet MAC...\r\n");
00118 
00119    //Save underlying network interface
00120    nicDriverInterface = interface;
00121 
00122    //GPIO configuration
00123    fm4EthInitGpio(interface);
00124 
00125    //Enable Ethernet MAC clock
00126    FM4_ETHERNET_CONTROL->ETH_CLKG_f.MACEN = 1;
00127 
00128    //Reset Ethernet MAC peripheral
00129    FM4_ETHERNET_CONTROL->ETH_MODE_f.RST0 = 1;
00130    FM4_ETHERNET_CONTROL->ETH_MODE_f.RST0 = 0;
00131 
00132    //Perform a software reset
00133    FM4_ETHERNET_MAC0->BMR_f.SWR = 1;
00134    //Wait for the reset to complete
00135    while(FM4_ETHERNET_MAC0->BMR_f.SWR);
00136 
00137    //Ensure that ongoing AHB transactions are complete
00138    while(FM4_ETHERNET_MAC0->AHBSR_f.AHBS);
00139 
00140    //Adjust MDC clock range depending on HCLK frequency
00141    FM4_ETHERNET_MAC0->GAR_f.CR = 5;
00142 
00143    //PHY transceiver initialization
00144    error = interface->phyDriver->init(interface);
00145    //Failed to initialize PHY transceiver?
00146    if(error)
00147       return error;
00148 
00149    //Use default MAC configuration
00150    FM4_ETHERNET_MAC0->MCR = 0;
00151    FM4_ETHERNET_MAC0->MCR_f.PS = 1;
00152    FM4_ETHERNET_MAC0->MCR_f.DO = 1;
00153 
00154    //Set the MAC address
00155    FM4_ETHERNET_MAC0->MAR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
00156    FM4_ETHERNET_MAC0->MAR0H = interface->macAddr.w[2];
00157 
00158    //Initialize hash table
00159    FM4_ETHERNET_MAC0->MHTRL = 0;
00160    FM4_ETHERNET_MAC0->MHTRH = 0;
00161 
00162    //Configure the receive filter
00163    FM4_ETHERNET_MAC0->MFFR = 0;
00164    FM4_ETHERNET_MAC0->MFFR_f.HPF = 1;
00165    FM4_ETHERNET_MAC0->MFFR_f.HMC = 1;
00166 
00167    //Disable flow control
00168    FM4_ETHERNET_MAC0->FCR = 0;
00169 
00170    //Enable store and forward mode
00171    FM4_ETHERNET_MAC0->OMR = 0;
00172    FM4_ETHERNET_MAC0->OMR_f.RSF = 1;
00173    FM4_ETHERNET_MAC0->OMR_f.TSF = 1;
00174 
00175    //Configure DMA bus mode
00176    FM4_ETHERNET_MAC0->BMR = 0;
00177    FM4_ETHERNET_MAC0->BMR_f.TXPR = 0;
00178    FM4_ETHERNET_MAC0->BMR_f.MB = 1;
00179    FM4_ETHERNET_MAC0->BMR_f.AAL = 0;
00180    FM4_ETHERNET_MAC0->BMR_f._8XPBL = 0;
00181    FM4_ETHERNET_MAC0->BMR_f.USP = 1;
00182    FM4_ETHERNET_MAC0->BMR_f.RPBL = 1;
00183    FM4_ETHERNET_MAC0->BMR_f.FB = 0;
00184    FM4_ETHERNET_MAC0->BMR_f.PR = 0;
00185    FM4_ETHERNET_MAC0->BMR_f.PBL = 1;
00186    FM4_ETHERNET_MAC0->BMR_f.ATDS = 1;
00187    FM4_ETHERNET_MAC0->BMR_f.DSL = 0;
00188    FM4_ETHERNET_MAC0->BMR_f.DA = 0;
00189 
00190    //Initialize DMA descriptor lists
00191    fm4EthInitDmaDesc(interface);
00192 
00193    //Prevent interrupts from being generated when statistic counters reach
00194    //half their maximum value
00195    FM4_ETHERNET_MAC0->mmc_intr_mask_tx = 0xFFFFFFFF;
00196    FM4_ETHERNET_MAC0->mmc_intr_mask_rx = 0xFFFFFFFF;
00197    FM4_ETHERNET_MAC0->mmc_ipc_intr_mask_rx = 0xFFFFFFFF;
00198 
00199    //Disable MAC interrupts
00200    bFM4_ETHERNET_MAC0_IMR_LPIIM = 1;
00201    bFM4_ETHERNET_MAC0_IMR_TSIM = 1;
00202    bFM4_ETHERNET_MAC0_IMR_PIM = 1;
00203    bFM4_ETHERNET_MAC0_IMR_RGIM = 1;
00204 
00205    //Enable the desired DMA interrupts
00206    bFM4_ETHERNET_MAC0_IER_NIE = 1;
00207    bFM4_ETHERNET_MAC0_IER_RIE = 1;
00208    bFM4_ETHERNET_MAC0_IER_TIE = 1;
00209 
00210    //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
00211    NVIC_SetPriorityGrouping(FM4_ETH_IRQ_PRIORITY_GROUPING);
00212 
00213    //Configure Ethernet interrupt priority
00214    NVIC_SetPriority(ETHER0_IRQn, NVIC_EncodePriority(FM4_ETH_IRQ_PRIORITY_GROUPING,
00215       FM4_ETH_IRQ_GROUP_PRIORITY, FM4_ETH_IRQ_SUB_PRIORITY));
00216 
00217    //Enable MAC transmission and reception
00218    bFM4_ETHERNET_MAC0_MCR_TE = 1;
00219    bFM4_ETHERNET_MAC0_MCR_RE = 1;
00220 
00221    //Enable DMA transmission and reception
00222    bFM4_ETHERNET_MAC0_OMR_ST = 1;
00223    bFM4_ETHERNET_MAC0_OMR_SR = 1;
00224 
00225    //Accept any packets from the upper layer
00226    osSetEvent(&interface->nicTxEvent);
00227 
00228    //Successful initialization
00229    return NO_ERROR;
00230 }
00231 
00232 
00233 //SK-FM4-176L-S6E2CC-ETH evaluation board?
00234 #if defined(USE_SK_FM4_176L_S6E2CC_ETH)
00235 
00236 /**
00237  * @brief GPIO configuration
00238  * @param[in] interface Underlying network interface
00239  **/
00240 
00241 void fm4EthInitGpio(NetInterface *interface)
00242 {
00243    //Select MII interface mode
00244    FM4_ETHERNET_CONTROL->ETH_MODE_f.IFMODE = 0;
00245 
00246    //Configure E_RXER (PC0)
00247    FM4_GPIO->PFRC_f.P0 = 1;
00248    //Configure E_RX03 (PC1)
00249    FM4_GPIO->PFRC_f.P1 = 1;
00250    //Configure E_RX02 (PC2)
00251    FM4_GPIO->PFRC_f.P2 = 1;
00252    //Configure E_RX01 (PC3)
00253    FM4_GPIO->PFRC_f.P3 = 1;
00254    //Configure E_RX00 (PC4)
00255    FM4_GPIO->PFRC_f.P4 = 1;
00256    //Configure E_RXDV (PC5)
00257    FM4_GPIO->PFRC_f.P5 = 1;
00258    //Configure E_MDIO (PC6)
00259    FM4_GPIO->PFRC_f.P6 = 1;
00260    //Configure E_MDC (PC7)
00261    FM4_GPIO->PFRC_f.P7 = 1;
00262    //Configure E_RXCK_REFCK (PC8)
00263    FM4_GPIO->PFRC_f.P8 = 1;
00264    //Configure E_COL (PC9)
00265    FM4_GPIO->PFRC_f.P9 = 1;
00266    //Configure E_CRS (PCA)
00267    FM4_GPIO->PFRC_f.PA = 1;
00268    //Configure E_TCK (PCC)
00269    FM4_GPIO->PFRC_f.PC = 1;
00270    //Configure E_TXER (PCD)
00271    FM4_GPIO->PFRC_f.PD = 1;
00272    //Configure E_TX03 (PCE)
00273    FM4_GPIO->PFRC_f.PE = 1;
00274    //Configure E_TX02 (PCF)
00275    FM4_GPIO->PFRC_f.PF = 1;
00276    //Configure E_TX01 (PD0)
00277    FM4_GPIO->PFRD_f.P0 = 1;
00278    //Configure E_TX00 (PD1)
00279    FM4_GPIO->PFRD_f.P1 = 1;
00280    //Configure E_TXEN (PD2)
00281    FM4_GPIO->PFRD_f.P2 = 1;
00282 
00283    //Peripheral assignment
00284    FM4_GPIO->EPFR14_f.E_TD0E = 1;
00285    FM4_GPIO->EPFR14_f.E_TD1E = 1;
00286    FM4_GPIO->EPFR14_f.E_TE0E = 1;
00287    FM4_GPIO->EPFR14_f.E_TE1E = 1;
00288    FM4_GPIO->EPFR14_f.E_MC0E = 1;
00289    FM4_GPIO->EPFR14_f.E_MC1B = 1;
00290    FM4_GPIO->EPFR14_f.E_MD0B = 1;
00291    FM4_GPIO->EPFR14_f.E_MD1B = 1;
00292    FM4_GPIO->EPFR14_f.E_SPLC = 1;
00293 
00294    //Configure PHY_RST as an output
00295    FM4_GPIO->PFR6_f.PA = 0;
00296    FM4_GPIO->DDR6_f.PA = 1;
00297 
00298    //Reset PHY transceiver
00299    FM4_GPIO->PDOR6_f.PA = 0;
00300    sleep(10);
00301 
00302    //Take the PHY transceiver out of reset
00303    FM4_GPIO->PDOR6_f.PA = 1;
00304    sleep(10);
00305 }
00306 
00307 #endif
00308 
00309 
00310 /**
00311  * @brief Initialize DMA descriptor lists
00312  * @param[in] interface Underlying network interface
00313  **/
00314 
00315 void fm4EthInitDmaDesc(NetInterface *interface)
00316 {
00317    uint_t i;
00318 
00319    //Initialize TX DMA descriptor list
00320    for(i = 0; i < FM4_ETH_TX_BUFFER_COUNT; i++)
00321    {
00322       //Use chain structure rather than ring structure
00323       txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
00324       //Initialize transmit buffer size
00325       txDmaDesc[i].tdes1 = 0;
00326       //Transmit buffer address
00327       txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
00328       //Next descriptor address
00329       txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
00330       //Reserved fields
00331       txDmaDesc[i].tdes4 = 0;
00332       txDmaDesc[i].tdes5 = 0;
00333       //Transmit frame time stamp
00334       txDmaDesc[i].tdes6 = 0;
00335       txDmaDesc[i].tdes7 = 0;
00336    }
00337 
00338    //The last descriptor is chained to the first entry
00339    txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
00340    //Point to the very first descriptor
00341    txCurDmaDesc = &txDmaDesc[0];
00342 
00343    //Initialize RX DMA descriptor list
00344    for(i = 0; i < FM4_ETH_RX_BUFFER_COUNT; i++)
00345    {
00346       //The descriptor is initially owned by the DMA
00347       rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
00348       //Use chain structure rather than ring structure
00349       rxDmaDesc[i].rdes1 = ETH_RDES1_RCH | (FM4_ETH_RX_BUFFER_SIZE & ETH_RDES1_RBS1);
00350       //Receive buffer address
00351       rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
00352       //Next descriptor address
00353       rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
00354       //Extended status
00355       rxDmaDesc[i].rdes4 = 0;
00356       //Reserved field
00357       rxDmaDesc[i].rdes5 = 0;
00358       //Receive frame time stamp
00359       rxDmaDesc[i].rdes6 = 0;
00360       rxDmaDesc[i].rdes7 = 0;
00361    }
00362 
00363    //The last descriptor is chained to the first entry
00364    rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
00365    //Point to the very first descriptor
00366    rxCurDmaDesc = &rxDmaDesc[0];
00367 
00368    //Start location of the TX descriptor list
00369    FM4_ETHERNET_MAC0->TDLAR = (uint32_t) txDmaDesc;
00370    //Start location of the RX descriptor list
00371    FM4_ETHERNET_MAC0->RDLAR = (uint32_t) rxDmaDesc;
00372 }
00373 
00374 
00375 /**
00376  * @brief Spansion FM4 Ethernet MAC timer handler
00377  *
00378  * This routine is periodically called by the TCP/IP stack to
00379  * handle periodic operations such as polling the link state
00380  *
00381  * @param[in] interface Underlying network interface
00382  **/
00383 
00384 void fm4EthTick(NetInterface *interface)
00385 {
00386    //Handle periodic operations
00387    interface->phyDriver->tick(interface);
00388 }
00389 
00390 
00391 /**
00392  * @brief Enable interrupts
00393  * @param[in] interface Underlying network interface
00394  **/
00395 
00396 void fm4EthEnableIrq(NetInterface *interface)
00397 {
00398    //Enable Ethernet MAC interrupts
00399    NVIC_EnableIRQ(ETHER0_IRQn);
00400    //Enable Ethernet PHY interrupts
00401    interface->phyDriver->enableIrq(interface);
00402 }
00403 
00404 
00405 /**
00406  * @brief Disable interrupts
00407  * @param[in] interface Underlying network interface
00408  **/
00409 
00410 void fm4EthDisableIrq(NetInterface *interface)
00411 {
00412    //Disable Ethernet MAC interrupts
00413    NVIC_DisableIRQ(ETHER0_IRQn);
00414    //Disable Ethernet PHY interrupts
00415    interface->phyDriver->disableIrq(interface);
00416 }
00417 
00418 
00419 /**
00420  * @brief Spansion FM4 Ethernet MAC interrupt service routine
00421  **/
00422 
00423 void ETHER0_IRQHandler(void)
00424 {
00425    bool_t flag;
00426 
00427    //Enter interrupt service routine
00428    osEnterIsr();
00429 
00430    //This flag will be set if a higher priority task must be woken
00431    flag = FALSE;
00432 
00433    //A packet has been transmitted?
00434    if(bFM4_ETHERNET_MAC0_SR_TI)
00435    {
00436       //Clear TI interrupt flag
00437       bFM4_ETHERNET_MAC0_SR_TI = 1;
00438 
00439       //Check whether the TX buffer is available for writing
00440       if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
00441       {
00442          //Notify the TCP/IP stack that the transmitter is ready to send
00443          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00444       }
00445    }
00446 
00447    //A packet has been received?
00448    if(bFM4_ETHERNET_MAC0_SR_RI)
00449    {
00450       //Disable RIE interrupt
00451       bFM4_ETHERNET_MAC0_IER_RIE = 0;
00452 
00453       //Set event flag
00454       nicDriverInterface->nicEvent = TRUE;
00455       //Notify the TCP/IP stack of the event
00456       flag |= osSetEventFromIsr(&netEvent);
00457    }
00458 
00459    //Clear NIS interrupt flag
00460    bFM4_ETHERNET_MAC0_SR_NIS = 1;
00461 
00462    //Leave interrupt service routine
00463    osExitIsr(flag);
00464 }
00465 
00466 
00467 /**
00468  * @brief Spansion FM4 Ethernet MAC event handler
00469  * @param[in] interface Underlying network interface
00470  **/
00471 
00472 void fm4EthEventHandler(NetInterface *interface)
00473 {
00474    error_t error;
00475 
00476    //Packet received?
00477    if(bFM4_ETHERNET_MAC0_SR_RI)
00478    {
00479       //Clear interrupt flag
00480       bFM4_ETHERNET_MAC0_SR_RI = 1;
00481 
00482       //Process all pending packets
00483       do
00484       {
00485          //Read incoming packet
00486          error = fm4EthReceivePacket(interface);
00487 
00488          //No more data in the receive buffer?
00489       } while(error != ERROR_BUFFER_EMPTY);
00490    }
00491 
00492    //Re-enable DMA interrupts
00493    bFM4_ETHERNET_MAC0_IER_NIE = 1;
00494    bFM4_ETHERNET_MAC0_IER_RIE = 1;
00495    bFM4_ETHERNET_MAC0_IER_TIE = 1;
00496 }
00497 
00498 
00499 /**
00500  * @brief Send a packet
00501  * @param[in] interface Underlying network interface
00502  * @param[in] buffer Multi-part buffer containing the data to send
00503  * @param[in] offset Offset to the first data byte
00504  * @return Error code
00505  **/
00506 
00507 error_t fm4EthSendPacket(NetInterface *interface,
00508    const NetBuffer *buffer, size_t offset)
00509 {
00510    size_t length;
00511 
00512    //Retrieve the length of the packet
00513    length = netBufferGetLength(buffer) - offset;
00514 
00515    //Check the frame length
00516    if(length > FM4_ETH_TX_BUFFER_SIZE)
00517    {
00518       //The transmitter can accept another packet
00519       osSetEvent(&interface->nicTxEvent);
00520       //Report an error
00521       return ERROR_INVALID_LENGTH;
00522    }
00523 
00524    //Make sure the current buffer is available for writing
00525    if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)
00526       return ERROR_FAILURE;
00527 
00528    //Copy user data to the transmit buffer
00529    netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
00530 
00531    //Write the number of bytes to send
00532    txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
00533    //Set LS and FS flags as the data fits in a single buffer
00534    txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
00535    //Give the ownership of the descriptor to the DMA
00536    txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
00537 
00538    //Clear TU flag to resume processing
00539    bFM4_ETHERNET_MAC0_SR_TU = 1;
00540    //Instruct the DMA to poll the transmit descriptor list
00541    FM4_ETHERNET_MAC0->TPDR = 0;
00542 
00543    //Point to the next descriptor in the list
00544    txCurDmaDesc = (Fm4TxDmaDesc *) txCurDmaDesc->tdes3;
00545 
00546    //Check whether the next buffer is available for writing
00547    if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
00548    {
00549       //The transmitter can accept another packet
00550       osSetEvent(&interface->nicTxEvent);
00551    }
00552 
00553    //Data successfully written
00554    return NO_ERROR;
00555 }
00556 
00557 
00558 /**
00559  * @brief Receive a packet
00560  * @param[in] interface Underlying network interface
00561  * @return Error code
00562  **/
00563 
00564 error_t fm4EthReceivePacket(NetInterface *interface)
00565 {
00566    error_t error;
00567    size_t n;
00568 
00569    //The current buffer is available for reading?
00570    if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN))
00571    {
00572       //FS and LS flags should be set
00573       if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS))
00574       {
00575          //Make sure no error occurred
00576          if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES))
00577          {
00578             //Retrieve the length of the frame
00579             n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
00580             //Limit the number of data to read
00581             n = MIN(n, FM4_ETH_RX_BUFFER_SIZE);
00582 
00583             //Pass the packet to the upper layer
00584             nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
00585 
00586             //Valid packet received
00587             error = NO_ERROR;
00588          }
00589          else
00590          {
00591             //The received packet contains an error
00592             error = ERROR_INVALID_PACKET;
00593          }
00594       }
00595       else
00596       {
00597          //The packet is not valid
00598          error = ERROR_INVALID_PACKET;
00599       }
00600 
00601       //Give the ownership of the descriptor back to the DMA
00602       rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
00603       //Point to the next descriptor in the list
00604       rxCurDmaDesc = (Fm4RxDmaDesc *) rxCurDmaDesc->rdes3;
00605    }
00606    else
00607    {
00608       //No more data in the receive buffer
00609       error = ERROR_BUFFER_EMPTY;
00610    }
00611 
00612    //Clear RU flag to resume processing
00613    bFM4_ETHERNET_MAC0_SR_RU = 1;
00614    //Instruct the DMA to poll the receive descriptor list
00615    FM4_ETHERNET_MAC0->RPDR = 0;
00616 
00617    //Return status code
00618    return error;
00619 }
00620 
00621 
00622 /**
00623  * @brief Configure multicast MAC address filtering
00624  * @param[in] interface Underlying network interface
00625  * @return Error code
00626  **/
00627 
00628 error_t fm4EthSetMulticastFilter(NetInterface *interface)
00629 {
00630    uint_t i;
00631    uint_t k;
00632    uint32_t crc;
00633    uint32_t hashTable[2];
00634    MacFilterEntry *entry;
00635 
00636    //Debug message
00637    TRACE_DEBUG("Updating Spansion FM4 hash table...\r\n");
00638 
00639    //Clear hash table
00640    hashTable[0] = 0;
00641    hashTable[1] = 0;
00642 
00643    //The MAC filter table contains the multicast MAC addresses
00644    //to accept when receiving an Ethernet frame
00645    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00646    {
00647       //Point to the current entry
00648       entry = &interface->macMulticastFilter[i];
00649 
00650       //Valid entry?
00651       if(entry->refCount > 0)
00652       {
00653          //Compute CRC over the current MAC address
00654          crc = fm4EthCalcCrc(&entry->addr, sizeof(MacAddr));
00655 
00656          //The upper 6 bits in the CRC register are used to index the
00657          //contents of the hash table
00658          k = (crc >> 26) & 0x3F;
00659 
00660          //Update hash table contents
00661          hashTable[k / 32] |= (1 << (k % 32));
00662       }
00663    }
00664 
00665    //Write the hash table
00666    FM4_ETHERNET_MAC0->MHTRL = hashTable[0];
00667    FM4_ETHERNET_MAC0->MHTRH = hashTable[1];
00668 
00669    //Debug message
00670    TRACE_DEBUG("  MACHTLR = %08" PRIX32 "\r\n", FM4_ETHERNET_MAC0->MHTRL);
00671    TRACE_DEBUG("  MACHTHR = %08" PRIX32 "\r\n", FM4_ETHERNET_MAC0->MHTRH);
00672 
00673    //Successful processing
00674    return NO_ERROR;
00675 }
00676 
00677 
00678 /**
00679  * @brief Adjust MAC configuration parameters for proper operation
00680  * @param[in] interface Underlying network interface
00681  * @return Error code
00682  **/
00683 
00684 error_t fm4EthUpdateMacConfig(NetInterface *interface)
00685 {
00686    //10BASE-T or 100BASE-TX operation mode?
00687    if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
00688       bFM4_ETHERNET_MAC0_MCR_FES = 1;
00689    else
00690       bFM4_ETHERNET_MAC0_MCR_FES = 0;
00691 
00692    //Half-duplex or full-duplex mode?
00693    if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00694       bFM4_ETHERNET_MAC0_MCR_DM = 1;
00695    else
00696       bFM4_ETHERNET_MAC0_MCR_DM = 0;
00697 
00698    //Successful processing
00699    return NO_ERROR;
00700 }
00701 
00702 
00703 /**
00704  * @brief Write PHY register
00705  * @param[in] phyAddr PHY address
00706  * @param[in] regAddr Register address
00707  * @param[in] data Register value
00708  **/
00709 
00710 void fm4EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
00711 {
00712    //Set up a write operation
00713    FM4_ETHERNET_MAC0->GAR_f.GW = 1;
00714    //PHY address
00715    FM4_ETHERNET_MAC0->GAR_f.PA = phyAddr;
00716    //Register address
00717    FM4_ETHERNET_MAC0->GAR_f.GR = regAddr;
00718 
00719    //Data to be written in the PHY register
00720    FM4_ETHERNET_MAC0->GDR_f.GD = data;
00721 
00722    //Start a write operation
00723    FM4_ETHERNET_MAC0->GAR_f.GB = 1;
00724    //Wait for the write to complete
00725    while(FM4_ETHERNET_MAC0->GAR_f.GB);
00726 }
00727 
00728 
00729 /**
00730  * @brief Read PHY register
00731  * @param[in] phyAddr PHY address
00732  * @param[in] regAddr Register address
00733  * @return Register value
00734  **/
00735 
00736 uint16_t fm4EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
00737 {
00738    //Set up a read operation
00739    FM4_ETHERNET_MAC0->GAR_f.GW = 0;
00740    //PHY address
00741    FM4_ETHERNET_MAC0->GAR_f.PA = phyAddr;
00742    //Register address
00743    FM4_ETHERNET_MAC0->GAR_f.GR = regAddr;
00744 
00745    //Start a read operation
00746    FM4_ETHERNET_MAC0->GAR_f.GB = 1;
00747    //Wait for the read to complete
00748    while(FM4_ETHERNET_MAC0->GAR_f.GB);
00749 
00750    //Return PHY register contents
00751    return FM4_ETHERNET_MAC0->GDR_f.GD;
00752 }
00753 
00754 
00755 /**
00756  * @brief CRC calculation
00757  * @param[in] data Pointer to the data over which to calculate the CRC
00758  * @param[in] length Number of bytes to process
00759  * @return Resulting CRC value
00760  **/
00761 
00762 uint32_t fm4EthCalcCrc(const void *data, size_t length)
00763 {
00764    uint_t i;
00765    uint_t j;
00766 
00767    //Point to the data over which to calculate the CRC
00768    const uint8_t *p = (uint8_t *) data;
00769    //CRC preset value
00770    uint32_t crc = 0xFFFFFFFF;
00771 
00772    //Loop through data
00773    for(i = 0; i < length; i++)
00774    {
00775       //The message is processed bit by bit
00776       for(j = 0; j < 8; j++)
00777       {
00778          //Update CRC value
00779          if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
00780             crc = (crc << 1) ^ 0x04C11DB7;
00781          else
00782             crc = crc << 1;
00783       }
00784    }
00785 
00786    //Return CRC value
00787    return ~crc;
00788 }
00789