mpfsxxx_eth1_driver.c
Go to the documentation of this file.
1 /**
2  * @file mpfsxxx_eth1_driver.c
3  * @brief PolarFire SoC Gigabit Ethernet MAC driver (MAC0 instance)
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.2
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 "mpfs_hal/common/mss_plic.h"
37 #include "mpfs_hal/common/mss_sysreg.h"
38 #include "drivers/mss/mss_ethernet_mac/mss_ethernet_registers.h"
39 #include "drivers/mss/mss_ethernet_mac/mss_ethernet_mac_regs.h"
40 #include "core/net.h"
42 #include "debug.h"
43 
44 #if defined(USE_MPFS_ICICLE_KIT_ES)
46 #endif
47 
48 //Underlying network interface
49 static NetInterface *nicDriverInterface;
50 
51 //TX buffer
53  __attribute__((aligned(8), __section__(MPFSXXX_ETH1_RAM_SECTION)));
54 //RX buffer
56  __attribute__((aligned(8), __section__(MPFSXXX_ETH1_RAM_SECTION)));
57 //TX buffer descriptors
59  __attribute__((aligned(8), __section__(MPFSXXX_ETH1_RAM_SECTION)));
60 //RX buffer descriptors
62  __attribute__((aligned(8), __section__(MPFSXXX_ETH1_RAM_SECTION)));
63 
64 //Dummy TX buffer
66  __attribute__((aligned(8), __section__(MPFSXXX_ETH1_RAM_SECTION)));
67 //Dummy RX buffer
69  __attribute__((aligned(8), __section__(MPFSXXX_ETH1_RAM_SECTION)));
70 //Dummy TX buffer descriptors
72  __attribute__((aligned(8), __section__(MPFSXXX_ETH1_RAM_SECTION)));
73 //Dummy RX buffer descriptors
75  __attribute__((aligned(8), __section__(MPFSXXX_ETH1_RAM_SECTION)));
76 
77 //TX buffer index
78 static uint_t txBufferIndex;
79 //RX buffer index
80 static uint_t rxBufferIndex;
81 
82 
83 /**
84  * @brief MPFSxxx Ethernet MAC driver (MAC0 instance)
85  **/
86 
88 {
90  ETH_MTU,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief MPFSxxx Ethernet MAC initialization
110  * @param[in] interface Underlying network interface
111  * @return Error code
112  **/
113 
115 {
116  error_t error;
117  volatile uint32_t temp;
118 
119  //Debug message
120  TRACE_INFO("Initializing MPFSxxx Ethernet MAC (MAC0)...\r\n");
121 
122  //Save underlying network interface
123  nicDriverInterface = interface;
124 
125  //Enable MAC0 peripheral clock
126  SYSREG->SUBBLK_CLOCK_CR |= 2U;
127 
128  //Reset MAC0 peripheral
129  SYSREG->SOFT_RESET_CR |= 2U;
130  SYSREG->SOFT_RESET_CR &= ~2U;
131 
132  //Disable transmit and receive circuits
133  MAC0->NETWORK_CONTROL = 0;
134 
135  //GPIO configuration
136  mpfsxxxEth1InitGpio(interface);
137 
138  //Configure MDC clock speed
139  MAC0->NETWORK_CONFIG = GEM_SGMII_MODE_ENABLE | GEM_PCS_SELECT |
140  (1 << GEM_DATA_BUS_WIDTH_SHIFT) | (5 << GEM_MDC_CLOCK_DIVISOR_SHIFT);
141 
142  //Enable management port (MDC and MDIO)
143  MAC0->NETWORK_CONTROL |= GEM_MAN_PORT_EN;
144 
145  //Valid Ethernet PHY or switch driver?
146  if(interface->phyDriver != NULL)
147  {
148  //Ethernet PHY initialization
149  error = interface->phyDriver->init(interface);
150  }
151  else if(interface->switchDriver != NULL)
152  {
153  //Ethernet switch initialization
154  error = interface->switchDriver->init(interface);
155  }
156  else
157  {
158  //The interface is not properly configured
159  error = ERROR_FAILURE;
160  }
161 
162  //Any error to report?
163  if(error)
164  {
165  return error;
166  }
167 
168  //Set the MAC address of the station
169  MAC0->SPEC_ADD1_BOTTOM = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
170  MAC0->SPEC_ADD1_TOP = interface->macAddr.w[2];
171 
172  //The MAC supports 3 additional addresses for unicast perfect filtering
173  MAC0->SPEC_ADD2_BOTTOM = 0;
174  MAC0->SPEC_ADD3_BOTTOM = 0;
175  MAC0->SPEC_ADD4_BOTTOM = 0;
176 
177  //Initialize hash table
178  MAC0->HASH_BOTTOM = 0;
179  MAC0->HASH_TOP = 0;
180 
181  //Configure the receive filter
182  MAC0->NETWORK_CONFIG |= GEM_RECEIVE_1536_BYTE_FRAMES | GEM_MULTICAST_HASH_ENABLE;
183 
184  //Set RX buffer size
185  temp = ((MPFSXXX_ETH1_RX_BUFFER_SIZE / 64) << GEM_RX_BUF_SIZE_SHIFT) &
186  GEM_RX_BUF_SIZE;
187 
188  //Select 64-bit bus width
189  temp |= GEM_DMA_ADDR_BUS_WIDTH_1;
190  //Use extended buffer descriptors
191  temp |= GEM_TX_BD_EXTENDED_MODE_EN | GEM_RX_BD_EXTENDED_MODE_EN;
192  //Use full configured addressable space for transmit and receive packet buffers
193  temp |= GEM_TX_PBUF_SIZE | GEM_RX_PBUF_SIZE;
194 
195  //DMA configuration
196  MAC0->DMA_CONFIG = temp;
197  MAC0->DMA_RXBUF_SIZE_Q1 = MPFSXXX_ETH1_DUMMY_BUFFER_SIZE / 64;
198  MAC0->DMA_RXBUF_SIZE_Q1 = MPFSXXX_ETH1_DUMMY_BUFFER_SIZE / 64;
199  MAC0->DMA_RXBUF_SIZE_Q1 = MPFSXXX_ETH1_DUMMY_BUFFER_SIZE / 64;
200 
201  //Initialize buffer descriptors
202  mpfsxxxEth1InitBufferDesc(interface);
203 
204  //Clear transmit status register
205  MAC0->TRANSMIT_STATUS = GEM_TX_RESP_NOT_OK | GEM_STAT_TRANSMIT_UNDER_RUN |
206  GEM_STAT_TRANSMIT_COMPLETE | GEM_STAT_AMBA_ERROR | GEM_TRANSMIT_GO |
207  GEM_RETRY_LIMIT_EXCEEDED | GEM_COLLISION_OCCURRED | GEM_USED_BIT_READ;
208 
209  //Clear receive status register
210  MAC0->RECEIVE_STATUS = GEM_RX_RESP_NOT_OK | GEM_RECEIVE_OVERRUN |
211  GEM_FRAME_RECEIVED | GEM_BUFFER_NOT_AVAILABLE;
212 
213  //First disable all interrupts
214  MAC0->INT_DISABLE = 0xFFFFFFFF;
215  MAC0->INT_Q1_DISABLE = 0xFFFFFFFF;
216  MAC0->INT_Q2_DISABLE = 0xFFFFFFFF;
217  MAC0->INT_Q3_DISABLE = 0xFFFFFFFF;
218 
219  //Only the desired ones are enabled
220  MAC0->INT_ENABLE = GEM_RESP_NOT_OK_INT |
221  GEM_RECEIVE_OVERRUN_INT | GEM_TRANSMIT_COMPLETE | GEM_AMBA_ERROR |
222  GEM_RETRY_LIMIT_EXCEEDED_OR_LATE_COLLISION | GEM_TRANSMIT_UNDER_RUN |
223  GEM_RX_USED_BIT_READ | GEM_RECEIVE_COMPLETE;
224 
225  //Read interrupt status register to clear any pending interrupt
226  temp = MAC0->INT_STATUS;
227  (void) temp;
228 
229  //Configure interrupt priority
230  PLIC_SetPriority(MAC0_INT_PLIC, MPFSXXX_ETH1_IRQ_PRIORITY);
231 
232  //Enable the transmitter and the receiver
233  MAC0->NETWORK_CONTROL |= GEM_ENABLE_TRANSMIT | GEM_ENABLE_RECEIVE;
234 
235  //Accept any packets from the upper layer
236  osSetEvent(&interface->nicTxEvent);
237 
238  //Successful initialization
239  return NO_ERROR;
240 }
241 
242 
243 /**
244  * @brief GPIO configuration
245  * @param[in] interface Underlying network interface
246  **/
247 
248 __weak_func void mpfsxxxEth1InitGpio(NetInterface *interface)
249 {
250 //MPFS-ICICLE-KIT-ES evaluation board?
251 #if defined(USE_MPFS_ICICLE_KIT_ES)
252  //Enable MAC1 peripheral clock
253  SYSREG->SUBBLK_CLOCK_CR |= 4U;
254 
255  //Configure MDC clock speed
256  MAC1->NETWORK_CONFIG = GEM_SGMII_MODE_ENABLE | GEM_PCS_SELECT |
257  (1 << GEM_DATA_BUS_WIDTH_SHIFT) | (5 << GEM_MDC_CLOCK_DIVISOR_SHIFT);
258 
259  //Enable management port (MDC and MDIO)
260  MAC1->NETWORK_CONTROL |= GEM_MAN_PORT_EN;
261 #endif
262 }
263 
264 
265 /**
266  * @brief Initialize buffer descriptors
267  * @param[in] interface Underlying network interface
268  **/
269 
271 {
272  uint_t i;
273  uint64_t address;
274 
275  //Initialize TX buffer descriptors
276  for(i = 0; i < MPFSXXX_ETH1_TX_BUFFER_COUNT; i++)
277  {
278  //Calculate the address of the current TX buffer
279  address = (uint64_t) txBuffer[i];
280 
281  //Write the address to the descriptor entry
282  txBufferDesc[i].addrLow = (uint32_t) address;
283  txBufferDesc[i].addrHigh = (uint32_t) (address >> 32);
284 
285  //Initialize status field
286  txBufferDesc[i].status = MAC_TX_USED;
287 
288  //Clear unused fields
289  txBufferDesc[i].reserved = 0;
290  txBufferDesc[i].nanoSeconds = 0;
291  txBufferDesc[i].seconds = 0;
292  }
293 
294  //Mark the last descriptor entry with the wrap flag
295  txBufferDesc[i - 1].status |= MAC_TX_WRAP;
296  //Initialize TX buffer index
297  txBufferIndex = 0;
298 
299  //Initialize RX buffer descriptors
300  for(i = 0; i < MPFSXXX_ETH1_RX_BUFFER_COUNT; i++)
301  {
302  //Calculate the address of the current RX buffer
303  address = (uint64_t) rxBuffer[i];
304 
305  //Write the address to the descriptor entry
306  rxBufferDesc[i].addrLow = (uint32_t) address & MAC_RX_ADDRESS;
307  rxBufferDesc[i].addrHigh = (uint32_t) (address >> 32);
308 
309  //Clear status field
310  rxBufferDesc[i].status = 0;
311 
312  //Clear unused fields
313  rxBufferDesc[i].reserved = 0;
314  rxBufferDesc[i].nanoSeconds = 0;
315  rxBufferDesc[i].seconds = 0;
316  }
317 
318  //Mark the last descriptor entry with the wrap flag
319  rxBufferDesc[i - 1].addrLow |= MAC_RX_WRAP;
320  //Initialize RX buffer index
321  rxBufferIndex = 0;
322 
323  //Initialize dummy TX buffer descriptors
324  for(i = 0; i < MPFSXXX_ETH1_DUMMY_BUFFER_COUNT; i++)
325  {
326  //Calculate the address of the current TX buffer
327  address = (uint64_t) dummyTxBuffer[i];
328 
329  //Write the address to the descriptor entry
330  dummyTxBufferDesc[i].addrLow = (uint32_t) address;
331  dummyTxBufferDesc[i].addrHigh = (uint32_t) (address >> 32);
332 
333  //Initialize status field
334  dummyTxBufferDesc[i].status = MAC_TX_USED;
335 
336  //Clear unused fields
337  dummyTxBufferDesc[i].reserved = 0;
338  dummyTxBufferDesc[i].nanoSeconds = 0;
339  dummyTxBufferDesc[i].seconds = 0;
340  }
341 
342  //Mark the last descriptor entry with the wrap flag
343  dummyTxBufferDesc[i - 1].status |= MAC_TX_WRAP;
344 
345  //Initialize dummy RX buffer descriptors
346  for(i = 0; i < MPFSXXX_ETH1_DUMMY_BUFFER_COUNT; i++)
347  {
348  //Calculate the address of the current RX buffer
349  address = (uint64_t) dummyRxBuffer[i];
350 
351  //Write the address to the descriptor entry
352  dummyRxBufferDesc[i].addrLow = ((uint32_t) address & MAC_RX_ADDRESS) | MAC_RX_OWNERSHIP;
353  dummyRxBufferDesc[i].addrHigh = (uint32_t) (address >> 32);
354 
355  //Clear status field
356  dummyRxBufferDesc[i].status = 0;
357 
358  //Clear unused fields
359  dummyRxBufferDesc[i].reserved = 0;
360  dummyRxBufferDesc[i].nanoSeconds = 0;
361  dummyRxBufferDesc[i].seconds = 0;
362  }
363 
364  //Mark the last descriptor entry with the wrap flag
365  dummyRxBufferDesc[i - 1].addrLow |= MAC_RX_WRAP;
366 
367  //Start location of the TX descriptor list
368  MAC0->TRANSMIT_Q_PTR = (uint32_t) ((uint64_t) txBufferDesc);
369  MAC0->UPPER_TX_Q_BASE_ADDR = (uint32_t) ((uint64_t) txBufferDesc >> 32);
370 
371  MAC0->TRANSMIT_Q1_PTR = (uint32_t) ((uint64_t) dummyTxBufferDesc) | 1;
372  MAC0->TRANSMIT_Q2_PTR = (uint32_t) ((uint64_t) dummyTxBufferDesc) | 1;
373  MAC0->TRANSMIT_Q3_PTR = (uint32_t) ((uint64_t) dummyTxBufferDesc) | 1;
374 
375  //Start location of the RX descriptor list
376  MAC0->RECEIVE_Q_PTR = (uint32_t) ((uint64_t) rxBufferDesc);
377  MAC0->UPPER_RX_Q_BASE_ADDR = (uint32_t) ((uint64_t) rxBufferDesc >> 32);
378 
379  MAC0->RECEIVE_Q1_PTR = (uint32_t) ((uint64_t) dummyRxBufferDesc) | 1;
380  MAC0->RECEIVE_Q2_PTR = (uint32_t) ((uint64_t) dummyRxBufferDesc) | 1;
381  MAC0->RECEIVE_Q3_PTR = (uint32_t) ((uint64_t) dummyRxBufferDesc) | 1;
382 }
383 
384 
385 /**
386  * @brief MPFSxxx Ethernet MAC timer handler
387  *
388  * This routine is periodically called by the TCP/IP stack to handle periodic
389  * operations such as polling the link state
390  *
391  * @param[in] interface Underlying network interface
392  **/
393 
395 {
396  //Valid Ethernet PHY or switch driver?
397  if(interface->phyDriver != NULL)
398  {
399  //Handle periodic operations
400  interface->phyDriver->tick(interface);
401  }
402  else if(interface->switchDriver != NULL)
403  {
404  //Handle periodic operations
405  interface->switchDriver->tick(interface);
406  }
407  else
408  {
409  //Just for sanity
410  }
411 }
412 
413 
414 /**
415  * @brief Enable interrupts
416  * @param[in] interface Underlying network interface
417  **/
418 
420 {
421  //Enable Ethernet MAC interrupts
422  PLIC_EnableIRQ(MAC0_INT_PLIC);
423 
424  //Valid Ethernet PHY or switch driver?
425  if(interface->phyDriver != NULL)
426  {
427  //Enable Ethernet PHY interrupts
428  interface->phyDriver->enableIrq(interface);
429  }
430  else if(interface->switchDriver != NULL)
431  {
432  //Enable Ethernet switch interrupts
433  interface->switchDriver->enableIrq(interface);
434  }
435  else
436  {
437  //Just for sanity
438  }
439 }
440 
441 
442 /**
443  * @brief Disable interrupts
444  * @param[in] interface Underlying network interface
445  **/
446 
448 {
449  //Disable Ethernet MAC interrupts
450  PLIC_DisableIRQ(MAC0_INT_PLIC);
451 
452  //Valid Ethernet PHY or switch driver?
453  if(interface->phyDriver != NULL)
454  {
455  //Disable Ethernet PHY interrupts
456  interface->phyDriver->disableIrq(interface);
457  }
458  else if(interface->switchDriver != NULL)
459  {
460  //Disable Ethernet switch interrupts
461  interface->switchDriver->disableIrq(interface);
462  }
463  else
464  {
465  //Just for sanity
466  }
467 }
468 
469 
470 /**
471  * @brief MPFSxxx Ethernet MAC interrupt service routine
472  **/
473 
475 {
476  bool_t flag;
477  volatile uint32_t isr;
478  volatile uint32_t tsr;
479  volatile uint32_t rsr;
480 
481  //Interrupt service routine prologue
482  osEnterIsr();
483 
484  //This flag will be set if a higher priority task must be woken
485  flag = FALSE;
486 
487  //Each time the software reads INT_STATUS, it has to check the contents
488  //of TRANSMIT_STATUS, RECEIVE_STATUS and NETWORK_STATUS
489  isr = MAC0->INT_Q1_STATUS;
490  isr = MAC0->INT_Q2_STATUS;
491  isr = MAC0->INT_Q3_STATUS;
492  isr = MAC0->INT_STATUS;
493  tsr = MAC0->TRANSMIT_STATUS;
494  rsr = MAC0->RECEIVE_STATUS;
495 
496  //Clear interrupt flags
497  MAC0->INT_STATUS = isr;
498 
499  //Packet transmitted?
500  if((tsr & (GEM_TX_RESP_NOT_OK | GEM_STAT_TRANSMIT_UNDER_RUN |
501  GEM_STAT_TRANSMIT_COMPLETE | GEM_STAT_AMBA_ERROR | GEM_TRANSMIT_GO |
502  GEM_RETRY_LIMIT_EXCEEDED | GEM_COLLISION_OCCURRED | GEM_USED_BIT_READ)) != 0)
503  {
504  //Only clear TRANSMIT_STATUS flags that are currently set
505  MAC0->TRANSMIT_STATUS = tsr;
506 
507  //Check whether the TX buffer is available for writing
508  if((txBufferDesc[txBufferIndex].status & MAC_TX_USED) != 0)
509  {
510  //Notify the TCP/IP stack that the transmitter is ready to send
511  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
512  }
513  }
514 
515  //Packet received?
516  if((rsr & (GEM_RX_RESP_NOT_OK | GEM_RECEIVE_OVERRUN | GEM_FRAME_RECEIVED |
517  GEM_BUFFER_NOT_AVAILABLE)) != 0)
518  {
519  //Set event flag
520  nicDriverInterface->nicEvent = TRUE;
521  //Notify the TCP/IP stack of the event
522  flag |= osSetEventFromIsr(&netEvent);
523  }
524 
525  //Interrupt service routine epilogue
526  osExitIsr(flag);
527 
528  //Return from IRQ handler
529  return EXT_IRQ_KEEP_ENABLED;
530 }
531 
532 
533 /**
534  * @brief MPFSxxx Ethernet MAC event handler
535  * @param[in] interface Underlying network interface
536  **/
537 
539 {
540  error_t error;
541  uint32_t rsr;
542 
543  //Read receive status
544  rsr = MAC0->RECEIVE_STATUS;
545 
546  //Packet received?
547  if((rsr & (GEM_RX_RESP_NOT_OK | GEM_RECEIVE_OVERRUN | GEM_FRAME_RECEIVED |
548  GEM_BUFFER_NOT_AVAILABLE)) != 0)
549  {
550  //Only clear RECEIVE_STATUS flags that are currently set
551  MAC0->RECEIVE_STATUS = rsr;
552 
553  //Process all pending packets
554  do
555  {
556  //Read incoming packet
557  error = mpfsxxxEth1ReceivePacket(interface);
558 
559  //No more data in the receive buffer?
560  } while(error != ERROR_BUFFER_EMPTY);
561  }
562 }
563 
564 
565 /**
566  * @brief Send a packet
567  * @param[in] interface Underlying network interface
568  * @param[in] buffer Multi-part buffer containing the data to send
569  * @param[in] offset Offset to the first data byte
570  * @param[in] ancillary Additional options passed to the stack along with
571  * the packet
572  * @return Error code
573  **/
574 
576  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
577 {
578  size_t length;
579 
580  //Retrieve the length of the packet
581  length = netBufferGetLength(buffer) - offset;
582 
583  //Check the frame length
585  {
586  //The transmitter can accept another packet
587  osSetEvent(&interface->nicTxEvent);
588  //Report an error
589  return ERROR_INVALID_LENGTH;
590  }
591 
592  //Make sure the current buffer is available for writing
593  if((txBufferDesc[txBufferIndex].status & MAC_TX_USED) == 0)
594  {
595  return ERROR_FAILURE;
596  }
597 
598  //Copy user data to the transmit buffer
599  netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
600 
601  //Set the necessary flags in the descriptor entry
602  if(txBufferIndex < (MPFSXXX_ETH1_TX_BUFFER_COUNT - 1))
603  {
604  //Write the status word
605  txBufferDesc[txBufferIndex].status = MAC_TX_LAST |
606  (length & MAC_TX_LENGTH);
607 
608  //Point to the next buffer
609  txBufferIndex++;
610  }
611  else
612  {
613  //Write the status word
614  txBufferDesc[txBufferIndex].status = MAC_TX_WRAP | MAC_TX_LAST |
615  (length & MAC_TX_LENGTH);
616 
617  //Wrap around
618  txBufferIndex = 0;
619  }
620 
621  //Set the TRANSMIT_START bit to initiate transmission
622  MAC0->NETWORK_CONTROL |= GEM_TRANSMIT_START;
623 
624  //Check whether the next buffer is available for writing
625  if((txBufferDesc[txBufferIndex].status & MAC_TX_USED) != 0)
626  {
627  //The transmitter can accept another packet
628  osSetEvent(&interface->nicTxEvent);
629  }
630 
631  //Successful processing
632  return NO_ERROR;
633 }
634 
635 
636 /**
637  * @brief Receive a packet
638  * @param[in] interface Underlying network interface
639  * @return Error code
640  **/
641 
643 {
644  static uint32_t temp[ETH_MAX_FRAME_SIZE / 4];
645  error_t error;
646  uint_t i;
647  uint_t j;
648  uint_t sofIndex;
649  uint_t eofIndex;
650  size_t n;
651  size_t size;
652  size_t length;
653 
654  //Initialize variables
655  size = 0;
656  sofIndex = UINT_MAX;
657  eofIndex = UINT_MAX;
658 
659  //Search for SOF and EOF flags
660  for(i = 0; i < MPFSXXX_ETH1_RX_BUFFER_COUNT; i++)
661  {
662  //Point to the current entry
663  j = rxBufferIndex + i;
664 
665  //Wrap around to the beginning of the buffer if necessary
667  {
669  }
670 
671  //No more entries to process?
672  if((rxBufferDesc[j].addrLow & MAC_RX_OWNERSHIP) == 0)
673  {
674  //Stop processing
675  break;
676  }
677 
678  //A valid SOF has been found?
679  if((rxBufferDesc[j].status & MAC_RX_SOF) != 0)
680  {
681  //Save the position of the SOF
682  sofIndex = i;
683  }
684 
685  //A valid EOF has been found?
686  if((rxBufferDesc[j].status & MAC_RX_EOF) != 0 && sofIndex != UINT_MAX)
687  {
688  //Save the position of the EOF
689  eofIndex = i;
690  //Retrieve the length of the frame
691  size = rxBufferDesc[j].status & MAC_RX_LENGTH;
692  //Limit the number of data to read
693  size = MIN(size, ETH_MAX_FRAME_SIZE);
694  //Stop processing since we have reached the end of the frame
695  break;
696  }
697  }
698 
699  //Determine the number of entries to process
700  if(eofIndex != UINT_MAX)
701  {
702  j = eofIndex + 1;
703  }
704  else if(sofIndex != UINT_MAX)
705  {
706  j = sofIndex;
707  }
708  else
709  {
710  j = i;
711  }
712 
713  //Total number of bytes that have been copied from the receive buffer
714  length = 0;
715 
716  //Process incoming frame
717  for(i = 0; i < j; i++)
718  {
719  //Any data to copy from current buffer?
720  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
721  {
722  //Calculate the number of bytes to read at a time
724  //Copy data from receive buffer
725  osMemcpy((uint8_t *) temp + length, rxBuffer[rxBufferIndex], n);
726  //Update byte counters
727  length += n;
728  size -= n;
729  }
730 
731  //Mark the current buffer as free
732  rxBufferDesc[rxBufferIndex].addrLow &= ~MAC_RX_OWNERSHIP;
733 
734  //Point to the following entry
735  rxBufferIndex++;
736 
737  //Wrap around to the beginning of the buffer if necessary
738  if(rxBufferIndex >= MPFSXXX_ETH1_RX_BUFFER_COUNT)
739  {
740  rxBufferIndex = 0;
741  }
742  }
743 
744  //Any packet to process?
745  if(length > 0)
746  {
747  NetRxAncillary ancillary;
748 
749  //Additional options can be passed to the stack along with the packet
750  ancillary = NET_DEFAULT_RX_ANCILLARY;
751 
752  //Pass the packet to the upper layer
753  nicProcessPacket(interface, (uint8_t *) temp, length, &ancillary);
754  //Valid packet received
755  error = NO_ERROR;
756  }
757  else
758  {
759  //No more data in the receive buffer
760  error = ERROR_BUFFER_EMPTY;
761  }
762 
763  //Return status code
764  return error;
765 }
766 
767 
768 /**
769  * @brief Configure MAC address filtering
770  * @param[in] interface Underlying network interface
771  * @return Error code
772  **/
773 
775 {
776  uint_t i;
777  uint_t j;
778  uint_t k;
779  uint8_t *p;
780  uint32_t hashTable[2];
781  MacAddr unicastMacAddr[3];
782  MacFilterEntry *entry;
783 
784  //Debug message
785  TRACE_DEBUG("Updating MAC filter...\r\n");
786 
787  //Set the MAC address of the station
788  MAC0->SPEC_ADD1_BOTTOM = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
789  MAC0->SPEC_ADD1_TOP = interface->macAddr.w[2];
790 
791  //The MAC supports 3 additional addresses for unicast perfect filtering
792  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
793  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
794  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
795 
796  //The hash table is used for multicast address filtering
797  hashTable[0] = 0;
798  hashTable[1] = 0;
799 
800  //The MAC address filter contains the list of MAC addresses to accept
801  //when receiving an Ethernet frame
802  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
803  {
804  //Point to the current entry
805  entry = &interface->macAddrFilter[i];
806 
807  //Valid entry?
808  if(entry->refCount > 0)
809  {
810  //Multicast address?
811  if(macIsMulticastAddr(&entry->addr))
812  {
813  //Point to the MAC address
814  p = entry->addr.b;
815 
816  //Apply the hash function
817  k = (p[0] >> 6) ^ p[0];
818  k ^= (p[1] >> 4) ^ (p[1] << 2);
819  k ^= (p[2] >> 2) ^ (p[2] << 4);
820  k ^= (p[3] >> 6) ^ p[3];
821  k ^= (p[4] >> 4) ^ (p[4] << 2);
822  k ^= (p[5] >> 2) ^ (p[5] << 4);
823 
824  //The hash value is reduced to a 6-bit index
825  k &= 0x3F;
826 
827  //Update hash table contents
828  hashTable[k / 32] |= (1 << (k % 32));
829  }
830  else
831  {
832  //Up to 3 additional MAC addresses can be specified
833  if(j < 3)
834  {
835  //Save the unicast address
836  unicastMacAddr[j] = entry->addr;
837  }
838  else
839  {
840  //Point to the MAC address
841  p = entry->addr.b;
842 
843  //Apply the hash function
844  k = (p[0] >> 6) ^ p[0];
845  k ^= (p[1] >> 4) ^ (p[1] << 2);
846  k ^= (p[2] >> 2) ^ (p[2] << 4);
847  k ^= (p[3] >> 6) ^ p[3];
848  k ^= (p[4] >> 4) ^ (p[4] << 2);
849  k ^= (p[5] >> 2) ^ (p[5] << 4);
850 
851  //The hash value is reduced to a 6-bit index
852  k &= 0x3F;
853 
854  //Update hash table contents
855  hashTable[k / 32] |= (1 << (k % 32));
856  }
857 
858  //Increment the number of unicast addresses
859  j++;
860  }
861  }
862  }
863 
864  //Configure the first unicast address filter
865  if(j >= 1)
866  {
867  //The address is activated when SAT register is written
868  MAC0->SPEC_ADD2_BOTTOM = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
869  MAC0->SPEC_ADD2_TOP = unicastMacAddr[0].w[2];
870  }
871  else
872  {
873  //The address is deactivated when SAB register is written
874  MAC0->SPEC_ADD2_BOTTOM = 0;
875  }
876 
877  //Configure the second unicast address filter
878  if(j >= 2)
879  {
880  //The address is activated when SAT register is written
881  MAC0->SPEC_ADD3_BOTTOM = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
882  MAC0->SPEC_ADD3_TOP = unicastMacAddr[1].w[2];
883  }
884  else
885  {
886  //The address is deactivated when SAB register is written
887  MAC0->SPEC_ADD3_BOTTOM = 0;
888  }
889 
890  //Configure the third unicast address filter
891  if(j >= 3)
892  {
893  //The address is activated when SAT register is written
894  MAC0->SPEC_ADD4_BOTTOM = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
895  MAC0->SPEC_ADD4_TOP = unicastMacAddr[2].w[2];
896  }
897  else
898  {
899  //The address is deactivated when SAB register is written
900  MAC0->SPEC_ADD4_BOTTOM = 0;
901  }
902 
903  //The perfect MAC filter supports only 3 unicast addresses
904  if(j >= 4)
905  {
906  MAC0->NETWORK_CONFIG |= GEM_UNICAST_HASH_ENABLE;
907  }
908  else
909  {
910  MAC0->NETWORK_CONFIG &= ~GEM_UNICAST_HASH_ENABLE;
911  }
912 
913  //Configure the multicast hash table
914  MAC0->HASH_BOTTOM = hashTable[0];
915  MAC0->HASH_TOP = hashTable[1];
916 
917  //Debug message
918  TRACE_DEBUG(" HASH_BOTTOM = %08" PRIX32 "\r\n", MAC0->HASH_BOTTOM);
919  TRACE_DEBUG(" HASH_TOP = %08" PRIX32 "\r\n", MAC0->HASH_TOP);
920 
921  //Successful processing
922  return NO_ERROR;
923 }
924 
925 
926 /**
927  * @brief Adjust MAC configuration parameters for proper operation
928  * @param[in] interface Underlying network interface
929  * @return Error code
930  **/
931 
933 {
934  uint32_t config;
935 
936  //Read network configuration register
937  config = MAC0->NETWORK_CONFIG;
938 
939  //1000BASE-T operation mode?
940  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
941  {
942  config |= GEM_GIGABIT_MODE_ENABLE;
943  config &= ~GEM_SPEED;
944  }
945  //100BASE-TX operation mode?
946  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
947  {
948  config &= ~GEM_GIGABIT_MODE_ENABLE;
949  config |= GEM_SPEED;
950  }
951  //10BASE-T operation mode?
952  else
953  {
954  config &= ~GEM_GIGABIT_MODE_ENABLE;
955  config &= ~GEM_SPEED;
956  }
957 
958  //Half-duplex or full-duplex mode?
959  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
960  {
961  config |= GEM_FULL_DUPLEX;
962  }
963  else
964  {
965  config &= ~GEM_FULL_DUPLEX;
966  }
967 
968  //Write configuration value back to NCFGR register
969  MAC0->NETWORK_CONFIG = config;
970 
971  //Successful processing
972  return NO_ERROR;
973 }
974 
975 
976 /**
977  * @brief Write PHY register
978  * @param[in] opcode Access type (2 bits)
979  * @param[in] phyAddr PHY address (5 bits)
980  * @param[in] regAddr Register address (5 bits)
981  * @param[in] data Register value
982  **/
983 
984 void mpfsxxxEth1WritePhyReg(uint8_t opcode, uint8_t phyAddr,
985  uint8_t regAddr, uint16_t data)
986 {
987  uint32_t temp;
988 
989  //Valid opcode?
990  if(opcode == SMI_OPCODE_WRITE)
991  {
992  //Set up a write operation
993  temp = GEM_WRITE1 | (GEM_PHY_OP_CL22_WRITE << GEM_OPERATION_SHIFT) |
994  (2 << GEM_WRITE10_SHIFT);
995 
996  //PHY address
997  temp |= (phyAddr << GEM_PHY_ADDRESS_SHIFT) & GEM_PHY_ADDRESS;
998  //Register address
999  temp |= (regAddr << GEM_REGISTER_ADDRESS_SHIFT) & GEM_REGISTER_ADDRESS;
1000  //Register value
1001  temp |= data;
1002 
1003  //Start a write operation
1004  MAC0->PHY_MANAGEMENT = temp;
1005  //Wait for the write to complete
1006  while((MAC0->NETWORK_STATUS & GEM_MAN_DONE) == 0)
1007  {
1008  }
1009  }
1010  else
1011  {
1012  //The MAC peripheral only supports standard Clause 22 opcodes
1013  }
1014 }
1015 
1016 
1017 /**
1018  * @brief Read PHY register
1019  * @param[in] opcode Access type (2 bits)
1020  * @param[in] phyAddr PHY address (5 bits)
1021  * @param[in] regAddr Register address (5 bits)
1022  * @return Register value
1023  **/
1024 
1025 uint16_t mpfsxxxEth1ReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1026  uint8_t regAddr)
1027 {
1028  uint16_t data;
1029  uint32_t temp;
1030 
1031  //Valid opcode?
1032  if(opcode == SMI_OPCODE_READ)
1033  {
1034  //Set up a read operation
1035  temp = GEM_WRITE1 | (GEM_PHY_OP_CL22_READ << GEM_OPERATION_SHIFT) |
1036  (2 << GEM_WRITE10_SHIFT);
1037 
1038  //PHY address
1039  temp |= (phyAddr << GEM_PHY_ADDRESS_SHIFT) & GEM_PHY_ADDRESS;
1040  //Register address
1041  temp |= (regAddr << GEM_REGISTER_ADDRESS_SHIFT) & GEM_REGISTER_ADDRESS;
1042 
1043  //Start a read operation
1044  MAC0->PHY_MANAGEMENT = temp;
1045  //Wait for the read to complete
1046  while((MAC0->NETWORK_STATUS & GEM_MAN_DONE) == 0)
1047  {
1048  }
1049 
1050  //Get register value
1051  data = (uint16_t) MAC0->PHY_MANAGEMENT;
1052  }
1053  else
1054  {
1055  //The MAC peripheral only supports standard Clause 22 opcodes
1056  data = 0;
1057  }
1058 
1059  //Return the value of the PHY register
1060  return data;
1061 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
error_t mpfsxxxEth1UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:53
#define netEvent
Definition: net_legacy.h:196
#define MAC_RX_WRAP
#define MAC_TX_LAST
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
PolarFire SoC Gigabit Ethernet MAC driver (MAC1 instance)
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
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:110
#define MPFSXXX_ETH1_DUMMY_BUFFER_COUNT
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
__weak_func void mpfsxxxEth1InitGpio(NetInterface *interface)
GPIO configuration.
error_t mpfsxxxEth1UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
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 macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define MAC_RX_SOF
#define FALSE
Definition: os_port.h:46
#define MPFSXXX_ETH1_IRQ_PRIORITY
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
uint16_t mpfsxxxEth1ReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define MAC_RX_OWNERSHIP
void mpfsxxxEth1Tick(NetInterface *interface)
MPFSxxx Ethernet MAC timer handler.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:101
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
PolarFire SoC Gigabit Ethernet MAC driver (MAC0 instance)
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:263
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define MAC_RX_ADDRESS
#define MPFSXXX_ETH1_RAM_SECTION
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
void mpfsxxxEth1EventHandler(NetInterface *interface)
MPFSxxx Ethernet MAC event handler.
#define NetTxAncillary
Definition: net_misc.h:36
#define MPFSXXX_ETH1_TX_BUFFER_COUNT
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MAC_RX_LENGTH
#define MIN(a, b)
Definition: os_port.h:63
#define MAC_RX_EOF
Transmit buffer descriptor.
#define MAC_TX_USED
#define rxBuffer
void mpfsxxxEth1WritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
MacAddr
Definition: ethernet.h:195
void mpfsxxxEth1InitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
void mpfsxxxEth1DisableIrq(NetInterface *interface)
Disable interrupts.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define MAC0
void mpfsxxxEth1EnableIrq(NetInterface *interface)
Enable interrupts.
Receive buffer descriptor.
uint16_t regAddr
#define MAC1
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
#define MAC_TX_WRAP
MAC filter table entry.
Definition: ethernet.h:262
uint8_t mac0_int_plic_IRQHandler(void)
MPFSxxx Ethernet MAC interrupt service routine.
Ipv6Addr address[]
Definition: ipv6.h:316
error_t mpfsxxxEth1ReceivePacket(NetInterface *interface)
Receive a packet.
#define osEnterIsr()
const NicDriver mpfsxxxEth1Driver
MPFSxxx Ethernet MAC driver (MAC0 instance)
#define MAC_TX_LENGTH
#define MPFSXXX_ETH1_RX_BUFFER_COUNT
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define MPFSXXX_ETH1_RX_BUFFER_SIZE
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
#define MPFSXXX_ETH1_TX_BUFFER_SIZE
NIC driver.
Definition: nic.h:283
error_t mpfsxxxEth1Init(NetInterface *interface)
MPFSxxx Ethernet MAC initialization.
error_t mpfsxxxEth1SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define MPFSXXX_ETH1_DUMMY_BUFFER_SIZE