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 controller
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 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 1.9.6
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 = ".ram_no_cache"
56 //RX buffer
57 #pragma data_alignment = 8
58 #pragma location = ".ram_no_cache"
60 //TX buffer descriptors
61 #pragma data_alignment = 4
62 #pragma location = ".ram_no_cache"
64 //RX buffer descriptors
65 #pragma data_alignment = 4
66 #pragma location = ".ram_no_cache"
68 
69 //Keil MDK-ARM or GCC compiler?
70 #else
71 
72 //TX buffer
74  __attribute__((aligned(8), __section__(".ram_no_cache")));
75 //RX buffer
77  __attribute__((aligned(8), __section__(".ram_no_cache")));
78 //TX buffer descriptors
80  __attribute__((aligned(4), __section__(".ram_no_cache")));
81 //RX buffer descriptors
83  __attribute__((aligned(4), __section__(".ram_no_cache")));
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  //PHY transceiver initialization
161  error = interface->phyDriver->init(interface);
162  //Failed to initialize PHY transceiver?
163  if(error)
164  return error;
165 
166  //Set the MAC address of the station
167  XEMACPS_LADDR1L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
168  XEMACPS_LADDR1H = interface->macAddr.w[2];
169 
170  //Configure the receive filter
171  XEMACPS_NWCFG |= XEMACPS_NWCFG_UCASTHASHEN_MASK | XEMACPS_NWCFG_MCASTHASHEN_MASK;
172 
173  //Initialize hash table
174  XEMACPS_HASHL = 0;
175  XEMACPS_HASHH = 0;
176 
177  //Initialize buffer descriptors
178  zynq7000EthInitBufferDesc(interface);
179 
180  //Set RX buffer size
181  temp = ((ZYNQ7000_ETH_RX_BUFFER_SIZE / 64) << XEMACPS_DMACR_RXBUF_SHIFT) &
182  XEMACPS_DMACR_RXBUF_MASK;
183 
184  //Use full configured addressable space for transmit and receive packet buffers
185  temp |= XEMACPS_DMACR_TXSIZE_MASK | XEMACPS_DMACR_RXSIZE_MASK;
186  //Select the burst length for DMA data operations
187  temp |= XEMACPS_DMACR_INCR16_AHB_BURST;
188  //Set DMA configuration register
189  XEMACPS_DMACR = temp;
190 
191  //Clear transmit status register
192  XEMACPS_TXSR = XEMACPS_TXSR_TXCOMPL_MASK | XEMACPS_TXSR_TXGO_MASK |
193  XEMACPS_TXSR_ERROR_MASK;
194 
195  //Clear receive status register
196  XEMACPS_RXSR = XEMACPS_RXSR_FRAMERX_MASK | XEMACPS_RXSR_ERROR_MASK;
197 
198  //First disable all interrupts
199  XEMACPS_IDR = 0xFFFFFFFF;
200 
201  //Only the desired ones are enabled
202  XEMACPS_IER = XEMACPS_IXR_HRESPNOK_MASK | XEMACPS_IXR_RXOVR_MASK |
203  XEMACPS_IXR_TXCOMPL_MASK | XEMACPS_IXR_TXEXH_MASK | XEMACPS_IXR_RETRY_MASK |
204  XEMACPS_IXR_URUN_MASK | XEMACPS_IXR_RXUSED_MASK | XEMACPS_IXR_FRAMERX_MASK;
205 
206  //Read interrupt status register to clear any pending interrupt
207  temp = XEMACPS_ISR;
208 
209  //Register interrupt handler
210  XScuGic_Connect(&ZYNQ7000_ETH_GIC_INSTANCE, XPS_GEM0_INT_ID,
211  (Xil_InterruptHandler) zynq7000EthIrqHandler, interface);
212 
213  //Configure interrupt priority
214  XScuGic_SetPriorityTriggerType(&ZYNQ7000_ETH_GIC_INSTANCE,
215  XPS_GEM0_INT_ID, ZYNQ7000_ETH_IRQ_PRIORITY, 1);
216 
217  //Enable the transmitter and the receiver
218  XEMACPS_NWCTRL |= XEMACPS_NWCTRL_TXEN_MASK | XEMACPS_NWCTRL_RXEN_MASK;
219 
220  //Accept any packets from the upper layer
221  osSetEvent(&interface->nicTxEvent);
222 
223  //Successful initialization
224  return NO_ERROR;
225 }
226 
227 
228 /**
229  * @brief Initialize buffer descriptors
230  * @param[in] interface Underlying network interface
231  **/
232 
234 {
235  uint_t i;
236  uint32_t address;
237 
238  //Initialize TX buffer descriptors
239  for(i = 0; i < ZYNQ7000_ETH_TX_BUFFER_COUNT; i++)
240  {
241  //Calculate the address of the current TX buffer
242  address = (uint32_t) txBuffer[i];
243  //Write the address to the descriptor entry
244  txBufferDesc[i].address = address;
245  //Initialize status field
246  txBufferDesc[i].status = XEMACPS_TX_USED;
247  }
248 
249  //Mark the last descriptor entry with the wrap flag
250  txBufferDesc[i - 1].status |= XEMACPS_TX_WRAP;
251  //Initialize TX buffer index
252  txBufferIndex = 0;
253 
254  //Initialize RX buffer descriptors
255  for(i = 0; i < ZYNQ7000_ETH_RX_BUFFER_COUNT; i++)
256  {
257  //Calculate the address of the current RX buffer
258  address = (uint32_t) rxBuffer[i];
259  //Write the address to the descriptor entry
260  rxBufferDesc[i].address = address & XEMACPS_RX_ADDRESS;
261  //Clear status field
262  rxBufferDesc[i].status = 0;
263  }
264 
265  //Mark the last descriptor entry with the wrap flag
266  rxBufferDesc[i - 1].address |= XEMACPS_RX_WRAP;
267  //Initialize RX buffer index
268  rxBufferIndex = 0;
269 
270  //Start location of the TX descriptor list
271  XEMACPS_TXQBASE = (uint32_t) txBufferDesc;
272  //Start location of the RX descriptor list
273  XEMACPS_RXQBASE = (uint32_t) rxBufferDesc;
274 }
275 
276 
277 /**
278  * @brief Zynq-7000 Ethernet MAC timer handler
279  *
280  * This routine is periodically called by the TCP/IP stack to
281  * handle periodic operations such as polling the link state
282  *
283  * @param[in] interface Underlying network interface
284  **/
285 
287 {
288  //Handle periodic operations
289  interface->phyDriver->tick(interface);
290 }
291 
292 
293 /**
294  * @brief Enable interrupts
295  * @param[in] interface Underlying network interface
296  **/
297 
299 {
300  //Enable Ethernet MAC interrupts
301  XScuGic_Enable(&ZYNQ7000_ETH_GIC_INSTANCE, XPS_GEM0_INT_ID);
302  //Enable Ethernet PHY interrupts
303  interface->phyDriver->enableIrq(interface);
304 }
305 
306 
307 /**
308  * @brief Disable interrupts
309  * @param[in] interface Underlying network interface
310  **/
311 
313 {
314  //Disable Ethernet MAC interrupts
315  XScuGic_Disable(&ZYNQ7000_ETH_GIC_INSTANCE, XPS_GEM0_INT_ID);
316  //Disable Ethernet PHY interrupts
317  interface->phyDriver->disableIrq(interface);
318 }
319 
320 
321 /**
322  * @brief Zynq-7000 Ethernet MAC interrupt service routine
323  * @param[in] interface Underlying network interface
324  **/
325 
327 {
328  bool_t flag;
329  volatile uint32_t isr;
330  volatile uint32_t tsr;
331  volatile uint32_t rsr;
332 
333  //Interrupt service routine prologue
334  osEnterIsr();
335 
336  //This flag will be set if a higher priority task must be woken
337  flag = FALSE;
338 
339  //Each time the software reads XEMACPS_ISR, it has to check the
340  //contents of XEMACPS_TXSR, XEMACPS_RXSR
341  isr = XEMACPS_ISR;
342  tsr = XEMACPS_TXSR;
343  rsr = XEMACPS_RXSR;
344 
345  //Clear interrupt flags
346  XEMACPS_ISR = isr;
347 
348  //A packet has been transmitted?
349  if(tsr & (XEMACPS_TXSR_TXCOMPL_MASK | XEMACPS_TXSR_TXGO_MASK | XEMACPS_TXSR_ERROR_MASK))
350  {
351  //Only clear TSR flags that are currently set
352  XEMACPS_TXSR = tsr;
353 
354  //Check whether the TX buffer is available for writing
355  if(txBufferDesc[txBufferIndex].status & XEMACPS_TX_USED)
356  {
357  //Notify the TCP/IP stack that the transmitter is ready to send
358  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
359  }
360  }
361 
362  //A packet has been received?
363  if(rsr & (XEMACPS_RXSR_FRAMERX_MASK | XEMACPS_RXSR_ERROR_MASK))
364  {
365  //Set event flag
366  nicDriverInterface->nicEvent = TRUE;
367  //Notify the TCP/IP stack of the event
368  flag |= osSetEventFromIsr(&netEvent);
369  }
370 
371  //Flush packet if the receive buffer not available
372  if (isr & XEMACPS_IXR_RXUSED_MASK)
373  XEMACPS_NWCTRL |= XEMACPS_NWCTRL_FLUSH_DPRAM_MASK;
374 
375  //Interrupt service routine epilogue
376  osExitIsr(flag);
377 }
378 
379 
380 /**
381  * @brief Zynq-7000 Ethernet MAC event handler
382  * @param[in] interface Underlying network interface
383  **/
384 
386 {
387  error_t error;
388  uint32_t rsr;
389 
390  //Read receive status
391  rsr = XEMACPS_RXSR;
392 
393  //Packet received?
394  if(rsr & (XEMACPS_RXSR_FRAMERX_MASK | XEMACPS_RXSR_ERROR_MASK))
395  {
396  //Only clear RSR flags that are currently set
397  XEMACPS_RXSR = rsr;
398 
399  //Process all pending packets
400  do
401  {
402  //Read incoming packet
403  error = zynq7000EthReceivePacket(interface);
404 
405  //No more data in the receive buffer?
406  } while(error != ERROR_BUFFER_EMPTY);
407  }
408 }
409 
410 
411 /**
412  * @brief Send a packet
413  * @param[in] interface Underlying network interface
414  * @param[in] buffer Multi-part buffer containing the data to send
415  * @param[in] offset Offset to the first data byte
416  * @return Error code
417  **/
418 
420  const NetBuffer *buffer, size_t offset)
421 {
422  static uint8_t temp[ZYNQ7000_ETH_TX_BUFFER_SIZE];
423  size_t length;
424 
425  //Retrieve the length of the packet
426  length = netBufferGetLength(buffer) - offset;
427 
428  //Check the frame length
430  {
431  //The transmitter can accept another packet
432  osSetEvent(&interface->nicTxEvent);
433  //Report an error
434  return ERROR_INVALID_LENGTH;
435  }
436 
437  //Make sure the current buffer is available for writing
438  if(!(txBufferDesc[txBufferIndex].status & XEMACPS_TX_USED))
439  return ERROR_FAILURE;
440 
441  //Copy user data to the transmit buffer
442  netBufferRead(temp, buffer, offset, length);
443  memcpy(txBuffer[txBufferIndex], temp, length);
444 
445  //Set the necessary flags in the descriptor entry
446  if(txBufferIndex < (ZYNQ7000_ETH_TX_BUFFER_COUNT - 1))
447  {
448  //Write the status word
449  txBufferDesc[txBufferIndex].status =
451 
452  //Point to the next buffer
453  txBufferIndex++;
454  }
455  else
456  {
457  //Write the status word
458  txBufferDesc[txBufferIndex].status = XEMACPS_TX_WRAP |
460 
461  //Wrap around
462  txBufferIndex = 0;
463  }
464 
465  //Set the STARTTX bit to initiate transmission
466  XEMACPS_NWCTRL |= XEMACPS_NWCTRL_STARTTX_MASK;
467 
468  //Check whether the next buffer is available for writing
469  if(txBufferDesc[txBufferIndex].status & XEMACPS_TX_USED)
470  {
471  //The transmitter can accept another packet
472  osSetEvent(&interface->nicTxEvent);
473  }
474 
475  //Successful processing
476  return NO_ERROR;
477 }
478 
479 
480 /**
481  * @brief Receive a packet
482  * @param[in] interface Underlying network interface
483  * @return Error code
484  **/
485 
487 {
488  static uint8_t temp[ETH_MAX_FRAME_SIZE];
489  error_t error;
490  uint_t i;
491  uint_t j;
492  uint_t sofIndex;
493  uint_t eofIndex;
494  size_t n;
495  size_t size;
496  size_t length;
497 
498  //Initialize SOF and EOF indices
499  sofIndex = UINT_MAX;
500  eofIndex = UINT_MAX;
501 
502  //Search for SOF and EOF flags
503  for(i = 0; i < ZYNQ7000_ETH_RX_BUFFER_COUNT; i++)
504  {
505  //Point to the current entry
506  j = rxBufferIndex + i;
507 
508  //Wrap around to the beginning of the buffer if necessary
511 
512  //No more entries to process?
513  if(!(rxBufferDesc[j].address & XEMACPS_RX_OWNERSHIP))
514  {
515  //Stop processing
516  break;
517  }
518  //A valid SOF has been found?
519  if(rxBufferDesc[j].status & XEMACPS_RX_SOF)
520  {
521  //Save the position of the SOF
522  sofIndex = i;
523  }
524  //A valid EOF has been found?
525  if((rxBufferDesc[j].status & XEMACPS_RX_EOF) && sofIndex != UINT_MAX)
526  {
527  //Save the position of the EOF
528  eofIndex = i;
529  //Retrieve the length of the frame
530  size = rxBufferDesc[j].status & XEMACPS_RX_LENGTH;
531  //Limit the number of data to read
532  size = MIN(size, ETH_MAX_FRAME_SIZE);
533  //Stop processing since we have reached the end of the frame
534  break;
535  }
536  }
537 
538  //Determine the number of entries to process
539  if(eofIndex != UINT_MAX)
540  j = eofIndex + 1;
541  else if(sofIndex != UINT_MAX)
542  j = sofIndex;
543  else
544  j = i;
545 
546  //Total number of bytes that have been copied from the receive buffer
547  length = 0;
548 
549  //Process incoming frame
550  for(i = 0; i < j; i++)
551  {
552  //Any data to copy from current buffer?
553  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
554  {
555  //Calculate the number of bytes to read at a time
557  //Copy data from receive buffer
558  memcpy(temp + length, rxBuffer[rxBufferIndex], n);
559  //Update byte counters
560  length += n;
561  size -= n;
562  }
563 
564  //Mark the current buffer as free
565  rxBufferDesc[rxBufferIndex].address &= ~XEMACPS_RX_OWNERSHIP;
566 
567  //Point to the following entry
568  rxBufferIndex++;
569 
570  //Wrap around to the beginning of the buffer if necessary
571  if(rxBufferIndex >= ZYNQ7000_ETH_RX_BUFFER_COUNT)
572  rxBufferIndex = 0;
573  }
574 
575  //Any packet to process?
576  if(length > 0)
577  {
578  //Pass the packet to the upper layer
579  nicProcessPacket(interface, temp, length);
580  //Valid packet received
581  error = NO_ERROR;
582  }
583  else
584  {
585  //No more data in the receive buffer
586  error = ERROR_BUFFER_EMPTY;
587  }
588 
589  //Return status code
590  return error;
591 }
592 
593 
594 /**
595  * @brief Configure MAC address filtering
596  * @param[in] interface Underlying network interface
597  * @return Error code
598  **/
599 
601 {
602  uint_t i;
603  uint_t k;
604  uint8_t *p;
605  uint32_t hashTable[2];
606  MacFilterEntry *entry;
607 
608  //Debug message
609  TRACE_DEBUG("Updating MAC filter...\r\n");
610 
611  //Set the MAC address of the station
612  XEMACPS_LADDR1L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
613  XEMACPS_LADDR1H = interface->macAddr.w[2];
614 
615  //Clear hash table
616  hashTable[0] = 0;
617  hashTable[1] = 0;
618 
619  //The MAC address filter contains the list of MAC addresses to accept
620  //to accept when receiving an Ethernet frame
621  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
622  {
623  //Point to the current entry
624  entry = &interface->macAddrFilter[i];
625 
626  //Valid entry?
627  if(entry->refCount > 0)
628  {
629  //Point to the MAC address
630  p = entry->addr.b;
631 
632  //Apply the hash function
633  k = (p[0] >> 6) ^ p[0];
634  k ^= (p[1] >> 4) ^ (p[1] << 2);
635  k ^= (p[2] >> 2) ^ (p[2] << 4);
636  k ^= (p[3] >> 6) ^ p[3];
637  k ^= (p[4] >> 4) ^ (p[4] << 2);
638  k ^= (p[5] >> 2) ^ (p[5] << 4);
639 
640  //The hash value is reduced to a 6-bit index
641  k &= 0x3F;
642 
643  //Update hash table contents
644  hashTable[k / 32] |= (1 << (k % 32));
645  }
646  }
647 
648  //Write the hash table
649  XEMACPS_HASHL = hashTable[0];
650  XEMACPS_HASHH = hashTable[1];
651 
652  //Debug message
653  TRACE_DEBUG(" HASHL = %08" PRIX32 "\r\n", XEMACPS_HASHL);
654  TRACE_DEBUG(" HASHH = %08" PRIX32 "\r\n", XEMACPS_HASHH);
655 
656  //Successful processing
657  return NO_ERROR;
658 }
659 
660 
661 /**
662  * @brief Adjust MAC configuration parameters for proper operation
663  * @param[in] interface Underlying network interface
664  * @return Error code
665  **/
666 
668 {
669  uint32_t config;
670  uint32_t clockCtrl;
671 
672  //Read network configuration register
673  config = XEMACPS_NWCFG;
674 
675  //Read clock control register
676  clockCtrl = XSLCR_GEM0_CLK_CTRL;
678 
679  //1000BASE-T operation mode?
680  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
681  {
682  //Update network configuration
683  config |= XEMACPS_NWCFG_1000_MASK;
684  config &= ~XEMACPS_NWCFG_100_MASK;
685 
686  //Update clock configuration
687  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK;
688  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK;
689  }
690  //100BASE-TX operation mode?
691  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
692  {
693  //Update network configuration
694  config &= ~XEMACPS_NWCFG_1000_MASK;
695  config |= XEMACPS_NWCFG_100_MASK;
696 
697  //Update clock configuration
698  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK;
699  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK;
700  }
701  //10BASE-T operation mode?
702  else
703  {
704  //Update network configuration
705  config &= ~XEMACPS_NWCFG_1000_MASK;
706  config &= ~XEMACPS_NWCFG_100_MASK;
707 
708  //Update clock configuration
709  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1 << 20) & XSLCR_GEM0_CLK_CTRL_DIV1_MASK;
710  clockCtrl |= (XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 << 8) & XSLCR_GEM0_CLK_CTRL_DIV0_MASK;
711  }
712 
713  //Half-duplex or full-duplex mode?
714  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
715  config |= XEMACPS_NWCFG_FDEN_MASK;
716  else
717  config &= ~XEMACPS_NWCFG_FDEN_MASK;
718 
719  //Write network configuration register
720  XEMACPS_NWCFG = config;
721 
722  //Unlock SLCR
724  //Write clock control register
725  XSLCR_GEM0_CLK_CTRL = clockCtrl;
726  //Lock SLCR
728 
729  //Successful processing
730  return NO_ERROR;
731 }
732 
733 
734 /**
735  * @brief Write PHY register
736  * @param[in] opcode Access type (2 bits)
737  * @param[in] phyAddr PHY address (5 bits)
738  * @param[in] regAddr Register address (5 bits)
739  * @param[in] data Register value
740  **/
741 
742 void zynq7000EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
743  uint8_t regAddr, uint16_t data)
744 {
745  uint32_t temp;
746 
747  //Valid opcode?
748  if(opcode == SMI_OPCODE_WRITE)
749  {
750  //Set up a write operation
751  temp = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK;
752  //PHY address
753  temp |= (phyAddr << 23) & XEMACPS_PHYMNTNC_ADDR_MASK;
754  //Register address
755  temp |= (regAddr << 18) & XEMACPS_PHYMNTNC_REG_MASK;
756  //Register value
757  temp |= data & XEMACPS_PHYMNTNC_DATA_MASK;
758 
759  //Start a write operation
760  XEMACPS_PHYMNTNC = temp;
761  //Wait for the write to complete
762  while(!(XEMACPS_NWSR & XEMACPS_NWSR_MDIOIDLE_MASK))
763  {
764  }
765  }
766  else
767  {
768  //The MAC peripheral only supports standard Clause 22 opcodes
769  }
770 }
771 
772 
773 /**
774  * @brief Read PHY register
775  * @param[in] opcode Access type (2 bits)
776  * @param[in] phyAddr PHY address (5 bits)
777  * @param[in] regAddr Register address (5 bits)
778  * @return Register value
779  **/
780 
781 uint16_t zynq7000EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
782  uint8_t regAddr)
783 {
784  uint16_t data;
785  uint32_t temp;
786 
787  //Valid opcode?
788  if(opcode == SMI_OPCODE_READ)
789  {
790  //Set up a read operation
791  temp = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK;
792  //PHY address
793  temp |= (phyAddr << 23) & XEMACPS_PHYMNTNC_ADDR_MASK;
794  //Register address
795  temp |= (regAddr << 18) & XEMACPS_PHYMNTNC_REG_MASK;
796 
797  //Start a read operation
798  XEMACPS_PHYMNTNC = temp;
799  //Wait for the read to complete
800  while(!(XEMACPS_NWSR & XEMACPS_NWSR_MDIOIDLE_MASK))
801  {
802  }
803 
804  //Get register value
805  data = XEMACPS_PHYMNTNC & XEMACPS_PHYMNTNC_DATA_MASK;
806  }
807  else
808  {
809  //The MAC peripheral only supports standard Clause 22 opcodes
810  data = 0;
811  }
812 
813  //Return the value of the PHY register
814  return data;
815 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
error_t zynq7000EthInit(NetInterface *interface)
Zynq-7000 Ethernet MAC initialization.
void zynq7000EthTick(NetInterface *interface)
Zynq-7000 Ethernet MAC timer handler.
uint8_t length
Definition: dtls_misc.h:149
uint8_t opcode
Definition: dns_common.h:172
#define XSLCR_GEM0_CLK_CTRL_DIV1_MASK
error_t zynq7000EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
int bool_t
Definition: compiler_port.h:49
#define XEMACPS_TXSR
void zynq7000EthEventHandler(NetInterface *interface)
Zynq-7000 Ethernet MAC event handler.
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:672
#define XSLCR_LOCK_KEY_VALUE
#define ZYNQ7000_ETH_IRQ_PRIORITY
#define XEMACPS_NWCFG
#define XEMACPS_RX_WRAP
#define ZYNQ7000_ETH_RX_BUFFER_COUNT
uint8_t p
Definition: ndp.h:298
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:383
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
void zynq7000EthEnableIrq(NetInterface *interface)
Enable interrupts.
error_t zynq7000EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define TRUE
Definition: os_port.h:50
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:89
void zynq7000EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define XEMACPS_TX_LAST
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:223
#define XSLCR_GEM0_RCLK_CTRL_CLKACT_MASK
#define XEMACPS_HASHH
error_t zynq7000EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define osExitIsr(flag)
Receive buffer descriptor.
#define XEMACPS_IDR
#define SMI_OPCODE_WRITE
Definition: nic.h:62
#define XEMACPS_TX_USED
Zynq-7000 Gigabit Ethernet MAC controller.
#define FALSE
Definition: os_port.h:46
Transmit buffer descriptor.
const NicDriver zynq7000EthDriver
Zynq-7000 Ethernet MAC driver.
error_t
Error codes.
Definition: error.h:42
#define XEMACPS_ISR
#define XEMACPS_DMACR
void zynq7000EthIrqHandler(NetInterface *interface)
Zynq-7000 Ethernet MAC interrupt service routine.
#define XSLCR_GEM0_CLK_CTRL
#define XEMACPS_LADDR1L
Generic error code.
Definition: error.h:45
#define XEMACPS_LADDR1H
#define XSLCR_GEM0_CLK_CTRL_DIV0_MASK
#define txBuffer
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:222
#define XEMACPS_RX_ADDRESS
#define XSLCR_UNLOCK
#define XEMACPS_RXSR
uint16_t zynq7000EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define XEMACPS_IER
OsEvent netEvent
Definition: net.c:77
#define XEMACPS_NWCTRL
#define ZYNQ7000_ETH_TX_BUFFER_COUNT
#define SMI_OPCODE_READ
Definition: nic.h:63
#define TRACE_INFO(...)
Definition: debug.h:94
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define XSLCR_LOCK
#define XEMACPS_RX_EOF
#define XSLCR_GEM0_RCLK_CTRL
#define MIN(a, b)
Definition: os_port.h:62
#define XSLCR_UNLOCK_KEY_VALUE
#define rxBuffer
void zynq7000EthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
#define ZYNQ7000_ETH_TX_BUFFER_SIZE
#define TRACE_DEBUG(...)
Definition: debug.h:106
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:91
uint8_t n
MAC filter table entry.
Definition: ethernet.h:220
#define osEnterIsr()
#define XEMACPS_RX_SOF
#define XEMACPS_PHYMNTNC
#define XEMACPS_NWSR
Ipv6Addr address
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define XEMACPS_TXQBASE
#define XEMACPS_RX_LENGTH
#define XSLCR_GEM0_CLK_CTRL_CLKACT_MASK
#define XEMACPS_RXQBASE
#define ZYNQ7000_ETH_RX_BUFFER_SIZE
error_t zynq7000EthReceivePacket(NetInterface *interface)
Receive a packet.
#define XEMACPS_TX_LENGTH
unsigned int uint_t
Definition: compiler_port.h:45
#define XEMACPS_HASHL
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
NIC driver.
Definition: nic.h:179
#define XEMACPS_TX_WRAP
XScuGic ZYNQ7000_ETH_GIC_INSTANCE
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
#define XEMACPS_RX_OWNERSHIP
Debugging facilities.
Ethernet interface.
Definition: nic.h:79
void zynq7000EthDisableIrq(NetInterface *interface)
Disable interrupts.