Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
zynq7000_eth.c
00001 /** 00002 * @file zynq7000_eth.c 00003 * @brief Zynq-7000 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 "xemacps_hw.h" 00035 #include "xscugic.h" 00036 #include "xil_misc_psreset_api.h" 00037 #include "core/net.h" 00038 #include "drivers/zynq7000_eth.h" 00039 #include "debug.h" 00040 00041 //Underlying network interface 00042 static NetInterface *nicDriverInterface; 00043 00044 //GIC instance 00045 extern XScuGic ZYNQ7000_ETH_GIC_INSTANCE; 00046 00047 //IAR EWARM compiler? 00048 #if defined(__ICCARM__) 00049 00050 //TX buffer 00051 #pragma data_alignment = 8 00052 #pragma location = ".ram_no_cache" 00053 static uint8_t txBuffer[ZYNQ7000_ETH_TX_BUFFER_COUNT][ZYNQ7000_ETH_TX_BUFFER_SIZE]; 00054 //RX buffer 00055 #pragma data_alignment = 8 00056 #pragma location = ".ram_no_cache" 00057 static uint8_t rxBuffer[ZYNQ7000_ETH_RX_BUFFER_COUNT][ZYNQ7000_ETH_RX_BUFFER_SIZE]; 00058 //TX buffer descriptors 00059 #pragma data_alignment = 4 00060 #pragma location = ".ram_no_cache" 00061 static Zynq7000TxBufferDesc txBufferDesc[ZYNQ7000_ETH_TX_BUFFER_COUNT]; 00062 //RX buffer descriptors 00063 #pragma data_alignment = 4 00064 #pragma location = ".ram_no_cache" 00065 static Zynq7000RxBufferDesc rxBufferDesc[ZYNQ7000_ETH_RX_BUFFER_COUNT]; 00066 00067 //Keil MDK-ARM or GCC compiler? 00068 #else 00069 00070 //TX buffer 00071 static uint8_t txBuffer[ZYNQ7000_ETH_TX_BUFFER_COUNT][ZYNQ7000_ETH_TX_BUFFER_SIZE] 00072 __attribute__((aligned(8), __section__(".ram_no_cache"))); 00073 //RX buffer 00074 static uint8_t rxBuffer[ZYNQ7000_ETH_RX_BUFFER_COUNT][ZYNQ7000_ETH_RX_BUFFER_SIZE] 00075 __attribute__((aligned(8), __section__(".ram_no_cache"))); 00076 //TX buffer descriptors 00077 static Zynq7000TxBufferDesc txBufferDesc[ZYNQ7000_ETH_TX_BUFFER_COUNT] 00078 __attribute__((aligned(4), __section__(".ram_no_cache"))); 00079 //RX buffer descriptors 00080 static Zynq7000RxBufferDesc rxBufferDesc[ZYNQ7000_ETH_RX_BUFFER_COUNT] 00081 __attribute__((aligned(4), __section__(".ram_no_cache"))); 00082 00083 #endif 00084 00085 //TX buffer index 00086 static uint_t txBufferIndex; 00087 //RX buffer index 00088 static uint_t rxBufferIndex; 00089 00090 00091 /** 00092 * @brief Zynq-7000 Ethernet MAC driver 00093 **/ 00094 00095 const NicDriver zynq7000EthDriver = 00096 { 00097 NIC_TYPE_ETHERNET, 00098 ETH_MTU, 00099 zynq7000EthInit, 00100 zynq7000EthTick, 00101 zynq7000EthEnableIrq, 00102 zynq7000EthDisableIrq, 00103 zynq7000EthEventHandler, 00104 zynq7000EthSendPacket, 00105 zynq7000EthSetMulticastFilter, 00106 zynq7000EthUpdateMacConfig, 00107 zynq7000EthWritePhyReg, 00108 zynq7000EthReadPhyReg, 00109 TRUE, 00110 TRUE, 00111 TRUE, 00112 FALSE 00113 }; 00114 00115 00116 /** 00117 * @brief Zynq-7000 Ethernet MAC initialization 00118 * @param[in] interface Underlying network interface 00119 * @return Error code 00120 **/ 00121 00122 error_t zynq7000EthInit(NetInterface *interface) 00123 { 00124 error_t error; 00125 volatile uint32_t temp; 00126 00127 //Debug message 00128 TRACE_INFO("Initializing Zynq-7000 Ethernet MAC...\r\n"); 00129 00130 //Save underlying network interface 00131 nicDriverInterface = interface; 00132 00133 //Unlock SLCR 00134 XSLCR_UNLOCK = XSLCR_UNLOCK_KEY_VALUE; 00135 00136 //Configure Ethernet controller reference clock 00137 temp = XSLCR_GEM0_CLK_CTRL_CLKACT_MASK; 00138 temp |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK; 00139 temp |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK; 00140 XSLCR_GEM0_CLK_CTRL = temp; 00141 00142 //Enable Ethernet controller RX clock 00143 XSLCR_GEM0_RCLK_CTRL = XSLCR_GEM0_RCLK_CTRL_CLKACT_MASK; 00144 00145 //Lock SLCR 00146 XSLCR_LOCK = XSLCR_LOCK_KEY_VALUE; 00147 00148 //Clear network control register 00149 XEMACPS_NWCTRL = 0; 00150 //Clear statistics registers 00151 XEMACPS_NWCTRL |= XEMACPS_NWCTRL_STATCLR_MASK; 00152 00153 //Configure MDC clock speed 00154 XEMACPS_NWCFG = (MDC_DIV_224 << XEMACPS_NWCFG_MDC_SHIFT_MASK) | XEMACPS_NWCFG_MDCCLKDIV_MASK; 00155 //Enable management port (MDC and MDIO) 00156 XEMACPS_NWCTRL |= XEMACPS_NWCTRL_MDEN_MASK; 00157 00158 //PHY transceiver initialization 00159 error = interface->phyDriver->init(interface); 00160 //Failed to initialize PHY transceiver? 00161 if(error) 00162 return error; 00163 00164 //Set the MAC address 00165 XEMACPS_LADDR1L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16); 00166 XEMACPS_LADDR1H = interface->macAddr.w[2]; 00167 00168 //Configure the receive filter 00169 XEMACPS_NWCFG |= XEMACPS_NWCFG_UCASTHASHEN_MASK | XEMACPS_NWCFG_MCASTHASHEN_MASK; 00170 00171 //Initialize hash table 00172 XEMACPS_HASHL = 0; 00173 XEMACPS_HASHH = 0; 00174 00175 //Initialize buffer descriptors 00176 zynq7000EthInitBufferDesc(interface); 00177 00178 //Set RX buffer size 00179 temp = ((ZYNQ7000_ETH_RX_BUFFER_SIZE / 64) << XEMACPS_DMACR_RXBUF_SHIFT) & 00180 XEMACPS_DMACR_RXBUF_MASK; 00181 00182 //Use full configured addressable space for transmit and receive packet buffers 00183 temp |= XEMACPS_DMACR_TXSIZE_MASK | XEMACPS_DMACR_RXSIZE_MASK; 00184 //Select the burst length for DMA data operations 00185 temp |= XEMACPS_DMACR_INCR16_AHB_BURST; 00186 //Set DMA configuration register 00187 XEMACPS_DMACR = temp; 00188 00189 //Clear transmit status register 00190 XEMACPS_TXSR = XEMACPS_TXSR_TXCOMPL_MASK | XEMACPS_TXSR_TXGO_MASK | 00191 XEMACPS_TXSR_ERROR_MASK; 00192 00193 //Clear receive status register 00194 XEMACPS_RXSR = XEMACPS_RXSR_FRAMERX_MASK | XEMACPS_RXSR_ERROR_MASK; 00195 00196 //First disable all interrupts 00197 XEMACPS_IDR = 0xFFFFFFFF; 00198 00199 //Only the desired ones are enabled 00200 XEMACPS_IER = XEMACPS_IXR_HRESPNOK_MASK | XEMACPS_IXR_RXOVR_MASK | 00201 XEMACPS_IXR_TXCOMPL_MASK | XEMACPS_IXR_TXEXH_MASK | XEMACPS_IXR_RETRY_MASK | 00202 XEMACPS_IXR_URUN_MASK | XEMACPS_IXR_RXUSED_MASK | XEMACPS_IXR_FRAMERX_MASK; 00203 00204 //Read interrupt status register to clear any pending interrupt 00205 temp = XEMACPS_ISR; 00206 00207 //Register interrupt handler 00208 XScuGic_Connect(&ZYNQ7000_ETH_GIC_INSTANCE, XPS_GEM0_INT_ID, 00209 (Xil_InterruptHandler) zynq7000EthIrqHandler, interface); 00210 00211 //Configure interrupt priority 00212 XScuGic_SetPriorityTriggerType(&ZYNQ7000_ETH_GIC_INSTANCE, 00213 XPS_GEM0_INT_ID, ZYNQ7000_ETH_IRQ_PRIORITY, 1); 00214 00215 //Enable the transmitter and the receiver 00216 XEMACPS_NWCTRL |= XEMACPS_NWCTRL_TXEN_MASK | XEMACPS_NWCTRL_RXEN_MASK; 00217 00218 //Accept any packets from the upper layer 00219 osSetEvent(&interface->nicTxEvent); 00220 00221 //Successful initialization 00222 return NO_ERROR; 00223 } 00224 00225 00226 /** 00227 * @brief Initialize buffer descriptors 00228 * @param[in] interface Underlying network interface 00229 **/ 00230 00231 void zynq7000EthInitBufferDesc(NetInterface *interface) 00232 { 00233 uint_t i; 00234 uint32_t address; 00235 00236 //Initialize TX buffer descriptors 00237 for(i = 0; i < ZYNQ7000_ETH_TX_BUFFER_COUNT; i++) 00238 { 00239 //Calculate the address of the current TX buffer 00240 address = (uint32_t) txBuffer[i]; 00241 //Write the address to the descriptor entry 00242 txBufferDesc[i].address = address; 00243 //Initialize status field 00244 txBufferDesc[i].status = XEMACPS_TX_USED; 00245 } 00246 00247 //Mark the last descriptor entry with the wrap flag 00248 txBufferDesc[i - 1].status |= XEMACPS_TX_WRAP; 00249 //Initialize TX buffer index 00250 txBufferIndex = 0; 00251 00252 //Initialize RX buffer descriptors 00253 for(i = 0; i < ZYNQ7000_ETH_RX_BUFFER_COUNT; i++) 00254 { 00255 //Calculate the address of the current RX buffer 00256 address = (uint32_t) rxBuffer[i]; 00257 //Write the address to the descriptor entry 00258 rxBufferDesc[i].address = address & XEMACPS_RX_ADDRESS; 00259 //Clear status field 00260 rxBufferDesc[i].status = 0; 00261 } 00262 00263 //Mark the last descriptor entry with the wrap flag 00264 rxBufferDesc[i - 1].address |= XEMACPS_RX_WRAP; 00265 //Initialize RX buffer index 00266 rxBufferIndex = 0; 00267 00268 //Start location of the TX descriptor list 00269 XEMACPS_TXQBASE = (uint32_t) txBufferDesc; 00270 //Start location of the RX descriptor list 00271 XEMACPS_RXQBASE = (uint32_t) rxBufferDesc; 00272 } 00273 00274 00275 /** 00276 * @brief Zynq-7000 Ethernet MAC timer handler 00277 * 00278 * This routine is periodically called by the TCP/IP stack to 00279 * handle periodic operations such as polling the link state 00280 * 00281 * @param[in] interface Underlying network interface 00282 **/ 00283 00284 void zynq7000EthTick(NetInterface *interface) 00285 { 00286 //Handle periodic operations 00287 interface->phyDriver->tick(interface); 00288 } 00289 00290 00291 /** 00292 * @brief Enable interrupts 00293 * @param[in] interface Underlying network interface 00294 **/ 00295 00296 void zynq7000EthEnableIrq(NetInterface *interface) 00297 { 00298 //Enable Ethernet MAC interrupts 00299 XScuGic_Enable(&ZYNQ7000_ETH_GIC_INSTANCE, XPS_GEM0_INT_ID); 00300 //Enable Ethernet PHY interrupts 00301 interface->phyDriver->enableIrq(interface); 00302 } 00303 00304 00305 /** 00306 * @brief Disable interrupts 00307 * @param[in] interface Underlying network interface 00308 **/ 00309 00310 void zynq7000EthDisableIrq(NetInterface *interface) 00311 { 00312 //Disable Ethernet MAC interrupts 00313 XScuGic_Disable(&ZYNQ7000_ETH_GIC_INSTANCE, XPS_GEM0_INT_ID); 00314 //Disable Ethernet PHY interrupts 00315 interface->phyDriver->disableIrq(interface); 00316 } 00317 00318 00319 /** 00320 * @brief Zynq-7000 Ethernet MAC interrupt service routine 00321 * @param[in] interface Underlying network interface 00322 **/ 00323 00324 void zynq7000EthIrqHandler(NetInterface *interface) 00325 { 00326 bool_t flag; 00327 volatile uint32_t isr; 00328 volatile uint32_t tsr; 00329 volatile uint32_t rsr; 00330 00331 //Enter interrupt service routine 00332 osEnterIsr(); 00333 00334 //This flag will be set if a higher priority task must be woken 00335 flag = FALSE; 00336 00337 //Each time the software reads XEMACPS_ISR, it has to check the 00338 //contents of XEMACPS_TXSR, XEMACPS_RXSR 00339 isr = XEMACPS_ISR; 00340 tsr = XEMACPS_TXSR; 00341 rsr = XEMACPS_RXSR; 00342 00343 //Clear interrupt flags 00344 XEMACPS_ISR = isr; 00345 00346 //A packet has been transmitted? 00347 if(tsr & (XEMACPS_TXSR_TXCOMPL_MASK | XEMACPS_TXSR_TXGO_MASK | XEMACPS_TXSR_ERROR_MASK)) 00348 { 00349 //Only clear TSR flags that are currently set 00350 XEMACPS_TXSR = tsr; 00351 00352 //Check whether the TX buffer is available for writing 00353 if(txBufferDesc[txBufferIndex].status & XEMACPS_TX_USED) 00354 { 00355 //Notify the TCP/IP stack that the transmitter is ready to send 00356 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00357 } 00358 } 00359 00360 //A packet has been received? 00361 if(rsr & (XEMACPS_RXSR_FRAMERX_MASK | XEMACPS_RXSR_ERROR_MASK)) 00362 { 00363 //Set event flag 00364 nicDriverInterface->nicEvent = TRUE; 00365 //Notify the TCP/IP stack of the event 00366 flag |= osSetEventFromIsr(&netEvent); 00367 } 00368 00369 //Flush packet if the receive buffer not available 00370 if (isr & XEMACPS_IXR_RXUSED_MASK) 00371 XEMACPS_NWCTRL |= XEMACPS_NWCTRL_FLUSH_DPRAM_MASK; 00372 00373 //Leave interrupt service routine 00374 osExitIsr(flag); 00375 } 00376 00377 00378 /** 00379 * @brief Zynq-7000 Ethernet MAC event handler 00380 * @param[in] interface Underlying network interface 00381 **/ 00382 00383 void zynq7000EthEventHandler(NetInterface *interface) 00384 { 00385 error_t error; 00386 uint32_t rsr; 00387 00388 //Read receive status 00389 rsr = XEMACPS_RXSR; 00390 00391 //Packet received? 00392 if(rsr & (XEMACPS_RXSR_FRAMERX_MASK | XEMACPS_RXSR_ERROR_MASK)) 00393 { 00394 //Only clear RSR flags that are currently set 00395 XEMACPS_RXSR = rsr; 00396 00397 //Process all pending packets 00398 do 00399 { 00400 //Read incoming packet 00401 error = zynq7000EthReceivePacket(interface); 00402 00403 //No more data in the receive buffer? 00404 } while(error != ERROR_BUFFER_EMPTY); 00405 } 00406 } 00407 00408 00409 /** 00410 * @brief Send a packet 00411 * @param[in] interface Underlying network interface 00412 * @param[in] buffer Multi-part buffer containing the data to send 00413 * @param[in] offset Offset to the first data byte 00414 * @return Error code 00415 **/ 00416 00417 error_t zynq7000EthSendPacket(NetInterface *interface, 00418 const NetBuffer *buffer, size_t offset) 00419 { 00420 static uint8_t temp[ZYNQ7000_ETH_TX_BUFFER_SIZE]; 00421 size_t length; 00422 00423 //Retrieve the length of the packet 00424 length = netBufferGetLength(buffer) - offset; 00425 00426 //Check the frame length 00427 if(length > ZYNQ7000_ETH_TX_BUFFER_SIZE) 00428 { 00429 //The transmitter can accept another packet 00430 osSetEvent(&interface->nicTxEvent); 00431 //Report an error 00432 return ERROR_INVALID_LENGTH; 00433 } 00434 00435 //Make sure the current buffer is available for writing 00436 if(!(txBufferDesc[txBufferIndex].status & XEMACPS_TX_USED)) 00437 return ERROR_FAILURE; 00438 00439 //Copy user data to the transmit buffer 00440 netBufferRead(temp, buffer, offset, length); 00441 memcpy(txBuffer[txBufferIndex], temp, length); 00442 00443 //Set the necessary flags in the descriptor entry 00444 if(txBufferIndex < (ZYNQ7000_ETH_TX_BUFFER_COUNT - 1)) 00445 { 00446 //Write the status word 00447 txBufferDesc[txBufferIndex].status = 00448 XEMACPS_TX_LAST | (length & XEMACPS_TX_LENGTH); 00449 00450 //Point to the next buffer 00451 txBufferIndex++; 00452 } 00453 else 00454 { 00455 //Write the status word 00456 txBufferDesc[txBufferIndex].status = XEMACPS_TX_WRAP | 00457 XEMACPS_TX_LAST | (length & XEMACPS_TX_LENGTH); 00458 00459 //Wrap around 00460 txBufferIndex = 0; 00461 } 00462 00463 //Set the STARTTX bit to initiate transmission 00464 XEMACPS_NWCTRL |= XEMACPS_NWCTRL_STARTTX_MASK; 00465 00466 //Check whether the next buffer is available for writing 00467 if(txBufferDesc[txBufferIndex].status & XEMACPS_TX_USED) 00468 { 00469 //The transmitter can accept another packet 00470 osSetEvent(&interface->nicTxEvent); 00471 } 00472 00473 //Successful processing 00474 return NO_ERROR; 00475 } 00476 00477 00478 /** 00479 * @brief Receive a packet 00480 * @param[in] interface Underlying network interface 00481 * @return Error code 00482 **/ 00483 00484 error_t zynq7000EthReceivePacket(NetInterface *interface) 00485 { 00486 static uint8_t temp[ETH_MAX_FRAME_SIZE]; 00487 error_t error; 00488 uint_t i; 00489 uint_t j; 00490 uint_t sofIndex; 00491 uint_t eofIndex; 00492 size_t n; 00493 size_t size; 00494 size_t length; 00495 00496 //Initialize SOF and EOF indices 00497 sofIndex = UINT_MAX; 00498 eofIndex = UINT_MAX; 00499 00500 //Search for SOF and EOF flags 00501 for(i = 0; i < ZYNQ7000_ETH_RX_BUFFER_COUNT; i++) 00502 { 00503 //Point to the current entry 00504 j = rxBufferIndex + i; 00505 00506 //Wrap around to the beginning of the buffer if necessary 00507 if(j >= ZYNQ7000_ETH_RX_BUFFER_COUNT) 00508 j -= ZYNQ7000_ETH_RX_BUFFER_COUNT; 00509 00510 //No more entries to process? 00511 if(!(rxBufferDesc[j].address & XEMACPS_RX_OWNERSHIP)) 00512 { 00513 //Stop processing 00514 break; 00515 } 00516 //A valid SOF has been found? 00517 if(rxBufferDesc[j].status & XEMACPS_RX_SOF) 00518 { 00519 //Save the position of the SOF 00520 sofIndex = i; 00521 } 00522 //A valid EOF has been found? 00523 if((rxBufferDesc[j].status & XEMACPS_RX_EOF) && sofIndex != UINT_MAX) 00524 { 00525 //Save the position of the EOF 00526 eofIndex = i; 00527 //Retrieve the length of the frame 00528 size = rxBufferDesc[j].status & XEMACPS_RX_LENGTH; 00529 //Limit the number of data to read 00530 size = MIN(size, ETH_MAX_FRAME_SIZE); 00531 //Stop processing since we have reached the end of the frame 00532 break; 00533 } 00534 } 00535 00536 //Determine the number of entries to process 00537 if(eofIndex != UINT_MAX) 00538 j = eofIndex + 1; 00539 else if(sofIndex != UINT_MAX) 00540 j = sofIndex; 00541 else 00542 j = i; 00543 00544 //Total number of bytes that have been copied from the receive buffer 00545 length = 0; 00546 00547 //Process incoming frame 00548 for(i = 0; i < j; i++) 00549 { 00550 //Any data to copy from current buffer? 00551 if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex) 00552 { 00553 //Calculate the number of bytes to read at a time 00554 n = MIN(size, ZYNQ7000_ETH_RX_BUFFER_SIZE); 00555 //Copy data from receive buffer 00556 memcpy(temp + length, rxBuffer[rxBufferIndex], n); 00557 //Update byte counters 00558 length += n; 00559 size -= n; 00560 } 00561 00562 //Mark the current buffer as free 00563 rxBufferDesc[rxBufferIndex].address &= ~XEMACPS_RX_OWNERSHIP; 00564 00565 //Point to the following entry 00566 rxBufferIndex++; 00567 00568 //Wrap around to the beginning of the buffer if necessary 00569 if(rxBufferIndex >= ZYNQ7000_ETH_RX_BUFFER_COUNT) 00570 rxBufferIndex = 0; 00571 } 00572 00573 //Any packet to process? 00574 if(length > 0) 00575 { 00576 //Pass the packet to the upper layer 00577 nicProcessPacket(interface, temp, length); 00578 //Valid packet received 00579 error = NO_ERROR; 00580 } 00581 else 00582 { 00583 //No more data in the receive buffer 00584 error = ERROR_BUFFER_EMPTY; 00585 } 00586 00587 //Return status code 00588 return error; 00589 } 00590 00591 00592 /** 00593 * @brief Configure multicast MAC address filtering 00594 * @param[in] interface Underlying network interface 00595 * @return Error code 00596 **/ 00597 00598 error_t zynq7000EthSetMulticastFilter(NetInterface *interface) 00599 { 00600 uint_t i; 00601 uint_t k; 00602 uint8_t *p; 00603 uint32_t hashTable[2]; 00604 MacFilterEntry *entry; 00605 00606 //Debug message 00607 TRACE_DEBUG("Updating Zynq-7000 hash table...\r\n"); 00608 00609 //Clear hash table 00610 hashTable[0] = 0; 00611 hashTable[1] = 0; 00612 00613 //The MAC filter table contains the multicast MAC addresses 00614 //to accept when receiving an Ethernet frame 00615 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00616 { 00617 //Point to the current entry 00618 entry = &interface->macMulticastFilter[i]; 00619 00620 //Valid entry? 00621 if(entry->refCount > 0) 00622 { 00623 //Point to the MAC address 00624 p = entry->addr.b; 00625 00626 //Apply the hash function 00627 k = (p[0] >> 6) ^ p[0]; 00628 k ^= (p[1] >> 4) ^ (p[1] << 2); 00629 k ^= (p[2] >> 2) ^ (p[2] << 4); 00630 k ^= (p[3] >> 6) ^ p[3]; 00631 k ^= (p[4] >> 4) ^ (p[4] << 2); 00632 k ^= (p[5] >> 2) ^ (p[5] << 4); 00633 00634 //The hash value is reduced to a 6-bit index 00635 k &= 0x3F; 00636 00637 //Update hash table contents 00638 hashTable[k / 32] |= (1 << (k % 32)); 00639 } 00640 } 00641 00642 //Write the hash table 00643 XEMACPS_HASHL = hashTable[0]; 00644 XEMACPS_HASHH = hashTable[1]; 00645 00646 //Debug message 00647 TRACE_DEBUG(" HASHL = %08" PRIX32 "\r\n", XEMACPS_HASHL); 00648 TRACE_DEBUG(" HASHH = %08" PRIX32 "\r\n", XEMACPS_HASHH); 00649 00650 //Successful processing 00651 return NO_ERROR; 00652 } 00653 00654 00655 /** 00656 * @brief Adjust MAC configuration parameters for proper operation 00657 * @param[in] interface Underlying network interface 00658 * @return Error code 00659 **/ 00660 00661 error_t zynq7000EthUpdateMacConfig(NetInterface *interface) 00662 { 00663 uint32_t config; 00664 uint32_t clockCtrl; 00665 00666 //Read network configuration register 00667 config = XEMACPS_NWCFG; 00668 00669 //Read clock control register 00670 clockCtrl = XSLCR_GEM0_CLK_CTRL; 00671 clockCtrl &= ~(XSLCR_GEM0_CLK_CTRL_DIV1_MASK | XSLCR_GEM0_CLK_CTRL_DIV0_MASK); 00672 00673 //1000BASE-T operation mode? 00674 if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS) 00675 { 00676 //Update network configuration 00677 config |= XEMACPS_NWCFG_1000_MASK; 00678 config &= ~XEMACPS_NWCFG_100_MASK; 00679 00680 //Update clock configuration 00681 clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK; 00682 clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK; 00683 } 00684 //100BASE-TX operation mode? 00685 else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00686 { 00687 //Update network configuration 00688 config &= ~XEMACPS_NWCFG_1000_MASK; 00689 config |= XEMACPS_NWCFG_100_MASK; 00690 00691 //Update clock configuration 00692 clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK; 00693 clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK; 00694 } 00695 //10BASE-T operation mode? 00696 else 00697 { 00698 //Update network configuration 00699 config &= ~XEMACPS_NWCFG_1000_MASK; 00700 config &= ~XEMACPS_NWCFG_100_MASK; 00701 00702 //Update clock configuration 00703 clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK; 00704 clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK; 00705 } 00706 00707 //Half-duplex or full-duplex mode? 00708 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00709 config |= XEMACPS_NWCFG_FDEN_MASK; 00710 else 00711 config &= ~XEMACPS_NWCFG_FDEN_MASK; 00712 00713 //Write network configuration register 00714 XEMACPS_NWCFG = config; 00715 00716 //Unlock SLCR 00717 XSLCR_UNLOCK = XSLCR_UNLOCK_KEY_VALUE; 00718 //Write clock control register 00719 XSLCR_GEM0_CLK_CTRL = clockCtrl; 00720 //Lock SLCR 00721 XSLCR_LOCK = XSLCR_LOCK_KEY_VALUE; 00722 00723 //Successful processing 00724 return NO_ERROR; 00725 } 00726 00727 00728 /** 00729 * @brief Write PHY register 00730 * @param[in] phyAddr PHY address 00731 * @param[in] regAddr Register address 00732 * @param[in] data Register value 00733 **/ 00734 00735 void zynq7000EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00736 { 00737 uint32_t value; 00738 00739 //Set up a write operation 00740 value = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK; 00741 //PHY address 00742 value |= (phyAddr << 23) & XEMACPS_PHYMNTNC_ADDR_MASK; 00743 //Register address 00744 value |= (regAddr << 18) & XEMACPS_PHYMNTNC_REG_MASK; 00745 //Register value 00746 value |= data & XEMACPS_PHYMNTNC_DATA_MASK; 00747 00748 //Start a write operation 00749 XEMACPS_PHYMNTNC = value; 00750 //Wait for the write to complete 00751 while(!(XEMACPS_NWSR & XEMACPS_NWSR_MDIOIDLE_MASK)); 00752 } 00753 00754 00755 /** 00756 * @brief Read PHY register 00757 * @param[in] phyAddr PHY address 00758 * @param[in] regAddr Register address 00759 * @return Register value 00760 **/ 00761 00762 uint16_t zynq7000EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00763 { 00764 uint32_t value; 00765 00766 //Set up a read operation 00767 value = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK; 00768 //PHY address 00769 value |= (phyAddr << 23) & XEMACPS_PHYMNTNC_ADDR_MASK; 00770 //Register address 00771 value |= (regAddr << 18) & XEMACPS_PHYMNTNC_REG_MASK; 00772 00773 //Start a read operation 00774 XEMACPS_PHYMNTNC = value; 00775 //Wait for the read to complete 00776 while(!(XEMACPS_NWSR & XEMACPS_NWSR_MDIOIDLE_MASK)); 00777 00778 //Return PHY register contents 00779 return XEMACPS_PHYMNTNC & XEMACPS_PHYMNTNC_DATA_MASK; 00780 } 00781
Generated on Tue Jul 12 2022 17:10:18 by
1.7.2