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