lan9370_driver.c
Go to the documentation of this file.
1 /**
2  * @file lan9370_driver.c
3  * @brief LAN9370 5-port 100Base-T1 Ethernet switch 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 "core/net.h"
36 #include "core/ethernet_misc.h"
38 #include "debug.h"
39 
40 
41 /**
42  * @brief LAN9370 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to LAN9370)
75  **/
76 
77 const uint16_t lan9370IngressTailTag[5] =
78 {
88 };
89 
90 
91 /**
92  * @brief LAN9370 Ethernet switch initialization
93  * @param[in] interface Underlying network interface
94  * @return Error code
95  **/
96 
98 {
99  uint_t port;
100  uint16_t temp;
101 
102  //Debug message
103  TRACE_INFO("Initializing LAN9370...\r\n");
104 
105  //SPI slave mode?
106  if(interface->spiDriver != NULL)
107  {
108  //Initialize SPI interface
109  interface->spiDriver->init();
110 
111  //Wait for the serial interface to be ready
112  do
113  {
114  //Read CHIP_ID1 register
115  temp = lan9370ReadSwitchReg8(interface, LAN9370_GLB_CHID1);
116 
117  //The returned data is invalid until the serial interface is ready
118  } while(temp != LAN9370_GLB_CHID1_DEFAULT);
119 
120  //Enable indirect access from SPI to the VPHY registers
121  temp = lan9370ReadSwitchReg8(interface, LAN9370_GLB_CTL0);
123  lan9370WriteSwitchReg8(interface, LAN9370_GLB_CTL0, temp);
124 
128 
129 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
130  //Enable tail tag feature
131  temp = lan9370ReadSwitchReg8(interface, LAN9370_PORT5_OP_CTL0);
134 
135  //Disable frame length check
139 #else
140  //Disable tail tag feature
141  temp = lan9370ReadSwitchReg8(interface, LAN9370_PORT5_OP_CTL0);
144 
145  //Enable frame length check
146  temp = lan9370ReadSwitchReg8(interface, LAN9370_PORT5_MAC_CTRL0);
147  temp |= LAN9370_PORTn_MAC_CTRL0_FRAME_LEN_CHECK_EN;
148  lan9370WriteSwitchReg8(interface, LAN9370_PORT5_MAC_CTRL0, temp);
149 #endif
150 
151  //Loop through the ports
153  {
154 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
155  //Port separation mode?
156  if(interface->port != 0)
157  {
158  //Disable packet transmission and address learning
160  }
161  else
162 #endif
163  {
164  //Enable transmission, reception and address learning
166  }
167  }
168 
169  //Restore default age count
174 
175  //Restore default age period
178 
181 
182  //Add internal delay to ingress and egress RGMII clocks
187 
188  //Start switch operation
191  }
192  else if(interface->smiDriver != NULL)
193  {
194  //Initialize serial management interface
195  interface->smiDriver->init();
196  }
197  else
198  {
199  //Just for sanity
200  }
201 
202  //Loop through the ports
204  {
205  //Debug message
206  TRACE_DEBUG("Port %u:\r\n", port);
207  //Dump PHY registers for debugging purpose
208  lan9370DumpPhyReg(interface, port);
209  }
210 
211  //Perform custom configuration
212  lan9370InitHook(interface);
213 
214  //Force the TCP/IP stack to poll the link state at startup
215  interface->phyEvent = TRUE;
216  //Notify the TCP/IP stack of the event
217  osSetEvent(&interface->netContext->event);
218 
219  //Successful initialization
220  return NO_ERROR;
221 }
222 
223 
224 /**
225  * @brief LAN9370 custom configuration
226  * @param[in] interface Underlying network interface
227  **/
228 
229 __weak_func void lan9370InitHook(NetInterface *interface)
230 {
231 }
232 
233 
234 /**
235  * @brief LAN9370 timer handler
236  * @param[in] interface Underlying network interface
237  **/
238 
239 __weak_func void lan9370Tick(NetInterface *interface)
240 {
241  uint_t port;
242  bool_t linkState;
243 
244 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
245  //Port separation mode?
246  if(interface->port != 0)
247  {
248  uint_t i;
249  NetContext *context;
250  NetInterface *virtualInterface;
251 
252  //Point to the TCP/IP stack context
253  context = interface->netContext;
254 
255  //Loop through network interfaces
256  for(i = 0; i < context->numInterfaces; i++)
257  {
258  //Point to the current interface
259  virtualInterface = &context->interfaces[i];
260 
261  //Check whether the current virtual interface is attached to the
262  //physical interface
263  if(virtualInterface == interface ||
264  virtualInterface->parent == interface)
265  {
266  //Retrieve current link state
267  linkState = lan9370GetLinkState(interface, virtualInterface->port);
268 
269  //Link up or link down event?
270  if(linkState != virtualInterface->linkState)
271  {
272  //Set event flag
273  interface->phyEvent = TRUE;
274  //Notify the TCP/IP stack of the event
275  osSetEvent(&interface->netContext->event);
276  }
277  }
278  }
279  }
280  else
281 #endif
282  {
283  //Initialize link state
284  linkState = FALSE;
285 
286  //Loop through the ports
288  {
289  //Retrieve current link state
290  if(lan9370GetLinkState(interface, port))
291  {
292  linkState = TRUE;
293  }
294  }
295 
296  //Link up or link down event?
297  if(linkState != interface->linkState)
298  {
299  //Set event flag
300  interface->phyEvent = TRUE;
301  //Notify the TCP/IP stack of the event
302  osSetEvent(&interface->netContext->event);
303  }
304  }
305 }
306 
307 
308 /**
309  * @brief Enable interrupts
310  * @param[in] interface Underlying network interface
311  **/
312 
314 {
315 }
316 
317 
318 /**
319  * @brief Disable interrupts
320  * @param[in] interface Underlying network interface
321  **/
322 
324 {
325 }
326 
327 
328 /**
329  * @brief LAN9370 event handler
330  * @param[in] interface Underlying network interface
331  **/
332 
333 __weak_func void lan9370EventHandler(NetInterface *interface)
334 {
335  uint_t port;
336  bool_t linkState;
337 
338 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
339  //Port separation mode?
340  if(interface->port != 0)
341  {
342  uint_t i;
343  NetContext *context;
344  NetInterface *virtualInterface;
345 
346  //Point to the TCP/IP stack context
347  context = interface->netContext;
348 
349  //Loop through network interfaces
350  for(i = 0; i < context->numInterfaces; i++)
351  {
352  //Point to the current interface
353  virtualInterface = &context->interfaces[i];
354 
355  //Check whether the current virtual interface is attached to the
356  //physical interface
357  if(virtualInterface == interface ||
358  virtualInterface->parent == interface)
359  {
360  //Get the port number associated with the current interface
361  port = virtualInterface->port;
362 
363  //Valid port?
364  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
365  {
366  //Retrieve current link state
367  linkState = lan9370GetLinkState(interface, port);
368 
369  //Link up event?
370  if(linkState && !virtualInterface->linkState)
371  {
372  //Retrieve host interface speed
373  interface->linkSpeed = lan9370GetLinkSpeed(interface,
374  LAN9370_PORT5);
375 
376  //Retrieve host interface duplex mode
377  interface->duplexMode = lan9370GetDuplexMode(interface,
378  LAN9370_PORT5);
379 
380  //Adjust MAC configuration parameters for proper operation
381  interface->nicDriver->updateMacConfig(interface);
382 
383  //Check current speed
384  virtualInterface->linkSpeed = lan9370GetLinkSpeed(interface,
385  port);
386 
387  //Check current duplex mode
388  virtualInterface->duplexMode = lan9370GetDuplexMode(interface,
389  port);
390 
391  //Update link state
392  virtualInterface->linkState = TRUE;
393 
394  //Process link state change event
395  nicNotifyLinkChange(virtualInterface);
396  }
397  //Link down event
398  else if(!linkState && virtualInterface->linkState)
399  {
400  //Update link state
401  virtualInterface->linkState = FALSE;
402 
403  //Process link state change event
404  nicNotifyLinkChange(virtualInterface);
405  }
406  }
407  }
408  }
409  }
410  else
411 #endif
412  {
413  //Initialize link state
414  linkState = FALSE;
415 
416  //Loop through the ports
418  {
419  //Retrieve current link state
420  if(lan9370GetLinkState(interface, port))
421  {
422  linkState = TRUE;
423  }
424  }
425 
426  //Link up event?
427  if(linkState)
428  {
429  //Retrieve host interface speed
430  interface->linkSpeed = lan9370GetLinkSpeed(interface, LAN9370_PORT5);
431  //Retrieve host interface duplex mode
432  interface->duplexMode = lan9370GetDuplexMode(interface, LAN9370_PORT5);
433 
434  //Adjust MAC configuration parameters for proper operation
435  interface->nicDriver->updateMacConfig(interface);
436 
437  //Update link state
438  interface->linkState = TRUE;
439  }
440  else
441  {
442  //Update link state
443  interface->linkState = FALSE;
444  }
445 
446  //Process link state change event
447  nicNotifyLinkChange(interface);
448  }
449 }
450 
451 
452 /**
453  * @brief Add tail tag to Ethernet frame
454  * @param[in] interface Underlying network interface
455  * @param[in] buffer Multi-part buffer containing the payload
456  * @param[in,out] offset Offset to the first payload byte
457  * @param[in] ancillary Additional options passed to the stack along with
458  * the packet
459  * @return Error code
460  **/
461 
463  size_t *offset, NetTxAncillary *ancillary)
464 {
465  error_t error;
466 
467  //Initialize status code
468  error = NO_ERROR;
469 
470 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
471  //SPI slave mode?
472  if(interface->spiDriver != NULL)
473  {
474  //Valid port?
475  if(ancillary->port <= LAN9370_PORT5)
476  {
477  size_t length;
478  const uint16_t *tailTag;
479 
480  //The two-byte tail tagging is used to indicate the destination port
481  tailTag = &lan9370IngressTailTag[ancillary->port];
482 
483  //Retrieve the length of the Ethernet frame
484  length = netBufferGetLength(buffer) - *offset;
485 
486  //The host controller should manually add padding to the packet before
487  //inserting the tail tag
488  error = ethPadFrame(buffer, &length);
489 
490  //Check status code
491  if(!error)
492  {
493  //The tail tag is inserted at the end of the packet, just before
494  //the CRC
495  error = netBufferAppend(buffer, tailTag, sizeof(uint16_t));
496  }
497  }
498  else
499  {
500  //The port number is not valid
501  error = ERROR_INVALID_PORT;
502  }
503  }
504 #endif
505 
506  //Return status code
507  return error;
508 }
509 
510 
511 /**
512  * @brief Decode tail tag from incoming Ethernet frame
513  * @param[in] interface Underlying network interface
514  * @param[in,out] frame Pointer to the received Ethernet frame
515  * @param[in,out] length Length of the frame, in bytes
516  * @param[in,out] ancillary Additional options passed to the stack along with
517  * the packet
518  * @return Error code
519  **/
520 
521 error_t lan9370UntagFrame(NetInterface *interface, uint8_t **frame,
522  size_t *length, NetRxAncillary *ancillary)
523 {
524  error_t error;
525 
526  //Initialize status code
527  error = NO_ERROR;
528 
529 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
530  //SPI slave mode?
531  if(interface->spiDriver != NULL)
532  {
533  //Valid Ethernet frame received?
534  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
535  {
536  uint8_t *tailTag;
537 
538  //The tail tag is inserted at the end of the packet, just before
539  //the CRC
540  tailTag = *frame + *length - sizeof(uint8_t);
541 
542  //The one byte tail tagging is used to indicate the source port
543  ancillary->port = (*tailTag & LAN9370_TAIL_TAG_SRC_PORT) + 1;
544 
545  //Strip tail tag from Ethernet frame
546  *length -= sizeof(uint8_t);
547  }
548  else
549  {
550  //Drop the received frame
551  error = ERROR_INVALID_LENGTH;
552  }
553  }
554  else
555  {
556  //Tail tagging mode cannot be enabled through MDC/MDIO interface
557  ancillary->port = 0;
558  }
559 #endif
560 
561  //Return status code
562  return error;
563 }
564 
565 
566 /**
567  * @brief Get link state
568  * @param[in] interface Underlying network interface
569  * @param[in] port Port number
570  * @return Link state
571  **/
572 
574 {
575  uint16_t value;
576  bool_t linkState;
577 
578  //Check port number
579  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
580  {
581  //Any link failure condition is latched in the status register. Reading
582  //the register twice will always return the actual link status
585 
586  //Retrieve current link state
587  linkState = (value & LAN9370_BASIC_STATUS_LINK_STATUS) ? TRUE : FALSE;
588  }
589  else
590  {
591  //The specified port number is not valid
592  linkState = FALSE;
593  }
594 
595  //Return link status
596  return linkState;
597 }
598 
599 
600 /**
601  * @brief Get link speed
602  * @param[in] interface Underlying network interface
603  * @param[in] port Port number
604  * @return Link speed
605  **/
606 
607 uint32_t lan9370GetLinkSpeed(NetInterface *interface, uint8_t port)
608 {
609  uint8_t type;
610  uint16_t value;
611  uint32_t linkSpeed;
612 
613  //Check port number
614  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
615  {
616  //The PHY is only able to operate in 100 Mbps mode
617  linkSpeed = NIC_LINK_SPEED_100MBPS;
618  }
619  else if(port == LAN9370_PORT5)
620  {
621  //SPI slave mode?
622  if(interface->spiDriver != NULL)
623  {
624  //Read port 5 XMII control 1 register
626 
627  //Retrieve host interface type
629 
630  //Gigabit interface?
633  {
634  //1000 Mb/s mode
635  linkSpeed = NIC_LINK_SPEED_1GBPS;
636  }
637  else
638  {
639  //Read port 5 XMII control 0 register
641 
642  //Retrieve host interface speed
644  {
645  //100 Mb/s mode
646  linkSpeed = NIC_LINK_SPEED_100MBPS;
647  }
648  else
649  {
650  //10 Mb/s mode
651  linkSpeed = NIC_LINK_SPEED_10MBPS;
652  }
653  }
654  }
655  else
656  {
657  //The MDC/MDIO interface does not have access to all the configuration
658  //registers. It can only access the standard MIIM registers
659  linkSpeed = NIC_LINK_SPEED_100MBPS;
660  }
661  }
662  else
663  {
664  //The specified port number is not valid
665  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
666  }
667 
668  //Return link speed
669  return linkSpeed;
670 }
671 
672 
673 /**
674  * @brief Get duplex mode
675  * @param[in] interface Underlying network interface
676  * @param[in] port Port number
677  * @return Duplex mode
678  **/
679 
681 {
682  uint16_t value;
683  NicDuplexMode duplexMode;
684 
685  //Check port number
686  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
687  {
688  //The PHY is only able to operate in full duplex mode
689  duplexMode = NIC_FULL_DUPLEX_MODE;
690  }
691  else if(port == LAN9370_PORT5)
692  {
693  //SPI slave mode?
694  if(interface->spiDriver != NULL)
695  {
696  //Read port 5 XMII control 0 register
698 
699  //Retrieve host interface duplex mode
701  {
702  duplexMode = NIC_FULL_DUPLEX_MODE;
703  }
704  else
705  {
706  duplexMode = NIC_HALF_DUPLEX_MODE;
707  }
708  }
709  else
710  {
711  //The MDC/MDIO interface does not have access to all the configuration
712  //registers. It can only access the standard MIIM registers
713  duplexMode = NIC_FULL_DUPLEX_MODE;
714  }
715  }
716  else
717  {
718  //The specified port number is not valid
719  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
720  }
721 
722  //Return duplex mode
723  return duplexMode;
724 }
725 
726 
727 /**
728  * @brief Set port state
729  * @param[in] interface Underlying network interface
730  * @param[in] port Port number
731  * @param[in] state Port state
732  **/
733 
734 void lan9370SetPortState(NetInterface *interface, uint8_t port,
735  SwitchPortState state)
736 {
737  uint8_t temp;
738 
739  //Check port number
740  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
741  {
742  //Read MSTP state register
743  temp = lan9370ReadSwitchReg8(interface,
745 
746  //Update port state
747  switch(state)
748  {
749  //Listening state
754  break;
755 
756  //Learning state
761  break;
762 
763  //Forwarding state
768  break;
769 
770  //Disabled state
771  default:
775  break;
776  }
777 
778  //Write the value back to MSTP state register
780  temp);
781  }
782 }
783 
784 
785 /**
786  * @brief Get port state
787  * @param[in] interface Underlying network interface
788  * @param[in] port Port number
789  * @return Port state
790  **/
791 
793 {
794  uint8_t temp;
795  SwitchPortState state;
796 
797  //Check port number
798  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
799  {
800  //Read MSTP state register
801  temp = lan9370ReadSwitchReg8(interface,
803 
804  //Check port state
805  if((temp & LAN9370_PORTn_LUE_MSTP_STATE_TRANSMIT_EN) == 0 &&
808  {
809  //Disabled state
811  }
812  else if((temp & LAN9370_PORTn_LUE_MSTP_STATE_TRANSMIT_EN) == 0 &&
815  {
816  //Listening state
818  }
819  else if((temp & LAN9370_PORTn_LUE_MSTP_STATE_TRANSMIT_EN) == 0 &&
822  {
823  //Learning state
825  }
826  else if((temp & LAN9370_PORTn_LUE_MSTP_STATE_TRANSMIT_EN) != 0 &&
829  {
830  //Forwarding state
832  }
833  else
834  {
835  //Unknown state
837  }
838  }
839  else
840  {
841  //The specified port number is not valid
843  }
844 
845  //Return port state
846  return state;
847 }
848 
849 
850 /**
851  * @brief Set aging time for dynamic filtering entries
852  * @param[in] interface Underlying network interface
853  * @param[in] agingTime Aging time, in seconds
854  **/
855 
856 void lan9370SetAgingTime(NetInterface *interface, uint32_t agingTime)
857 {
858  //The Age Period in combination with the Age Count field determines the
859  //aging time of dynamic entries in the address lookup table
860  agingTime = (agingTime + 3) / 4;
861 
862  //The full Age Period has 20 bits
863  agingTime = MIN(agingTime, 0xFFFFF);
864 
865  //Write the lower 8 bits
868 
869  //Write the upper 12 bits
871  (agingTime >> 8) & LAN9370_GLB_SW_LUE_AGE_AGE_PERIOD_19_8);
872 }
873 
874 
875 /**
876  * @brief Enable IGMP snooping
877  * @param[in] interface Underlying network interface
878  * @param[in] enable Enable or disable IGMP snooping
879  **/
880 
882 {
883  uint8_t temp;
884 
885  //Read the Global Port Mirroring and Snooping Control register
887 
888  //Enable or disable IGMP snooping
889  if(enable)
890  {
892  }
893  else
894  {
896  }
897 
898  //Write the value back to Global Port Mirroring and Snooping Control register
900 }
901 
902 
903 /**
904  * @brief Enable MLD snooping
905  * @param[in] interface Underlying network interface
906  * @param[in] enable Enable or disable MLD snooping
907  **/
908 
910 {
911  uint8_t temp;
912 
913  //Read the Global Port Mirroring and Snooping Control register
915 
916  //Enable or disable MLD snooping
917  if(enable)
918  {
920  }
921  else
922  {
924  }
925 
926  //Write the value back to Global Port Mirroring and Snooping Control register
928 }
929 
930 
931 /**
932  * @brief Enable reserved multicast table
933  * @param[in] interface Underlying network interface
934  * @param[in] enable Enable or disable reserved group addresses
935  **/
936 
938 {
939  uint8_t temp;
940 
941  //Read the Switch Lookup Engine Control 0 register
943 
944  //Enable or disable the reserved multicast table
945  if(enable)
946  {
948  }
949  else
950  {
952  }
953 
954  //Write the value back to Switch Lookup Engine Control 0 register
956 }
957 
958 
959 /**
960  * @brief Add a new entry to the static MAC table
961  * @param[in] interface Underlying network interface
962  * @param[in] entry Pointer to the forwarding database entry
963  * @return Error code
964  **/
965 
967  const SwitchFdbEntry *entry)
968 {
969  error_t error;
970  uint_t i;
971  uint_t j;
972  uint32_t value;
973  SwitchFdbEntry currentEntry;
974 
975  //Keep track of the first free entry
977 
978  //Loop through the static MAC table
979  for(i = 0; i < LAN9370_STATIC_MAC_TABLE_SIZE; i++)
980  {
981  //Read current entry
982  error = lan9370GetStaticFdbEntry(interface, i, &currentEntry);
983 
984  //Valid entry?
985  if(!error)
986  {
987  //Check whether the table already contains the specified MAC address
988  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
989  {
990  j = i;
991  break;
992  }
993  }
994  else
995  {
996  //Keep track of the first free entry
998  {
999  j = i;
1000  }
1001  }
1002  }
1003 
1004  //Any entry available?
1006  {
1007  //Write the Static Address Table Entry 1 register
1010 
1011  //Set the relevant forward ports
1012  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1013  {
1015  }
1016  else
1017  {
1018  value = entry->destPorts & LAN9370_PORT_MASK;
1019  }
1020 
1021  //Enable overriding of port state
1022  if(entry->override)
1023  {
1025  }
1026 
1027  //Write the Static Address Table Entry 2 register
1029 
1030  //Copy MAC address (first 16 bits)
1031  value = (entry->macAddr.b[0] << 8) | entry->macAddr.b[1];
1032 
1033  //Write the Static Address Table Entry 3 register
1035 
1036  //Copy MAC address (last 32 bits)
1037  value = (entry->macAddr.b[2] << 24) | (entry->macAddr.b[3] << 16) |
1038  (entry->macAddr.b[4] << 8) | entry->macAddr.b[5];
1039 
1040  //Write the Static Address Table Entry 4 register
1042 
1043  //Setup a write operation
1047 
1048  //Write the TABLE_INDEX field with the 8-bit index value
1050 
1051  //Start the write operation
1053  value);
1054 
1055  //When the operation is complete, the START_FINISH bit will be cleared
1056  //automatically
1057  do
1058  {
1059  //Read the Static Address and Reserved Multicast Table Control register
1060  value = lan9370ReadSwitchReg32(interface,
1062 
1063  //Poll the START_FINISH bit
1065 
1066  //Successful processing
1067  error = NO_ERROR;
1068  }
1069  else
1070  {
1071  //The static MAC table is full
1072  error = ERROR_TABLE_FULL;
1073  }
1074 
1075  //Return status code
1076  return error;
1077 }
1078 
1079 
1080 /**
1081  * @brief Remove an entry from the static MAC table
1082  * @param[in] interface Underlying network interface
1083  * @param[in] entry Forwarding database entry to remove from the table
1084  * @return Error code
1085  **/
1086 
1088  const SwitchFdbEntry *entry)
1089 {
1090  error_t error;
1091  uint_t j;
1092  uint32_t value;
1093  SwitchFdbEntry currentEntry;
1094 
1095  //Loop through the static MAC table
1096  for(j = 0; j < LAN9370_STATIC_MAC_TABLE_SIZE; j++)
1097  {
1098  //Read current entry
1099  error = lan9370GetStaticFdbEntry(interface, j, &currentEntry);
1100 
1101  //Valid entry?
1102  if(!error)
1103  {
1104  //Check whether the table contains the specified MAC address
1105  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1106  {
1107  break;
1108  }
1109  }
1110  }
1111 
1112  //Any matching entry?
1114  {
1115  //Clear Static Address Table Entry registers
1120 
1121  //Setup a write operation
1125 
1126  //Write the TABLE_INDEX field with the 8-bit index value
1128 
1129  //Start the write operation
1131  value);
1132 
1133  //When the operation is complete, the START_FINISH bit will be cleared
1134  //automatically
1135  do
1136  {
1137  //Read the Static Address and Reserved Multicast Table Control register
1138  value = lan9370ReadSwitchReg32(interface,
1140 
1141  //Poll the START_FINISH bit
1143 
1144  //Successful processing
1145  error = NO_ERROR;
1146  }
1147  else
1148  {
1149  //The static MAC table does not contain the specified address
1150  error = ERROR_NOT_FOUND;
1151  }
1152 
1153  //Return status code
1154  return error;
1155 }
1156 
1157 
1158 /**
1159  * @brief Read an entry from the static MAC table
1160  * @param[in] interface Underlying network interface
1161  * @param[in] index Zero-based index of the entry to read
1162  * @param[out] entry Pointer to the forwarding database entry
1163  * @return Error code
1164  **/
1165 
1167  SwitchFdbEntry *entry)
1168 {
1169  error_t error;
1170  uint32_t value;
1171 
1172  //Check index parameter
1173  if(index < LAN9370_STATIC_MAC_TABLE_SIZE)
1174  {
1175  //Setup a write operation
1180 
1181  //Write the TABLE_INDEX field with the 8-bit index value
1183 
1184  //Start the read operation
1186  value);
1187 
1188  //When the operation is complete, the START_FINISH bit will be cleared
1189  //automatically
1190  do
1191  {
1192  //Read the Static Address and Reserved Multicast Table Control register
1193  value = lan9370ReadSwitchReg32(interface,
1195 
1196  //Poll the START_FINISH bit
1198 
1199  //Read the Static Address Table Entry 1 register
1201 
1202  //Valid entry?
1204  {
1205  //Read the Static Address Table Entry 2 register
1207 
1208  //Retrieve the ports associated with this MAC address
1209  entry->srcPort = 0;
1211 
1212  //Check the value of the OVERRIDE bit
1214  {
1215  entry->override = TRUE;
1216  }
1217  else
1218  {
1219  entry->override = FALSE;
1220  }
1221 
1222  //Read the Static Address Table Entry 3 register
1224 
1225  //Copy MAC address (first 16 bits)
1226  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1227  entry->macAddr.b[1] = value & 0xFF;
1228 
1229  //Read the Static Address Table Entry 4 register
1231 
1232  //Copy MAC address (last 32 bits)
1233  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1234  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1235  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1236  entry->macAddr.b[5] = value & 0xFF;
1237 
1238  //Successful processing
1239  error = NO_ERROR;
1240  }
1241  else
1242  {
1243  //The entry is not valid
1244  error = ERROR_INVALID_ENTRY;
1245  }
1246  }
1247  else
1248  {
1249  //The end of the table has been reached
1250  error = ERROR_END_OF_TABLE;
1251  }
1252 
1253  //Return status code
1254  return error;
1255 }
1256 
1257 
1258 /**
1259  * @brief Flush static MAC table
1260  * @param[in] interface Underlying network interface
1261  **/
1262 
1264 {
1265  uint_t i;
1266  uint32_t value;
1267 
1268  //Loop through the static MAC table
1269  for(i = 0; i < LAN9370_STATIC_MAC_TABLE_SIZE; i++)
1270  {
1271  //Clear Static Address Table Entry registers
1276 
1277  //Setup a write operation
1281 
1282  //Write the TABLE_INDEX field with the 8-bit index value
1284 
1285  //Start the write operation
1287  value);
1288 
1289  //When the operation is complete, the START_FINISH bit will be cleared
1290  //automatically
1291  do
1292  {
1293  //Read the Static Address and Reserved Multicast Table Control register
1294  value = lan9370ReadSwitchReg32(interface,
1296 
1297  //Poll the START_FINISH bit
1299  }
1300 }
1301 
1302 
1303 /**
1304  * @brief Read an entry from the dynamic MAC table
1305  * @param[in] interface Underlying network interface
1306  * @param[in] index Zero-based index of the entry to read
1307  * @param[out] entry Pointer to the forwarding database entry
1308  * @return Error code
1309  **/
1310 
1312  SwitchFdbEntry *entry)
1313 {
1314  error_t error;
1315  uint32_t value;
1316 
1317  //First entry?
1318  if(index == 0)
1319  {
1320  //Clear the ALU Table Access Control register to stop any operation
1322 
1323  //Start the search operation
1327  }
1328 
1329  //Poll the VALID_ENTRY_OR_SEARCH_END bit until it is set
1330  do
1331  {
1332  //Read the ALU Table Access Control register
1334 
1335  //This bit goes high to indicate either a new valid entry is returned or
1336  //the search is complete
1338 
1339  //Check whether the next valid entry is ready
1341  {
1342  //Store the data from the ALU table entry
1343  entry->destPorts = 0;
1344  entry->override = FALSE;
1345 
1346  //Read the ALU Table Entry 1 and 2 registers
1349 
1350  //Retrieve the port associated with this MAC address
1352  {
1354  entry->srcPort = LAN9370_PORT1;
1355  break;
1357  entry->srcPort = LAN9370_PORT2;
1358  break;
1360  entry->srcPort = LAN9370_PORT3;
1361  break;
1363  entry->srcPort = LAN9370_PORT4;
1364  break;
1366  entry->srcPort = LAN9370_PORT5;
1367  break;
1368  default:
1369  entry->srcPort = 0;
1370  break;
1371  }
1372 
1373  //Read the ALU Table Entry 3 register
1375 
1376  //Copy MAC address (first 16 bits)
1377  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1378  entry->macAddr.b[1] = value & 0xFF;
1379 
1380  //Read the ALU Table Entry 4 register
1382 
1383  //Copy MAC address (last 32 bits)
1384  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1385  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1386  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1387  entry->macAddr.b[5] = value & 0xFF;
1388 
1389  //Successful processing
1390  error = NO_ERROR;
1391  }
1392  else
1393  {
1394  //The search can be stopped any time by setting the START_FINISH bit to 0
1396 
1397  //The end of the table has been reached
1398  error = ERROR_END_OF_TABLE;
1399  }
1400 
1401  //Return status code
1402  return error;
1403 }
1404 
1405 
1406 /**
1407  * @brief Flush dynamic MAC table
1408  * @param[in] interface Underlying network interface
1409  * @param[in] port Port number
1410  **/
1411 
1413 {
1414  uint_t temp;
1415  uint8_t state;
1416 
1417  //Flush only dynamic table entries
1422 
1423  //Valid port number?
1424  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT5)
1425  {
1426  //Save the current state of the port
1427  state = lan9370ReadSwitchReg8(interface,
1429 
1430  //Turn off learning capability
1433 
1434  //All the entries associated with a port that has its learning capability
1435  //being turned off will be flushed
1439 
1440  //Restore the original state of the port
1442  state);
1443  }
1444  else
1445  {
1446  //Trigger a flush of the entire address lookup table
1450  }
1451 }
1452 
1453 
1454 /**
1455  * @brief Set forward ports for unknown multicast packets
1456  * @param[in] interface Underlying network interface
1457  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1458  * @param[in] forwardPorts Port map
1459  **/
1460 
1462  bool_t enable, uint32_t forwardPorts)
1463 {
1464  uint32_t temp;
1465 
1466  //Read Unknown Multicast Control register
1468 
1469  //Clear port map
1471 
1472  //Enable or disable forwarding of unknown multicast packets
1473  if(enable)
1474  {
1475  //Enable forwarding
1477 
1478  //Check whether unknown multicast packets should be forwarded to the CPU port
1479  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1480  {
1482  }
1483 
1484  //Select the desired forward ports
1485  temp |= forwardPorts & LAN9370_GLB_SW_LUE_UNK1_FWD_MAP_ALL;
1486  }
1487  else
1488  {
1489  //Disable forwarding
1490  temp &= ~LAN9370_GLB_SW_LUE_UNK1_FWD;
1491  }
1492 
1493  //Write the value back to Unknown Multicast Control register
1495 }
1496 
1497 
1498 /**
1499  * @brief Write PHY register
1500  * @param[in] interface Underlying network interface
1501  * @param[in] port Port number
1502  * @param[in] address PHY register address
1503  * @param[in] data Register value
1504  **/
1505 
1506 void lan9370WritePhyReg(NetInterface *interface, uint8_t port,
1507  uint8_t address, uint16_t data)
1508 {
1509  uint16_t n;
1510 
1511  //SPI slave mode?
1512  if(interface->spiDriver != NULL)
1513  {
1514  //The SPI interface provides access to all PHY registers
1516 
1517  //Set register address
1519  //Set register value
1521 
1522  //Start a write operation
1525 
1526  //Wait for the write to complete
1527  while((lan9370ReadSwitchReg16(interface, LAN9370_IND_CTRL) &
1528  LAN9370_IND_CTRL_BUSY) != 0)
1529  {
1530  }
1531  }
1532  else if(interface->smiDriver != NULL)
1533  {
1534  //Write the specified PHY register
1535  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1536  }
1537  else
1538  {
1539  //Write the specified PHY register
1540  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1541  }
1542 }
1543 
1544 
1545 /**
1546  * @brief Read PHY register
1547  * @param[in] interface Underlying network interface
1548  * @param[in] port Port number
1549  * @param[in] address PHY register address
1550  * @return Register value
1551  **/
1552 
1553 uint16_t lan9370ReadPhyReg(NetInterface *interface, uint8_t port,
1554  uint8_t address)
1555 {
1556  uint16_t n;
1557  uint16_t data;
1558 
1559  //SPI slave mode?
1560  if(interface->spiDriver != NULL)
1561  {
1562  //The SPI interface provides access to all PHY registers
1564 
1565  //Set register address
1567 
1568  //Start a read operation
1571 
1572  //Wait for the read to complete
1573  while((lan9370ReadSwitchReg16(interface, LAN9370_IND_CTRL) &
1574  LAN9370_IND_CTRL_BUSY) != 0)
1575  {
1576  }
1577 
1578  //Read the 16-bit value
1580  }
1581  else if(interface->smiDriver != NULL)
1582  {
1583  //Read the specified PHY register
1584  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1585  }
1586  else
1587  {
1588  //Read the specified PHY register
1589  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1590  }
1591 
1592  //Return register value
1593  return data;
1594 }
1595 
1596 
1597 /**
1598  * @brief Dump PHY registers for debugging purpose
1599  * @param[in] interface Underlying network interface
1600  * @param[in] port Port number
1601  **/
1602 
1603 void lan9370DumpPhyReg(NetInterface *interface, uint8_t port)
1604 {
1605  uint8_t i;
1606 
1607  //Loop through PHY registers
1608  for(i = 0; i < 32; i++)
1609  {
1610  //Display current PHY register
1611  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1612  lan9370ReadPhyReg(interface, port, i));
1613  }
1614 
1615  //Terminate with a line feed
1616  TRACE_DEBUG("\r\n");
1617 }
1618 
1619 
1620 /**
1621  * @brief Write extended register
1622  * @param[in] interface Underlying network interface
1623  * @param[in] port Port number
1624  * @param[in] bank Register bank
1625  * @param[in] addr Register address
1626  * @param[in] data Extended register value
1627  **/
1628 
1629 void lan9370WriteExtReg(NetInterface *interface, uint8_t port, uint8_t bank,
1630  uint8_t addr, uint16_t data)
1631 {
1632  uint16_t temp;
1633 
1634  //Set up a write operation
1636  //Select register bank
1637  temp |= (bank << 8) & LAN9370_EXT_REG_CTL_REGISTER_BANK;
1638  //Select register address
1640 
1641  //Write the EXT_REG_WR_DATA register with the desired 16-bit data
1643 
1644  //Write the EXT_REG_CTL register
1645  lan9370WritePhyReg(interface, port, LAN9370_EXT_REG_CTL, temp);
1646 }
1647 
1648 
1649 /**
1650  * @brief Read extended register
1651  * @param[in] interface Underlying network interface
1652  * @param[in] port Port number
1653  * @param[in] bank Register bank
1654  * @param[in] addr Register address
1655  * @return Extended register value
1656  **/
1657 
1658 uint16_t lan9370ReadExtReg(NetInterface *interface, uint8_t port, uint8_t bank,
1659  uint8_t addr)
1660 {
1661  uint16_t temp;
1662 
1663  //Set up a read operation
1665  //Select register bank
1666  temp |= (bank << 8) & LAN9370_EXT_REG_CTL_REGISTER_BANK;
1667  //Select register address
1669 
1670  //Write the EXT_REG_CTL register
1671  lan9370WritePhyReg(interface, port, LAN9370_EXT_REG_CTL, temp);
1672 
1673  //Read the EXT_REG_RD_DATA register
1674  return lan9370ReadPhyReg(interface, port, LAN9370_EXT_REG_RD_DATA);
1675 }
1676 
1677 
1678 /**
1679  * @brief Write switch register (8 bits)
1680  * @param[in] interface Underlying network interface
1681  * @param[in] address Switch register address
1682  * @param[in] data Register value
1683  **/
1684 
1685 void lan9370WriteSwitchReg8(NetInterface *interface, uint16_t address,
1686  uint8_t data)
1687 {
1688  uint32_t command;
1689 
1690  //SPI slave mode?
1691  if(interface->spiDriver != NULL)
1692  {
1693  //Set up a write operation
1694  command = LAN9370_SPI_CMD_WRITE;
1695  //Set register address
1696  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1697 
1698  //Pull the CS pin low
1699  interface->spiDriver->assertCs();
1700 
1701  //Write 32-bit command
1702  interface->spiDriver->transfer((command >> 24) & 0xFF);
1703  interface->spiDriver->transfer((command >> 16) & 0xFF);
1704  interface->spiDriver->transfer((command >> 8) & 0xFF);
1705  interface->spiDriver->transfer(command & 0xFF);
1706 
1707  //Write 8-bit data
1708  interface->spiDriver->transfer(data);
1709 
1710  //Terminate the operation by raising the CS pin
1711  interface->spiDriver->deassertCs();
1712  }
1713  else
1714  {
1715  //The MDC/MDIO interface does not have access to all the configuration
1716  //registers. It can only access the standard MIIM registers
1717  }
1718 }
1719 
1720 
1721 /**
1722  * @brief Read switch register (8 bits)
1723  * @param[in] interface Underlying network interface
1724  * @param[in] address Switch register address
1725  * @return Register value
1726  **/
1727 
1728 uint8_t lan9370ReadSwitchReg8(NetInterface *interface, uint16_t address)
1729 {
1730  uint8_t data;
1731  uint32_t command;
1732 
1733  //SPI slave mode?
1734  if(interface->spiDriver != NULL)
1735  {
1736  //Set up a read operation
1737  command = LAN9370_SPI_CMD_READ;
1738  //Set register address
1739  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1740 
1741  //Pull the CS pin low
1742  interface->spiDriver->assertCs();
1743 
1744  //Write 32-bit command
1745  interface->spiDriver->transfer((command >> 24) & 0xFF);
1746  interface->spiDriver->transfer((command >> 16) & 0xFF);
1747  interface->spiDriver->transfer((command >> 8) & 0xFF);
1748  interface->spiDriver->transfer(command & 0xFF);
1749 
1750  //Read 8-bit data
1751  data = interface->spiDriver->transfer(0xFF);
1752 
1753  //Terminate the operation by raising the CS pin
1754  interface->spiDriver->deassertCs();
1755  }
1756  else
1757  {
1758  //The MDC/MDIO interface does not have access to all the configuration
1759  //registers. It can only access the standard MIIM registers
1760  data = 0;
1761  }
1762 
1763  //Return register value
1764  return data;
1765 }
1766 
1767 
1768 /**
1769  * @brief Write switch register (16 bits)
1770  * @param[in] interface Underlying network interface
1771  * @param[in] address Switch register address
1772  * @param[in] data Register value
1773  **/
1774 
1776  uint16_t data)
1777 {
1778  uint32_t command;
1779 
1780  //SPI slave mode?
1781  if(interface->spiDriver != NULL)
1782  {
1783  //Set up a write operation
1784  command = LAN9370_SPI_CMD_WRITE;
1785  //Set register address
1786  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1787 
1788  //Pull the CS pin low
1789  interface->spiDriver->assertCs();
1790 
1791  //Write 32-bit command
1792  interface->spiDriver->transfer((command >> 24) & 0xFF);
1793  interface->spiDriver->transfer((command >> 16) & 0xFF);
1794  interface->spiDriver->transfer((command >> 8) & 0xFF);
1795  interface->spiDriver->transfer(command & 0xFF);
1796 
1797  //Write 16-bit data
1798  interface->spiDriver->transfer((data >> 8) & 0xFF);
1799  interface->spiDriver->transfer(data & 0xFF);
1800 
1801  //Terminate the operation by raising the CS pin
1802  interface->spiDriver->deassertCs();
1803  }
1804  else
1805  {
1806  //The MDC/MDIO interface does not have access to all the configuration
1807  //registers. It can only access the standard MIIM registers
1808  }
1809 }
1810 
1811 
1812 /**
1813  * @brief Read switch register (16 bits)
1814  * @param[in] interface Underlying network interface
1815  * @param[in] address Switch register address
1816  * @return Register value
1817  **/
1818 
1819 uint16_t lan9370ReadSwitchReg16(NetInterface *interface, uint16_t address)
1820 {
1821  uint16_t data;
1822  uint32_t command;
1823 
1824  //SPI slave mode?
1825  if(interface->spiDriver != NULL)
1826  {
1827  //Set up a read operation
1828  command = LAN9370_SPI_CMD_READ;
1829  //Set register address
1830  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1831 
1832  //Pull the CS pin low
1833  interface->spiDriver->assertCs();
1834 
1835  //Write 32-bit command
1836  interface->spiDriver->transfer((command >> 24) & 0xFF);
1837  interface->spiDriver->transfer((command >> 16) & 0xFF);
1838  interface->spiDriver->transfer((command >> 8) & 0xFF);
1839  interface->spiDriver->transfer(command & 0xFF);
1840 
1841  //Read 16-bit data
1842  data = interface->spiDriver->transfer(0xFF) << 8;
1843  data |= interface->spiDriver->transfer(0xFF);
1844 
1845  //Terminate the operation by raising the CS pin
1846  interface->spiDriver->deassertCs();
1847  }
1848  else
1849  {
1850  //The MDC/MDIO interface does not have access to all the configuration
1851  //registers. It can only access the standard MIIM registers
1852  data = 0;
1853  }
1854 
1855  //Return register value
1856  return data;
1857 }
1858 
1859 
1860 /**
1861  * @brief Write switch register (32 bits)
1862  * @param[in] interface Underlying network interface
1863  * @param[in] address Switch register address
1864  * @param[in] data Register value
1865  **/
1866 
1868  uint32_t data)
1869 {
1870  uint32_t command;
1871 
1872  //SPI slave mode?
1873  if(interface->spiDriver != NULL)
1874  {
1875  //Set up a write operation
1876  command = LAN9370_SPI_CMD_WRITE;
1877  //Set register address
1878  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1879 
1880  //Pull the CS pin low
1881  interface->spiDriver->assertCs();
1882 
1883  //Write 32-bit command
1884  interface->spiDriver->transfer((command >> 24) & 0xFF);
1885  interface->spiDriver->transfer((command >> 16) & 0xFF);
1886  interface->spiDriver->transfer((command >> 8) & 0xFF);
1887  interface->spiDriver->transfer(command & 0xFF);
1888 
1889  //Write 32-bit data
1890  interface->spiDriver->transfer((data >> 24) & 0xFF);
1891  interface->spiDriver->transfer((data >> 16) & 0xFF);
1892  interface->spiDriver->transfer((data >> 8) & 0xFF);
1893  interface->spiDriver->transfer(data & 0xFF);
1894 
1895  //Terminate the operation by raising the CS pin
1896  interface->spiDriver->deassertCs();
1897  }
1898  else
1899  {
1900  //The MDC/MDIO interface does not have access to all the configuration
1901  //registers. It can only access the standard MIIM registers
1902  }
1903 }
1904 
1905 
1906 /**
1907  * @brief Read switch register (32 bits)
1908  * @param[in] interface Underlying network interface
1909  * @param[in] address Switch register address
1910  * @return Register value
1911  **/
1912 
1913 uint32_t lan9370ReadSwitchReg32(NetInterface *interface, uint16_t address)
1914 {
1915  uint32_t data;
1916  uint32_t command;
1917 
1918  //SPI slave mode?
1919  if(interface->spiDriver != NULL)
1920  {
1921  //Set up a read operation
1922  command = LAN9370_SPI_CMD_READ;
1923  //Set register address
1924  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1925 
1926  //Pull the CS pin low
1927  interface->spiDriver->assertCs();
1928 
1929  //Write 32-bit command
1930  interface->spiDriver->transfer((command >> 24) & 0xFF);
1931  interface->spiDriver->transfer((command >> 16) & 0xFF);
1932  interface->spiDriver->transfer((command >> 8) & 0xFF);
1933  interface->spiDriver->transfer(command & 0xFF);
1934 
1935  //Read 32-bit data
1936  data = interface->spiDriver->transfer(0xFF) << 24;
1937  data |= interface->spiDriver->transfer(0xFF) << 16;
1938  data |= interface->spiDriver->transfer(0xFF) << 8;
1939  data |= interface->spiDriver->transfer(0xFF);
1940 
1941  //Terminate the operation by raising the CS pin
1942  interface->spiDriver->deassertCs();
1943  }
1944  else
1945  {
1946  //The MDC/MDIO interface does not have access to all the configuration
1947  //registers. It can only access the standard MIIM registers
1948  data = 0;
1949  }
1950 
1951  //Return register value
1952  return data;
1953 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:601
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define LAN9370_PORT5_MASK
#define LAN9370_TAIL_TAG_DEST_PORT4
#define NetContext
Definition: net.h:36
#define LAN9370_GLB_SW_LUE_CTL0
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
#define LAN9370_GLB_CTL0
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
#define LAN9370_GLB_CTL0_APB_PHY_REG_BLK
uint32_t destPorts
Definition: nic.h:152
LAN9370 5-port 100Base-T1 Ethernet switch driver.
#define LAN9370_GLB_CHID1_DEFAULT
#define LAN9370_IND_CTRL_BUSY
#define LAN9370_BASIC_STATUS
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
__weak_func void lan9370Tick(NetInterface *interface)
LAN9370 timer handler.
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
void lan9370SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
#define LAN9370_GLB_ALU_ACCESS_CTRL
#define LAN9370_GLB_SW_LUE_CTL2_FLUSH_OPTION_DYNAMIC
#define LAN9370_GLB_SW_PORT_MIR_SNP_CTL_MLD_SNOOP_EN
#define LAN9370_GLB_ALU_TBL_ENT2_PORT_FORWARD
void lan9370EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
@ ERROR_END_OF_TABLE
Definition: error.h:292
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define TRUE
Definition: os_port.h:50
#define LAN9370_GLB_SW_LUE_CTL0_DROP_INVALID_VID
uint8_t data[]
Definition: ethernet.h:224
#define LAN9370_GLB_SW_LUE_CTL2
#define LAN9370_GLB_ALU_TBL_ENT2_PORT5_FORWARD
#define LAN9370_PORT2
#define LAN9370_PORTn_LUE_MSTP_STATE_TRANSMIT_EN
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
#define LAN9370_GLB_SW_LUE_UNK1
#define LAN9370_GLB_SW_PORT_MIR_SNP_CTL_IGMP_SNOOP_EN
uint8_t type
Definition: coap_common.h:176
#define LAN9370_GLB_STATIC_TBL_ENT2_OVERRIDE
#define LAN9370_GLB_SW_LUE_CTL0_RESERVED_LUE_EN
#define LAN9370_GLB_STATIC_MCAST_CTL_START_FINISH
@ ERROR_INVALID_PORT
Definition: error.h:104
error_t lan9370DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
#define LAN9370_GLB_SW_CONTROL0_START_SWITCH
@ ERROR_TABLE_FULL
Definition: error.h:291
#define LAN9370_TAIL_TAG_PORT_BLOCKING_OVERRIDE
#define LAN9370_GLB_STATIC_TBL_ENT2
#define LAN9370_GLB_CHID1
void lan9370WriteExtReg(NetInterface *interface, uint8_t port, uint8_t bank, uint8_t addr, uint16_t data)
Write extended register.
EthHeader
Definition: ethernet.h:225
error_t lan9370UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
#define LAN9370_GLB_STATIC_MCAST_CTL_TABLE_SELECT_STATIC
#define LAN9370_PORT3
#define SMI_OPCODE_WRITE
Definition: nic.h:66
uint8_t lan9370ReadSwitchReg8(NetInterface *interface, uint16_t address)
Read switch register (8 bits)
#define LAN9370_GLB_STATIC_MCAST_CTL_DIRECT_ACCESS
#define LAN9370_IND_CTRL_OP_WRITE
#define LAN9370_GLB_SW_LUE_UNK1_FWD_MAP_PORT5
#define LAN9370_GLB_ALU_ACCESS_CTRL_VALID
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
#define FALSE
Definition: os_port.h:46
error_t lan9370GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
#define LAN9370_PORTn_XMII_CTL1_MII_INTF_SEL
error_t
Error codes.
Definition: error.h:43
void lan9370DisableIrq(NetInterface *interface)
Disable interrupts.
#define LAN9370_PORTn_XMII_CTL1_RGMII_ID_IG
#define LAN9370_GLB_SW_LUE_AGE_AGE_PERIOD_19_8_DEFAULT
void lan9370SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
#define LAN9370_GLB_SW_CONTROL0
#define LAN9370_GLB_SW_LUE_CTL1
void lan9370FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
#define LAN9370_PORTn_XMII_CTL1_MII_INTF_SEL_RGMII
#define LAN9370_PORTn_XMII_CTL0_DUPLEX
#define LAN9370_GLB_STATIC_MCAST_CTL_ACTION_WRITE
#define LAN9370_TAIL_TAG_DEST_PORT1
#define LAN9370_GLB_ALU_TBL_ENT4
#define LAN9370_GLB_ALU_TBL_ENT2_PORT3_FORWARD
void lan9370WriteSwitchReg32(NetInterface *interface, uint16_t address, uint32_t data)
Write switch register (32 bits)
#define LAN9370_VPHY_SPECIAL_CTRL
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:40
#define LAN9370_PORT5
#define LAN9370_GLB_ALU_TBL_ENT2_PORT2_FORWARD
error_t lan9370AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
#define LAN9370_GLB_ALU_ACCESS_CTRL_VALID_ENTRY_OR_SEARCH_END
@ ERROR_INVALID_LENGTH
Definition: error.h:111
void lan9370FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
bool_t lan9370GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
#define NetTxAncillary
Definition: net_misc.h:36
#define LAN9370_PORT5_XMII_CTL1
#define LAN9370_GLB_STATIC_MCAST_CTL_TABLE_INDEX
#define LAN9370_GLB_ALU_TBL_ENT2_PORT4_FORWARD
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
#define LAN9370_EXT_REG_RD_DATA
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
#define LAN9370_SPI_CMD_ADDR
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
void lan9370DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
#define LAN9370_STATIC_MAC_TABLE_SIZE
#define LAN9370_PORT1
const SwitchDriver lan9370SwitchDriver
LAN9370 Ethernet switch driver.
#define LAN9370_IND_CTRL_OP_READ
#define MIN(a, b)
Definition: os_port.h:63
void lan9370WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
uint16_t lan9370ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
#define LAN9370_GLB_SW_LUE_CTL1_FLUSH_ALU_TABLE
#define LAN9370_PORT5_MAC_CTL0
#define LAN9370_GLB_STATIC_MCAST_CTL_ACTION_READ
#define LAN9370_VPHY_SPECIAL_CTRL_SPI_INDIRECT_EN
uint16_t lan9370ReadSwitchReg16(NetInterface *interface, uint16_t address)
Read switch register (16 bits)
#define LAN9370_PORTn_MAC_CTL0_FR_LEN_CHK
#define LAN9370_EXT_REG_CTL_WRITE_CONTROL
#define LAN9370_GLB_SW_LUE_CTL2_FLUSH_OPTION
#define LAN9370_GLB_SW_LUE_CTL3_AGE_PERIOD_7_0_DEFAULT
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
#define LAN9370_GLB_STATIC_TBL_ENT1_VALID
#define LAN9370_EXT_REG_WR_DATA
uint16_t port
Definition: dns_common.h:270
#define LAN9370_GLB_SW_LUE_AGE_AGE_PERIOD_19_8
#define LAN9370_GLB_STATIC_MCAST_CTL
#define LAN9370_TAIL_TAG_DEST_PORT2
#define LAN9370_TAIL_TAG_SRC_PORT
void lan9370WriteSwitchReg8(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register (8 bits)
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define LAN9370_GLB_SW_LUE_AGE
#define LAN9370_SPI_CMD_WRITE
#define LAN9370_TAIL_TAG_DEST_PORT3
uint32_t lan9370ReadSwitchReg32(NetInterface *interface, uint16_t address)
Read switch register (32 bits)
#define LAN9370_PORT4
#define LAN9370_GLB_SW_LUE_UNK1_FWD_MAP
#define LAN9370_PORTn_XMII_CTL0_SPEED_10_100
__weak_func void lan9370EventHandler(NetInterface *interface)
LAN9370 event handler.
#define LAN9370_GLB_ALU_ACCESS_CTRL_START_FINISH
#define LAN9370_EXT_REG_CTL_READ_CONTROL
#define LAN9370_GLB_STATIC_TBL_ENT3
#define LAN9370_GLB_SW_LUE_UNK1_FWD
#define LAN9370_PORTn_XMII_CTL1_RGMII_ID_EG
Ethernet switch driver.
Definition: nic.h:325
#define HTONS(value)
Definition: cpu_endian.h:410
uint8_t n
error_t lan9370TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
@ ERROR_INVALID_ENTRY
Definition: error.h:290
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:604
NicDuplexMode lan9370GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
Ipv6Addr address[]
Definition: ipv6.h:345
void lan9370EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
__weak_func void lan9370InitHook(NetInterface *interface)
LAN9370 custom configuration.
#define LAN9370_GLB_ALU_TBL_ENT2
NicDuplexMode
Duplex mode.
Definition: nic.h:122
#define LAN9370_GLB_SW_LUE_CTL1_FLUSH_MSTP_ENTRIES
MacAddr macAddr
Definition: nic.h:150
#define LAN9370_EXT_REG_CTL_REGISTER_BANK
uint8_t srcPort
Definition: nic.h:151
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
uint8_t value[]
Definition: tcp.h:376
#define LAN9370_GLB_STATIC_TBL_ENT1
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
uint32_t lan9370GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
#define LAN9370_SPI_CMD_READ
const uint16_t lan9370IngressTailTag[5]
Tail tag rules (host to LAN9370)
#define LAN9370_GLB_ALU_TBL_ENT3
#define LAN9370_BASIC_STATUS_LINK_STATUS
void lan9370SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
#define LAN9370_EXT_REG_CTL_REGISTER_ADDR
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define LAN9370_PORT5_XMII_CTL0
#define LAN9370_IND_ADDR
#define LAN9370_GLB_ALU_TBL_ENT1
uint16_t lan9370ReadExtReg(NetInterface *interface, uint8_t port, uint8_t bank, uint8_t addr)
Read extended register.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define LAN9370_GLB_STATIC_TBL_ENT2_PORT_FORWARD
#define LAN9370_GLB_ALU_ACCESS_CTRL_ACTION_SEARCH
#define LAN9370_GLB_SW_PORT_MIR_SNP_CTL
void lan9370EnableIrq(NetInterface *interface)
Enable interrupts.
Ipv4Addr addr
Definition: nbns_common.h:141
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define LAN9370_PORTn_T1_PHY_REG(port, addr)
error_t lan9370Init(NetInterface *interface)
LAN9370 Ethernet switch initialization.
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
#define LAN9370_PORTn_OP_CTL0_TAIL_TAG_EN
#define LAN9370_IND_CTRL
#define LAN9370_EXT_REG_CTL
#define LAN9370_GLB_SW_LUE_CTL0_AGE_COUNT_DEFAULT
void lan9370WriteSwitchReg16(NetInterface *interface, uint16_t address, uint16_t data)
Write switch register (16 bits)
#define LAN9370_GLB_SW_LUE_CTL3
#define LAN9370_TAIL_TAG_VALID
error_t lan9370GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
#define LAN9370_GLB_SW_LUE_CTL3_AGE_PERIOD_7_0
#define LAN9370_PORTn_LUE_MSTP_STATE(port)
#define LAN9370_GLB_SW_LUE_CTL0_HASH_OPTION_CRC
Helper functions for Ethernet.
#define LAN9370_GLB_SW_LUE_UNK1_FWD_MAP_ALL
#define LAN9370_GLB_ALU_TBL_ENT2_PORT1_FORWARD
#define LAN9370_TAIL_TAG_NORMAL_ADDR_LOOKUP
#define LAN9370_IND_DATA
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
#define LAN9370_PORTn_LUE_MSTP_STATE_RECEIVE_EN
Debugging facilities.
#define LAN9370_PORT5_OP_CTL0
Forwarding database entry.
Definition: nic.h:149
#define LAN9370_GLB_STATIC_TBL_ENT4
void lan9370EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
#define LAN9370_PORTn_LUE_MSTP_STATE_LEARNING_DIS
#define LAN9370_PORT_MASK
SwitchPortState lan9370GetPortState(NetInterface *interface, uint8_t port)
Get port state.
#define LAN9370_PORTn_XMII_CTL1_RGMII_SPEED_1000