sc598_eth2_driver.c
Go to the documentation of this file.
1 /**
2  * @file sc598_eth2_driver.c
3  * @brief ADSP-SC598 Ethernet MAC driver (EMAC1 instance)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <sys/platform.h>
36 #include <services/int/adi_int.h>
37 #include "core/net.h"
39 #include "debug.h"
40 
41 //Underlying network interface
42 static NetInterface *nicDriverInterface;
43 
44 //IAR EWARM compiler?
45 #if defined(__ICCARM__)
46 
47 //Transmit buffer
48 #pragma data_alignment = 4
49 #pragma location = SC598_ETH2_RAM_SECTION
51 //Receive buffer
52 #pragma data_alignment = 4
53 #pragma location = SC598_ETH2_RAM_SECTION
55 //Transmit DMA descriptors
56 #pragma data_alignment = 8
57 #pragma location = SC598_ETH2_RAM_SECTION
59 //Receive DMA descriptors
60 #pragma data_alignment = 8
61 #pragma location = SC598_ETH2_RAM_SECTION
63 
64 //GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4), __section__(SC598_ETH2_RAM_SECTION)));
70 //Receive buffer
72  __attribute__((aligned(4), __section__(SC598_ETH2_RAM_SECTION)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(8), __section__(SC598_ETH2_RAM_SECTION)));
76 //Receive DMA descriptors
78  __attribute__((aligned(8), __section__(SC598_ETH2_RAM_SECTION)));
79 
80 #endif
81 
82 //Current transmit descriptor
83 static uint_t txIndex;
84 //Current receive descriptor
85 static uint_t rxIndex;
86 
87 
88 /**
89  * @brief ADSP-SC598 Ethernet MAC driver (EMAC1 instance)
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief ADSP-SC598 Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122  uint32_t temp;
123 
124  //Debug message
125  TRACE_INFO("Initializing ADSP-SC598 Ethernet MAC (EMAC1)...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //GPIO configuration
131  sc598Eth2InitGpio(interface);
132 
133  //Set DMA transfer format (little-endian)
134  *pREG_PADS0_PCFG0 &= ~BITM_PADS_PCFG0_EMAC1_ENDIANNESS;
135 
136  //Perform a software reset
137  *pREG_EMAC1_DMA_MODE |= BITM_EMAC_DMA_MODE_SWR;
138  //Wait for the reset to complete
139  while((*pREG_EMAC1_DMA_MODE & BITM_EMAC_DMA_MODE_SWR) != 0)
140  {
141  }
142 
143  //Adjust MDC clock range depending on SCLK0 frequency
144  *pREG_EMAC1_MDIO_ADDR = (4 << BITP_EMAC_MDIO_ADDR_CR);
145 
146  //Valid Ethernet PHY or switch driver?
147  if(interface->phyDriver != NULL)
148  {
149  //Ethernet PHY initialization
150  error = interface->phyDriver->init(interface);
151  }
152  else if(interface->switchDriver != NULL)
153  {
154  //Ethernet switch initialization
155  error = interface->switchDriver->init(interface);
156  }
157  else
158  {
159  //The interface is not properly configured
160  error = ERROR_FAILURE;
161  }
162 
163  //Any error to report?
164  if(error)
165  {
166  return error;
167  }
168 
169  //Use default MAC configuration
170  *pREG_EMAC1_MAC_CFG = BITM_EMAC_MAC_CFG_GPSLCE | BITM_EMAC_MAC_CFG_PS |
171  BITM_EMAC_MAC_CFG_DO;
172 
173  //Set the maximum packet size that can be accepted
174  temp = *pREG_EMAC1_MAC_EXT_CFG & ~BITM_EMAC_MAC_EXT_CFG_GPSL;
175  *pREG_EMAC1_MAC_EXT_CFG = temp | SC598_ETH2_RX_BUFFER_SIZE;
176 
177  //Configure MAC address filtering
178  sc598Eth2UpdateMacAddrFilter(interface);
179 
180  //Disable flow control
181  *pREG_EMAC1_Q0_TXFLOW_CTL = 0;
182  *pREG_EMAC1_RXFLOW_CTL = 0;
183 
184  //Configure DMA operating mode
185  *pREG_EMAC1_DMA_MODE = ENUM_EMAC_DMA_MODE_MODE0 |
186  ENUM_EMAC_DMA_MODE_DSPW_DISABLE;
187 
188  //Configure system bus mode
189  *pREG_EMAC1_DMA_SYSBMODE |= BITM_EMAC_DMA_SYSBMODE_AAL;
190 
191  //The DMA takes the descriptor table as contiguous
192  *pREG_EMAC1_DMA0_CTL = (0 << BITP_EMAC_DMA_CTL_DSL);
193  //Configure TX features
194  *pREG_EMAC1_DMA0_TXCTL = (32 << BITP_EMAC_DMA_TXCTL_TXPBL);
195 
196  //Configure RX features
197  *pREG_EMAC1_DMA0_RXCTL = (32 << BITP_EMAC_DMA_RXCTL_RXPBL) |
198  ((SC598_ETH2_RX_BUFFER_SIZE / 4) << BITP_EMAC_DMA_RXCTL_RBSZ_13_Y);
199 
200  //Set the threshold level of the MTL TX queue
201  *pREG_EMAC1_TQ0_OPMODE = (1 << BITP_EMAC_TQ_OPMODE_TTC);
202  //Set the threshold level of the MTL RX queue
203  *pREG_EMAC1_RQ0_OPMODE = (1 << BITP_EMAC_RQ_OPMODE_RTC);
204 
205  //Initialize DMA descriptor lists
206  sc598Eth2InitDmaDesc(interface);
207 
208  //Prevent interrupts from being generated when statistic counters reach
209  //half their maximum value
210  *pREG_EMAC1_MMC_TXIMSK = 0x0FFFFFFF;
211  *pREG_EMAC1_MMC_RXIMSK = 0x0FFFFFFF;
212  *pREG_EMAC1_MMC_IPC_RXIMSK = 0x3FFFFFFF;
213 
214  //Disable MAC interrupts
215  *pREG_EMAC1_MAC_IEN = 0;
216 
217  //Enable the desired DMA interrupts
218  *pREG_EMAC1_DMA0_IEN = BITM_EMAC_DMA_IEN_NIE | BITM_EMAC_DMA_IEN_RIE |
219  BITM_EMAC_DMA_IEN_TIE;
220 
221  //Register interrupt handler
222  adi_int_InstallHandler(INTR_EMAC1_STAT, sc598Eth2IrqHandler, interface,
223  false);
224 
225  //Enable MAC transmission and reception
226  *pREG_EMAC1_MAC_CFG |= BITM_EMAC_MAC_CFG_TE | BITM_EMAC_MAC_CFG_RE;
227 
228  //Enable DMA transmission and reception
229  *pREG_EMAC1_DMA0_TXCTL |= BITM_EMAC_DMA_TXCTL_ST;
230  *pREG_EMAC1_DMA0_RXCTL |= BITM_EMAC_DMA_RXCTL_SR;
231 
232  //Accept any packets from the upper layer
233  osSetEvent(&interface->nicTxEvent);
234 
235  //Successful initialization
236  return NO_ERROR;
237 }
238 
239 
240 /**
241  * @brief GPIO configuration
242  * @param[in] interface Underlying network interface
243  **/
244 
245 __weak_func void sc598Eth2InitGpio(NetInterface *interface)
246 {
247 //EV-SC598-SOM evaluation board?
248 #if defined(USE_EV_SC598_SOM)
249  uint32_t temp;
250 
251  //Configure PE_11 (ETH1_REFCLK), PE_12 (ETH1_TXEN), PE_13 (ETH1_TXD0),
252  //PE_14 (ETH1_TXD1) and PE_15 (ETH1_RXD0)
253  temp = *pREG_PORTE_MUX;
254  temp = (temp & ~BITM_PORT_MUX_MUX11) | (0 << BITP_PORT_MUX_MUX11);
255  temp = (temp & ~BITM_PORT_MUX_MUX12) | (0 << BITP_PORT_MUX_MUX12);
256  temp = (temp & ~BITM_PORT_MUX_MUX13) | (0 << BITP_PORT_MUX_MUX13);
257  temp = (temp & ~BITM_PORT_MUX_MUX14) | (0 << BITP_PORT_MUX_MUX14);
258  temp = (temp & ~BITM_PORT_MUX_MUX15) | (0 << BITP_PORT_MUX_MUX15);
259  *pREG_PORTE_MUX = temp;
260 
261  //Select peripheral mode
262  *pREG_PORTE_FER_SET = BITM_PORT_FER_PX11 | BITM_PORT_FER_PX12 |
263  BITM_PORT_FER_PX13 | BITM_PORT_FER_PX14 | BITM_PORT_FER_PX15;
264 
265  //Configure PF_00 (ETH1_RXD1), PF_01 (ETH1_MDIO), PF_02 (ETH1_MDC) and
266  //PF_03 (ETH1_CRS)
267  temp = *pREG_PORTF_MUX;
268  temp = (temp & ~BITM_PORT_MUX_MUX0) | (0 << BITP_PORT_MUX_MUX0);
269  temp = (temp & ~BITM_PORT_MUX_MUX1) | (0 << BITP_PORT_MUX_MUX1);
270  temp = (temp & ~BITM_PORT_MUX_MUX2) | (0 << BITP_PORT_MUX_MUX2);
271  temp = (temp & ~BITM_PORT_MUX_MUX3) | (0 << BITP_PORT_MUX_MUX3);
272  *pREG_PORTF_MUX = temp;
273 
274  //Select peripheral mode
275  *pREG_PORTF_FER_SET = BITM_PORT_FER_PX0 | BITM_PORT_FER_PX1 |
276  BITM_PORT_FER_PX2 | BITM_PORT_FER_PX3;
277 
278  //Reset PHY transceiver (hard reset)
279  sc598Eth2ResetPhy(interface);
280 #endif
281 }
282 
283 
284 /**
285  * @brief Reset PHY transceiver
286  * @param[in] interface Underlying network interface
287  **/
288 
289 __weak_func void sc598Eth2ResetPhy(NetInterface *interface)
290 {
291 }
292 
293 
294 /**
295  * @brief Initialize DMA descriptor lists
296  * @param[in] interface Underlying network interface
297  **/
298 
300 {
301  uint_t i;
302 
303  //Initialize TX DMA descriptor list
304  for(i = 0; i < SC598_ETH2_TX_BUFFER_COUNT; i++)
305  {
306  //The descriptor is initially owned by the application
307  txDmaDesc[i].tdes0 = 0;
308  txDmaDesc[i].tdes1 = 0;
309  txDmaDesc[i].tdes2 = 0;
310  txDmaDesc[i].tdes3 = 0;
311  }
312 
313  //Initialize TX descriptor index
314  txIndex = 0;
315 
316  //Initialize RX DMA descriptor list
317  for(i = 0; i < SC598_ETH2_RX_BUFFER_COUNT; i++)
318  {
319  //The descriptor is initially owned by the DMA
320  rxDmaDesc[i].rdes0 = adi_rtl_internal_to_system_addr(
321  (uint32_t)(uintptr_t) rxBuffer[i], 1);
322 
323  rxDmaDesc[i].rdes1 = 0;
324  rxDmaDesc[i].rdes2 = 0;
326  }
327 
328  //Initialize RX descriptor index
329  rxIndex = 0;
330 
331  //Start location of the TX descriptor list
332  *pREG_EMAC1_DMA0_TXDSC_ADDR = adi_rtl_internal_to_system_addr(
333  (uint32_t)(uintptr_t) &txDmaDesc[0], 1);
334 
335  //Length of the transmit descriptor ring
336  *pREG_EMAC1_DMA0_TXDSC_RLEN = SC598_ETH2_TX_BUFFER_COUNT - 1;
337 
338  //Start location of the RX descriptor list
339  *pREG_EMAC1_DMA0_RXDSC_ADDR = adi_rtl_internal_to_system_addr(
340  (uint32_t)(uintptr_t) &rxDmaDesc[0], 1);
341 
342  //Length of the receive descriptor ring
343  *pREG_EMAC1_DMA0_RXCTL2 = SC598_ETH2_RX_BUFFER_COUNT - 1;
344 }
345 
346 
347 /**
348  * @brief ADSP-SC598 Ethernet MAC timer handler
349  *
350  * This routine is periodically called by the TCP/IP stack to handle periodic
351  * operations such as polling the link state
352  *
353  * @param[in] interface Underlying network interface
354  **/
355 
356 void sc598Eth2Tick(NetInterface *interface)
357 {
358  //Valid Ethernet PHY or switch driver?
359  if(interface->phyDriver != NULL)
360  {
361  //Handle periodic operations
362  interface->phyDriver->tick(interface);
363  }
364  else if(interface->switchDriver != NULL)
365  {
366  //Handle periodic operations
367  interface->switchDriver->tick(interface);
368  }
369  else
370  {
371  //Just for sanity
372  }
373 }
374 
375 
376 /**
377  * @brief Enable interrupts
378  * @param[in] interface Underlying network interface
379  **/
380 
382 {
383  //Enable Ethernet MAC interrupts
384  adi_int_EnableInt(INTR_EMAC1_STAT, true);
385 
386  //Valid Ethernet PHY or switch driver?
387  if(interface->phyDriver != NULL)
388  {
389  //Enable Ethernet PHY interrupts
390  interface->phyDriver->enableIrq(interface);
391  }
392  else if(interface->switchDriver != NULL)
393  {
394  //Enable Ethernet switch interrupts
395  interface->switchDriver->enableIrq(interface);
396  }
397  else
398  {
399  //Just for sanity
400  }
401 }
402 
403 
404 /**
405  * @brief Disable interrupts
406  * @param[in] interface Underlying network interface
407  **/
408 
410 {
411  //Disable Ethernet MAC interrupts
412  adi_int_EnableInt(INTR_EMAC1_STAT, false);
413 
414  //Valid Ethernet PHY or switch driver?
415  if(interface->phyDriver != NULL)
416  {
417  //Disable Ethernet PHY interrupts
418  interface->phyDriver->disableIrq(interface);
419  }
420  else if(interface->switchDriver != NULL)
421  {
422  //Disable Ethernet switch interrupts
423  interface->switchDriver->disableIrq(interface);
424  }
425  else
426  {
427  //Just for sanity
428  }
429 }
430 
431 
432 /**
433  * @brief ADSP-SC598 Ethernet MAC interrupt service routine
434  * @param id Interrupt identifier
435  * @param param Unused parameter
436  **/
437 
438 void sc598Eth2IrqHandler(uint32_t id, void *param)
439 {
440  bool_t flag;
441  uint32_t status;
442 
443  //Interrupt service routine prologue
444  osEnterIsr();
445 
446  //This flag will be set if a higher priority task must be woken
447  flag = FALSE;
448 
449  //Read DMA status register
450  status = *pREG_EMAC1_DMA0_STAT;
451 
452  //Packet transmitted?
453  if((status & BITM_EMAC_DMA_STAT_TI) != 0)
454  {
455  //Clear TI interrupt flag
456  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA_STAT_TI;
457 
458  //Check whether the TX buffer is available for writing
459  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
460  {
461  //Notify the TCP/IP stack that the transmitter is ready to send
462  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
463  }
464  }
465 
466  //Packet received?
467  if((status & BITM_EMAC_DMA_STAT_RI) != 0)
468  {
469  //Clear RI interrupt flag
470  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA_STAT_RI;
471 
472  //Set event flag
473  nicDriverInterface->nicEvent = TRUE;
474  //Notify the TCP/IP stack of the event
475  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
476  }
477 
478  //Clear NIS interrupt flag
479  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA_STAT_NIS;
480 
481  //Interrupt service routine epilogue
482  osExitIsr(flag);
483 }
484 
485 
486 /**
487  * @brief ADSP-SC598 Ethernet MAC event handler
488  * @param[in] interface Underlying network interface
489  **/
490 
492 {
493  error_t error;
494 
495  //Process all pending packets
496  do
497  {
498  //Read incoming packet
499  error = sc598Eth2ReceivePacket(interface);
500 
501  //No more data in the receive buffer?
502  } while(error != ERROR_BUFFER_EMPTY);
503 }
504 
505 
506 /**
507  * @brief Send a packet
508  * @param[in] interface Underlying network interface
509  * @param[in] buffer Multi-part buffer containing the data to send
510  * @param[in] offset Offset to the first data byte
511  * @param[in] ancillary Additional options passed to the stack along with
512  * the packet
513  * @return Error code
514  **/
515 
517  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
518 {
519  size_t length;
520 
521  //Retrieve the length of the packet
522  length = netBufferGetLength(buffer) - offset;
523 
524  //Check the frame length
526  {
527  //The transmitter can accept another packet
528  osSetEvent(&interface->nicTxEvent);
529  //Report an error
530  return ERROR_INVALID_LENGTH;
531  }
532 
533  //Make sure the current buffer is available for writing
534  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) != 0)
535  {
536  return ERROR_FAILURE;
537  }
538 
539  //Copy user data to the transmit buffer
540  netBufferRead(txBuffer[txIndex], buffer, offset, length);
541 
542  //Set the start address of the buffer
543  txDmaDesc[txIndex].tdes0 = adi_rtl_internal_to_system_addr(
544  (uint32_t)(uintptr_t) txBuffer[txIndex], 1);
545 
546  //Write the number of bytes to send
547  txDmaDesc[txIndex].tdes2 = EMAC_TDES2_IOC | (length & EMAC_TDES2_HL_B1L);
548  //Give the ownership of the descriptor to the DMA
550 
551  //Data synchronization barrier
552  __asm("dsb sy");
553 
554  //Clear TBU flag to resume processing
555  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA_STAT_TBU;
556  //Instruct the DMA to poll the transmit descriptor list
557  *pREG_EMAC1_DMA0_TXDSC_TLPTR = 0;
558 
559  //Increment index and wrap around if necessary
560  if(++txIndex >= SC598_ETH2_TX_BUFFER_COUNT)
561  {
562  txIndex = 0;
563  }
564 
565  //Check whether the next buffer is available for writing
566  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
567  {
568  //The transmitter can accept another packet
569  osSetEvent(&interface->nicTxEvent);
570  }
571 
572  //Data successfully written
573  return NO_ERROR;
574 }
575 
576 
577 /**
578  * @brief Receive a packet
579  * @param[in] interface Underlying network interface
580  * @return Error code
581  **/
582 
584 {
585  error_t error;
586  size_t n;
587  NetRxAncillary ancillary;
588 
589  //Current buffer available for reading?
590  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_OWN) == 0)
591  {
592  //FD and LD flags should be set
593  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_FD) != 0 &&
594  (rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_LD) != 0)
595  {
596  //Make sure no error occurred
597  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_ES) == 0)
598  {
599  //Retrieve the length of the frame
600  n = rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_PL;
601  //Limit the number of data to read
603 
604  //Additional options can be passed to the stack along with the packet
605  ancillary = NET_DEFAULT_RX_ANCILLARY;
606 
607  //Pass the packet to the upper layer
608  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
609 
610  //Valid packet received
611  error = NO_ERROR;
612  }
613  else
614  {
615  //The received packet contains an error
616  error = ERROR_INVALID_PACKET;
617  }
618  }
619  else
620  {
621  //The packet is not valid
622  error = ERROR_INVALID_PACKET;
623  }
624 
625  //Set the start address of the buffer
626  rxDmaDesc[rxIndex].rdes0 = adi_rtl_internal_to_system_addr(
627  (uint32_t)(uintptr_t) rxBuffer[rxIndex], 1);
628 
629  //Give the ownership of the descriptor back to the DMA
631 
632  //Increment index and wrap around if necessary
633  if(++rxIndex >= SC598_ETH2_RX_BUFFER_COUNT)
634  {
635  rxIndex = 0;
636  }
637  }
638  else
639  {
640  //No more data in the receive buffer
641  error = ERROR_BUFFER_EMPTY;
642  }
643 
644  //Clear RBU flag to resume processing
645  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA_STAT_RBU;
646  //Instruct the DMA to poll the receive descriptor list
647  *pREG_EMAC1_DMA0_RXDSC_TLPTR = 0;
648 
649  //Return status code
650  return error;
651 }
652 
653 
654 /**
655  * @brief Configure MAC address filtering
656  * @param[in] interface Underlying network interface
657  * @return Error code
658  **/
659 
661 {
662  uint_t i;
663  uint_t j;
664  uint_t k;
665  uint32_t crc;
666  uint32_t hashTable[2];
667  MacAddr unicastMacAddr[1];
668  MacFilterEntry *entry;
669 
670  //Debug message
671  TRACE_DEBUG("Updating MAC filter...\r\n");
672 
673  //Promiscuous mode?
674  if(interface->promiscuous)
675  {
676  //Pass all incoming frames regardless of their destination address
677  *pREG_EMAC1_MACPKT_FILT = BITM_EMAC_MACPKT_FILT_PR;
678  }
679  else
680  {
681  //Set the MAC address of the station
682  *pREG_EMAC1_ADDR0_LO = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
683  *pREG_EMAC1_ADDR0_HI = interface->macAddr.w[2];
684 
685  //The MAC supports one additional address for unicast perfect filtering
686  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
687 
688  //The hash table is used for multicast address filtering
689  hashTable[0] = 0;
690  hashTable[1] = 0;
691 
692  //The MAC address filter contains the list of MAC addresses to accept
693  //when receiving an Ethernet frame
694  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
695  {
696  //Point to the current entry
697  entry = &interface->macAddrFilter[i];
698 
699  //Valid entry?
700  if(entry->refCount > 0)
701  {
702  //Multicast address?
703  if(macIsMulticastAddr(&entry->addr))
704  {
705  //Compute CRC over the current MAC address
706  crc = sc598Eth2CalcCrc(&entry->addr, sizeof(MacAddr));
707 
708  //The upper 6 bits in the CRC register are used to index the
709  //contents of the hash table
710  k = (crc >> 26) & 0x3F;
711 
712  //Update hash table contents
713  hashTable[k / 32] |= (1 << (k % 32));
714  }
715  else
716  {
717  //One additional MAC address can be specified
718  if(j < 1)
719  {
720  //Save the unicast address
721  unicastMacAddr[j++] = entry->addr;
722  }
723  }
724  }
725  }
726 
727  //Configure the first unicast address filter
728  if(j >= 1)
729  {
730  //When the AE bit is set, the entry is used for perfect filtering
731  *pREG_EMAC1_ADDR1_LO = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
732  *pREG_EMAC1_ADDR1_HI = unicastMacAddr[0].w[2] | BITM_EMAC_ADDR_HI_AE;
733  }
734  else
735  {
736  //When the AE bit is cleared, the entry is ignored
737  *pREG_EMAC1_ADDR1_LO = 0;
738  *pREG_EMAC1_ADDR1_HI = 0;
739  }
740 
741  //Check whether frames with a multicast destination address should be
742  //accepted
743  if(interface->acceptAllMulticast)
744  {
745  //Configure the receive filter
746  *pREG_EMAC1_MACPKT_FILT = BITM_EMAC_MACPKT_FILT_HPF | BITM_EMAC_MACPKT_FILT_PM;
747  }
748  else
749  {
750  //Configure the receive filter
751  *pREG_EMAC1_MACPKT_FILT = BITM_EMAC_MACPKT_FILT_HPF | BITM_EMAC_MACPKT_FILT_HMC;
752 
753  //Configure the multicast hash table
754  *pREG_EMAC1_HASHTBL_REG0 = hashTable[0];
755  *pREG_EMAC1_HASHTBL_REG1 = hashTable[1];
756 
757  //Debug message
758  TRACE_DEBUG(" EMAC_HASHTBL_REG0 = 0x%08" PRIX32 "\r\n", *pREG_EMAC1_HASHTBL_REG0);
759  TRACE_DEBUG(" EMAC_HASHTBL_REG1 = 0x%08" PRIX32 "\r\n", *pREG_EMAC1_HASHTBL_REG1);
760  }
761  }
762 
763  //Successful processing
764  return NO_ERROR;
765 }
766 
767 
768 /**
769  * @brief Adjust MAC configuration parameters for proper operation
770  * @param[in] interface Underlying network interface
771  * @return Error code
772  **/
773 
775 {
776  uint32_t config;
777 
778  //Read current MAC configuration
779  config = *pREG_EMAC1_MAC_CFG;
780 
781  //10BASE-T or 100BASE-TX operation mode?
782  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
783  {
784  config |= BITM_EMAC_MAC_CFG_FES;
785  }
786  else
787  {
788  config &= ~BITM_EMAC_MAC_CFG_FES;
789  }
790 
791  //Half-duplex or full-duplex mode?
792  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
793  {
794  config |= BITM_EMAC_MAC_CFG_DM;
795  }
796  else
797  {
798  config &= ~BITM_EMAC_MAC_CFG_DM;
799  }
800 
801  //Update MAC configuration register
802  *pREG_EMAC1_MAC_CFG = config;
803 
804  //Successful processing
805  return NO_ERROR;
806 }
807 
808 
809 /**
810  * @brief Write PHY register
811  * @param[in] opcode Access type (2 bits)
812  * @param[in] phyAddr PHY address (5 bits)
813  * @param[in] regAddr Register address (5 bits)
814  * @param[in] data Register value
815  **/
816 
817 void sc598Eth2WritePhyReg(uint8_t opcode, uint8_t phyAddr,
818  uint8_t regAddr, uint16_t data)
819 {
820  uint32_t temp;
821 
822  //Valid opcode?
823  if(opcode == SMI_OPCODE_WRITE)
824  {
825  //Take care not to alter MDC clock configuration
826  temp = *pREG_EMAC1_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_CR;
827  //Set up a write operation
828  temp |= BITM_EMAC_MDIO_ADDR_GOC_0 | BITM_EMAC_MDIO_ADDR_GB;
829  //PHY address
830  temp |= (phyAddr << BITP_EMAC_MDIO_ADDR_PA) & BITM_EMAC_MDIO_ADDR_PA;
831  //Register address
832  temp |= (regAddr << BITP_EMAC_MDIO_ADDR_RDA) & BITM_EMAC_MDIO_ADDR_RDA;
833 
834  //Data to be written in the PHY register
835  *pREG_EMAC1_MDIO_DATA = data & BITM_EMAC_MDIO_DATA_GD;
836 
837  //Start a write operation
838  *pREG_EMAC1_MDIO_ADDR = temp;
839  //Wait for the write to complete
840  while((*pREG_EMAC1_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_GB) != 0)
841  {
842  }
843  }
844  else
845  {
846  //The MAC peripheral only supports standard Clause 22 opcodes
847  }
848 }
849 
850 
851 /**
852  * @brief Read PHY register
853  * @param[in] opcode Access type (2 bits)
854  * @param[in] phyAddr PHY address (5 bits)
855  * @param[in] regAddr Register address (5 bits)
856  * @return Register value
857  **/
858 
859 uint16_t sc598Eth2ReadPhyReg(uint8_t opcode, uint8_t phyAddr,
860  uint8_t regAddr)
861 {
862  uint16_t data;
863  uint32_t temp;
864 
865  //Valid opcode?
866  if(opcode == SMI_OPCODE_READ)
867  {
868  //Take care not to alter MDC clock configuration
869  temp = *pREG_EMAC1_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_CR;
870 
871  //Set up a read operation
872  temp |= BITM_EMAC_MDIO_ADDR_GOC_1 | BITM_EMAC_MDIO_ADDR_GOC_0 |
873  BITM_EMAC_MDIO_ADDR_GB;
874 
875  //PHY address
876  temp |= (phyAddr << BITP_EMAC_MDIO_ADDR_PA) & BITM_EMAC_MDIO_ADDR_PA;
877  //Register address
878  temp |= (regAddr << BITP_EMAC_MDIO_ADDR_RDA) & BITM_EMAC_MDIO_ADDR_RDA;
879 
880  //Start a read operation
881  *pREG_EMAC1_MDIO_ADDR = temp;
882  //Wait for the read to complete
883  while((*pREG_EMAC1_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_GB) != 0)
884  {
885  }
886 
887  //Get register value
888  data = *pREG_EMAC1_MDIO_DATA & BITM_EMAC_MDIO_DATA_GD;
889  }
890  else
891  {
892  //The MAC peripheral only supports standard Clause 22 opcodes
893  data = 0;
894  }
895 
896  //Return the value of the PHY register
897  return data;
898 }
899 
900 
901 /**
902  * @brief CRC calculation
903  * @param[in] data Pointer to the data over which to calculate the CRC
904  * @param[in] length Number of bytes to process
905  * @return Resulting CRC value
906  **/
907 
908 uint32_t sc598Eth2CalcCrc(const void *data, size_t length)
909 {
910  uint_t i;
911  uint_t j;
912  uint32_t crc;
913  const uint8_t *p;
914 
915  //Point to the data over which to calculate the CRC
916  p = (uint8_t *) data;
917  //CRC preset value
918  crc = 0xFFFFFFFF;
919 
920  //Loop through data
921  for(i = 0; i < length; i++)
922  {
923  //The message is processed bit by bit
924  for(j = 0; j < 8; j++)
925  {
926  //Update CRC value
927  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
928  {
929  crc = (crc << 1) ^ 0x04C11DB7;
930  }
931  else
932  {
933  crc = crc << 1;
934  }
935  }
936  }
937 
938  //Return CRC value
939  return ~crc;
940 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define EMAC_TDES3_OWN
uint8_t opcode
Definition: dns_common.h:191
int bool_t
Definition: compiler_port.h:63
#define EMAC_RDES3_PL
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
void sc598Eth2DisableIrq(NetInterface *interface)
Disable interrupts.
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
Receive descriptor.
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
void sc598Eth2WritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define EMAC_RDES3_BUF1V
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
#define EMAC_RDES3_ES
uint8_t data[]
Definition: ethernet.h:224
error_t sc598Eth2Init(NetInterface *interface)
ADSP-SC598 Ethernet MAC initialization.
__weak_func void sc598Eth2InitGpio(NetInterface *interface)
GPIO configuration.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
error_t sc598Eth2ReceivePacket(NetInterface *interface)
Receive a packet.
error_t sc598Eth2UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:418
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
#define EMAC_TDES3_FD
#define SMI_OPCODE_WRITE
Definition: nic.h:66
Transmit descriptor.
#define SC598_ETH2_RX_BUFFER_SIZE
#define SC598_ETH2_RAM_SECTION
void sc598Eth2EventHandler(NetInterface *interface)
ADSP-SC598 Ethernet MAC event handler.
#define FALSE
Definition: os_port.h:46
#define EMAC_TDES2_HL_B1L
error_t
Error codes.
Definition: error.h:43
#define EMAC_TDES3_LD
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void sc598Eth2IrqHandler(uint32_t id, void *param)
ADSP-SC598 Ethernet MAC interrupt service routine.
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
MacAddr addr
MAC address.
Definition: ethernet.h:265
@ ERROR_INVALID_LENGTH
Definition: error.h:111
__weak_func void sc598Eth2ResetPhy(NetInterface *interface)
Reset PHY transceiver.
#define SC598_ETH2_TX_BUFFER_SIZE
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:105
uint16_t sc598Eth2ReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:63
#define rxBuffer
MacAddr
Definition: ethernet.h:197
#define EMAC_RDES3_FD
const NicDriver sc598Eth2Driver
ADSP-SC598 Ethernet MAC driver (EMAC1 instance)
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define EMAC_TDES2_IOC
error_t sc598Eth2UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
uint16_t regAddr
#define SC598_ETH2_TX_BUFFER_COUNT
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:264
void sc598Eth2EnableIrq(NetInterface *interface)
Enable interrupts.
#define osEnterIsr()
#define SC598_ETH2_RX_BUFFER_COUNT
#define EMAC_RDES3_LD
#define EMAC_RDES3_IOC
#define EMAC_RDES3_OWN
#define rxDmaDesc
uint32_t sc598Eth2CalcCrc(const void *data, size_t length)
CRC calculation.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
void sc598Eth2InitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
NIC driver.
Definition: nic.h:286
void sc598Eth2Tick(NetInterface *interface)
ADSP-SC598 Ethernet MAC timer handler.
ADSP-SC598 Ethernet MAC driver (EMAC1 instance)
error_t sc598Eth2SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:51
@ 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