Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sam4e_eth.c Source File

sam4e_eth.c

Go to the documentation of this file.
00001 /**
00002  * @file sam4e_eth.c
00003  * @brief SAM4E 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 <limits.h>
00034 #include "sam4e.h"
00035 #include "core/net.h"
00036 #include "drivers/sam4e_eth.h"
00037 #include "debug.h"
00038 
00039 //Underlying network interface
00040 static NetInterface *nicDriverInterface;
00041 
00042 //IAR EWARM compiler?
00043 #if defined(__ICCARM__)
00044 
00045 //TX buffer
00046 #pragma data_alignment = 8
00047 static uint8_t txBuffer[SAM4E_ETH_TX_BUFFER_COUNT][SAM4E_ETH_TX_BUFFER_SIZE];
00048 //RX buffer
00049 #pragma data_alignment = 8
00050 static uint8_t rxBuffer[SAM4E_ETH_RX_BUFFER_COUNT][SAM4E_ETH_RX_BUFFER_SIZE];
00051 //TX buffer descriptors
00052 #pragma data_alignment = 4
00053 static Sam4eTxBufferDesc txBufferDesc[SAM4E_ETH_TX_BUFFER_COUNT];
00054 //RX buffer descriptors
00055 #pragma data_alignment = 4
00056 static Sam4eRxBufferDesc rxBufferDesc[SAM4E_ETH_RX_BUFFER_COUNT];
00057 
00058 //Keil MDK-ARM or GCC compiler?
00059 #else
00060 
00061 //TX buffer
00062 static uint8_t txBuffer[SAM4E_ETH_TX_BUFFER_COUNT][SAM4E_ETH_TX_BUFFER_SIZE]
00063    __attribute__((aligned(8)));
00064 //RX buffer
00065 static uint8_t rxBuffer[SAM4E_ETH_RX_BUFFER_COUNT][SAM4E_ETH_RX_BUFFER_SIZE]
00066    __attribute__((aligned(8)));
00067 //TX buffer descriptors
00068 static Sam4eTxBufferDesc txBufferDesc[SAM4E_ETH_TX_BUFFER_COUNT]
00069    __attribute__((aligned(4)));
00070 //RX buffer descriptors
00071 static Sam4eRxBufferDesc rxBufferDesc[SAM4E_ETH_RX_BUFFER_COUNT]
00072    __attribute__((aligned(4)));
00073 
00074 #endif
00075 
00076 //TX buffer index
00077 static uint_t txBufferIndex;
00078 //RX buffer index
00079 static uint_t rxBufferIndex;
00080 
00081 
00082 /**
00083  * @brief SAM4E Ethernet MAC driver
00084  **/
00085 
00086 const NicDriver sam4eEthDriver =
00087 {
00088    NIC_TYPE_ETHERNET,
00089    ETH_MTU,
00090    sam4eEthInit,
00091    sam4eEthTick,
00092    sam4eEthEnableIrq,
00093    sam4eEthDisableIrq,
00094    sam4eEthEventHandler,
00095    sam4eEthSendPacket,
00096    sam4eEthSetMulticastFilter,
00097    sam4eEthUpdateMacConfig,
00098    sam4eEthWritePhyReg,
00099    sam4eEthReadPhyReg,
00100    TRUE,
00101    TRUE,
00102    TRUE,
00103    FALSE
00104 };
00105 
00106 
00107 /**
00108  * @brief SAM4E Ethernet MAC initialization
00109  * @param[in] interface Underlying network interface
00110  * @return Error code
00111  **/
00112 
00113 error_t sam4eEthInit(NetInterface *interface)
00114 {
00115    error_t error;
00116    volatile uint32_t status;
00117 
00118    //Debug message
00119    TRACE_INFO("Initializing SAM4E Ethernet MAC...\r\n");
00120 
00121    //Save underlying network interface
00122    nicDriverInterface = interface;
00123 
00124    //Enable GMAC peripheral clock
00125    PMC->PMC_PCER1 = (1 << (ID_GMAC - 32));
00126 
00127    //GPIO configuration
00128    sam4eEthInitGpio(interface);
00129 
00130    //Configure MDC clock speed
00131    GMAC->GMAC_NCFGR = GMAC_NCFGR_CLK_MCK_96;
00132    //Enable management port (MDC and MDIO)
00133    GMAC->GMAC_NCR |= GMAC_NCR_MPE;
00134 
00135    //PHY transceiver initialization
00136    error = interface->phyDriver->init(interface);
00137    //Failed to initialize PHY transceiver?
00138    if(error)
00139       return error;
00140 
00141    //Set the MAC address
00142    GMAC->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
00143    GMAC->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2];
00144 
00145    //Configure the receive filter
00146    GMAC->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN | GMAC_NCFGR_MTIHEN;
00147 
00148    //Initialize hash table
00149    GMAC->GMAC_HRB = 0;
00150    GMAC->GMAC_HRT = 0;
00151 
00152    //Initialize buffer descriptors
00153    sam4eEthInitBufferDesc(interface);
00154 
00155    //Clear transmit status register
00156    GMAC->GMAC_TSR = GMAC_TSR_HRESP | GMAC_TSR_UND | GMAC_TSR_TXCOMP | GMAC_TSR_TFC |
00157       GMAC_TSR_TXGO | GMAC_TSR_RLE | GMAC_TSR_COL | GMAC_TSR_UBR;
00158    //Clear receive status register
00159    GMAC->GMAC_RSR = GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA;
00160 
00161    //First disable all GMAC interrupts
00162    GMAC->GMAC_IDR = 0xFFFFFFFF;
00163    //Only the desired ones are enabled
00164    GMAC->GMAC_IER = GMAC_IER_HRESP | GMAC_IER_ROVR | GMAC_IER_TCOMP | GMAC_IER_TFC |
00165       GMAC_IER_RLEX | GMAC_IER_TUR | GMAC_IER_RXUBR | GMAC_IER_RCOMP;
00166 
00167    //Read GMAC ISR register to clear any pending interrupt
00168    status = GMAC->GMAC_ISR;
00169 
00170    //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
00171    NVIC_SetPriorityGrouping(SAM4E_ETH_IRQ_PRIORITY_GROUPING);
00172 
00173    //Configure GMAC interrupt priority
00174    NVIC_SetPriority(GMAC_IRQn, NVIC_EncodePriority(SAM4E_ETH_IRQ_PRIORITY_GROUPING,
00175       SAM4E_ETH_IRQ_GROUP_PRIORITY, SAM4E_ETH_IRQ_SUB_PRIORITY));
00176 
00177    //Enable the GMAC to transmit and receive data
00178    GMAC->GMAC_NCR |= GMAC_NCR_TXEN | GMAC_NCR_RXEN;
00179 
00180    //Accept any packets from the upper layer
00181    osSetEvent(&interface->nicTxEvent);
00182 
00183    //Successful initialization
00184    return NO_ERROR;
00185 }
00186 
00187 
00188 //SAM4E-EK or SAM4E-Xplained-Pro evaluation board?
00189 #if defined(USE_SAM4E_EK) || defined(USE_SAM4E_XPLAINED_PRO)
00190 
00191 /**
00192  * @brief GPIO configuration
00193  * @param[in] interface Underlying network interface
00194  **/
00195 
00196 void sam4eEthInitGpio(NetInterface *interface)
00197 {
00198    //Enable PIO peripheral clock
00199    PMC->PMC_PCER0 = (1 << ID_PIOD);
00200 
00201    //Disable pull-up resistors on MII pins
00202    PIOD->PIO_PUDR = GMAC_MII_MASK;
00203    //Disable interrupts-on-change
00204    PIOD->PIO_IDR = GMAC_MII_MASK;
00205    //Assign MII pins to peripheral A function
00206    PIOD->PIO_ABCDSR[0] &= ~GMAC_MII_MASK;
00207    PIOD->PIO_ABCDSR[1] &= ~GMAC_MII_MASK;
00208    //Disable the PIO from controlling the corresponding pins
00209    PIOD->PIO_PDR = GMAC_MII_MASK;
00210 
00211    //Select MII operation mode
00212    GMAC->GMAC_UR = GMAC_UR_RMIIMII;
00213 }
00214 
00215 #endif
00216 
00217 
00218 /**
00219  * @brief Initialize buffer descriptors
00220  * @param[in] interface Underlying network interface
00221  **/
00222 
00223 void sam4eEthInitBufferDesc(NetInterface *interface)
00224 {
00225    uint_t i;
00226    uint32_t address;
00227 
00228    //Initialize TX buffer descriptors
00229    for(i = 0; i < SAM4E_ETH_TX_BUFFER_COUNT; i++)
00230    {
00231       //Calculate the address of the current TX buffer
00232       address = (uint32_t) txBuffer[i];
00233       //Write the address to the descriptor entry
00234       txBufferDesc[i].address = address;
00235       //Initialize status field
00236       txBufferDesc[i].status = GMAC_TX_USED;
00237    }
00238 
00239    //Mark the last descriptor entry with the wrap flag
00240    txBufferDesc[i - 1].status |= GMAC_TX_WRAP;
00241    //Initialize TX buffer index
00242    txBufferIndex = 0;
00243 
00244    //Initialize RX buffer descriptors
00245    for(i = 0; i < SAM4E_ETH_RX_BUFFER_COUNT; i++)
00246    {
00247       //Calculate the address of the current RX buffer
00248       address = (uint32_t) rxBuffer[i];
00249       //Write the address to the descriptor entry
00250       rxBufferDesc[i].address = address & GMAC_RX_ADDRESS;
00251       //Clear status field
00252       rxBufferDesc[i].status = 0;
00253    }
00254 
00255    //Mark the last descriptor entry with the wrap flag
00256    rxBufferDesc[i - 1].address |= GMAC_RX_WRAP;
00257    //Initialize RX buffer index
00258    rxBufferIndex = 0;
00259 
00260    //Start location of the TX descriptor list
00261    GMAC->GMAC_TBQB = (uint32_t) txBufferDesc;
00262    //Start location of the RX descriptor list
00263    GMAC->GMAC_RBQB = (uint32_t) rxBufferDesc;
00264 }
00265 
00266 
00267 /**
00268  * @brief SAM4E Ethernet MAC timer handler
00269  *
00270  * This routine is periodically called by the TCP/IP stack to
00271  * handle periodic operations such as polling the link state
00272  *
00273  * @param[in] interface Underlying network interface
00274  **/
00275 
00276 void sam4eEthTick(NetInterface *interface)
00277 {
00278    //Handle periodic operations
00279    interface->phyDriver->tick(interface);
00280 }
00281 
00282 
00283 /**
00284  * @brief Enable interrupts
00285  * @param[in] interface Underlying network interface
00286  **/
00287 
00288 void sam4eEthEnableIrq(NetInterface *interface)
00289 {
00290    //Enable Ethernet MAC interrupts
00291    NVIC_EnableIRQ(GMAC_IRQn);
00292    //Enable Ethernet PHY interrupts
00293    interface->phyDriver->enableIrq(interface);
00294 }
00295 
00296 
00297 /**
00298  * @brief Disable interrupts
00299  * @param[in] interface Underlying network interface
00300  **/
00301 
00302 void sam4eEthDisableIrq(NetInterface *interface)
00303 {
00304    //Disable Ethernet MAC interrupts
00305    NVIC_DisableIRQ(GMAC_IRQn);
00306    //Disable Ethernet PHY interrupts
00307    interface->phyDriver->disableIrq(interface);
00308 }
00309 
00310 
00311 /**
00312  * @brief SAM4E Ethernet MAC interrupt service routine
00313  **/
00314 
00315 void GMAC_Handler(void)
00316 {
00317    bool_t flag;
00318    volatile uint32_t isr;
00319    volatile uint32_t tsr;
00320    volatile uint32_t rsr;
00321 
00322    //Enter interrupt service routine
00323    osEnterIsr();
00324 
00325    //This flag will be set if a higher priority task must be woken
00326    flag = FALSE;
00327 
00328    //Each time the software reads GMAC_ISR, it has to check the
00329    //contents of GMAC_TSR, GMAC_RSR and GMAC_NSR
00330    isr = GMAC->GMAC_ISR;
00331    tsr = GMAC->GMAC_TSR;
00332    rsr = GMAC->GMAC_RSR;
00333 
00334    //A packet has been transmitted?
00335    if(tsr & (GMAC_TSR_HRESP | GMAC_TSR_UND | GMAC_TSR_TXCOMP | GMAC_TSR_TFC |
00336       GMAC_TSR_TXGO | GMAC_TSR_RLE | GMAC_TSR_COL | GMAC_TSR_UBR))
00337    {
00338       //Only clear TSR flags that are currently set
00339       GMAC->GMAC_TSR = tsr;
00340 
00341       //Check whether the TX buffer is available for writing
00342       if(txBufferDesc[txBufferIndex].status & GMAC_TX_USED)
00343       {
00344          //Notify the TCP/IP stack that the transmitter is ready to send
00345          flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
00346       }
00347    }
00348 
00349    //A packet has been received?
00350    if(rsr & (GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA))
00351    {
00352       //Set event flag
00353       nicDriverInterface->nicEvent = TRUE;
00354       //Notify the TCP/IP stack of the event
00355       flag |= osSetEventFromIsr(&netEvent);
00356    }
00357 
00358    //Leave interrupt service routine
00359    osExitIsr(flag);
00360 }
00361 
00362 
00363 /**
00364  * @brief SAM4E Ethernet MAC event handler
00365  * @param[in] interface Underlying network interface
00366  **/
00367 
00368 void sam4eEthEventHandler(NetInterface *interface)
00369 {
00370    error_t error;
00371    uint32_t rsr;
00372 
00373    //Read receive status
00374    rsr = GMAC->GMAC_RSR;
00375 
00376    //Packet received?
00377    if(rsr & (GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA))
00378    {
00379       //Only clear RSR flags that are currently set
00380       GMAC->GMAC_RSR = rsr;
00381 
00382       //Process all pending packets
00383       do
00384       {
00385          //Read incoming packet
00386          error = sam4eEthReceivePacket(interface);
00387 
00388          //No more data in the receive buffer?
00389       } while(error != ERROR_BUFFER_EMPTY);
00390    }
00391 }
00392 
00393 
00394 /**
00395  * @brief Send a packet
00396  * @param[in] interface Underlying network interface
00397  * @param[in] buffer Multi-part buffer containing the data to send
00398  * @param[in] offset Offset to the first data byte
00399  * @return Error code
00400  **/
00401 
00402 error_t sam4eEthSendPacket(NetInterface *interface,
00403    const NetBuffer *buffer, size_t offset)
00404 {
00405    size_t length;
00406 
00407    //Retrieve the length of the packet
00408    length = netBufferGetLength(buffer) - offset;
00409 
00410    //Check the frame length
00411    if(length > SAM4E_ETH_TX_BUFFER_SIZE)
00412    {
00413       //The transmitter can accept another packet
00414       osSetEvent(&interface->nicTxEvent);
00415       //Report an error
00416       return ERROR_INVALID_LENGTH;
00417    }
00418 
00419    //Make sure the current buffer is available for writing
00420    if(!(txBufferDesc[txBufferIndex].status & GMAC_TX_USED))
00421       return ERROR_FAILURE;
00422 
00423    //Copy user data to the transmit buffer
00424    netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
00425 
00426    //Set the necessary flags in the descriptor entry
00427    if(txBufferIndex < (SAM4E_ETH_TX_BUFFER_COUNT - 1))
00428    {
00429       //Write the status word
00430       txBufferDesc[txBufferIndex].status =
00431          GMAC_TX_LAST | (length & GMAC_TX_LENGTH);
00432 
00433       //Point to the next buffer
00434       txBufferIndex++;
00435    }
00436    else
00437    {
00438       //Write the status word
00439       txBufferDesc[txBufferIndex].status = GMAC_TX_WRAP |
00440          GMAC_TX_LAST | (length & GMAC_TX_LENGTH);
00441 
00442       //Wrap around
00443       txBufferIndex = 0;
00444    }
00445 
00446    //Set the TSTART bit to initiate transmission
00447    GMAC->GMAC_NCR |= GMAC_NCR_TSTART;
00448 
00449    //Check whether the next buffer is available for writing
00450    if(txBufferDesc[txBufferIndex].status & GMAC_TX_USED)
00451    {
00452       //The transmitter can accept another packet
00453       osSetEvent(&interface->nicTxEvent);
00454    }
00455 
00456    //Successful processing
00457    return NO_ERROR;
00458 }
00459 
00460 
00461 /**
00462  * @brief Receive a packet
00463  * @param[in] interface Underlying network interface
00464  * @return Error code
00465  **/
00466 
00467 error_t sam4eEthReceivePacket(NetInterface *interface)
00468 {
00469    static uint8_t temp[ETH_MAX_FRAME_SIZE];
00470    error_t error;
00471    uint_t i;
00472    uint_t j;
00473    uint_t sofIndex;
00474    uint_t eofIndex;
00475    size_t n;
00476    size_t size;
00477    size_t length;
00478 
00479    //Initialize SOF and EOF indices
00480    sofIndex = UINT_MAX;
00481    eofIndex = UINT_MAX;
00482 
00483    //Search for SOF and EOF flags
00484    for(i = 0; i < SAM4E_ETH_RX_BUFFER_COUNT; i++)
00485    {
00486       //Point to the current entry
00487       j = rxBufferIndex + i;
00488 
00489       //Wrap around to the beginning of the buffer if necessary
00490       if(j >= SAM4E_ETH_RX_BUFFER_COUNT)
00491          j -= SAM4E_ETH_RX_BUFFER_COUNT;
00492 
00493       //No more entries to process?
00494       if(!(rxBufferDesc[j].address & GMAC_RX_OWNERSHIP))
00495       {
00496          //Stop processing
00497          break;
00498       }
00499       //A valid SOF has been found?
00500       if(rxBufferDesc[j].status & GMAC_RX_SOF)
00501       {
00502          //Save the position of the SOF
00503          sofIndex = i;
00504       }
00505       //A valid EOF has been found?
00506       if((rxBufferDesc[j].status & GMAC_RX_EOF) && sofIndex != UINT_MAX)
00507       {
00508          //Save the position of the EOF
00509          eofIndex = i;
00510          //Retrieve the length of the frame
00511          size = rxBufferDesc[j].status & GMAC_RX_LENGTH;
00512          //Limit the number of data to read
00513          size = MIN(size, ETH_MAX_FRAME_SIZE);
00514          //Stop processing since we have reached the end of the frame
00515          break;
00516       }
00517    }
00518 
00519    //Determine the number of entries to process
00520    if(eofIndex != UINT_MAX)
00521       j = eofIndex + 1;
00522    else if(sofIndex != UINT_MAX)
00523       j = sofIndex;
00524    else
00525       j = i;
00526 
00527    //Total number of bytes that have been copied from the receive buffer
00528    length = 0;
00529 
00530    //Process incoming frame
00531    for(i = 0; i < j; i++)
00532    {
00533       //Any data to copy from current buffer?
00534       if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
00535       {
00536          //Calculate the number of bytes to read at a time
00537          n = MIN(size, SAM4E_ETH_RX_BUFFER_SIZE);
00538          //Copy data from receive buffer
00539          memcpy(temp + length, rxBuffer[rxBufferIndex], n);
00540          //Update byte counters
00541          length += n;
00542          size -= n;
00543       }
00544 
00545       //Mark the current buffer as free
00546       rxBufferDesc[rxBufferIndex].address &= ~GMAC_RX_OWNERSHIP;
00547 
00548       //Point to the following entry
00549       rxBufferIndex++;
00550 
00551       //Wrap around to the beginning of the buffer if necessary
00552       if(rxBufferIndex >= SAM4E_ETH_RX_BUFFER_COUNT)
00553          rxBufferIndex = 0;
00554    }
00555 
00556    //Any packet to process?
00557    if(length > 0)
00558    {
00559       //Pass the packet to the upper layer
00560       nicProcessPacket(interface, temp, length);
00561       //Valid packet received
00562       error = NO_ERROR;
00563    }
00564    else
00565    {
00566       //No more data in the receive buffer
00567       error = ERROR_BUFFER_EMPTY;
00568    }
00569 
00570    //Return status code
00571    return error;
00572 }
00573 
00574 
00575 /**
00576  * @brief Configure multicast MAC address filtering
00577  * @param[in] interface Underlying network interface
00578  * @return Error code
00579  **/
00580 
00581 error_t sam4eEthSetMulticastFilter(NetInterface *interface)
00582 {
00583    uint_t i;
00584    uint_t k;
00585    uint8_t *p;
00586    uint32_t hashTable[2];
00587    MacFilterEntry *entry;
00588 
00589    //Debug message
00590    TRACE_DEBUG("Updating SAM4E hash table...\r\n");
00591 
00592    //Clear hash table
00593    hashTable[0] = 0;
00594    hashTable[1] = 0;
00595 
00596    //The MAC filter table contains the multicast MAC addresses
00597    //to accept when receiving an Ethernet frame
00598    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00599    {
00600       //Point to the current entry
00601       entry = &interface->macMulticastFilter[i];
00602 
00603       //Valid entry?
00604       if(entry->refCount > 0)
00605       {
00606          //Point to the MAC address
00607          p = entry->addr.b;
00608 
00609          //Apply the hash function
00610          k = (p[0] >> 6) ^ p[0];
00611          k ^= (p[1] >> 4) ^ (p[1] << 2);
00612          k ^= (p[2] >> 2) ^ (p[2] << 4);
00613          k ^= (p[3] >> 6) ^ p[3];
00614          k ^= (p[4] >> 4) ^ (p[4] << 2);
00615          k ^= (p[5] >> 2) ^ (p[5] << 4);
00616 
00617          //The hash value is reduced to a 6-bit index
00618          k &= 0x3F;
00619 
00620          //Update hash table contents
00621          hashTable[k / 32] |= (1 << (k % 32));
00622       }
00623    }
00624 
00625    //Write the hash table
00626    GMAC->GMAC_HRB = hashTable[0];
00627    GMAC->GMAC_HRT = hashTable[1];
00628 
00629    //Debug message
00630    TRACE_DEBUG("  HRB = %08" PRIX32 "\r\n", GMAC->GMAC_HRB);
00631    TRACE_DEBUG("  HRT = %08" PRIX32 "\r\n", GMAC->GMAC_HRT);
00632 
00633    //Successful processing
00634    return NO_ERROR;
00635 }
00636 
00637 
00638 /**
00639  * @brief Adjust MAC configuration parameters for proper operation
00640  * @param[in] interface Underlying network interface
00641  * @return Error code
00642  **/
00643 
00644 error_t sam4eEthUpdateMacConfig(NetInterface *interface)
00645 {
00646    uint32_t config;
00647 
00648    //Read network configuration register
00649    config = GMAC->GMAC_NCFGR;
00650 
00651    //10BASE-T or 100BASE-TX operation mode?
00652    if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
00653       config |= GMAC_NCFGR_SPD;
00654    else
00655       config &= ~GMAC_NCFGR_SPD;
00656 
00657    //Half-duplex or full-duplex mode?
00658    if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00659       config |= GMAC_NCFGR_FD;
00660    else
00661       config &= ~GMAC_NCFGR_FD;
00662 
00663    //Write configuration value back to NCFGR register
00664    GMAC->GMAC_NCFGR = config;
00665 
00666    //Successful processing
00667    return NO_ERROR;
00668 }
00669 
00670 
00671 /**
00672  * @brief Write PHY register
00673  * @param[in] phyAddr PHY address
00674  * @param[in] regAddr Register address
00675  * @param[in] data Register value
00676  **/
00677 
00678 void sam4eEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
00679 {
00680    uint32_t value;
00681 
00682    //Set up a write operation
00683    value = GMAC_MAN_CLTTO | GMAC_MAN_OP(1) | GMAC_MAN_WTN(2);
00684    //PHY address
00685    value |= GMAC_MAN_PHYA(phyAddr);
00686    //Register address
00687    value |= GMAC_MAN_REGA(regAddr);
00688    //Register value
00689    value |= GMAC_MAN_DATA(data);
00690 
00691    //Start a write operation
00692    GMAC->GMAC_MAN = value;
00693    //Wait for the write to complete
00694    while(!(GMAC->GMAC_NSR & GMAC_NSR_IDLE));
00695 }
00696 
00697 
00698 /**
00699  * @brief Read PHY register
00700  * @param[in] phyAddr PHY address
00701  * @param[in] regAddr Register address
00702  * @return Register value
00703  **/
00704 
00705 uint16_t sam4eEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
00706 {
00707    uint32_t value;
00708 
00709    //Set up a read operation
00710    value = GMAC_MAN_CLTTO | GMAC_MAN_OP(2) | GMAC_MAN_WTN(2);
00711    //PHY address
00712    value |= GMAC_MAN_PHYA(phyAddr);
00713    //Register address
00714    value |= GMAC_MAN_REGA(regAddr);
00715 
00716    //Start a read operation
00717    GMAC->GMAC_MAN = value;
00718    //Wait for the read to complete
00719    while(!(GMAC->GMAC_NSR & GMAC_NSR_IDLE));
00720 
00721    //Return PHY register contents
00722    return GMAC->GMAC_MAN & GMAC_MAN_DATA_Msk;
00723 }
00724