sc594_eth1_driver.c
Go to the documentation of this file.
1 /**
2  * @file sc594_eth1_driver.c
3  * @brief ADSP-SC594 Ethernet MAC driver (EMAC0 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_ETH1_RAM_SECTION
51 //Receive buffer
52 #pragma data_alignment = 4
53 #pragma location = SC594_ETH1_RAM_SECTION
55 //Transmit DMA descriptors
56 #pragma data_alignment = 8
57 #pragma location = SC594_ETH1_RAM_SECTION
59 //Receive DMA descriptors
60 #pragma data_alignment = 8
61 #pragma location = SC594_ETH1_RAM_SECTION
63 
64 //GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4), __section__(SC594_ETH1_RAM_SECTION)));
70 //Receive buffer
72  __attribute__((aligned(4), __section__(SC594_ETH1_RAM_SECTION)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(8), __section__(SC594_ETH1_RAM_SECTION)));
76 //Receive DMA descriptors
78  __attribute__((aligned(8), __section__(SC594_ETH1_RAM_SECTION)));
79 
80 #endif
81 
82 //Pointer to the current TX DMA descriptor
83 static Sc594Eth1TxDmaDesc *txCurDmaDesc;
84 //Pointer to the current RX DMA descriptor
85 static Sc594Eth1RxDmaDesc *rxCurDmaDesc;
86 
87 
88 /**
89  * @brief ADSP-SC594 Ethernet MAC driver (EMAC0 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 (EMAC0)...\r\n");
125 
126  //Save underlying network interface
127  nicDriverInterface = interface;
128 
129  //GPIO configuration
130  sc594Eth1InitGpio(interface);
131 
132  //Perform a software reset
133  *pREG_EMAC0_DMA0_BUSMODE |= BITM_EMAC_DMA0_BUSMODE_SWR;
134  //Wait for the reset to complete
135  while((*pREG_EMAC0_DMA0_BUSMODE & BITM_EMAC_DMA0_BUSMODE_SWR) != 0)
136  {
137  }
138 
139  //Adjust MDC clock range depending on CLKO7 frequency
140  *pREG_EMAC0_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_EMAC0_MACCFG = BITM_EMAC_MACCFG_PS | BITM_EMAC_MACCFG_DO;
167 
168  //Configure MAC address filtering
169  sc594Eth1UpdateMacAddrFilter(interface);
170 
171  //Disable flow control
172  *pREG_EMAC0_FLOWCTL = 0;
173 
174  //Enable store and forward mode
175  *pREG_EMAC0_DMA0_OPMODE = BITM_EMAC_DMA0_OPMODE_RSF |
176  BITM_EMAC_DMA0_OPMODE_TSF;
177 
178  //Configure DMA bus mode
179  *pREG_EMAC0_DMA0_BUSMODE = BITM_EMAC_DMA0_BUSMODE_AAL |
180  BITM_EMAC_DMA0_BUSMODE_USP | ENUM_EMAC_DMA_BUSMODE_RPBL_32 |
181  ENUM_EMAC_DMA_BUSMODE_PBL_32 | BITM_EMAC_DMA0_BUSMODE_ATDS;
182 
183  //Initialize DMA descriptor lists
184  sc594Eth1InitDmaDesc(interface);
185 
186  //Prevent interrupts from being generated when statistic counters reach
187  //half their maximum value
188  *pREG_EMAC0_MMC_TXIMSK = 0x01FFFFFF;
189  *pREG_EMAC0_MMC_RXIMSK = 0x01FFFFFF;
190  *pREG_EMAC0_IPC_RXIMSK = 0x3FFFFFFF;
191 
192  //Disable MAC interrupts
193  *pREG_EMAC0_IMSK = BITM_EMAC_IMSK_LPIIM | BITM_EMAC_IMSK_TS;
194 
195  //Enable the desired DMA interrupts
196  *pREG_EMAC0_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_EMAC0_DMA0, sc594Eth1IrqHandler, interface,
201  false);
202 
203  //Enable MAC transmission and reception
204  *pREG_EMAC0_MACCFG |= BITM_EMAC_MACCFG_TE | BITM_EMAC_MACCFG_RE;
205  //Enable DMA transmission and reception
206  *pREG_EMAC0_DMA0_OPMODE |= BITM_EMAC_DMA0_OPMODE_ST | BITM_EMAC_DMA0_OPMODE_SR;
207 
208  //Accept any packets from the upper layer
209  osSetEvent(&interface->nicTxEvent);
210 
211  //Successful initialization
212  return NO_ERROR;
213 }
214 
215 
216 /**
217  * @brief GPIO configuration
218  * @param[in] interface Underlying network interface
219  **/
220 
221 __weak_func void sc594Eth1InitGpio(NetInterface *interface)
222 {
223 //EV-SC594-SOM evaluation board?
224 #if defined(USE_EV_SC594_SOM)
225  uint32_t temp;
226 
227  //Configure PH_03 (ETH0_MDC), PH_04 (ETH0_MDIO), PH_05 (ETH0_RXD0),
228  //PH_06 (ETH0_RXD1), PH_07 (ETH0_RXCLK_REFCLK), PH_08 (ETH0_RXCTL_RXDV),
229  //PH_09 (ETH0_TXD0), PH_10 (ETH0_TXD1), PH_11 (ETH0_RXD2), PH_12 (ETH0_RXD3),
230  //PH_13 (ETH0_TXCTL_TXEN), PH_14 (ETH0_TXCLK) and PH_15 (ETH0_TXD2)
231  temp = *pREG_PORTH_MUX;
232  temp = (temp & ~BITM_PORT_MUX_MUX3) | (0 << BITP_PORT_MUX_MUX3);
233  temp = (temp & ~BITM_PORT_MUX_MUX4) | (0 << BITP_PORT_MUX_MUX4);
234  temp = (temp & ~BITM_PORT_MUX_MUX5) | (0 << BITP_PORT_MUX_MUX5);
235  temp = (temp & ~BITM_PORT_MUX_MUX6) | (0 << BITP_PORT_MUX_MUX6);
236  temp = (temp & ~BITM_PORT_MUX_MUX7) | (0 << BITP_PORT_MUX_MUX7);
237  temp = (temp & ~BITM_PORT_MUX_MUX8) | (0 << BITP_PORT_MUX_MUX8);
238  temp = (temp & ~BITM_PORT_MUX_MUX9) | (0 << BITP_PORT_MUX_MUX9);
239  temp = (temp & ~BITM_PORT_MUX_MUX10) | (0 << BITP_PORT_MUX_MUX10);
240  temp = (temp & ~BITM_PORT_MUX_MUX11) | (0 << BITP_PORT_MUX_MUX11);
241  temp = (temp & ~BITM_PORT_MUX_MUX12) | (0 << BITP_PORT_MUX_MUX12);
242  temp = (temp & ~BITM_PORT_MUX_MUX13) | (0 << BITP_PORT_MUX_MUX13);
243  temp = (temp & ~BITM_PORT_MUX_MUX14) | (0 << BITP_PORT_MUX_MUX14);
244  temp = (temp & ~BITM_PORT_MUX_MUX15) | (0 << BITP_PORT_MUX_MUX15);
245  *pREG_PORTH_MUX = temp;
246 
247  //Select peripheral mode
248  *pREG_PORTH_FER_SET = BITM_PORT_FER_PX3 | BITM_PORT_FER_PX4 |
249  BITM_PORT_FER_PX5 | BITM_PORT_FER_PX6 | BITM_PORT_FER_PX7 |
250  BITM_PORT_FER_PX8 | BITM_PORT_FER_PX9 | BITM_PORT_FER_PX10 |
251  BITM_PORT_FER_PX11 | BITM_PORT_FER_PX12 | BITM_PORT_FER_PX13 |
252  BITM_PORT_FER_PX14 | BITM_PORT_FER_PX15;
253 
254  //Configure PI_00 (ETH0_TXD3)
255  temp = *pREG_PORTI_MUX;
256  temp = (temp & ~BITM_PORT_MUX_MUX0) | (0 << BITP_PORT_MUX_MUX0);
257  *pREG_PORTI_MUX = temp;
258 
259  //Select peripheral mode
260  *pREG_PORTI_FER_SET = BITM_PORT_FER_PX0;
261 
262  //Reset PHY transceiver (hard reset)
263  sc594Eth1ResetPhy(interface);
264 
265  //Select RGMII interface mode
266  temp = *pREG_PADS0_PCFG0 & ~BITM_PADS_PCFG0_EMACPHYISEL;
267  *pREG_PADS0_PCFG0 = temp | ENUM_PADS_PCFG0_EMACPHY_RGMII;
268 
269  //Reset PHY interface
270  *pREG_PADS0_PCFG0 |= BITM_PADS_PCFG0_EMACRESET;
271 #endif
272 }
273 
274 
275 /**
276  * @brief Reset PHY transceiver
277  * @param[in] interface Underlying network interface
278  **/
279 
280 __weak_func void sc594Eth1ResetPhy(NetInterface *interface)
281 {
282 }
283 
284 
285 /**
286  * @brief Initialize DMA descriptor lists
287  * @param[in] interface Underlying network interface
288  **/
289 
291 {
292  uint_t i;
293 
294  //Initialize TX DMA descriptor list
295  for(i = 0; i < SC594_ETH1_TX_BUFFER_COUNT; i++)
296  {
297  //Use chain structure rather than ring structure
299  //Initialize transmit buffer size
300  txDmaDesc[i].tdes1 = 0;
301 
302  //Transmit buffer address
303  txDmaDesc[i].tdes2 = adi_rtl_internal_to_system_addr(
304  (uint32_t) txBuffer[i], 1);
305 
306  //Next descriptor address
307  txDmaDesc[i].tdes3 = adi_rtl_internal_to_system_addr(
308  (uint32_t) &txDmaDesc[i + 1], 1);
309 
310  //Reserved fields
311  txDmaDesc[i].tdes4 = 0;
312  txDmaDesc[i].tdes5 = 0;
313  //Transmit frame time stamp
314  txDmaDesc[i].tdes6 = 0;
315  txDmaDesc[i].tdes7 = 0;
316  }
317 
318  //The last descriptor is chained to the first entry
319  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
320  //Point to the very first descriptor
321  txCurDmaDesc = &txDmaDesc[0];
322 
323  //Initialize RX DMA descriptor list
324  for(i = 0; i < SC594_ETH1_RX_BUFFER_COUNT; i++)
325  {
326  //The descriptor is initially owned by the DMA
327  rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
328  //Use chain structure rather than ring structure
330 
331  //Receive buffer address
332  rxDmaDesc[i].rdes2 = adi_rtl_internal_to_system_addr(
333  (uint32_t) rxBuffer[i], 1);
334 
335  //Next descriptor address
336  rxDmaDesc[i].rdes3 = adi_rtl_internal_to_system_addr(
337  (uint32_t) &rxDmaDesc[i + 1], 1);
338 
339  //Extended status
340  rxDmaDesc[i].rdes4 = 0;
341  //Reserved field
342  rxDmaDesc[i].rdes5 = 0;
343  //Receive frame time stamp
344  rxDmaDesc[i].rdes6 = 0;
345  rxDmaDesc[i].rdes7 = 0;
346  }
347 
348  //The last descriptor is chained to the first entry
349  rxDmaDesc[i - 1].rdes3 = adi_rtl_internal_to_system_addr(
350  (uint32_t) &rxDmaDesc[0], 1);
351 
352  //Point to the very first descriptor
353  rxCurDmaDesc = &rxDmaDesc[0];
354 
355  //Start location of the TX descriptor list
356  *pREG_EMAC0_DMA0_TXDSC_ADDR = adi_rtl_internal_to_system_addr(
357  (uint32_t) txDmaDesc, 1);
358 
359  //Start location of the RX descriptor list
360  *pREG_EMAC0_DMA0_RXDSC_ADDR = adi_rtl_internal_to_system_addr(
361  (uint32_t) rxDmaDesc, 1);
362 }
363 
364 
365 /**
366  * @brief ADSP-SC594 Ethernet MAC timer handler
367  *
368  * This routine is periodically called by the TCP/IP stack to handle periodic
369  * operations such as polling the link state
370  *
371  * @param[in] interface Underlying network interface
372  **/
373 
374 void sc594Eth1Tick(NetInterface *interface)
375 {
376  //Valid Ethernet PHY or switch driver?
377  if(interface->phyDriver != NULL)
378  {
379  //Handle periodic operations
380  interface->phyDriver->tick(interface);
381  }
382  else if(interface->switchDriver != NULL)
383  {
384  //Handle periodic operations
385  interface->switchDriver->tick(interface);
386  }
387  else
388  {
389  //Just for sanity
390  }
391 }
392 
393 
394 /**
395  * @brief Enable interrupts
396  * @param[in] interface Underlying network interface
397  **/
398 
400 {
401  //Enable Ethernet MAC interrupts
402  adi_int_EnableInt(INTR_EMAC0_DMA0, true);
403 
404  //Valid Ethernet PHY or switch driver?
405  if(interface->phyDriver != NULL)
406  {
407  //Enable Ethernet PHY interrupts
408  interface->phyDriver->enableIrq(interface);
409  }
410  else if(interface->switchDriver != NULL)
411  {
412  //Enable Ethernet switch interrupts
413  interface->switchDriver->enableIrq(interface);
414  }
415  else
416  {
417  //Just for sanity
418  }
419 }
420 
421 
422 /**
423  * @brief Disable interrupts
424  * @param[in] interface Underlying network interface
425  **/
426 
428 {
429  //Disable Ethernet MAC interrupts
430  adi_int_EnableInt(INTR_EMAC0_DMA0, false);
431 
432  //Valid Ethernet PHY or switch driver?
433  if(interface->phyDriver != NULL)
434  {
435  //Disable Ethernet PHY interrupts
436  interface->phyDriver->disableIrq(interface);
437  }
438  else if(interface->switchDriver != NULL)
439  {
440  //Disable Ethernet switch interrupts
441  interface->switchDriver->disableIrq(interface);
442  }
443  else
444  {
445  //Just for sanity
446  }
447 }
448 
449 
450 /**
451  * @brief ADSP-SC594 Ethernet MAC interrupt service routine
452  * @param id Interrupt identifier
453  * @param param Unused parameter
454  **/
455 
456 void sc594Eth1IrqHandler(uint32_t id, void *param)
457 {
458  bool_t flag;
459  uint32_t status;
460 
461  //Interrupt service routine prologue
462  osEnterIsr();
463 
464  //This flag will be set if a higher priority task must be woken
465  flag = FALSE;
466 
467  //Read DMA status register
468  status = *pREG_EMAC0_DMA0_STAT;
469 
470  //Packet transmitted?
471  if((status & BITM_EMAC_DMA0_STAT_TI) != 0)
472  {
473  //Clear TI interrupt flag
474  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA0_STAT_TI;
475 
476  //Check whether the TX buffer is available for writing
477  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
478  {
479  //Notify the TCP/IP stack that the transmitter is ready to send
480  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
481  }
482  }
483 
484  //Packet received?
485  if((status & BITM_EMAC_DMA0_STAT_RI) != 0)
486  {
487  //Clear RI interrupt flag
488  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA0_STAT_RI;
489 
490  //Set event flag
491  nicDriverInterface->nicEvent = TRUE;
492  //Notify the TCP/IP stack of the event
493  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
494  }
495 
496  //Clear NIS interrupt flag
497  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA0_STAT_NIS;
498 
499  //Interrupt service routine epilogue
500  osExitIsr(flag);
501 }
502 
503 
504 /**
505  * @brief ADSP-SC594 Ethernet MAC event handler
506  * @param[in] interface Underlying network interface
507  **/
508 
510 {
511  error_t error;
512 
513  //Process all pending packets
514  do
515  {
516  //Read incoming packet
517  error = sc594Eth1ReceivePacket(interface);
518 
519  //No more data in the receive buffer?
520  } while(error != ERROR_BUFFER_EMPTY);
521 }
522 
523 
524 /**
525  * @brief Send a packet
526  * @param[in] interface Underlying network interface
527  * @param[in] buffer Multi-part buffer containing the data to send
528  * @param[in] offset Offset to the first data byte
529  * @param[in] ancillary Additional options passed to the stack along with
530  * the packet
531  * @return Error code
532  **/
533 
535  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
536 {
537  size_t length;
538 
539  //Retrieve the length of the packet
540  length = netBufferGetLength(buffer) - offset;
541 
542  //Check the frame length
544  {
545  //The transmitter can accept another packet
546  osSetEvent(&interface->nicTxEvent);
547  //Report an error
548  return ERROR_INVALID_LENGTH;
549  }
550 
551  //Make sure the current buffer is available for writing
552  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) != 0)
553  {
554  return ERROR_FAILURE;
555  }
556 
557  //Copy user data to the transmit buffer
558  netBufferRead((uint8_t *) adi_rtl_system_to_internal_addr(
559  txCurDmaDesc->tdes2), buffer, offset, length);
560 
561  //Write the number of bytes to send
562  txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
563  //Set LS and FS flags as the data fits in a single buffer
564  txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
565  //Give the ownership of the descriptor to the DMA
566  txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
567 
568  //Data synchronization barrier
569  __asm("dsb");
570 
571  //Clear TU flag to resume processing
572  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA0_STAT_TU;
573  //Instruct the DMA to poll the transmit descriptor list
574  *pREG_EMAC0_DMA0_TXPOLL = 0;
575 
576  //Point to the next descriptor in the list
577  txCurDmaDesc = (Sc594Eth1TxDmaDesc *) adi_rtl_system_to_internal_addr(
578  txCurDmaDesc->tdes3);
579 
580  //Check whether the next buffer is available for writing
581  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
582  {
583  //The transmitter can accept another packet
584  osSetEvent(&interface->nicTxEvent);
585  }
586 
587  //Data successfully written
588  return NO_ERROR;
589 }
590 
591 
592 /**
593  * @brief Receive a packet
594  * @param[in] interface Underlying network interface
595  * @return Error code
596  **/
597 
599 {
600  error_t error;
601  size_t n;
602  NetRxAncillary ancillary;
603 
604  //Current buffer available for reading?
605  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN) == 0)
606  {
607  //FS and LS flags should be set
608  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) != 0 &&
609  (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS) != 0)
610  {
611  //Make sure no error occurred
612  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_ES) == 0)
613  {
614  //Retrieve the length of the frame
615  n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
616  //Limit the number of data to read
618 
619  //Additional options can be passed to the stack along with the packet
620  ancillary = NET_DEFAULT_RX_ANCILLARY;
621 
622  //Pass the packet to the upper layer
623  nicProcessPacket(interface, (uint8_t *) adi_rtl_system_to_internal_addr(
624  rxCurDmaDesc->rdes2), n, &ancillary);
625 
626  //Valid packet received
627  error = NO_ERROR;
628  }
629  else
630  {
631  //The received packet contains an error
632  error = ERROR_INVALID_PACKET;
633  }
634  }
635  else
636  {
637  //The packet is not valid
638  error = ERROR_INVALID_PACKET;
639  }
640 
641  //Give the ownership of the descriptor back to the DMA
642  rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
643 
644  //Point to the next descriptor in the list
645  rxCurDmaDesc = (Sc594Eth1RxDmaDesc *) adi_rtl_system_to_internal_addr(
646  rxCurDmaDesc->rdes3);
647  }
648  else
649  {
650  //No more data in the receive buffer
651  error = ERROR_BUFFER_EMPTY;
652  }
653 
654  //Clear RU flag to resume processing
655  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA0_STAT_RU;
656  //Instruct the DMA to poll the receive descriptor list
657  *pREG_EMAC0_DMA0_RXPOLL = 0;
658 
659  //Return status code
660  return error;
661 }
662 
663 
664 /**
665  * @brief Configure MAC address filtering
666  * @param[in] interface Underlying network interface
667  * @return Error code
668  **/
669 
671 {
672  uint_t i;
673  uint_t j;
674  uint_t k;
675  uint32_t crc;
676  uint32_t hashTable[2];
677  MacAddr unicastMacAddr[1];
678  MacFilterEntry *entry;
679 
680  //Debug message
681  TRACE_DEBUG("Updating MAC filter...\r\n");
682 
683  //Promiscuous mode?
684  if(interface->promiscuous)
685  {
686  //Pass all incoming frames regardless of their destination address
687  *pREG_EMAC0_MACFRMFILT = BITM_EMAC_MACFRMFILT_PR;
688  }
689  else
690  {
691  //Set the MAC address of the station
692  *pREG_EMAC0_ADDR0_LO = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
693  *pREG_EMAC0_ADDR0_HI = interface->macAddr.w[2];
694 
695  //The MAC supports one additional address for unicast perfect filtering
696  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
697 
698  //The hash table is used for multicast address filtering
699  hashTable[0] = 0;
700  hashTable[1] = 0;
701 
702  //The MAC address filter contains the list of MAC addresses to accept
703  //when receiving an Ethernet frame
704  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
705  {
706  //Point to the current entry
707  entry = &interface->macAddrFilter[i];
708 
709  //Valid entry?
710  if(entry->refCount > 0)
711  {
712  //Multicast address?
713  if(macIsMulticastAddr(&entry->addr))
714  {
715  //Compute CRC over the current MAC address
716  crc = sc594Eth1CalcCrc(&entry->addr, sizeof(MacAddr));
717 
718  //The upper 6 bits in the CRC register are used to index the
719  //contents of the hash table
720  k = (crc >> 26) & 0x3F;
721 
722  //Update hash table contents
723  hashTable[k / 32] |= (1 << (k % 32));
724  }
725  else
726  {
727  //One additional MAC address can be specified
728  if(j < 1)
729  {
730  //Save the unicast address
731  unicastMacAddr[j++] = entry->addr;
732  }
733  }
734  }
735  }
736 
737  //Configure the first unicast address filter
738  if(j >= 1)
739  {
740  //When the AE bit is set, the entry is used for perfect filtering
741  *pREG_EMAC0_ADDR1_LO = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
742  *pREG_EMAC0_ADDR1_HI = unicastMacAddr[0].w[2] | BITM_EMAC_ADDR1_HI_AE;
743  }
744  else
745  {
746  //When the AE bit is cleared, the entry is ignored
747  *pREG_EMAC0_ADDR1_LO = 0;
748  *pREG_EMAC0_ADDR1_HI = 0;
749  }
750 
751  //Check whether frames with a multicast destination address should be
752  //accepted
753  if(interface->acceptAllMulticast)
754  {
755  //Configure the receive filter
756  *pREG_EMAC0_MACFRMFILT = BITM_EMAC_MACFRMFILT_HPF | BITM_EMAC_MACFRMFILT_PM;
757  }
758  else
759  {
760  //Configure the receive filter
761  *pREG_EMAC0_MACFRMFILT = BITM_EMAC_MACFRMFILT_HPF | BITM_EMAC_MACFRMFILT_HMC;
762 
763  //Configure the multicast hash table
764  *pREG_EMAC0_HASHTBL_LO = hashTable[0];
765  *pREG_EMAC0_HASHTBL_HI = hashTable[1];
766 
767  //Debug message
768  TRACE_DEBUG(" EMAC_HASHTBL_LO = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_LO);
769  TRACE_DEBUG(" EMAC_HASHTBL_HI = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_HI);
770  }
771  }
772 
773  //Successful processing
774  return NO_ERROR;
775 }
776 
777 
778 /**
779  * @brief Adjust MAC configuration parameters for proper operation
780  * @param[in] interface Underlying network interface
781  * @return Error code
782  **/
783 
785 {
786  uint32_t config;
787 
788  //Read current MAC configuration
789  config = *pREG_EMAC0_MACCFG;
790 
791  //1000BASE-T operation mode?
792  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
793  {
794  config &= ~BITM_EMAC_MACCFG_PS;
795  config &= ~BITM_EMAC_MACCFG_FES;
796  }
797  //100BASE-TX operation mode?
798  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
799  {
800  config |= BITM_EMAC_MACCFG_PS;
801  config |= BITM_EMAC_MACCFG_FES;
802  }
803  //10BASE-T operation mode?
804  else
805  {
806  config |= BITM_EMAC_MACCFG_PS;
807  config &= ~BITM_EMAC_MACCFG_FES;
808  }
809 
810  //Half-duplex or full-duplex mode?
811  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
812  {
813  config |= BITM_EMAC_MACCFG_DM;
814  }
815  else
816  {
817  config &= ~BITM_EMAC_MACCFG_DM;
818  }
819 
820  //Update MAC configuration register
821  *pREG_EMAC0_MACCFG = config;
822 
823  //Successful processing
824  return NO_ERROR;
825 }
826 
827 
828 /**
829  * @brief Write PHY register
830  * @param[in] opcode Access type (2 bits)
831  * @param[in] phyAddr PHY address (5 bits)
832  * @param[in] regAddr Register address (5 bits)
833  * @param[in] data Register value
834  **/
835 
836 void sc594Eth1WritePhyReg(uint8_t opcode, uint8_t phyAddr,
837  uint8_t regAddr, uint16_t data)
838 {
839  uint32_t temp;
840 
841  //Valid opcode?
842  if(opcode == SMI_OPCODE_WRITE)
843  {
844  //Take care not to alter MDC clock configuration
845  temp = *pREG_EMAC0_SMI_ADDR & BITM_EMAC_SMI_ADDR_CR;
846  //Set up a write operation
847  temp |= BITM_EMAC_SMI_ADDR_SMIW | BITM_EMAC_SMI_ADDR_SMIB;
848  //PHY address
849  temp |= (phyAddr << BITP_EMAC_SMI_ADDR_PA) & BITM_EMAC_SMI_ADDR_PA;
850  //Register address
851  temp |= (regAddr << BITP_EMAC_SMI_ADDR_SMIR) & BITM_EMAC_SMI_ADDR_SMIR;
852 
853  //Data to be written in the PHY register
854  *pREG_EMAC0_SMI_DATA = data & BITM_EMAC_SMI_DATA_SMID;
855 
856  //Start a write operation
857  *pREG_EMAC0_SMI_ADDR = temp;
858  //Wait for the write to complete
859  while((*pREG_EMAC0_SMI_ADDR & BITM_EMAC_SMI_ADDR_SMIB) != 0)
860  {
861  }
862  }
863  else
864  {
865  //The MAC peripheral only supports standard Clause 22 opcodes
866  }
867 }
868 
869 
870 /**
871  * @brief Read PHY register
872  * @param[in] opcode Access type (2 bits)
873  * @param[in] phyAddr PHY address (5 bits)
874  * @param[in] regAddr Register address (5 bits)
875  * @return Register value
876  **/
877 
878 uint16_t sc594Eth1ReadPhyReg(uint8_t opcode, uint8_t phyAddr,
879  uint8_t regAddr)
880 {
881  uint16_t data;
882  uint32_t temp;
883 
884  //Valid opcode?
885  if(opcode == SMI_OPCODE_READ)
886  {
887  //Take care not to alter MDC clock configuration
888  temp = *pREG_EMAC0_SMI_ADDR & BITM_EMAC_SMI_ADDR_CR;
889  //Set up a read operation
890  temp |= BITM_EMAC_SMI_ADDR_SMIB;
891  //PHY address
892  temp |= (phyAddr << BITP_EMAC_SMI_ADDR_PA) & BITM_EMAC_SMI_ADDR_PA;
893  //Register address
894  temp |= (regAddr << BITP_EMAC_SMI_ADDR_SMIR) & BITM_EMAC_SMI_ADDR_SMIR;
895 
896  //Start a read operation
897  *pREG_EMAC0_SMI_ADDR = temp;
898  //Wait for the read to complete
899  while((*pREG_EMAC0_SMI_ADDR & BITM_EMAC_SMI_ADDR_SMIB) != 0)
900  {
901  }
902 
903  //Get register value
904  data = *pREG_EMAC0_SMI_DATA & BITM_EMAC_SMI_DATA_SMID;
905  }
906  else
907  {
908  //The MAC peripheral only supports standard Clause 22 opcodes
909  data = 0;
910  }
911 
912  //Return the value of the PHY register
913  return data;
914 }
915 
916 
917 /**
918  * @brief CRC calculation
919  * @param[in] data Pointer to the data over which to calculate the CRC
920  * @param[in] length Number of bytes to process
921  * @return Resulting CRC value
922  **/
923 
924 uint32_t sc594Eth1CalcCrc(const void *data, size_t length)
925 {
926  uint_t i;
927  uint_t j;
928  uint32_t crc;
929  const uint8_t *p;
930 
931  //Point to the data over which to calculate the CRC
932  p = (uint8_t *) data;
933  //CRC preset value
934  crc = 0xFFFFFFFF;
935 
936  //Loop through data
937  for(i = 0; i < length; i++)
938  {
939  //The message is processed bit by bit
940  for(j = 0; j < 8; j++)
941  {
942  //Update CRC value
943  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
944  {
945  crc = (crc << 1) ^ 0x04C11DB7;
946  }
947  else
948  {
949  crc = crc << 1;
950  }
951  }
952  }
953 
954  //Return CRC value
955  return ~crc;
956 }
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
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define EMAC_RDES1_RBS1
uint8_t opcode
Definition: dns_common.h:191
int bool_t
Definition: compiler_port.h:63
@ 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 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
#define SC594_ETH1_TX_BUFFER_SIZE
void sc594Eth1DisableIrq(NetInterface *interface)
Disable interrupts.
void sc594Eth1IrqHandler(uint32_t id, void *param)
ADSP-SC594 Ethernet MAC interrupt service routine.
#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
__weak_func void sc594Eth1InitGpio(NetInterface *interface)
GPIO configuration.
#define osExitIsr(flag)
#define SC594_ETH1_RAM_SECTION
#define SMI_OPCODE_WRITE
Definition: nic.h:66
Enhanced RX DMA descriptor.
error_t sc594Eth1SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
const NicDriver sc594Eth1Driver
ADSP-SC594 Ethernet MAC driver (EMAC0 instance)
void sc594Eth1Tick(NetInterface *interface)
ADSP-SC594 Ethernet MAC timer handler.
#define FALSE
Definition: os_port.h:46
#define EMAC_RDES1_RCH
#define EMAC_TDES1_TBS1
#define EMAC_RDES0_LS
__weak_func void sc594Eth1ResetPhy(NetInterface *interface)
Reset PHY transceiver.
error_t
Error codes.
Definition: error.h:43
#define SC594_ETH1_RX_BUFFER_SIZE
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
void sc594Eth1EventHandler(NetInterface *interface)
ADSP-SC594 Ethernet MAC event handler.
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#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
Enhanced TX DMA descriptor.
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
#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
#define EMAC_TDES0_LS
#define rxBuffer
MacAddr
Definition: ethernet.h:197
error_t sc594Eth1UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define EMAC_TDES0_TCH
#define EMAC_RDES0_FL
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define ENUM_EMAC_DMA_BUSMODE_PBL_32
ADSP-SC594 Ethernet MAC driver (EMAC0 instance)
uint16_t regAddr
#define SC594_ETH1_TX_BUFFER_COUNT
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:264
error_t sc594Eth1ReceivePacket(NetInterface *interface)
Receive a packet.
#define osEnterIsr()
error_t sc594Eth1Init(NetInterface *interface)
ADSP-SC594 Ethernet MAC initialization.
error_t sc594Eth1UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
uint16_t sc594Eth1ReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define EMAC_TDES0_FS
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define SC594_ETH1_RX_BUFFER_COUNT
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
void sc594Eth1WritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define EMAC_RDES0_OWN
uint32_t sc594Eth1CalcCrc(const void *data, size_t length)
CRC calculation.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:51
void sc594Eth1InitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
@ 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
void sc594Eth1EnableIrq(NetInterface *interface)
Enable interrupts.