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