sc589_eth2_driver.c
Go to the documentation of this file.
1 /**
2  * @file sc589_eth2_driver.c
3  * @brief ADSP-SC589 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 = SC589_ETH2_RAM_SECTION
51 //Receive buffer
52 #pragma data_alignment = 4
53 #pragma location = SC589_ETH2_RAM_SECTION
55 //Transmit DMA descriptors
56 #pragma data_alignment = 8
57 #pragma location = SC589_ETH2_RAM_SECTION
59 //Receive DMA descriptors
60 #pragma data_alignment = 8
61 #pragma location = SC589_ETH2_RAM_SECTION
63 
64 //GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4), __section__(SC589_ETH2_RAM_SECTION)));
70 //Receive buffer
72  __attribute__((aligned(4), __section__(SC589_ETH2_RAM_SECTION)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(8), __section__(SC589_ETH2_RAM_SECTION)));
76 //Receive DMA descriptors
78  __attribute__((aligned(8), __section__(SC589_ETH2_RAM_SECTION)));
79 
80 #endif
81 
82 //Pointer to the current TX DMA descriptor
83 static Sc589Eth2TxDmaDesc *txCurDmaDesc;
84 //Pointer to the current RX DMA descriptor
85 static Sc589Eth2RxDmaDesc *rxCurDmaDesc;
86 
87 
88 /**
89  * @brief ADSP-SC589 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-SC589 Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122 
123  //Debug message
124  TRACE_INFO("Initializing ADSP-SC589 Ethernet MAC (EMAC1)...\r\n");
125 
126  //Save underlying network interface
127  nicDriverInterface = interface;
128 
129  //GPIO configuration
130  sc589Eth2InitGpio(interface);
131 
132  //Perform a software reset
133  *pREG_EMAC1_DMA0_BUSMODE |= BITM_EMAC_DMA0_BUSMODE_SWR;
134  //Wait for the reset to complete
135  while((*pREG_EMAC1_DMA0_BUSMODE & BITM_EMAC_DMA0_BUSMODE_SWR) != 0)
136  {
137  }
138 
139  //Adjust MDC clock range depending on CLKO7 frequency
140  *pREG_EMAC1_SMI_ADDR = ENUM_EMAC_SMI_ADDR_CR_DIV62;
141 
142  //Valid Ethernet PHY or switch driver?
143  if(interface->phyDriver != NULL)
144  {
145  //Ethernet PHY initialization
146  error = interface->phyDriver->init(interface);
147  }
148  else if(interface->switchDriver != NULL)
149  {
150  //Ethernet switch initialization
151  error = interface->switchDriver->init(interface);
152  }
153  else
154  {
155  //The interface is not properly configured
156  error = ERROR_FAILURE;
157  }
158 
159  //Any error to report?
160  if(error)
161  {
162  return error;
163  }
164 
165  //Use default MAC configuration
166  *pREG_EMAC1_MACCFG = BITM_EMAC_MACCFG_PS | BITM_EMAC_MACCFG_DO;
167 
168  //Configure MAC address filtering
169  sc589Eth2UpdateMacAddrFilter(interface);
170 
171  //Disable flow control
172  *pREG_EMAC1_FLOWCTL = 0;
173 
174  //Set the threshold level of the transmit and receive FIFOs
175  *pREG_EMAC1_DMA0_OPMODE = ENUM_EMAC_DMA1_OPMODE_TTC_64 |
176  ENUM_EMAC_DMA1_OPMODE_RTC_32;
177 
178  //Configure DMA bus mode
179  *pREG_EMAC1_DMA0_BUSMODE = BITM_EMAC_DMA0_BUSMODE_AAL |
180  BITM_EMAC_DMA0_BUSMODE_USP | ENUM_EMAC_DMA_BUSMODE_RPBL_32 |
182 
183  //Initialize DMA descriptor lists
184  sc589Eth2InitDmaDesc(interface);
185 
186  //Prevent interrupts from being generated when statistic counters reach
187  //half their maximum value
188  *pREG_EMAC1_MMC_TXIMSK = 0x01FFFFFF;
189  *pREG_EMAC1_MMC_RXIMSK = 0x01FFFFFF;
190  *pREG_EMAC1_IPC_RXIMSK = 0x3FFFFFFF;
191 
192  //Disable MAC interrupts
193  *pREG_EMAC1_IMSK = BITM_EMAC_IMSK_LPIIM | BITM_EMAC_IMSK_TS;
194 
195  //Enable the desired DMA interrupts
196  *pREG_EMAC1_DMA0_IEN = BITM_EMAC_DMA0_IEN_NIE | BITM_EMAC_DMA0_IEN_RIE |
197  BITM_EMAC_DMA0_IEN_TIE;
198 
199  //Register interrupt handler
200  adi_int_InstallHandler(INTR_EMAC1_STAT, sc589Eth2IrqHandler, interface,
201  false);
202 
203  //Enable MAC transmission and reception
204  *pREG_EMAC1_MACCFG |= BITM_EMAC_MACCFG_TE | BITM_EMAC_MACCFG_RE;
205 
206  //Enable DMA transmission and reception
207  *pREG_EMAC1_DMA0_OPMODE |= BITM_EMAC_DMA0_OPMODE_ST |
208  BITM_EMAC_DMA0_OPMODE_SR;
209 
210  //Accept any packets from the upper layer
211  osSetEvent(&interface->nicTxEvent);
212 
213  //Successful initialization
214  return NO_ERROR;
215 }
216 
217 
218 /**
219  * @brief GPIO configuration
220  * @param[in] interface Underlying network interface
221  **/
222 
223 __weak_func void sc589Eth2InitGpio(NetInterface *interface)
224 {
225 //ADZS-SC589-EZLITE evaluation board?
226 #if defined(USE_ADZS_SC589_EZLITE)
227  uint32_t temp;
228 
229  //Configure PF_13 (ETH1_CRS), PF_14 (ETH1_MDC) and PF_15 (ETH1_MDIO)
230  temp = *pREG_PORTF_MUX;
231  temp = (temp & ~BITM_PORT_MUX_MUX13) | (0 << BITP_PORT_MUX_MUX13);
232  temp = (temp & ~BITM_PORT_MUX_MUX14) | (0 << BITP_PORT_MUX_MUX14);
233  temp = (temp & ~BITM_PORT_MUX_MUX15) | (0 << BITP_PORT_MUX_MUX15);
234  *pREG_PORTF_MUX = temp;
235 
236  //Select peripheral mode
237  *pREG_PORTF_FER_SET = BITM_PORT_FER_PX13 | BITM_PORT_FER_PX14 |
238  BITM_PORT_FER_PX15;
239 
240  //Configure PG_00 (ETH1_REFCLK), PG_01 (ETH1_TXEN), PG_02 (ETH1_TXD0),
241  //PG_03 (ETH1_TXD1) and PG_04 (ETH1_RXD0) and PG_05 (ETH1_RXD1)
242  temp = *pREG_PORTG_MUX;
243  temp = (temp & ~BITM_PORT_MUX_MUX0) | (0 << BITP_PORT_MUX_MUX0);
244  temp = (temp & ~BITM_PORT_MUX_MUX1) | (0 << BITP_PORT_MUX_MUX1);
245  temp = (temp & ~BITM_PORT_MUX_MUX2) | (0 << BITP_PORT_MUX_MUX2);
246  temp = (temp & ~BITM_PORT_MUX_MUX3) | (0 << BITP_PORT_MUX_MUX3);
247  temp = (temp & ~BITM_PORT_MUX_MUX4) | (0 << BITP_PORT_MUX_MUX4);
248  temp = (temp & ~BITM_PORT_MUX_MUX5) | (0 << BITP_PORT_MUX_MUX5);
249  *pREG_PORTG_MUX = temp;
250 
251  //Select peripheral mode
252  *pREG_PORTG_FER_SET = BITM_PORT_FER_PX0 | BITM_PORT_FER_PX1 |
253  BITM_PORT_FER_PX2 | BITM_PORT_FER_PX3 | BITM_PORT_FER_PX4 |
254  BITM_PORT_FER_PX5;
255 
256  //Configure ETH1_INT (PD_00) as an input
257  *pREG_PORTD_FER_CLR = BITM_PORT_FER_PX0;
258  *pREG_PORTD_DIR_CLR = BITM_PORT_DIR_PX0;
259  *pREG_PORTD_INEN_SET = BITM_PORT_INEN_PX0;
260 #endif
261 }
262 
263 
264 /**
265  * @brief Initialize DMA descriptor lists
266  * @param[in] interface Underlying network interface
267  **/
268 
270 {
271  uint_t i;
272 
273  //Initialize TX DMA descriptor list
274  for(i = 0; i < SC589_ETH2_TX_BUFFER_COUNT; i++)
275  {
276  //Use chain structure rather than ring structure
278  //Initialize transmit buffer size
279  txDmaDesc[i].tdes1 = 0;
280 
281  //Transmit buffer address
282  txDmaDesc[i].tdes2 = adi_rtl_internal_to_system_addr(
283  (uint32_t) txBuffer[i], 1);
284 
285  //Next descriptor address
286  txDmaDesc[i].tdes3 = adi_rtl_internal_to_system_addr(
287  (uint32_t) &txDmaDesc[i + 1], 1);
288  }
289 
290  //The last descriptor is chained to the first entry
291  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
292  //Point to the very first descriptor
293  txCurDmaDesc = &txDmaDesc[0];
294 
295  //Initialize RX DMA descriptor list
296  for(i = 0; i < SC589_ETH2_RX_BUFFER_COUNT; i++)
297  {
298  //The descriptor is initially owned by the DMA
299  rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
300  //Use chain structure rather than ring structure
302 
303  //Receive buffer address
304  rxDmaDesc[i].rdes2 = adi_rtl_internal_to_system_addr(
305  (uint32_t) rxBuffer[i], 1);
306 
307  //Next descriptor address
308  rxDmaDesc[i].rdes3 = adi_rtl_internal_to_system_addr(
309  (uint32_t) &rxDmaDesc[i + 1], 1);
310  }
311 
312  //The last descriptor is chained to the first entry
313  rxDmaDesc[i - 1].rdes3 = adi_rtl_internal_to_system_addr(
314  (uint32_t) &rxDmaDesc[0], 1);
315 
316  //Point to the very first descriptor
317  rxCurDmaDesc = &rxDmaDesc[0];
318 
319  //Start location of the TX descriptor list
320  *pREG_EMAC1_DMA0_TXDSC_ADDR = adi_rtl_internal_to_system_addr(
321  (uint32_t) txDmaDesc, 1);
322 
323  //Start location of the RX descriptor list
324  *pREG_EMAC1_DMA0_RXDSC_ADDR = adi_rtl_internal_to_system_addr(
325  (uint32_t) rxDmaDesc, 1);
326 }
327 
328 
329 /**
330  * @brief ADSP-SC589 Ethernet MAC timer handler
331  *
332  * This routine is periodically called by the TCP/IP stack to handle periodic
333  * operations such as polling the link state
334  *
335  * @param[in] interface Underlying network interface
336  **/
337 
338 void sc589Eth2Tick(NetInterface *interface)
339 {
340  //Valid Ethernet PHY or switch driver?
341  if(interface->phyDriver != NULL)
342  {
343  //Handle periodic operations
344  interface->phyDriver->tick(interface);
345  }
346  else if(interface->switchDriver != NULL)
347  {
348  //Handle periodic operations
349  interface->switchDriver->tick(interface);
350  }
351  else
352  {
353  //Just for sanity
354  }
355 }
356 
357 
358 /**
359  * @brief Enable interrupts
360  * @param[in] interface Underlying network interface
361  **/
362 
364 {
365  //Enable Ethernet MAC interrupts
366  adi_int_EnableInt(INTR_EMAC1_STAT, true);
367 
368  //Valid Ethernet PHY or switch driver?
369  if(interface->phyDriver != NULL)
370  {
371  //Enable Ethernet PHY interrupts
372  interface->phyDriver->enableIrq(interface);
373  }
374  else if(interface->switchDriver != NULL)
375  {
376  //Enable Ethernet switch interrupts
377  interface->switchDriver->enableIrq(interface);
378  }
379  else
380  {
381  //Just for sanity
382  }
383 }
384 
385 
386 /**
387  * @brief Disable interrupts
388  * @param[in] interface Underlying network interface
389  **/
390 
392 {
393  //Disable Ethernet MAC interrupts
394  adi_int_EnableInt(INTR_EMAC1_STAT, false);
395 
396  //Valid Ethernet PHY or switch driver?
397  if(interface->phyDriver != NULL)
398  {
399  //Disable Ethernet PHY interrupts
400  interface->phyDriver->disableIrq(interface);
401  }
402  else if(interface->switchDriver != NULL)
403  {
404  //Disable Ethernet switch interrupts
405  interface->switchDriver->disableIrq(interface);
406  }
407  else
408  {
409  //Just for sanity
410  }
411 }
412 
413 
414 /**
415  * @brief ADSP-SC589 Ethernet MAC interrupt service routine
416  * @param id Interrupt identifier
417  * @param param Unused parameter
418  **/
419 
420 void sc589Eth2IrqHandler(uint32_t id, void *param)
421 {
422  bool_t flag;
423  uint32_t status;
424 
425  //Interrupt service routine prologue
426  osEnterIsr();
427 
428  //This flag will be set if a higher priority task must be woken
429  flag = FALSE;
430 
431  //Read DMA status register
432  status = *pREG_EMAC1_DMA0_STAT;
433 
434  //Packet transmitted?
435  if((status & BITM_EMAC_DMA0_STAT_TI) != 0)
436  {
437  //Clear TI interrupt flag
438  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA0_STAT_TI;
439 
440  //Check whether the TX buffer is available for writing
441  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
442  {
443  //Notify the TCP/IP stack that the transmitter is ready to send
444  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
445  }
446  }
447 
448  //Packet received?
449  if((status & BITM_EMAC_DMA0_STAT_RI) != 0)
450  {
451  //Clear RI interrupt flag
452  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA0_STAT_RI;
453 
454  //Set event flag
455  nicDriverInterface->nicEvent = TRUE;
456  //Notify the TCP/IP stack of the event
457  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
458  }
459 
460  //Clear NIS interrupt flag
461  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA0_STAT_NIS;
462 
463  //Interrupt service routine epilogue
464  osExitIsr(flag);
465 }
466 
467 
468 /**
469  * @brief ADSP-SC589 Ethernet MAC event handler
470  * @param[in] interface Underlying network interface
471  **/
472 
474 {
475  error_t error;
476 
477  //Process all pending packets
478  do
479  {
480  //Read incoming packet
481  error = sc589Eth2ReceivePacket(interface);
482 
483  //No more data in the receive buffer?
484  } while(error != ERROR_BUFFER_EMPTY);
485 }
486 
487 
488 /**
489  * @brief Send a packet
490  * @param[in] interface Underlying network interface
491  * @param[in] buffer Multi-part buffer containing the data to send
492  * @param[in] offset Offset to the first data byte
493  * @param[in] ancillary Additional options passed to the stack along with
494  * the packet
495  * @return Error code
496  **/
497 
499  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
500 {
501  size_t length;
502 
503  //Retrieve the length of the packet
504  length = netBufferGetLength(buffer) - offset;
505 
506  //Check the frame length
508  {
509  //The transmitter can accept another packet
510  osSetEvent(&interface->nicTxEvent);
511  //Report an error
512  return ERROR_INVALID_LENGTH;
513  }
514 
515  //Make sure the current buffer is available for writing
516  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) != 0)
517  {
518  return ERROR_FAILURE;
519  }
520 
521  //Copy user data to the transmit buffer
522  netBufferRead((uint8_t *) adi_rtl_system_to_internal_addr(
523  txCurDmaDesc->tdes2), buffer, offset, length);
524 
525  //Write the number of bytes to send
526  txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
527  //Set LS and FS flags as the data fits in a single buffer
528  txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
529  //Give the ownership of the descriptor to the DMA
530  txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
531 
532  //Data synchronization barrier
533  __asm("dsb");
534 
535  //Clear TU flag to resume processing
536  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA0_STAT_TU;
537  //Instruct the DMA to poll the transmit descriptor list
538  *pREG_EMAC1_DMA0_TXPOLL = 0;
539 
540  //Point to the next descriptor in the list
541  txCurDmaDesc = (Sc589Eth2TxDmaDesc *) adi_rtl_system_to_internal_addr(
542  txCurDmaDesc->tdes3);
543 
544  //Check whether the next buffer is available for writing
545  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
546  {
547  //The transmitter can accept another packet
548  osSetEvent(&interface->nicTxEvent);
549  }
550 
551  //Data successfully written
552  return NO_ERROR;
553 }
554 
555 
556 /**
557  * @brief Receive a packet
558  * @param[in] interface Underlying network interface
559  * @return Error code
560  **/
561 
563 {
564  error_t error;
565  size_t n;
566  NetRxAncillary ancillary;
567 
568  //Current buffer available for reading?
569  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN) == 0)
570  {
571  //FS and LS flags should be set
572  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) != 0 &&
573  (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS) != 0)
574  {
575  //Make sure no error occurred
576  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_ES) == 0)
577  {
578  //Retrieve the length of the frame
579  n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
580  //Limit the number of data to read
582 
583  //Additional options can be passed to the stack along with the packet
584  ancillary = NET_DEFAULT_RX_ANCILLARY;
585 
586  //Pass the packet to the upper layer
587  nicProcessPacket(interface, (uint8_t *) adi_rtl_system_to_internal_addr(
588  rxCurDmaDesc->rdes2), n, &ancillary);
589 
590  //Valid packet received
591  error = NO_ERROR;
592  }
593  else
594  {
595  //The received packet contains an error
596  error = ERROR_INVALID_PACKET;
597  }
598  }
599  else
600  {
601  //The packet is not valid
602  error = ERROR_INVALID_PACKET;
603  }
604 
605  //Give the ownership of the descriptor back to the DMA
606  rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
607 
608  //Point to the next descriptor in the list
609  rxCurDmaDesc = (Sc589Eth2RxDmaDesc *) adi_rtl_system_to_internal_addr(
610  rxCurDmaDesc->rdes3);
611  }
612  else
613  {
614  //No more data in the receive buffer
615  error = ERROR_BUFFER_EMPTY;
616  }
617 
618  //Clear RU flag to resume processing
619  *pREG_EMAC1_DMA0_STAT = BITM_EMAC_DMA0_STAT_RU;
620  //Instruct the DMA to poll the receive descriptor list
621  *pREG_EMAC1_DMA0_RXPOLL = 0;
622 
623  //Return status code
624  return error;
625 }
626 
627 
628 /**
629  * @brief Configure MAC address filtering
630  * @param[in] interface Underlying network interface
631  * @return Error code
632  **/
633 
635 {
636  uint_t i;
637  uint_t j;
638  uint_t k;
639  uint32_t crc;
640  uint32_t hashTable[2];
641  MacAddr unicastMacAddr[1];
642  MacFilterEntry *entry;
643 
644  //Debug message
645  TRACE_DEBUG("Updating MAC filter...\r\n");
646 
647  //Promiscuous mode?
648  if(interface->promiscuous)
649  {
650  //Pass all incoming frames regardless of their destination address
651  *pREG_EMAC1_MACFRMFILT = BITM_EMAC_MACFRMFILT_PR;
652  }
653  else
654  {
655  //Set the MAC address of the station
656  *pREG_EMAC1_ADDR0_LO = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
657  *pREG_EMAC1_ADDR0_HI = interface->macAddr.w[2];
658 
659  //The MAC supports one additional address for unicast perfect filtering
660  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
661 
662  //The hash table is used for multicast address filtering
663  hashTable[0] = 0;
664  hashTable[1] = 0;
665 
666  //The MAC address filter contains the list of MAC addresses to accept
667  //when receiving an Ethernet frame
668  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
669  {
670  //Point to the current entry
671  entry = &interface->macAddrFilter[i];
672 
673  //Valid entry?
674  if(entry->refCount > 0)
675  {
676  //Multicast address?
677  if(macIsMulticastAddr(&entry->addr))
678  {
679  //Compute CRC over the current MAC address
680  crc = sc589Eth2CalcCrc(&entry->addr, sizeof(MacAddr));
681 
682  //The upper 6 bits in the CRC register are used to index the
683  //contents of the hash table
684  k = (crc >> 26) & 0x3F;
685 
686  //Update hash table contents
687  hashTable[k / 32] |= (1 << (k % 32));
688  }
689  else
690  {
691  //One additional MAC address can be specified
692  if(j < 1)
693  {
694  //Save the unicast address
695  unicastMacAddr[j++] = entry->addr;
696  }
697  }
698  }
699  }
700 
701  //Configure the first unicast address filter
702  if(j >= 1)
703  {
704  //When the AE bit is set, the entry is used for perfect filtering
705  *pREG_EMAC1_ADDR1_LO = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
706  *pREG_EMAC1_ADDR1_HI = unicastMacAddr[0].w[2] | BITM_EMAC_ADDR1_HI_AE;
707  }
708  else
709  {
710  //When the AE bit is cleared, the entry is ignored
711  *pREG_EMAC1_ADDR1_LO = 0;
712  *pREG_EMAC1_ADDR1_HI = 0;
713  }
714 
715  //Check whether frames with a multicast destination address should be
716  //accepted
717  if(interface->acceptAllMulticast)
718  {
719  //Configure the receive filter
720  *pREG_EMAC1_MACFRMFILT = BITM_EMAC_MACFRMFILT_HPF | BITM_EMAC_MACFRMFILT_PM;
721  }
722  else
723  {
724  //Configure the receive filter
725  *pREG_EMAC1_MACFRMFILT = BITM_EMAC_MACFRMFILT_HPF | BITM_EMAC_MACFRMFILT_HMC;
726 
727  //Configure the multicast hash table
728  *pREG_EMAC1_HASHTBL_LO = hashTable[0];
729  *pREG_EMAC1_HASHTBL_HI = hashTable[1];
730 
731  //Debug message
732  TRACE_DEBUG(" EMAC_HASHTBL_LO = 0x%08" PRIX32 "\r\n", *pREG_EMAC1_HASHTBL_LO);
733  TRACE_DEBUG(" EMAC_HASHTBL_HI = 0x%08" PRIX32 "\r\n", *pREG_EMAC1_HASHTBL_HI);
734  }
735  }
736 
737  //Successful processing
738  return NO_ERROR;
739 }
740 
741 
742 /**
743  * @brief Adjust MAC configuration parameters for proper operation
744  * @param[in] interface Underlying network interface
745  * @return Error code
746  **/
747 
749 {
750  uint32_t config;
751 
752  //Read current MAC configuration
753  config = *pREG_EMAC1_MACCFG;
754 
755  //10BASE-T or 100BASE-TX operation mode?
756  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
757  {
758  config |= BITM_EMAC_MACCFG_FES;
759  }
760  else
761  {
762  config &= ~BITM_EMAC_MACCFG_FES;
763  }
764 
765  //Half-duplex or full-duplex mode?
766  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
767  {
768  config |= BITM_EMAC_MACCFG_DM;
769  }
770  else
771  {
772  config &= ~BITM_EMAC_MACCFG_DM;
773  }
774 
775  //Update MAC configuration register
776  *pREG_EMAC1_MACCFG = config;
777 
778  //Successful processing
779  return NO_ERROR;
780 }
781 
782 
783 /**
784  * @brief Write PHY register
785  * @param[in] opcode Access type (2 bits)
786  * @param[in] phyAddr PHY address (5 bits)
787  * @param[in] regAddr Register address (5 bits)
788  * @param[in] data Register value
789  **/
790 
791 void sc589Eth2WritePhyReg(uint8_t opcode, uint8_t phyAddr,
792  uint8_t regAddr, uint16_t data)
793 {
794  uint32_t temp;
795 
796  //Valid opcode?
797  if(opcode == SMI_OPCODE_WRITE)
798  {
799  //Take care not to alter MDC clock configuration
800  temp = *pREG_EMAC1_SMI_ADDR & BITM_EMAC_SMI_ADDR_CR;
801  //Set up a write operation
802  temp |= BITM_EMAC_SMI_ADDR_SMIW | BITM_EMAC_SMI_ADDR_SMIB;
803  //PHY address
804  temp |= (phyAddr << BITP_EMAC_SMI_ADDR_PA) & BITM_EMAC_SMI_ADDR_PA;
805  //Register address
806  temp |= (regAddr << BITP_EMAC_SMI_ADDR_SMIR) & BITM_EMAC_SMI_ADDR_SMIR;
807 
808  //Data to be written in the PHY register
809  *pREG_EMAC1_SMI_DATA = data & BITM_EMAC_SMI_DATA_SMID;
810 
811  //Start a write operation
812  *pREG_EMAC1_SMI_ADDR = temp;
813  //Wait for the write to complete
814  while((*pREG_EMAC1_SMI_ADDR & BITM_EMAC_SMI_ADDR_SMIB) != 0)
815  {
816  }
817  }
818  else
819  {
820  //The MAC peripheral only supports standard Clause 22 opcodes
821  }
822 }
823 
824 
825 /**
826  * @brief Read PHY register
827  * @param[in] opcode Access type (2 bits)
828  * @param[in] phyAddr PHY address (5 bits)
829  * @param[in] regAddr Register address (5 bits)
830  * @return Register value
831  **/
832 
833 uint16_t sc589Eth2ReadPhyReg(uint8_t opcode, uint8_t phyAddr,
834  uint8_t regAddr)
835 {
836  uint16_t data;
837  uint32_t temp;
838 
839  //Valid opcode?
840  if(opcode == SMI_OPCODE_READ)
841  {
842  //Take care not to alter MDC clock configuration
843  temp = *pREG_EMAC1_SMI_ADDR & BITM_EMAC_SMI_ADDR_CR;
844  //Set up a read operation
845  temp |= BITM_EMAC_SMI_ADDR_SMIB;
846  //PHY address
847  temp |= (phyAddr << BITP_EMAC_SMI_ADDR_PA) & BITM_EMAC_SMI_ADDR_PA;
848  //Register address
849  temp |= (regAddr << BITP_EMAC_SMI_ADDR_SMIR) & BITM_EMAC_SMI_ADDR_SMIR;
850 
851  //Start a read operation
852  *pREG_EMAC1_SMI_ADDR = temp;
853  //Wait for the read to complete
854  while((*pREG_EMAC1_SMI_ADDR & BITM_EMAC_SMI_ADDR_SMIB) != 0)
855  {
856  }
857 
858  //Get register value
859  data = *pREG_EMAC1_SMI_DATA & BITM_EMAC_SMI_DATA_SMID;
860  }
861  else
862  {
863  //The MAC peripheral only supports standard Clause 22 opcodes
864  data = 0;
865  }
866 
867  //Return the value of the PHY register
868  return data;
869 }
870 
871 
872 /**
873  * @brief CRC calculation
874  * @param[in] data Pointer to the data over which to calculate the CRC
875  * @param[in] length Number of bytes to process
876  * @return Resulting CRC value
877  **/
878 
879 uint32_t sc589Eth2CalcCrc(const void *data, size_t length)
880 {
881  uint_t i;
882  uint_t j;
883  uint32_t crc;
884  const uint8_t *p;
885 
886  //Point to the data over which to calculate the CRC
887  p = (uint8_t *) data;
888  //CRC preset value
889  crc = 0xFFFFFFFF;
890 
891  //Loop through data
892  for(i = 0; i < length; i++)
893  {
894  //The message is processed bit by bit
895  for(j = 0; j < 8; j++)
896  {
897  //Update CRC value
898  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
899  {
900  crc = (crc << 1) ^ 0x04C11DB7;
901  }
902  else
903  {
904  crc = crc << 1;
905  }
906  }
907  }
908 
909  //Return CRC value
910  return ~crc;
911 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define ENUM_EMAC_SMI_ADDR_CR_DIV62
#define EMAC_RDES1_RBS1
uint8_t opcode
Definition: dns_common.h:191
int bool_t
Definition: compiler_port.h:63
uint32_t sc589Eth2CalcCrc(const void *data, size_t length)
CRC calculation.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
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
#define SC589_ETH2_RX_BUFFER_SIZE
#define EMAC_TDES0_OWN
error_t sc589Eth2SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
uint8_t p
Definition: ndp.h:300
#define EMAC_RDES0_ES
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
error_t sc589Eth2UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
void sc589Eth2IrqHandler(uint32_t id, void *param)
ADSP-SC589 Ethernet MAC interrupt service routine.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
#define EMAC_TDES0_IC
error_t sc589Eth2UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define ENUM_EMAC_DMA_BUSMODE_RPBL_32
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 SMI_OPCODE_WRITE
Definition: nic.h:66
#define FALSE
Definition: os_port.h:46
uint16_t sc589Eth2ReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define EMAC_RDES1_RCH
#define EMAC_TDES1_TBS1
#define EMAC_RDES0_LS
void sc589Eth2EventHandler(NetInterface *interface)
ADSP-SC589 Ethernet MAC event handler.
error_t
Error codes.
Definition: error.h:43
Enhanced RX DMA descriptor.
#define SC589_ETH2_TX_BUFFER_SIZE
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
error_t sc589Eth2Init(NetInterface *interface)
ADSP-SC589 Ethernet MAC initialization.
#define NetRxAncillary
Definition: net_misc.h:40
#define SC589_ETH2_TX_BUFFER_COUNT
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
void sc589Eth2Tick(NetInterface *interface)
ADSP-SC589 Ethernet MAC timer handler.
MacAddr addr
MAC address.
Definition: ethernet.h:265
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
void sc589Eth2InitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define TRACE_INFO(...)
Definition: debug.h:105
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
Enhanced TX DMA descriptor.
#define EMAC_TDES0_LS
void sc589Eth2EnableIrq(NetInterface *interface)
Enable interrupts.
#define rxBuffer
MacAddr
Definition: ethernet.h:197
#define SC589_ETH2_RAM_SECTION
#define EMAC_TDES0_TCH
__weak_func void sc589Eth2InitGpio(NetInterface *interface)
GPIO configuration.
error_t sc589Eth2ReceivePacket(NetInterface *interface)
Receive a packet.
#define EMAC_RDES0_FL
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define ENUM_EMAC_DMA_BUSMODE_PBL_32
uint16_t regAddr
void sc589Eth2DisableIrq(NetInterface *interface)
Disable interrupts.
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:264
#define osEnterIsr()
const NicDriver sc589Eth2Driver
ADSP-SC589 Ethernet MAC driver (EMAC1 instance)
#define EMAC_TDES0_FS
#define rxDmaDesc
void sc589Eth2WritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define txDmaDesc
ADSP-SC589 Ethernet MAC driver (EMAC1 instance)
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:57
#define SC589_ETH2_RX_BUFFER_COUNT
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define EMAC_RDES0_OWN
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
#define EMAC_RDES0_FS