zynq7000_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file zynq7000_eth_driver.c
3  * @brief Zynq-7000 Gigabit Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <limits.h>
36 #include "xemacps_hw.h"
37 #include "xscugic.h"
38 #include "xil_misc_psreset_api.h"
39 #include "core/net.h"
41 #include "debug.h"
42 
43 //Underlying network interface
44 static NetInterface *nicDriverInterface;
45 
46 //GIC instance
47 extern XScuGic ZYNQ7000_ETH_GIC_INSTANCE;
48 
49 //IAR EWARM compiler?
50 #if defined(__ICCARM__)
51 
52 //TX buffer
53 #pragma data_alignment = 8
54 #pragma location = ZYNQ7000_ETH_RAM_SECTION
56 //RX buffer
57 #pragma data_alignment = 8
58 #pragma location = ZYNQ7000_ETH_RAM_SECTION
60 //TX buffer descriptors
61 #pragma data_alignment = 4
62 #pragma location = ZYNQ7000_ETH_RAM_SECTION
64 //RX buffer descriptors
65 #pragma data_alignment = 4
66 #pragma location = ZYNQ7000_ETH_RAM_SECTION
68 
69 //GCC compiler?
70 #else
71 
72 //TX buffer
74  __attribute__((aligned(8), __section__(ZYNQ7000_ETH_RAM_SECTION)));
75 //RX buffer
77  __attribute__((aligned(8), __section__(ZYNQ7000_ETH_RAM_SECTION)));
78 //TX buffer descriptors
80  __attribute__((aligned(4), __section__(ZYNQ7000_ETH_RAM_SECTION)));
81 //RX buffer descriptors
83  __attribute__((aligned(4), __section__(ZYNQ7000_ETH_RAM_SECTION)));
84 
85 #endif
86 
87 //TX buffer index
88 static uint_t txBufferIndex;
89 //RX buffer index
90 static uint_t rxBufferIndex;
91 
92 
93 /**
94  * @brief Zynq-7000 Ethernet MAC driver
95  **/
96 
98 {
100  ETH_MTU,
111  TRUE,
112  TRUE,
113  TRUE,
114  FALSE
115 };
116 
117 
118 /**
119  * @brief Zynq-7000 Ethernet MAC initialization
120  * @param[in] interface Underlying network interface
121  * @return Error code
122  **/
123 
125 {
126  error_t error;
127  volatile uint32_t temp;
128 
129  //Debug message
130  TRACE_INFO("Initializing Zynq-7000 Ethernet MAC...\r\n");
131 
132  //Save underlying network interface
133  nicDriverInterface = interface;
134 
135  //Unlock SLCR
137 
138  //Configure Ethernet controller reference clock
140  temp |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK;
141  temp |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK;
142  XSLCR_GEM0_CLK_CTRL = temp;
143 
144  //Enable Ethernet controller RX clock
146 
147  //Lock SLCR
149 
150  //Clear network control register
151  XEMACPS_NWCTRL = 0;
152  //Clear statistics registers
153  XEMACPS_NWCTRL |= XEMACPS_NWCTRL_STATCLR_MASK;
154 
155  //Configure MDC clock speed
156  XEMACPS_NWCFG = (MDC_DIV_224 << XEMACPS_NWCFG_MDC_SHIFT_MASK) | XEMACPS_NWCFG_MDCCLKDIV_MASK;
157  //Enable management port (MDC and MDIO)
158  XEMACPS_NWCTRL |= XEMACPS_NWCTRL_MDEN_MASK;
159 
160  //Valid Ethernet PHY or switch driver?
161  if(interface->phyDriver != NULL)
162  {
163  //Ethernet PHY initialization
164  error = interface->phyDriver->init(interface);
165  }
166  else if(interface->switchDriver != NULL)
167  {
168  //Ethernet switch initialization
169  error = interface->switchDriver->init(interface);
170  }
171  else
172  {
173  //The interface is not properly configured
174  error = ERROR_FAILURE;
175  }
176 
177  //Any error to report?
178  if(error)
179  {
180  return error;
181  }
182 
183  //Set the MAC address of the station
184  XEMACPS_LADDR1L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
185  XEMACPS_LADDR1H = interface->macAddr.w[2];
186 
187  //Configure the receive filter
188  XEMACPS_NWCFG |= XEMACPS_NWCFG_UCASTHASHEN_MASK | XEMACPS_NWCFG_MCASTHASHEN_MASK;
189 
190  //Initialize hash table
191  XEMACPS_HASHL = 0;
192  XEMACPS_HASHH = 0;
193 
194  //Initialize buffer descriptors
195  zynq7000EthInitBufferDesc(interface);
196 
197  //Set RX buffer size
198  temp = ((ZYNQ7000_ETH_RX_BUFFER_SIZE / 64) << XEMACPS_DMACR_RXBUF_SHIFT) &
199  XEMACPS_DMACR_RXBUF_MASK;
200 
201  //Use full configured addressable space for transmit and receive packet buffers
202  temp |= XEMACPS_DMACR_TXSIZE_MASK | XEMACPS_DMACR_RXSIZE_MASK;
203  //Select the burst length for DMA data operations
204  temp |= XEMACPS_DMACR_INCR16_AHB_BURST;
205  //Set DMA configuration register
206  XEMACPS_DMACR = temp;
207 
208  //Clear transmit status register
209  XEMACPS_TXSR = XEMACPS_TXSR_TXCOMPL_MASK | XEMACPS_TXSR_TXGO_MASK |
210  XEMACPS_TXSR_ERROR_MASK;
211 
212  //Clear receive status register
213  XEMACPS_RXSR = XEMACPS_RXSR_FRAMERX_MASK | XEMACPS_RXSR_ERROR_MASK;
214 
215  //First disable all interrupts
216  XEMACPS_IDR = 0xFFFFFFFF;
217 
218  //Only the desired ones are enabled
219  XEMACPS_IER = XEMACPS_IXR_HRESPNOK_MASK | XEMACPS_IXR_RXOVR_MASK |
220  XEMACPS_IXR_TXCOMPL_MASK | XEMACPS_IXR_TXEXH_MASK |
221  XEMACPS_IXR_RETRY_MASK | XEMACPS_IXR_URUN_MASK |
222  XEMACPS_IXR_RXUSED_MASK | XEMACPS_IXR_FRAMERX_MASK;
223 
224  //Read interrupt status register to clear any pending interrupt
225  temp = XEMACPS_ISR;
226  (void) temp;
227 
228  //Register interrupt handler
229  XScuGic_Connect(&ZYNQ7000_ETH_GIC_INSTANCE, XPS_GEM0_INT_ID,
230  (Xil_InterruptHandler) zynq7000EthIrqHandler, interface);
231 
232  //Configure interrupt priority
233  XScuGic_SetPriorityTriggerType(&ZYNQ7000_ETH_GIC_INSTANCE,
234  XPS_GEM0_INT_ID, ZYNQ7000_ETH_IRQ_PRIORITY, 1);
235 
236  //Enable the transmitter and the receiver
237  XEMACPS_NWCTRL |= XEMACPS_NWCTRL_TXEN_MASK | XEMACPS_NWCTRL_RXEN_MASK;
238 
239  //Accept any packets from the upper layer
240  osSetEvent(&interface->nicTxEvent);
241 
242  //Successful initialization
243  return NO_ERROR;
244 }
245 
246 
247 /**
248  * @brief Initialize buffer descriptors
249  * @param[in] interface Underlying network interface
250  **/
251 
253 {
254  uint_t i;
255  uint32_t address;
256 
257  //Initialize TX buffer descriptors
258  for(i = 0; i < ZYNQ7000_ETH_TX_BUFFER_COUNT; i++)
259  {
260  //Calculate the address of the current TX buffer
261  address = (uint32_t) txBuffer[i];
262  //Write the address to the descriptor entry
263  txBufferDesc[i].address = address;
264  //Initialize status field
265  txBufferDesc[i].status = XEMACPS_TX_USED;
266  }
267 
268  //Mark the last descriptor entry with the wrap flag
269  txBufferDesc[i - 1].status |= XEMACPS_TX_WRAP;
270  //Initialize TX buffer index
271  txBufferIndex = 0;
272 
273  //Initialize RX buffer descriptors
274  for(i = 0; i < ZYNQ7000_ETH_RX_BUFFER_COUNT; i++)
275  {
276  //Calculate the address of the current RX buffer
277  address = (uint32_t) rxBuffer[i];
278  //Write the address to the descriptor entry
279  rxBufferDesc[i].address = address & XEMACPS_RX_ADDRESS;
280  //Clear status field
281  rxBufferDesc[i].status = 0;
282  }
283 
284  //Mark the last descriptor entry with the wrap flag
285  rxBufferDesc[i - 1].address |= XEMACPS_RX_WRAP;
286  //Initialize RX buffer index
287  rxBufferIndex = 0;
288 
289  //Start location of the TX descriptor list
290  XEMACPS_TXQBASE = (uint32_t) txBufferDesc;
291  //Start location of the RX descriptor list
292  XEMACPS_RXQBASE = (uint32_t) rxBufferDesc;
293 }
294 
295 
296 /**
297  * @brief Zynq-7000 Ethernet MAC timer handler
298  *
299  * This routine is periodically called by the TCP/IP stack to handle periodic
300  * operations such as polling the link state
301  *
302  * @param[in] interface Underlying network interface
303  **/
304 
306 {
307  //Valid Ethernet PHY or switch driver?
308  if(interface->phyDriver != NULL)
309  {
310  //Handle periodic operations
311  interface->phyDriver->tick(interface);
312  }
313  else if(interface->switchDriver != NULL)
314  {
315  //Handle periodic operations
316  interface->switchDriver->tick(interface);
317  }
318  else
319  {
320  //Just for sanity
321  }
322 }
323 
324 
325 /**
326  * @brief Enable interrupts
327  * @param[in] interface Underlying network interface
328  **/
329 
331 {
332  //Enable Ethernet MAC interrupts
333  XScuGic_Enable(&ZYNQ7000_ETH_GIC_INSTANCE, XPS_GEM0_INT_ID);
334 
335  //Valid Ethernet PHY or switch driver?
336  if(interface->phyDriver != NULL)
337  {
338  //Enable Ethernet PHY interrupts
339  interface->phyDriver->enableIrq(interface);
340  }
341  else if(interface->switchDriver != NULL)
342  {
343  //Enable Ethernet switch interrupts
344  interface->switchDriver->enableIrq(interface);
345  }
346  else
347  {
348  //Just for sanity
349  }
350 }
351 
352 
353 /**
354  * @brief Disable interrupts
355  * @param[in] interface Underlying network interface
356  **/
357 
359 {
360  //Disable Ethernet MAC interrupts
361  XScuGic_Disable(&ZYNQ7000_ETH_GIC_INSTANCE, XPS_GEM0_INT_ID);
362 
363  //Valid Ethernet PHY or switch driver?
364  if(interface->phyDriver != NULL)
365  {
366  //Disable Ethernet PHY interrupts
367  interface->phyDriver->disableIrq(interface);
368  }
369  else if(interface->switchDriver != NULL)
370  {
371  //Disable Ethernet switch interrupts
372  interface->switchDriver->disableIrq(interface);
373  }
374  else
375  {
376  //Just for sanity
377  }
378 }
379 
380 
381 /**
382  * @brief Zynq-7000 Ethernet MAC interrupt service routine
383  * @param[in] interface Underlying network interface
384  **/
385 
387 {
388  bool_t flag;
389  volatile uint32_t isr;
390  volatile uint32_t tsr;
391  volatile uint32_t rsr;
392 
393  //Interrupt service routine prologue
394  osEnterIsr();
395 
396  //This flag will be set if a higher priority task must be woken
397  flag = FALSE;
398 
399  //Each time the software reads XEMACPS_ISR, it has to check the contents
400  //of XEMACPS_TXSR, XEMACPS_RXSR
401  isr = XEMACPS_ISR;
402  tsr = XEMACPS_TXSR;
403  rsr = XEMACPS_RXSR;
404  (void) isr;
405 
406  //Clear interrupt flags
407  XEMACPS_ISR = isr;
408 
409  //Packet transmitted?
410  if((tsr & (XEMACPS_TXSR_TXCOMPL_MASK | XEMACPS_TXSR_TXGO_MASK |
411  XEMACPS_TXSR_ERROR_MASK)) != 0)
412  {
413  //Only clear TSR flags that are currently set
414  XEMACPS_TXSR = tsr;
415 
416  //Check whether the TX buffer is available for writing
417  if((txBufferDesc[txBufferIndex].status & XEMACPS_TX_USED) != 0)
418  {
419  //Notify the TCP/IP stack that the transmitter is ready to send
420  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
421  }
422  }
423 
424  //Packet received?
425  if((rsr & (XEMACPS_RXSR_FRAMERX_MASK | XEMACPS_RXSR_ERROR_MASK)) != 0)
426  {
427  //Set event flag
428  nicDriverInterface->nicEvent = TRUE;
429  //Notify the TCP/IP stack of the event
430  flag |= osSetEventFromIsr(&netEvent);
431  }
432 
433  //Flush packet if the receive buffer not available
434  if((isr & XEMACPS_IXR_RXUSED_MASK) != 0)
435  {
436  XEMACPS_NWCTRL |= XEMACPS_NWCTRL_FLUSH_DPRAM_MASK;
437  }
438 
439  //Interrupt service routine epilogue
440  osExitIsr(flag);
441 }
442 
443 
444 /**
445  * @brief Zynq-7000 Ethernet MAC event handler
446  * @param[in] interface Underlying network interface
447  **/
448 
450 {
451  error_t error;
452  uint32_t rsr;
453 
454  //Read receive status
455  rsr = XEMACPS_RXSR;
456 
457  //Packet received?
458  if((rsr & (XEMACPS_RXSR_FRAMERX_MASK | XEMACPS_RXSR_ERROR_MASK)) != 0)
459  {
460  //Only clear RSR flags that are currently set
461  XEMACPS_RXSR = rsr;
462 
463  //Process all pending packets
464  do
465  {
466  //Read incoming packet
467  error = zynq7000EthReceivePacket(interface);
468 
469  //No more data in the receive buffer?
470  } while(error != ERROR_BUFFER_EMPTY);
471  }
472 }
473 
474 
475 /**
476  * @brief Send a packet
477  * @param[in] interface Underlying network interface
478  * @param[in] buffer Multi-part buffer containing the data to send
479  * @param[in] offset Offset to the first data byte
480  * @param[in] ancillary Additional options passed to the stack along with
481  * the packet
482  * @return Error code
483  **/
484 
486  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
487 {
488  static uint32_t temp[ZYNQ7000_ETH_TX_BUFFER_SIZE / 4];
489  size_t length;
490 
491  //Retrieve the length of the packet
492  length = netBufferGetLength(buffer) - offset;
493 
494  //Check the frame length
496  {
497  //The transmitter can accept another packet
498  osSetEvent(&interface->nicTxEvent);
499  //Report an error
500  return ERROR_INVALID_LENGTH;
501  }
502 
503  //Make sure the current buffer is available for writing
504  if((txBufferDesc[txBufferIndex].status & XEMACPS_TX_USED) == 0)
505  {
506  return ERROR_FAILURE;
507  }
508 
509  //Copy user data to the transmit buffer
510  netBufferRead(temp, buffer, offset, length);
511  osMemcpy(txBuffer[txBufferIndex], temp, length);
512 
513  //Set the necessary flags in the descriptor entry
514  if(txBufferIndex < (ZYNQ7000_ETH_TX_BUFFER_COUNT - 1))
515  {
516  //Write the status word
517  txBufferDesc[txBufferIndex].status = XEMACPS_TX_LAST |
519 
520  //Point to the next buffer
521  txBufferIndex++;
522  }
523  else
524  {
525  //Write the status word
526  txBufferDesc[txBufferIndex].status = XEMACPS_TX_WRAP | XEMACPS_TX_LAST |
528 
529  //Wrap around
530  txBufferIndex = 0;
531  }
532 
533  //Set the STARTTX bit to initiate transmission
534  XEMACPS_NWCTRL |= XEMACPS_NWCTRL_STARTTX_MASK;
535 
536  //Check whether the next buffer is available for writing
537  if((txBufferDesc[txBufferIndex].status & XEMACPS_TX_USED) != 0)
538  {
539  //The transmitter can accept another packet
540  osSetEvent(&interface->nicTxEvent);
541  }
542 
543  //Successful processing
544  return NO_ERROR;
545 }
546 
547 
548 /**
549  * @brief Receive a packet
550  * @param[in] interface Underlying network interface
551  * @return Error code
552  **/
553 
555 {
556  static uint32_t temp[ETH_MAX_FRAME_SIZE / 4];
557  error_t error;
558  uint_t i;
559  uint_t j;
560  uint_t sofIndex;
561  uint_t eofIndex;
562  size_t n;
563  size_t size;
564  size_t length;
565 
566  //Initialize variables
567  size = 0;
568  sofIndex = UINT_MAX;
569  eofIndex = UINT_MAX;
570 
571  //Search for SOF and EOF flags
572  for(i = 0; i < ZYNQ7000_ETH_RX_BUFFER_COUNT; i++)
573  {
574  //Point to the current entry
575  j = rxBufferIndex + i;
576 
577  //Wrap around to the beginning of the buffer if necessary
579  {
581  }
582 
583  //No more entries to process?
584  if((rxBufferDesc[j].address & XEMACPS_RX_OWNERSHIP) == 0)
585  {
586  //Stop processing
587  break;
588  }
589 
590  //A valid SOF has been found?
591  if((rxBufferDesc[j].status & XEMACPS_RX_SOF) != 0)
592  {
593  //Save the position of the SOF
594  sofIndex = i;
595  }
596 
597  //A valid EOF has been found?
598  if((rxBufferDesc[j].status & XEMACPS_RX_EOF) != 0 && sofIndex != UINT_MAX)
599  {
600  //Save the position of the EOF
601  eofIndex = i;
602  //Retrieve the length of the frame
603  size = rxBufferDesc[j].status & XEMACPS_RX_LENGTH;
604  //Limit the number of data to read
605  size = MIN(size, ETH_MAX_FRAME_SIZE);
606  //Stop processing since we have reached the end of the frame
607  break;
608  }
609  }
610 
611  //Determine the number of entries to process
612  if(eofIndex != UINT_MAX)
613  {
614  j = eofIndex + 1;
615  }
616  else if(sofIndex != UINT_MAX)
617  {
618  j = sofIndex;
619  }
620  else
621  {
622  j = i;
623  }
624 
625  //Total number of bytes that have been copied from the receive buffer
626  length = 0;
627 
628  //Process incoming frame
629  for(i = 0; i < j; i++)
630  {
631  //Any data to copy from current buffer?
632  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
633  {
634  //Calculate the number of bytes to read at a time
636  //Copy data from receive buffer
637  osMemcpy((uint8_t *) temp + length, rxBuffer[rxBufferIndex], n);
638  //Update byte counters
639  length += n;
640  size -= n;
641  }
642 
643  //Mark the current buffer as free
644  rxBufferDesc[rxBufferIndex].address &= ~XEMACPS_RX_OWNERSHIP;
645 
646  //Point to the following entry
647  rxBufferIndex++;
648 
649  //Wrap around to the beginning of the buffer if necessary
650  if(rxBufferIndex >= ZYNQ7000_ETH_RX_BUFFER_COUNT)
651  {
652  rxBufferIndex = 0;
653  }
654  }
655 
656  //Any packet to process?
657  if(length > 0)
658  {
659  NetRxAncillary ancillary;
660 
661  //Additional options can be passed to the stack along with the packet
662  ancillary = NET_DEFAULT_RX_ANCILLARY;
663 
664  //Pass the packet to the upper layer
665  nicProcessPacket(interface, (uint8_t *) temp, length, &ancillary);
666  //Valid packet received
667  error = NO_ERROR;
668  }
669  else
670  {
671  //No more data in the receive buffer
672  error = ERROR_BUFFER_EMPTY;
673  }
674 
675  //Return status code
676  return error;
677 }
678 
679 
680 /**
681  * @brief Configure MAC address filtering
682  * @param[in] interface Underlying network interface
683  * @return Error code
684  **/
685 
687 {
688  uint_t i;
689  uint_t k;
690  uint8_t *p;
691  uint32_t hashTable[2];
692  MacFilterEntry *entry;
693 
694  //Debug message
695  TRACE_DEBUG("Updating MAC filter...\r\n");
696 
697  //Set the MAC address of the station
698  XEMACPS_LADDR1L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
699  XEMACPS_LADDR1H = interface->macAddr.w[2];
700 
701  //Clear hash table
702  hashTable[0] = 0;
703  hashTable[1] = 0;
704 
705  //The MAC address filter contains the list of MAC addresses to accept
706  //to accept when receiving an Ethernet frame
707  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
708  {
709  //Point to the current entry
710  entry = &interface->macAddrFilter[i];
711 
712  //Valid entry?
713  if(entry->refCount > 0)
714  {
715  //Point to the MAC address
716  p = entry->addr.b;
717 
718  //Apply the hash function
719  k = (p[0] >> 6) ^ p[0];
720  k ^= (p[1] >> 4) ^ (p[1] << 2);
721  k ^= (p[2] >> 2) ^ (p[2] << 4);
722  k ^= (p[3] >> 6) ^ p[3];
723  k ^= (p[4] >> 4) ^ (p[4] << 2);
724  k ^= (p[5] >> 2) ^ (p[5] << 4);
725 
726  //The hash value is reduced to a 6-bit index
727  k &= 0x3F;
728 
729  //Update hash table contents
730  hashTable[k / 32] |= (1 << (k % 32));
731  }
732  }
733 
734  //Write the hash table
735  XEMACPS_HASHL = hashTable[0];
736  XEMACPS_HASHH = hashTable[1];
737 
738  //Debug message
739  TRACE_DEBUG(" HASHL = %08" PRIX32 "\r\n", XEMACPS_HASHL);
740  TRACE_DEBUG(" HASHH = %08" PRIX32 "\r\n", XEMACPS_HASHH);
741 
742  //Successful processing
743  return NO_ERROR;
744 }
745 
746 
747 /**
748  * @brief Adjust MAC configuration parameters for proper operation
749  * @param[in] interface Underlying network interface
750  * @return Error code
751  **/
752 
754 {
755  uint32_t config;
756  uint32_t clockCtrl;
757 
758  //Read network configuration register
759  config = XEMACPS_NWCFG;
760 
761  //Read clock control register
762  clockCtrl = XSLCR_GEM0_CLK_CTRL;
764 
765  //1000BASE-T operation mode?
766  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
767  {
768  //Update network configuration
769  config |= XEMACPS_NWCFG_1000_MASK;
770  config &= ~XEMACPS_NWCFG_100_MASK;
771 
772  //Update clock configuration
773  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK;
774  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK;
775  }
776  //100BASE-TX operation mode?
777  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
778  {
779  //Update network configuration
780  config &= ~XEMACPS_NWCFG_1000_MASK;
781  config |= XEMACPS_NWCFG_100_MASK;
782 
783  //Update clock configuration
784  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK;
785  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK;
786  }
787  //10BASE-T operation mode?
788  else
789  {
790  //Update network configuration
791  config &= ~XEMACPS_NWCFG_1000_MASK;
792  config &= ~XEMACPS_NWCFG_100_MASK;
793 
794  //Update clock configuration
795  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK;
796  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK;
797  }
798 
799  //Half-duplex or full-duplex mode?
800  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
801  {
802  config |= XEMACPS_NWCFG_FDEN_MASK;
803  }
804  else
805  {
806  config &= ~XEMACPS_NWCFG_FDEN_MASK;
807  }
808 
809  //Write network configuration register
810  XEMACPS_NWCFG = config;
811 
812  //Unlock SLCR
814  //Write clock control register
815  XSLCR_GEM0_CLK_CTRL = clockCtrl;
816  //Lock SLCR
818 
819  //Successful processing
820  return NO_ERROR;
821 }
822 
823 
824 /**
825  * @brief Write PHY register
826  * @param[in] opcode Access type (2 bits)
827  * @param[in] phyAddr PHY address (5 bits)
828  * @param[in] regAddr Register address (5 bits)
829  * @param[in] data Register value
830  **/
831 
832 void zynq7000EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
833  uint8_t regAddr, uint16_t data)
834 {
835  uint32_t temp;
836 
837  //Valid opcode?
838  if(opcode == SMI_OPCODE_WRITE)
839  {
840  //Set up a write operation
841  temp = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK;
842  //PHY address
843  temp |= (phyAddr << 23) & XEMACPS_PHYMNTNC_ADDR_MASK;
844  //Register address
845  temp |= (regAddr << 18) & XEMACPS_PHYMNTNC_REG_MASK;
846  //Register value
847  temp |= data & XEMACPS_PHYMNTNC_DATA_MASK;
848 
849  //Start a write operation
850  XEMACPS_PHYMNTNC = temp;
851  //Wait for the write to complete
852  while((XEMACPS_NWSR & XEMACPS_NWSR_MDIOIDLE_MASK) == 0)
853  {
854  }
855  }
856  else
857  {
858  //The MAC peripheral only supports standard Clause 22 opcodes
859  }
860 }
861 
862 
863 /**
864  * @brief Read PHY register
865  * @param[in] opcode Access type (2 bits)
866  * @param[in] phyAddr PHY address (5 bits)
867  * @param[in] regAddr Register address (5 bits)
868  * @return Register value
869  **/
870 
871 uint16_t zynq7000EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
872  uint8_t regAddr)
873 {
874  uint16_t data;
875  uint32_t temp;
876 
877  //Valid opcode?
878  if(opcode == SMI_OPCODE_READ)
879  {
880  //Set up a read operation
881  temp = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK;
882  //PHY address
883  temp |= (phyAddr << 23) & XEMACPS_PHYMNTNC_ADDR_MASK;
884  //Register address
885  temp |= (regAddr << 18) & XEMACPS_PHYMNTNC_REG_MASK;
886 
887  //Start a read operation
888  XEMACPS_PHYMNTNC = temp;
889  //Wait for the read to complete
890  while((XEMACPS_NWSR & XEMACPS_NWSR_MDIOIDLE_MASK) == 0)
891  {
892  }
893 
894  //Get register value
895  data = XEMACPS_PHYMNTNC & XEMACPS_PHYMNTNC_DATA_MASK;
896  }
897  else
898  {
899  //The MAC peripheral only supports standard Clause 22 opcodes
900  data = 0;
901  }
902 
903  //Return the value of the PHY register
904  return data;
905 }
#define rxBuffer
#define txBuffer
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint8_t opcode
Definition: dns_common.h:188
error_t
Error codes.
Definition: error.h:43
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:110
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
Ipv6Addr address[]
Definition: ipv6.h:316
uint16_t regAddr
uint8_t p
Definition: ndp.h:300
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:674
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:101
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:391
#define SMI_OPCODE_WRITE
Definition: nic.h:66
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define SMI_OPCODE_READ
Definition: nic.h:67
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define osEnterIsr()
#define osExitIsr(flag)
MAC filter table entry.
Definition: ethernet.h:262
MacAddr addr
MAC address.
Definition: ethernet.h:263
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
NIC driver.
Definition: nic.h:283
Receive buffer descriptor.
Transmit buffer descriptor.
uint8_t length
Definition: tcp.h:368
void zynq7000EthEventHandler(NetInterface *interface)
Zynq-7000 Ethernet MAC event handler.
void zynq7000EthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
void zynq7000EthDisableIrq(NetInterface *interface)
Disable interrupts.
error_t zynq7000EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
uint16_t zynq7000EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
error_t zynq7000EthInit(NetInterface *interface)
Zynq-7000 Ethernet MAC initialization.
XScuGic ZYNQ7000_ETH_GIC_INSTANCE
void zynq7000EthTick(NetInterface *interface)
Zynq-7000 Ethernet MAC timer handler.
error_t zynq7000EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
error_t zynq7000EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void zynq7000EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
const NicDriver zynq7000EthDriver
Zynq-7000 Ethernet MAC driver.
error_t zynq7000EthReceivePacket(NetInterface *interface)
Receive a packet.
void zynq7000EthEnableIrq(NetInterface *interface)
Enable interrupts.
void zynq7000EthIrqHandler(NetInterface *interface)
Zynq-7000 Ethernet MAC interrupt service routine.
Zynq-7000 Gigabit Ethernet MAC driver.
#define XEMACPS_RX_WRAP
#define XEMACPS_NWCFG
#define XEMACPS_ISR
#define XSLCR_GEM0_CLK_CTRL_DIV0_MASK
#define XEMACPS_RX_LENGTH
#define XEMACPS_RXQBASE
#define XEMACPS_TXQBASE
#define XEMACPS_LADDR1L
#define XEMACPS_PHYMNTNC
#define XEMACPS_TX_LAST
#define ZYNQ7000_ETH_TX_BUFFER_COUNT
#define ZYNQ7000_ETH_RX_BUFFER_SIZE
#define XEMACPS_RXSR
#define XSLCR_GEM0_CLK_CTRL_CLKACT_MASK
#define XSLCR_LOCK_KEY_VALUE
#define XSLCR_LOCK
#define XSLCR_GEM0_RCLK_CTRL_CLKACT_MASK
#define XEMACPS_RX_OWNERSHIP
#define XSLCR_UNLOCK
#define XEMACPS_TXSR
#define XEMACPS_NWCTRL
#define ZYNQ7000_ETH_TX_BUFFER_SIZE
#define XEMACPS_IDR
#define XEMACPS_TX_USED
#define XEMACPS_RX_SOF
#define ZYNQ7000_ETH_RX_BUFFER_COUNT
#define XEMACPS_DMACR
#define ZYNQ7000_ETH_IRQ_PRIORITY
#define ZYNQ7000_ETH_RAM_SECTION
#define XSLCR_GEM0_CLK_CTRL
#define XEMACPS_TX_LENGTH
#define XEMACPS_IER
#define XEMACPS_RX_ADDRESS
#define XSLCR_UNLOCK_KEY_VALUE
#define XEMACPS_NWSR
#define XEMACPS_LADDR1H
#define XSLCR_GEM0_RCLK_CTRL
#define XEMACPS_TX_WRAP
#define XEMACPS_HASHH
#define XSLCR_GEM0_CLK_CTRL_DIV1_MASK
#define XEMACPS_RX_EOF
#define XEMACPS_HASHL