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