sc835_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file sc835_eth_driver.c
3  * @brief ADSP-SC835 Ethernet MAC driver
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 = SC835_ETH_RAM_SECTION
51 //Receive buffer
52 #pragma data_alignment = 4
53 #pragma location = SC835_ETH_RAM_SECTION
55 //Transmit DMA descriptors
56 #pragma data_alignment = 8
57 #pragma location = SC835_ETH_RAM_SECTION
59 //Receive DMA descriptors
60 #pragma data_alignment = 8
61 #pragma location = SC835_ETH_RAM_SECTION
63 
64 //GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4), __section__(SC835_ETH_RAM_SECTION)));
70 //Receive buffer
72  __attribute__((aligned(4), __section__(SC835_ETH_RAM_SECTION)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(8), __section__(SC835_ETH_RAM_SECTION)));
76 //Receive DMA descriptors
78  __attribute__((aligned(8), __section__(SC835_ETH_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-SC835 Ethernet MAC driver
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief ADSP-SC835 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-SC835 Ethernet MAC...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //GPIO configuration
131  sc835EthInitGpio(interface);
132 
133  //Set DMA transfer format (little-endian)
134  *pREG_PADS0_PCFG0 &= ~BITM_PADS_PCFG0_EMAC0_ENDIANNESS;
135 
136  //Perform a software reset
137  *pREG_EMAC0_DMA_MODE |= BITM_EMAC_DMA_MODE_SWR;
138  //Wait for the reset to complete
139  while((*pREG_EMAC0_DMA_MODE & BITM_EMAC_DMA_MODE_SWR) != 0)
140  {
141  }
142 
143  //Adjust MDC clock range depending on SCLK0 frequency
144  *pREG_EMAC0_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_EMAC0_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_EMAC0_MAC_EXT_CFG & ~BITM_EMAC_MAC_EXT_CFG_GPSL;
175  *pREG_EMAC0_MAC_EXT_CFG = temp | SC835_ETH_RX_BUFFER_SIZE;
176 
177  //Configure MAC address filtering
178  sc835EthUpdateMacAddrFilter(interface);
179 
180  //Disable flow control
181  *pREG_EMAC0_Q0_TXFLOW_CTL = 0;
182  *pREG_EMAC0_RXFLOW_CTL = 0;
183 
184  //Enable the first RX queue
185  *pREG_EMAC0_RXQ_CTL0 = ENUM_EMAC_RXQ_CTL0_RXQ0EN_EN_DCB_GEN;
186 
187  //Configure DMA operating mode
188  *pREG_EMAC0_DMA_MODE = ENUM_EMAC_DMA_MODE_MODE0 |
189  ENUM_EMAC_DMA_MODE_DSPW_DISABLE;
190 
191  //Configure system bus mode
192  *pREG_EMAC0_DMA_SYSBMODE |= BITM_EMAC_DMA_SYSBMODE_AAL;
193 
194  //The DMA takes the descriptor table as contiguous
195  *pREG_EMAC0_DMA0_CTL = (0 << BITP_EMAC_DMA_CTL_DSL);
196  //Configure TX features
197  *pREG_EMAC0_DMA0_TXCTL = (32 << BITP_EMAC_DMA_TXCTL_TXPBL);
198 
199  //Configure RX features
200  *pREG_EMAC0_DMA0_RXCTL = (32 << BITP_EMAC_DMA_RXCTL_RXPBL) |
201  ((SC835_ETH_RX_BUFFER_SIZE / 4) << BITP_EMAC_DMA_RXCTL_RBSZ_13_Y);
202 
203  //Enable store and forward mode for transmission
204  *pREG_EMAC0_TQ0_OPMODE |= (7 << BITP_EMAC_TQ_OPMODE_TQS) |
205  ENUM_EMAC_TQ_OPMODE_TXQEN_ENABLE | BITM_EMAC_TQ_OPMODE_TSF;
206 
207  //Enable store and forward mode for reception
208  *pREG_EMAC0_RQ0_OPMODE |= (7 << BITP_EMAC_RQ_OPMODE_RQS) |
209  BITM_EMAC_RQ_OPMODE_RSF;
210 
211  //Initialize DMA descriptor lists
212  sc835EthInitDmaDesc(interface);
213 
214  //Prevent interrupts from being generated when statistic counters reach
215  //half their maximum value
216  *pREG_EMAC0_MMC_TXIMSK = 0x0FFFFFFF;
217  *pREG_EMAC0_MMC_RXIMSK = 0x0FFFFFFF;
218  *pREG_EMAC0_MMC_IPC_RXIMSK = 0x3FFFFFFF;
219  *pREG_EMAC0_MMC_FPE_TXIMSK = 0x00000003;
220  *pREG_EMAC0_MMC_FPE_RXIMSK = 0x0000000F;
221 
222  //Disable MAC interrupts
223  *pREG_EMAC0_MAC_IEN = 0;
224 
225  //Enable the desired DMA interrupts
226  *pREG_EMAC0_DMA0_IEN = BITM_EMAC_DMA_IEN_NIE | BITM_EMAC_DMA_IEN_RIE |
227  BITM_EMAC_DMA_IEN_TIE;
228 
229  //Register interrupt handler
230  adi_int_InstallHandler(INTR_EMAC0_STAT, sc835EthIrqHandler, interface,
231  false);
232 
233  //Enable MAC transmission and reception
234  *pREG_EMAC0_MAC_CFG |= BITM_EMAC_MAC_CFG_TE | BITM_EMAC_MAC_CFG_RE;
235 
236  //Enable DMA transmission and reception
237  *pREG_EMAC0_DMA0_TXCTL |= BITM_EMAC_DMA_TXCTL_ST;
238  *pREG_EMAC0_DMA0_RXCTL |= BITM_EMAC_DMA_RXCTL_SR;
239 
240  //Accept any packets from the upper layer
241  osSetEvent(&interface->nicTxEvent);
242 
243  //Successful initialization
244  return NO_ERROR;
245 }
246 
247 
248 /**
249  * @brief GPIO configuration
250  * @param[in] interface Underlying network interface
251  **/
252 
253 __weak_func void sc835EthInitGpio(NetInterface *interface)
254 {
255 //ADSPSC835W-EV-SOM evaluation board?
256 #if defined(USE_ADSPSC835W_EV_SOM)
257  uint32_t temp;
258 
259  //Configure PC_15 (EMAC0_MDC)
260  temp = *pREG_PORTC_MUX;
261  temp = (temp & ~BITM_PORT_MUX_MUX15) | (0 << BITP_PORT_MUX_MUX15);
262  *pREG_PORTC_MUX = temp;
263 
264  //Select peripheral mode
265  *pREG_PORTC_FER_SET = BITM_PORT_FER_PX15;
266 
267  //Configure PD_00 (EMAC0_MDIO), PD_01 (EMAC0_RXD0), PD_02 (EMAC0_RXD1),
268  //PD_03 (EMAC0_RXCLK_REFCLK), PD_04 (EMAC0_RXCTL_RXDV), PD_05 (EMAC0_TXD0),
269  //PD_06 (EMAC0_TXD1), PD_07 (EMAC0_RXD2), PD_08 (EMAC0_RXD3),
270  //PD_09 (EMAC0_TXCTL_TXEN), PD_10 (EMAC0_TXCLK), PD_11 (EMAC0_TXD2) and
271  //PD_12 (EMAC0_TXD3)
272  temp = *pREG_PORTD_MUX;
273  temp = (temp & ~BITM_PORT_MUX_MUX0) | (0 << BITP_PORT_MUX_MUX0);
274  temp = (temp & ~BITM_PORT_MUX_MUX1) | (0 << BITP_PORT_MUX_MUX1);
275  temp = (temp & ~BITM_PORT_MUX_MUX2) | (0 << BITP_PORT_MUX_MUX2);
276  temp = (temp & ~BITM_PORT_MUX_MUX3) | (0 << BITP_PORT_MUX_MUX3);
277  temp = (temp & ~BITM_PORT_MUX_MUX4) | (0 << BITP_PORT_MUX_MUX4);
278  temp = (temp & ~BITM_PORT_MUX_MUX5) | (0 << BITP_PORT_MUX_MUX5);
279  temp = (temp & ~BITM_PORT_MUX_MUX6) | (0 << BITP_PORT_MUX_MUX6);
280  temp = (temp & ~BITM_PORT_MUX_MUX7) | (0 << BITP_PORT_MUX_MUX7);
281  temp = (temp & ~BITM_PORT_MUX_MUX8) | (0 << BITP_PORT_MUX_MUX8);
282  temp = (temp & ~BITM_PORT_MUX_MUX9) | (0 << BITP_PORT_MUX_MUX9);
283  temp = (temp & ~BITM_PORT_MUX_MUX10) | (0 << BITP_PORT_MUX_MUX10);
284  temp = (temp & ~BITM_PORT_MUX_MUX11) | (0 << BITP_PORT_MUX_MUX11);
285  temp = (temp & ~BITM_PORT_MUX_MUX12) | (0 << BITP_PORT_MUX_MUX12);
286  *pREG_PORTD_MUX = temp;
287 
288  //Select peripheral mode
289  *pREG_PORTD_FER_SET = BITM_PORT_FER_PX0 | BITM_PORT_FER_PX1 |
290  BITM_PORT_FER_PX2 | BITM_PORT_FER_PX3 | BITM_PORT_FER_PX4 |
291  BITM_PORT_FER_PX5 | BITM_PORT_FER_PX6 | BITM_PORT_FER_PX7 |
292  BITM_PORT_FER_PX8 | BITM_PORT_FER_PX9 | BITM_PORT_FER_PX10 |
293  BITM_PORT_FER_PX11 | BITM_PORT_FER_PX12;
294 
295  //Reset PHY transceiver (hard reset)
296  sc835EthResetPhy(interface);
297 
298  //Select RGMII interface mode
299  temp = *pREG_PADS0_PCFG0 & ~BITM_PADS_PCFG0_EMACPHYISEL;
300  *pREG_PADS0_PCFG0 = temp | ENUM_PADS_PCFG0_EMACPHY_RGMII;
301 
302  //Reset PHY interface
303  *pREG_PADS0_PCFG0 |= BITM_PADS_PCFG0_EMACRESET;
304 #endif
305 }
306 
307 
308 /**
309  * @brief Reset PHY transceiver
310  * @param[in] interface Underlying network interface
311  **/
312 
313 __weak_func void sc835EthResetPhy(NetInterface *interface)
314 {
315 }
316 
317 
318 /**
319  * @brief Initialize DMA descriptor lists
320  * @param[in] interface Underlying network interface
321  **/
322 
324 {
325  uint_t i;
326 
327  //Initialize TX DMA descriptor list
328  for(i = 0; i < SC835_ETH_TX_BUFFER_COUNT; i++)
329  {
330  //The descriptor is initially owned by the application
331  txDmaDesc[i].tdes0 = 0;
332  txDmaDesc[i].tdes1 = 0;
333  txDmaDesc[i].tdes2 = 0;
334  txDmaDesc[i].tdes3 = 0;
335  }
336 
337  //Initialize TX descriptor index
338  txIndex = 0;
339 
340  //Initialize RX DMA descriptor list
341  for(i = 0; i < SC835_ETH_RX_BUFFER_COUNT; i++)
342  {
343  //The descriptor is initially owned by the DMA
344  rxDmaDesc[i].rdes0 = adi_rtl_internal_to_system_addr(
345  (uint32_t) rxBuffer[i], 1);
346 
347  rxDmaDesc[i].rdes1 = 0;
348  rxDmaDesc[i].rdes2 = 0;
350  }
351 
352  //Initialize RX descriptor index
353  rxIndex = 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[0], 1);
358 
359  //Length of the transmit descriptor ring
360  *pREG_EMAC0_DMA0_TXDSC_RLEN = SC835_ETH_TX_BUFFER_COUNT - 1;
361 
362  //Start location of the RX descriptor list
363  *pREG_EMAC0_DMA0_RXDSC_ADDR = adi_rtl_internal_to_system_addr(
364  (uint32_t) &rxDmaDesc[0], 1);
365 
366  //Length of the receive descriptor ring
367  *pREG_EMAC0_DMA0_RXCTL2 = SC835_ETH_RX_BUFFER_COUNT - 1;
368 }
369 
370 
371 /**
372  * @brief ADSP-SC835 Ethernet MAC timer handler
373  *
374  * This routine is periodically called by the TCP/IP stack to handle periodic
375  * operations such as polling the link state
376  *
377  * @param[in] interface Underlying network interface
378  **/
379 
380 void sc835EthTick(NetInterface *interface)
381 {
382  //Valid Ethernet PHY or switch driver?
383  if(interface->phyDriver != NULL)
384  {
385  //Handle periodic operations
386  interface->phyDriver->tick(interface);
387  }
388  else if(interface->switchDriver != NULL)
389  {
390  //Handle periodic operations
391  interface->switchDriver->tick(interface);
392  }
393  else
394  {
395  //Just for sanity
396  }
397 }
398 
399 
400 /**
401  * @brief Enable interrupts
402  * @param[in] interface Underlying network interface
403  **/
404 
406 {
407  //Enable Ethernet MAC interrupts
408  adi_int_EnableInt(INTR_EMAC0_STAT, true);
409 
410  //Valid Ethernet PHY or switch driver?
411  if(interface->phyDriver != NULL)
412  {
413  //Enable Ethernet PHY interrupts
414  interface->phyDriver->enableIrq(interface);
415  }
416  else if(interface->switchDriver != NULL)
417  {
418  //Enable Ethernet switch interrupts
419  interface->switchDriver->enableIrq(interface);
420  }
421  else
422  {
423  //Just for sanity
424  }
425 }
426 
427 
428 /**
429  * @brief Disable interrupts
430  * @param[in] interface Underlying network interface
431  **/
432 
434 {
435  //Disable Ethernet MAC interrupts
436  adi_int_EnableInt(INTR_EMAC0_STAT, false);
437 
438  //Valid Ethernet PHY or switch driver?
439  if(interface->phyDriver != NULL)
440  {
441  //Disable Ethernet PHY interrupts
442  interface->phyDriver->disableIrq(interface);
443  }
444  else if(interface->switchDriver != NULL)
445  {
446  //Disable Ethernet switch interrupts
447  interface->switchDriver->disableIrq(interface);
448  }
449  else
450  {
451  //Just for sanity
452  }
453 }
454 
455 
456 /**
457  * @brief ADSP-SC835 Ethernet MAC interrupt service routine
458  * @param id Interrupt identifier
459  * @param param Unused parameter
460  **/
461 
462 void sc835EthIrqHandler(uint32_t id, void *param)
463 {
464  bool_t flag;
465  uint32_t status;
466 
467  //Interrupt service routine prologue
468  osEnterIsr();
469 
470  //This flag will be set if a higher priority task must be woken
471  flag = FALSE;
472 
473  //Read DMA status register
474  status = *pREG_EMAC0_DMA0_STAT;
475 
476  //Packet transmitted?
477  if((status & BITM_EMAC_DMA_STAT_TI) != 0)
478  {
479  //Clear TI interrupt flag
480  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_TI;
481 
482  //Check whether the TX buffer is available for writing
483  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
484  {
485  //Notify the TCP/IP stack that the transmitter is ready to send
486  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
487  }
488  }
489 
490  //Packet received?
491  if((status & BITM_EMAC_DMA_STAT_RI) != 0)
492  {
493  //Clear RI interrupt flag
494  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_RI;
495 
496  //Set event flag
497  nicDriverInterface->nicEvent = TRUE;
498  //Notify the TCP/IP stack of the event
499  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
500  }
501 
502  //Clear NIS interrupt flag
503  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_NIS;
504 
505  //Interrupt service routine epilogue
506  osExitIsr(flag);
507 }
508 
509 
510 /**
511  * @brief ADSP-SC835 Ethernet MAC event handler
512  * @param[in] interface Underlying network interface
513  **/
514 
516 {
517  error_t error;
518 
519  //Process all pending packets
520  do
521  {
522  //Read incoming packet
523  error = sc835EthReceivePacket(interface);
524 
525  //No more data in the receive buffer?
526  } while(error != ERROR_BUFFER_EMPTY);
527 }
528 
529 
530 /**
531  * @brief Send a packet
532  * @param[in] interface Underlying network interface
533  * @param[in] buffer Multi-part buffer containing the data to send
534  * @param[in] offset Offset to the first data byte
535  * @param[in] ancillary Additional options passed to the stack along with
536  * the packet
537  * @return Error code
538  **/
539 
541  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
542 {
543  size_t length;
544 
545  //Retrieve the length of the packet
546  length = netBufferGetLength(buffer) - offset;
547 
548  //Check the frame length
550  {
551  //The transmitter can accept another packet
552  osSetEvent(&interface->nicTxEvent);
553  //Report an error
554  return ERROR_INVALID_LENGTH;
555  }
556 
557  //Make sure the current buffer is available for writing
558  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) != 0)
559  {
560  return ERROR_FAILURE;
561  }
562 
563  //Copy user data to the transmit buffer
564  netBufferRead(txBuffer[txIndex], buffer, offset, length);
565 
566  //Set the start address of the buffer
567  txDmaDesc[txIndex].tdes0 = adi_rtl_internal_to_system_addr(
568  (uint32_t) txBuffer[txIndex], 1);
569 
570  //Write the number of bytes to send
571  txDmaDesc[txIndex].tdes2 = EMAC_TDES2_IOC | (length & EMAC_TDES2_HL_B1L);
572  //Give the ownership of the descriptor to the DMA
574 
575  //Clear TBU flag to resume processing
576  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_TBU;
577  //Instruct the DMA to poll the transmit descriptor list
578  *pREG_EMAC0_DMA0_TXDSC_TLPTR = 0;
579 
580  //Increment index and wrap around if necessary
581  if(++txIndex >= SC835_ETH_TX_BUFFER_COUNT)
582  {
583  txIndex = 0;
584  }
585 
586  //Check whether the next buffer is available for writing
587  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
588  {
589  //The transmitter can accept another packet
590  osSetEvent(&interface->nicTxEvent);
591  }
592 
593  //Data successfully written
594  return NO_ERROR;
595 }
596 
597 
598 /**
599  * @brief Receive a packet
600  * @param[in] interface Underlying network interface
601  * @return Error code
602  **/
603 
605 {
606  error_t error;
607  size_t n;
608  NetRxAncillary ancillary;
609 
610  //Current buffer available for reading?
611  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_OWN) == 0)
612  {
613  //FD and LD flags should be set
614  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_FD) != 0 &&
615  (rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_LD) != 0)
616  {
617  //Make sure no error occurred
618  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_ES) == 0)
619  {
620  //Retrieve the length of the frame
621  n = rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_PL;
622  //Limit the number of data to read
624 
625  //Additional options can be passed to the stack along with the packet
626  ancillary = NET_DEFAULT_RX_ANCILLARY;
627 
628  //Pass the packet to the upper layer
629  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
630 
631  //Valid packet received
632  error = NO_ERROR;
633  }
634  else
635  {
636  //The received packet contains an error
637  error = ERROR_INVALID_PACKET;
638  }
639  }
640  else
641  {
642  //The packet is not valid
643  error = ERROR_INVALID_PACKET;
644  }
645 
646  //Set the start address of the buffer
647  rxDmaDesc[rxIndex].rdes0 = adi_rtl_internal_to_system_addr(
648  (uint32_t) rxBuffer[rxIndex], 1);
649 
650  //Give the ownership of the descriptor back to the DMA
652 
653  //Increment index and wrap around if necessary
654  if(++rxIndex >= SC835_ETH_RX_BUFFER_COUNT)
655  {
656  rxIndex = 0;
657  }
658  }
659  else
660  {
661  //No more data in the receive buffer
662  error = ERROR_BUFFER_EMPTY;
663  }
664 
665  //Clear RBU flag to resume processing
666  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_RBU;
667  //Instruct the DMA to poll the receive descriptor list
668  *pREG_EMAC0_DMA0_RXDSC_TLPTR = 0;
669 
670  //Return status code
671  return error;
672 }
673 
674 
675 /**
676  * @brief Configure MAC address filtering
677  * @param[in] interface Underlying network interface
678  * @return Error code
679  **/
680 
682 {
683  uint_t i;
684  uint_t j;
685  uint_t k;
686  uint32_t crc;
687  uint32_t hashTable[8];
688  MacAddr unicastMacAddr[3];
689  MacFilterEntry *entry;
690 
691  //Debug message
692  TRACE_DEBUG("Updating MAC filter...\r\n");
693 
694  //Promiscuous mode?
695  if(interface->promiscuous)
696  {
697  //Pass all incoming frames regardless of their destination address
698  *pREG_EMAC0_MACPKT_FILT = BITM_EMAC_MACPKT_FILT_PR;
699  }
700  else
701  {
702  //Set the MAC address of the station
703  *pREG_EMAC0_ADDR0_LO = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
704  *pREG_EMAC0_ADDR0_HI = interface->macAddr.w[2];
705 
706  //The MAC supports 3 additional addresses for unicast perfect filtering
707  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
708  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
709  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
710 
711  //The hash table is used for multicast address filtering
712  hashTable[0] = 0;
713  hashTable[1] = 0;
714  hashTable[2] = 0;
715  hashTable[3] = 0;
716  hashTable[4] = 0;
717  hashTable[5] = 0;
718  hashTable[6] = 0;
719  hashTable[7] = 0;
720 
721  //The MAC address filter contains the list of MAC addresses to accept
722  //when receiving an Ethernet frame
723  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
724  {
725  //Point to the current entry
726  entry = &interface->macAddrFilter[i];
727 
728  //Valid entry?
729  if(entry->refCount > 0)
730  {
731  //Multicast address?
732  if(macIsMulticastAddr(&entry->addr))
733  {
734  //Compute CRC over the current MAC address
735  crc = sc835EthCalcCrc(&entry->addr, sizeof(MacAddr));
736 
737  //The upper 8 bits in the CRC register are used to index the
738  //contents of the hash table
739  k = (crc >> 24) & 0xFF;
740 
741  //Update hash table contents
742  hashTable[k / 32] |= (1 << (k % 32));
743  }
744  else
745  {
746  //Up to 3 additional MAC addresses can be specified
747  if(j < 3)
748  {
749  //Save the unicast address
750  unicastMacAddr[j++] = entry->addr;
751  }
752  }
753  }
754  }
755 
756  //Configure the first unicast address filter
757  if(j >= 1)
758  {
759  //When the AE bit is set, the entry is used for perfect filtering
760  *pREG_EMAC0_ADDR1_LO = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
761  *pREG_EMAC0_ADDR1_HI = unicastMacAddr[0].w[2] | BITM_EMAC_ADDR_HI_AE;
762  }
763  else
764  {
765  //When the AE bit is cleared, the entry is ignored
766  *pREG_EMAC0_ADDR1_LO = 0;
767  *pREG_EMAC0_ADDR1_HI = 0;
768  }
769 
770  //Configure the second unicast address filter
771  if(j >= 2)
772  {
773  //When the AE bit is set, the entry is used for perfect filtering
774  *pREG_EMAC0_ADDR2_LO = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
775  *pREG_EMAC0_ADDR2_HI = unicastMacAddr[1].w[2] | BITM_EMAC_ADDR_HI_AE;
776  }
777  else
778  {
779  //When the AE bit is cleared, the entry is ignored
780  *pREG_EMAC0_ADDR2_LO = 0;
781  *pREG_EMAC0_ADDR2_HI = 0;
782  }
783 
784  //Configure the third unicast address filter
785  if(j >= 3)
786  {
787  //When the AE bit is set, the entry is used for perfect filtering
788  *pREG_EMAC0_ADDR3_LO = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
789  *pREG_EMAC0_ADDR3_HI = unicastMacAddr[2].w[2] | BITM_EMAC_ADDR_HI_AE;
790  }
791  else
792  {
793  //When the AE bit is cleared, the entry is ignored
794  *pREG_EMAC0_ADDR3_LO = 0;
795  *pREG_EMAC0_ADDR3_HI = 0;
796  }
797 
798  //Check whether frames with a multicast destination address should be
799  //accepted
800  if(interface->acceptAllMulticast)
801  {
802  //Configure the receive filter
803  *pREG_EMAC0_MACPKT_FILT = BITM_EMAC_MACPKT_FILT_HPF | BITM_EMAC_MACPKT_FILT_PM;
804  }
805  else
806  {
807  //Configure the receive filter
808  *pREG_EMAC0_MACPKT_FILT = BITM_EMAC_MACPKT_FILT_HPF | BITM_EMAC_MACPKT_FILT_HMC;
809 
810  //Configure the multicast hash table
811  *pREG_EMAC0_HASHTBL_REG0 = hashTable[0];
812  *pREG_EMAC0_HASHTBL_REG1 = hashTable[1];
813  *pREG_EMAC0_HASHTBL_REG2 = hashTable[2];
814  *pREG_EMAC0_HASHTBL_REG3 = hashTable[3];
815  *pREG_EMAC0_HASHTBL_REG4 = hashTable[4];
816  *pREG_EMAC0_HASHTBL_REG5 = hashTable[5];
817  *pREG_EMAC0_HASHTBL_REG6 = hashTable[6];
818  *pREG_EMAC0_HASHTBL_REG7 = hashTable[7];
819 
820  //Debug message
821  TRACE_DEBUG(" EMAC_HASHTBL_REG0 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG0);
822  TRACE_DEBUG(" EMAC_HASHTBL_REG1 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG1);
823  TRACE_DEBUG(" EMAC_HASHTBL_REG2 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG2);
824  TRACE_DEBUG(" EMAC_HASHTBL_REG3 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG3);
825  TRACE_DEBUG(" EMAC_HASHTBL_REG4 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG4);
826  TRACE_DEBUG(" EMAC_HASHTBL_REG5 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG5);
827  TRACE_DEBUG(" EMAC_HASHTBL_REG6 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG6);
828  TRACE_DEBUG(" EMAC_HASHTBL_REG7 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG7);
829  }
830  }
831 
832  //Successful processing
833  return NO_ERROR;
834 }
835 
836 
837 /**
838  * @brief Adjust MAC configuration parameters for proper operation
839  * @param[in] interface Underlying network interface
840  * @return Error code
841  **/
842 
844 {
845  uint32_t config;
846 
847  //Read current MAC configuration
848  config = *pREG_EMAC0_MAC_CFG;
849 
850  //1000BASE-T operation mode?
851  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
852  {
853  config &= ~BITM_EMAC_MAC_CFG_PS;
854  config &= ~BITM_EMAC_MAC_CFG_FES;
855  }
856  //100BASE-TX operation mode?
857  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
858  {
859  config |= BITM_EMAC_MAC_CFG_PS;
860  config |= BITM_EMAC_MAC_CFG_FES;
861  }
862  //10BASE-T operation mode?
863  else
864  {
865  config |= BITM_EMAC_MAC_CFG_PS;
866  config &= ~BITM_EMAC_MAC_CFG_FES;
867  }
868 
869  //Half-duplex or full-duplex mode?
870  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
871  {
872  config |= BITM_EMAC_MAC_CFG_DM;
873  }
874  else
875  {
876  config &= ~BITM_EMAC_MAC_CFG_DM;
877  }
878 
879  //Update MAC configuration register
880  *pREG_EMAC0_MAC_CFG = config;
881 
882  //Successful processing
883  return NO_ERROR;
884 }
885 
886 
887 /**
888  * @brief Write PHY register
889  * @param[in] opcode Access type (2 bits)
890  * @param[in] phyAddr PHY address (5 bits)
891  * @param[in] regAddr Register address (5 bits)
892  * @param[in] data Register value
893  **/
894 
895 void sc835EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
896  uint8_t regAddr, uint16_t data)
897 {
898  uint32_t temp;
899 
900  //Valid opcode?
901  if(opcode == SMI_OPCODE_WRITE)
902  {
903  //Take care not to alter MDC clock configuration
904  temp = *pREG_EMAC0_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_CR;
905  //Set up a write operation
906  temp |= BITM_EMAC_MDIO_ADDR_GOC_0 | BITM_EMAC_MDIO_ADDR_GB;
907  //PHY address
908  temp |= (phyAddr << BITP_EMAC_MDIO_ADDR_PA) & BITM_EMAC_MDIO_ADDR_PA;
909  //Register address
910  temp |= (regAddr << BITP_EMAC_MDIO_ADDR_RDA) & BITM_EMAC_MDIO_ADDR_RDA;
911 
912  //Data to be written in the PHY register
913  *pREG_EMAC0_MDIO_DATA = data & BITM_EMAC_MDIO_DATA_GD;
914 
915  //Start a write operation
916  *pREG_EMAC0_MDIO_ADDR = temp;
917  //Wait for the write to complete
918  while((*pREG_EMAC0_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_GB) != 0)
919  {
920  }
921  }
922  else
923  {
924  //The MAC peripheral only supports standard Clause 22 opcodes
925  }
926 }
927 
928 
929 /**
930  * @brief Read PHY register
931  * @param[in] opcode Access type (2 bits)
932  * @param[in] phyAddr PHY address (5 bits)
933  * @param[in] regAddr Register address (5 bits)
934  * @return Register value
935  **/
936 
937 uint16_t sc835EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
938  uint8_t regAddr)
939 {
940  uint16_t data;
941  uint32_t temp;
942 
943  //Valid opcode?
944  if(opcode == SMI_OPCODE_READ)
945  {
946  //Take care not to alter MDC clock configuration
947  temp = *pREG_EMAC0_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_CR;
948 
949  //Set up a read operation
950  temp |= BITM_EMAC_MDIO_ADDR_GOC_1 | BITM_EMAC_MDIO_ADDR_GOC_0 |
951  BITM_EMAC_MDIO_ADDR_GB;
952 
953  //PHY address
954  temp |= (phyAddr << BITP_EMAC_MDIO_ADDR_PA) & BITM_EMAC_MDIO_ADDR_PA;
955  //Register address
956  temp |= (regAddr << BITP_EMAC_MDIO_ADDR_RDA) & BITM_EMAC_MDIO_ADDR_RDA;
957 
958  //Start a read operation
959  *pREG_EMAC0_MDIO_ADDR = temp;
960  //Wait for the read to complete
961  while((*pREG_EMAC0_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_GB) != 0)
962  {
963  }
964 
965  //Get register value
966  data = *pREG_EMAC0_MDIO_DATA & BITM_EMAC_MDIO_DATA_GD;
967  }
968  else
969  {
970  //The MAC peripheral only supports standard Clause 22 opcodes
971  data = 0;
972  }
973 
974  //Return the value of the PHY register
975  return data;
976 }
977 
978 
979 /**
980  * @brief CRC calculation
981  * @param[in] data Pointer to the data over which to calculate the CRC
982  * @param[in] length Number of bytes to process
983  * @return Resulting CRC value
984  **/
985 
986 uint32_t sc835EthCalcCrc(const void *data, size_t length)
987 {
988  uint_t i;
989  uint_t j;
990  uint32_t crc;
991  const uint8_t *p;
992 
993  //Point to the data over which to calculate the CRC
994  p = (uint8_t *) data;
995  //CRC preset value
996  crc = 0xFFFFFFFF;
997 
998  //Loop through data
999  for(i = 0; i < length; i++)
1000  {
1001  //The message is processed bit by bit
1002  for(j = 0; j < 8; j++)
1003  {
1004  //Update CRC value
1005  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
1006  {
1007  crc = (crc << 1) ^ 0x04C11DB7;
1008  }
1009  else
1010  {
1011  crc = crc << 1;
1012  }
1013  }
1014  }
1015 
1016  //Return CRC value
1017  return ~crc;
1018 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
error_t sc835EthInit(NetInterface *interface)
ADSP-SC835 Ethernet MAC initialization.
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#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
error_t sc835EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
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
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#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
void sc835EthTick(NetInterface *interface)
ADSP-SC835 Ethernet MAC timer handler.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
void sc835EthEnableIrq(NetInterface *interface)
Enable interrupts.
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
__weak_func void sc835EthResetPhy(NetInterface *interface)
Reset PHY transceiver.
uint16_t sc835EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define FALSE
Definition: os_port.h:46
#define SC835_ETH_RX_BUFFER_COUNT
#define EMAC_TDES2_HL_B1L
void sc835EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
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
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
#define SC835_ETH_TX_BUFFER_COUNT
MacAddr addr
MAC address.
Definition: ethernet.h:265
#define SC835_ETH_TX_BUFFER_SIZE
@ 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
#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
Receive descriptor.
#define rxBuffer
MacAddr
Definition: ethernet.h:197
__weak_func void sc835EthInitGpio(NetInterface *interface)
GPIO configuration.
#define SC835_ETH_RX_BUFFER_SIZE
#define EMAC_RDES3_FD
ADSP-SC835 Ethernet MAC driver.
#define TRACE_DEBUG(...)
Definition: debug.h:119
void sc835EthDisableIrq(NetInterface *interface)
Disable interrupts.
#define EMAC_TDES2_IOC
void sc835EthEventHandler(NetInterface *interface)
ADSP-SC835 Ethernet MAC event handler.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:264
const NicDriver sc835EthDriver
ADSP-SC835 Ethernet MAC driver.
#define osEnterIsr()
void sc835EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
Transmit descriptor.
#define SC835_ETH_RAM_SECTION
uint32_t sc835EthCalcCrc(const void *data, size_t length)
CRC calculation.
#define EMAC_RDES3_LD
#define EMAC_RDES3_IOC
#define EMAC_RDES3_OWN
#define rxDmaDesc
void sc835EthIrqHandler(uint32_t id, void *param)
ADSP-SC835 Ethernet MAC interrupt service routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t sc835EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
error_t sc835EthReceivePacket(NetInterface *interface)
Receive a packet.
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:57
error_t sc835EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
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