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-2024 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.4.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_CHIP_ID1);
116 
117  //The returned data is invalid until the serial interface is ready
118  } while(temp != LAN9370_CHIP_ID1_DEFAULT);
119 
120  //Enable indirect access from SPI to the VPHY registers
121  temp = lan9370ReadSwitchReg8(interface, LAN9370_GLOBAL_CTRL0);
124 
128 
129 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
130  //Enable tail tag feature
134 
135  //Disable frame length check
139 #else
140  //Disable tail tag feature
144 
145  //Enable frame length check
147  temp |= LAN9370_PORTn_MAC_CTRL0_FRAME_LEN_CHECK_EN;
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
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 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  NetInterface *virtualInterface;
250 
251  //Loop through network interfaces
252  for(i = 0; i < NET_INTERFACE_COUNT; i++)
253  {
254  //Point to the current interface
255  virtualInterface = &netInterface[i];
256 
257  //Check whether the current virtual interface is attached to the
258  //physical interface
259  if(virtualInterface == interface ||
260  virtualInterface->parent == interface)
261  {
262  //Retrieve current link state
263  linkState = lan9370GetLinkState(interface, virtualInterface->port);
264 
265  //Link up or link down event?
266  if(linkState != virtualInterface->linkState)
267  {
268  //Set event flag
269  interface->phyEvent = TRUE;
270  //Notify the TCP/IP stack of the event
272  }
273  }
274  }
275  }
276  else
277 #endif
278  {
279  //Initialize link state
280  linkState = FALSE;
281 
282  //Loop through the ports
284  {
285  //Retrieve current link state
286  if(lan9370GetLinkState(interface, port))
287  {
288  linkState = TRUE;
289  }
290  }
291 
292  //Link up or link down event?
293  if(linkState != interface->linkState)
294  {
295  //Set event flag
296  interface->phyEvent = TRUE;
297  //Notify the TCP/IP stack of the event
299  }
300  }
301 }
302 
303 
304 /**
305  * @brief Enable interrupts
306  * @param[in] interface Underlying network interface
307  **/
308 
310 {
311 }
312 
313 
314 /**
315  * @brief Disable interrupts
316  * @param[in] interface Underlying network interface
317  **/
318 
320 {
321 }
322 
323 
324 /**
325  * @brief LAN9370 event handler
326  * @param[in] interface Underlying network interface
327  **/
328 
330 {
331  uint_t port;
332  bool_t linkState;
333 
334 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
335  //Port separation mode?
336  if(interface->port != 0)
337  {
338  uint_t i;
339  NetInterface *virtualInterface;
340 
341  //Loop through network interfaces
342  for(i = 0; i < NET_INTERFACE_COUNT; i++)
343  {
344  //Point to the current interface
345  virtualInterface = &netInterface[i];
346 
347  //Check whether the current virtual interface is attached to the
348  //physical interface
349  if(virtualInterface == interface ||
350  virtualInterface->parent == interface)
351  {
352  //Get the port number associated with the current interface
353  port = virtualInterface->port;
354 
355  //Valid port?
356  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
357  {
358  //Retrieve current link state
359  linkState = lan9370GetLinkState(interface, port);
360 
361  //Link up event?
362  if(linkState && !virtualInterface->linkState)
363  {
364  //Retrieve host interface speed
365  interface->linkSpeed = lan9370GetLinkSpeed(interface,
366  LAN9370_PORT5);
367 
368  //Retrieve host interface duplex mode
369  interface->duplexMode = lan9370GetDuplexMode(interface,
370  LAN9370_PORT5);
371 
372  //Adjust MAC configuration parameters for proper operation
373  interface->nicDriver->updateMacConfig(interface);
374 
375  //Check current speed
376  virtualInterface->linkSpeed = lan9370GetLinkSpeed(interface,
377  port);
378 
379  //Check current duplex mode
380  virtualInterface->duplexMode = lan9370GetDuplexMode(interface,
381  port);
382 
383  //Update link state
384  virtualInterface->linkState = TRUE;
385 
386  //Process link state change event
387  nicNotifyLinkChange(virtualInterface);
388  }
389  //Link down event
390  else if(!linkState && virtualInterface->linkState)
391  {
392  //Update link state
393  virtualInterface->linkState = FALSE;
394 
395  //Process link state change event
396  nicNotifyLinkChange(virtualInterface);
397  }
398  }
399  }
400  }
401  }
402  else
403 #endif
404  {
405  //Initialize link state
406  linkState = FALSE;
407 
408  //Loop through the ports
410  {
411  //Retrieve current link state
412  if(lan9370GetLinkState(interface, port))
413  {
414  linkState = TRUE;
415  }
416  }
417 
418  //Link up event?
419  if(linkState)
420  {
421  //Retrieve host interface speed
422  interface->linkSpeed = lan9370GetLinkSpeed(interface, LAN9370_PORT5);
423  //Retrieve host interface duplex mode
424  interface->duplexMode = lan9370GetDuplexMode(interface, LAN9370_PORT5);
425 
426  //Adjust MAC configuration parameters for proper operation
427  interface->nicDriver->updateMacConfig(interface);
428 
429  //Update link state
430  interface->linkState = TRUE;
431  }
432  else
433  {
434  //Update link state
435  interface->linkState = FALSE;
436  }
437 
438  //Process link state change event
439  nicNotifyLinkChange(interface);
440  }
441 }
442 
443 
444 /**
445  * @brief Add tail tag to Ethernet frame
446  * @param[in] interface Underlying network interface
447  * @param[in] buffer Multi-part buffer containing the payload
448  * @param[in,out] offset Offset to the first payload byte
449  * @param[in] ancillary Additional options passed to the stack along with
450  * the packet
451  * @return Error code
452  **/
453 
455  size_t *offset, NetTxAncillary *ancillary)
456 {
457  error_t error;
458 
459  //Initialize status code
460  error = NO_ERROR;
461 
462 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
463  //SPI slave mode?
464  if(interface->spiDriver != NULL)
465  {
466  //Valid port?
467  if(ancillary->port <= LAN9370_PORT5)
468  {
469  size_t length;
470  const uint16_t *tailTag;
471 
472  //The two-byte tail tagging is used to indicate the destination port
473  tailTag = &lan9370IngressTailTag[ancillary->port];
474 
475  //Retrieve the length of the Ethernet frame
476  length = netBufferGetLength(buffer) - *offset;
477 
478  //The host controller should manually add padding to the packet before
479  //inserting the tail tag
480  error = ethPadFrame(buffer, &length);
481 
482  //Check status code
483  if(!error)
484  {
485  //The tail tag is inserted at the end of the packet, just before
486  //the CRC
487  error = netBufferAppend(buffer, tailTag, sizeof(uint16_t));
488  }
489  }
490  else
491  {
492  //The port number is not valid
493  error = ERROR_INVALID_PORT;
494  }
495  }
496 #endif
497 
498  //Return status code
499  return error;
500 }
501 
502 
503 /**
504  * @brief Decode tail tag from incoming Ethernet frame
505  * @param[in] interface Underlying network interface
506  * @param[in,out] frame Pointer to the received Ethernet frame
507  * @param[in,out] length Length of the frame, in bytes
508  * @param[in,out] ancillary Additional options passed to the stack along with
509  * the packet
510  * @return Error code
511  **/
512 
513 error_t lan9370UntagFrame(NetInterface *interface, uint8_t **frame,
514  size_t *length, NetRxAncillary *ancillary)
515 {
516  error_t error;
517 
518  //Initialize status code
519  error = NO_ERROR;
520 
521 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
522  //SPI slave mode?
523  if(interface->spiDriver != NULL)
524  {
525  //Valid Ethernet frame received?
526  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
527  {
528  uint8_t *tailTag;
529 
530  //The tail tag is inserted at the end of the packet, just before
531  //the CRC
532  tailTag = *frame + *length - sizeof(uint8_t);
533 
534  //The one byte tail tagging is used to indicate the source port
535  ancillary->port = (*tailTag & LAN9370_TAIL_TAG_SRC_PORT) + 1;
536 
537  //Strip tail tag from Ethernet frame
538  *length -= sizeof(uint8_t);
539  }
540  else
541  {
542  //Drop the received frame
543  error = ERROR_INVALID_LENGTH;
544  }
545  }
546  else
547  {
548  //Tail tagging mode cannot be enabled through MDC/MDIO interface
549  ancillary->port = 0;
550  }
551 #endif
552 
553  //Return status code
554  return error;
555 }
556 
557 
558 /**
559  * @brief Get link state
560  * @param[in] interface Underlying network interface
561  * @param[in] port Port number
562  * @return Link state
563  **/
564 
566 {
567  uint16_t value;
568  bool_t linkState;
569 
570  //Check port number
571  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
572  {
573  //Any link failure condition is latched in the status register. Reading
574  //the register twice will always return the actual link status
577 
578  //Retrieve current link state
579  linkState = (value & LAN9370_BASIC_STATUS_LINK_STATUS) ? TRUE : FALSE;
580  }
581  else
582  {
583  //The specified port number is not valid
584  linkState = FALSE;
585  }
586 
587  //Return link status
588  return linkState;
589 }
590 
591 
592 /**
593  * @brief Get link speed
594  * @param[in] interface Underlying network interface
595  * @param[in] port Port number
596  * @return Link speed
597  **/
598 
599 uint32_t lan9370GetLinkSpeed(NetInterface *interface, uint8_t port)
600 {
601  uint8_t type;
602  uint16_t value;
603  uint32_t linkSpeed;
604 
605  //Check port number
606  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
607  {
608  //The PHY is only able to operate in 100 Mbps mode
609  linkSpeed = NIC_LINK_SPEED_100MBPS;
610  }
611  else if(port == LAN9370_PORT5)
612  {
613  //SPI slave mode?
614  if(interface->spiDriver != NULL)
615  {
616  //Read port 5 XMII control 1 register
618 
619  //Retrieve host interface type
621 
622  //Gigabit interface?
625  {
626  //1000 Mb/s mode
627  linkSpeed = NIC_LINK_SPEED_1GBPS;
628  }
629  else
630  {
631  //Read port 5 XMII control 0 register
633 
634  //Retrieve host interface speed
636  {
637  //100 Mb/s mode
638  linkSpeed = NIC_LINK_SPEED_100MBPS;
639  }
640  else
641  {
642  //10 Mb/s mode
643  linkSpeed = NIC_LINK_SPEED_10MBPS;
644  }
645  }
646  }
647  else
648  {
649  //The MDC/MDIO interface does not have access to all the configuration
650  //registers. It can only access the standard MIIM registers
651  linkSpeed = NIC_LINK_SPEED_100MBPS;
652  }
653  }
654  else
655  {
656  //The specified port number is not valid
657  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
658  }
659 
660  //Return link status
661  return linkSpeed;
662 }
663 
664 
665 /**
666  * @brief Get duplex mode
667  * @param[in] interface Underlying network interface
668  * @param[in] port Port number
669  * @return Duplex mode
670  **/
671 
673 {
674  uint16_t value;
675  NicDuplexMode duplexMode;
676 
677  //Check port number
678  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
679  {
680  //The PHY is only able to operate in full duplex mode
681  duplexMode = NIC_FULL_DUPLEX_MODE;
682  }
683  else if(port == LAN9370_PORT5)
684  {
685  //SPI slave mode?
686  if(interface->spiDriver != NULL)
687  {
688  //Read port 5 XMII control 0 register
690 
691  //Retrieve host interface duplex mode
693  {
694  duplexMode = NIC_FULL_DUPLEX_MODE;
695  }
696  else
697  {
698  duplexMode = NIC_HALF_DUPLEX_MODE;
699  }
700  }
701  else
702  {
703  //The MDC/MDIO interface does not have access to all the configuration
704  //registers. It can only access the standard MIIM registers
705  duplexMode = NIC_FULL_DUPLEX_MODE;
706  }
707  }
708  else
709  {
710  //The specified port number is not valid
711  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
712  }
713 
714  //Return duplex mode
715  return duplexMode;
716 }
717 
718 
719 /**
720  * @brief Set port state
721  * @param[in] interface Underlying network interface
722  * @param[in] port Port number
723  * @param[in] state Port state
724  **/
725 
726 void lan9370SetPortState(NetInterface *interface, uint8_t port,
727  SwitchPortState state)
728 {
729  uint8_t temp;
730 
731  //Check port number
732  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
733  {
734  //Read MSTP state register
736 
737  //Update port state
738  switch(state)
739  {
740  //Listening state
745  break;
746 
747  //Learning state
752  break;
753 
754  //Forwarding state
759  break;
760 
761  //Disabled state
762  default:
766  break;
767  }
768 
769  //Write the value back to MSTP state register
771  }
772 }
773 
774 
775 /**
776  * @brief Get port state
777  * @param[in] interface Underlying network interface
778  * @param[in] port Port number
779  * @return Port state
780  **/
781 
783 {
784  uint8_t temp;
785  SwitchPortState state;
786 
787  //Check port number
788  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT4)
789  {
790  //Read MSTP state register
792 
793  //Check port state
794  if((temp & LAN9370_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
795  (temp & LAN9370_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
797  {
798  //Disabled state
800  }
801  else if((temp & LAN9370_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
802  (temp & LAN9370_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
804  {
805  //Listening state
807  }
808  else if((temp & LAN9370_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
809  (temp & LAN9370_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
811  {
812  //Learning state
814  }
815  else if((temp & LAN9370_PORTn_MSTP_STATE_TRANSMIT_EN) != 0 &&
816  (temp & LAN9370_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
818  {
819  //Forwarding state
821  }
822  else
823  {
824  //Unknown state
826  }
827  }
828  else
829  {
830  //The specified port number is not valid
832  }
833 
834  //Return port state
835  return state;
836 }
837 
838 
839 /**
840  * @brief Set aging time for dynamic filtering entries
841  * @param[in] interface Underlying network interface
842  * @param[in] agingTime Aging time, in seconds
843  **/
844 
845 void lan9370SetAgingTime(NetInterface *interface, uint32_t agingTime)
846 {
847  //The Age Period in combination with the Age Count field determines the
848  //aging time of dynamic entries in the address lookup table
849  agingTime = (agingTime + 3) / 4;
850 
851  //The full Age Period has 20 bits
852  agingTime = MIN(agingTime, 0xFFFFF);
853 
854  //Write the lower 8 bits
857 
858  //Write the upper 12 bits
860  (agingTime >> 8) & LAN9370_SWITCH_LUE_AGE_AGE_PERIOD_19_8);
861 }
862 
863 
864 /**
865  * @brief Enable IGMP snooping
866  * @param[in] interface Underlying network interface
867  * @param[in] enable Enable or disable IGMP snooping
868  **/
869 
871 {
872  uint8_t temp;
873 
874  //Read the Global Port Mirroring and Snooping Control register
875  temp = lan9370ReadSwitchReg8(interface,
877 
878  //Enable or disable IGMP snooping
879  if(enable)
880  {
882  }
883  else
884  {
886  }
887 
888  //Write the value back to Global Port Mirroring and Snooping Control register
890  temp);
891 }
892 
893 
894 /**
895  * @brief Enable MLD snooping
896  * @param[in] interface Underlying network interface
897  * @param[in] enable Enable or disable MLD snooping
898  **/
899 
901 {
902  uint8_t temp;
903 
904  //Read the Global Port Mirroring and Snooping Control register
905  temp = lan9370ReadSwitchReg8(interface,
907 
908  //Enable or disable MLD snooping
909  if(enable)
910  {
912  }
913  else
914  {
916  }
917 
918  //Write the value back to Global Port Mirroring and Snooping Control register
920  temp);
921 }
922 
923 
924 /**
925  * @brief Enable reserved multicast table
926  * @param[in] interface Underlying network interface
927  * @param[in] enable Enable or disable reserved group addresses
928  **/
929 
931 {
932  uint8_t temp;
933 
934  //Read the Switch Lookup Engine Control 0 register
936 
937  //Enable or disable the reserved multicast table
938  if(enable)
939  {
941  }
942  else
943  {
945  }
946 
947  //Write the value back to Switch Lookup Engine Control 0 register
949 }
950 
951 
952 /**
953  * @brief Add a new entry to the static MAC table
954  * @param[in] interface Underlying network interface
955  * @param[in] entry Pointer to the forwarding database entry
956  * @return Error code
957  **/
958 
960  const SwitchFdbEntry *entry)
961 {
962  error_t error;
963  uint_t i;
964  uint_t j;
965  uint32_t value;
966  SwitchFdbEntry currentEntry;
967 
968  //Keep track of the first free entry
970 
971  //Loop through the static MAC table
972  for(i = 0; i < LAN9370_STATIC_MAC_TABLE_SIZE; i++)
973  {
974  //Read current entry
975  error = lan9370GetStaticFdbEntry(interface, i, &currentEntry);
976 
977  //Valid entry?
978  if(!error)
979  {
980  //Check whether the table already contains the specified MAC address
981  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
982  {
983  j = i;
984  break;
985  }
986  }
987  else
988  {
989  //Keep track of the first free entry
991  {
992  j = i;
993  }
994  }
995  }
996 
997  //Any entry available?
999  {
1000  //Write the Static Address Table Entry 1 register
1003 
1004  //Set the relevant forward ports
1005  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1006  {
1008  }
1009  else
1010  {
1011  value = entry->destPorts & LAN9370_PORT_MASK;
1012  }
1013 
1014  //Enable overriding of port state
1015  if(entry->override)
1016  {
1018  }
1019 
1020  //Write the Static Address Table Entry 2 register
1022 
1023  //Copy MAC address (first 16 bits)
1024  value = (entry->macAddr.b[0] << 8) | entry->macAddr.b[1];
1025 
1026  //Write the Static Address Table Entry 3 register
1028 
1029  //Copy MAC address (last 32 bits)
1030  value = (entry->macAddr.b[2] << 24) | (entry->macAddr.b[3] << 16) |
1031  (entry->macAddr.b[4] << 8) | entry->macAddr.b[5];
1032 
1033  //Write the Static Address Table Entry 4 register
1035 
1036  //Setup a write operation
1040 
1041  //Write the TABLE_INDEX field with the 8-bit index value
1043 
1044  //Start the write operation
1046  value);
1047 
1048  //When the operation is complete, the START_FINISH bit will be cleared
1049  //automatically
1050  do
1051  {
1052  //Read the Static Address and Reserved Multicast Table Control register
1053  value = lan9370ReadSwitchReg32(interface,
1055 
1056  //Poll the START_FINISH bit
1058 
1059  //Successful processing
1060  error = NO_ERROR;
1061  }
1062  else
1063  {
1064  //The static MAC table is full
1065  error = ERROR_TABLE_FULL;
1066  }
1067 
1068  //Return status code
1069  return error;
1070 }
1071 
1072 
1073 /**
1074  * @brief Remove an entry from the static MAC table
1075  * @param[in] interface Underlying network interface
1076  * @param[in] entry Forwarding database entry to remove from the table
1077  * @return Error code
1078  **/
1079 
1081  const SwitchFdbEntry *entry)
1082 {
1083  error_t error;
1084  uint_t j;
1085  uint32_t value;
1086  SwitchFdbEntry currentEntry;
1087 
1088  //Loop through the static MAC table
1089  for(j = 0; j < LAN9370_STATIC_MAC_TABLE_SIZE; j++)
1090  {
1091  //Read current entry
1092  error = lan9370GetStaticFdbEntry(interface, j, &currentEntry);
1093 
1094  //Valid entry?
1095  if(!error)
1096  {
1097  //Check whether the table contains the specified MAC address
1098  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1099  {
1100  break;
1101  }
1102  }
1103  }
1104 
1105  //Any matching entry?
1107  {
1108  //Clear Static Address Table Entry registers
1113 
1114  //Setup a write operation
1118 
1119  //Write the TABLE_INDEX field with the 8-bit index value
1121 
1122  //Start the write operation
1124  value);
1125 
1126  //When the operation is complete, the START_FINISH bit will be cleared
1127  //automatically
1128  do
1129  {
1130  //Read the Static Address and Reserved Multicast Table Control register
1131  value = lan9370ReadSwitchReg32(interface,
1133 
1134  //Poll the START_FINISH bit
1136 
1137  //Successful processing
1138  error = NO_ERROR;
1139  }
1140  else
1141  {
1142  //The static MAC table does not contain the specified address
1143  error = ERROR_NOT_FOUND;
1144  }
1145 
1146  //Return status code
1147  return error;
1148 }
1149 
1150 
1151 /**
1152  * @brief Read an entry from the static MAC table
1153  * @param[in] interface Underlying network interface
1154  * @param[in] index Zero-based index of the entry to read
1155  * @param[out] entry Pointer to the forwarding database entry
1156  * @return Error code
1157  **/
1158 
1160  SwitchFdbEntry *entry)
1161 {
1162  error_t error;
1163  uint32_t value;
1164 
1165  //Check index parameter
1166  if(index < LAN9370_STATIC_MAC_TABLE_SIZE)
1167  {
1168  //Setup a write operation
1173 
1174  //Write the TABLE_INDEX field with the 8-bit index value
1176 
1177  //Start the read operation
1179  value);
1180 
1181  //When the operation is complete, the START_FINISH bit will be cleared
1182  //automatically
1183  do
1184  {
1185  //Read the Static Address and Reserved Multicast Table Control register
1186  value = lan9370ReadSwitchReg32(interface,
1188 
1189  //Poll the START_FINISH bit
1191 
1192  //Read the Static Address Table Entry 1 register
1194 
1195  //Valid entry?
1197  {
1198  //Read the Static Address Table Entry 2 register
1200 
1201  //Retrieve the ports associated with this MAC address
1202  entry->srcPort = 0;
1204 
1205  //Check the value of the OVERRIDE bit
1207  {
1208  entry->override = TRUE;
1209  }
1210  else
1211  {
1212  entry->override = FALSE;
1213  }
1214 
1215  //Read the Static Address Table Entry 3 register
1217 
1218  //Copy MAC address (first 16 bits)
1219  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1220  entry->macAddr.b[1] = value & 0xFF;
1221 
1222  //Read the Static Address Table Entry 4 register
1224 
1225  //Copy MAC address (last 32 bits)
1226  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1227  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1228  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1229  entry->macAddr.b[5] = value & 0xFF;
1230 
1231  //Successful processing
1232  error = NO_ERROR;
1233  }
1234  else
1235  {
1236  //The entry is not valid
1237  error = ERROR_INVALID_ENTRY;
1238  }
1239  }
1240  else
1241  {
1242  //The end of the table has been reached
1243  error = ERROR_END_OF_TABLE;
1244  }
1245 
1246  //Return status code
1247  return error;
1248 }
1249 
1250 
1251 /**
1252  * @brief Flush static MAC table
1253  * @param[in] interface Underlying network interface
1254  **/
1255 
1257 {
1258  uint_t i;
1259  uint32_t value;
1260 
1261  //Loop through the static MAC table
1262  for(i = 0; i < LAN9370_STATIC_MAC_TABLE_SIZE; i++)
1263  {
1264  //Clear Static Address Table Entry registers
1269 
1270  //Setup a write operation
1274 
1275  //Write the TABLE_INDEX field with the 8-bit index value
1277 
1278  //Start the write operation
1280  value);
1281 
1282  //When the operation is complete, the START_FINISH bit will be cleared
1283  //automatically
1284  do
1285  {
1286  //Read the Static Address and Reserved Multicast Table Control register
1287  value = lan9370ReadSwitchReg32(interface,
1289 
1290  //Poll the START_FINISH bit
1292  }
1293 }
1294 
1295 
1296 /**
1297  * @brief Read an entry from the dynamic MAC table
1298  * @param[in] interface Underlying network interface
1299  * @param[in] index Zero-based index of the entry to read
1300  * @param[out] entry Pointer to the forwarding database entry
1301  * @return Error code
1302  **/
1303 
1305  SwitchFdbEntry *entry)
1306 {
1307  error_t error;
1308  uint32_t value;
1309 
1310  //First entry?
1311  if(index == 0)
1312  {
1313  //Clear the ALU Table Access Control register to stop any operation
1315 
1316  //Start the search operation
1320  }
1321 
1322  //Poll the VALID_ENTRY_OR_SEARCH_END bit until it is set
1323  do
1324  {
1325  //Read the ALU Table Access Control register
1327 
1328  //This bit goes high to indicate either a new valid entry is returned or
1329  //the search is complete
1331 
1332  //Check whether the next valid entry is ready
1333  if((value & LAN9370_ALU_TABLE_CTRL_VALID) != 0)
1334  {
1335  //Store the data from the ALU table entry
1336  entry->destPorts = 0;
1337  entry->override = FALSE;
1338 
1339  //Read the ALU Table Entry 1 and 2 registers
1342 
1343  //Retrieve the port associated with this MAC address
1345  {
1347  entry->srcPort = LAN9370_PORT1;
1348  break;
1350  entry->srcPort = LAN9370_PORT2;
1351  break;
1353  entry->srcPort = LAN9370_PORT3;
1354  break;
1356  entry->srcPort = LAN9370_PORT4;
1357  break;
1359  entry->srcPort = LAN9370_PORT5;
1360  break;
1361  default:
1362  entry->srcPort = 0;
1363  break;
1364  }
1365 
1366  //Read the ALU Table Entry 3 register
1368 
1369  //Copy MAC address (first 16 bits)
1370  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1371  entry->macAddr.b[1] = value & 0xFF;
1372 
1373  //Read the ALU Table Entry 4 register
1375 
1376  //Copy MAC address (last 32 bits)
1377  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1378  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1379  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1380  entry->macAddr.b[5] = value & 0xFF;
1381 
1382  //Successful processing
1383  error = NO_ERROR;
1384  }
1385  else
1386  {
1387  //The search can be stopped any time by setting the START_FINISH bit to 0
1389 
1390  //The end of the table has been reached
1391  error = ERROR_END_OF_TABLE;
1392  }
1393 
1394  //Return status code
1395  return error;
1396 }
1397 
1398 
1399 /**
1400  * @brief Flush dynamic MAC table
1401  * @param[in] interface Underlying network interface
1402  * @param[in] port Port number
1403  **/
1404 
1406 {
1407  uint_t temp;
1408  uint8_t state;
1409 
1410  //Flush only dynamic table entries
1415 
1416  //Valid port number?
1417  if(port >= LAN9370_PORT1 && port <= LAN9370_PORT5)
1418  {
1419  //Save the current state of the port
1421 
1422  //Turn off learning capability
1425 
1426  //All the entries associated with a port that has its learning capability
1427  //being turned off will be flushed
1431 
1432  //Restore the original state of the port
1434  }
1435  else
1436  {
1437  //Trigger a flush of the entire address lookup table
1441  }
1442 }
1443 
1444 
1445 /**
1446  * @brief Set forward ports for unknown multicast packets
1447  * @param[in] interface Underlying network interface
1448  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1449  * @param[in] forwardPorts Port map
1450  **/
1451 
1453  bool_t enable, uint32_t forwardPorts)
1454 {
1455  uint32_t temp;
1456 
1457  //Read Unknown Multicast Control register
1459 
1460  //Clear port map
1462 
1463  //Enable or disable forwarding of unknown multicast packets
1464  if(enable)
1465  {
1466  //Enable forwarding
1468 
1469  //Check whether unknown multicast packets should be forwarded to the CPU port
1470  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1471  {
1473  }
1474 
1475  //Select the desired forward ports
1476  temp |= forwardPorts & LAN9370_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL;
1477  }
1478  else
1479  {
1480  //Disable forwarding
1482  }
1483 
1484  //Write the value back to Unknown Multicast Control register
1486 }
1487 
1488 
1489 /**
1490  * @brief Write PHY register
1491  * @param[in] interface Underlying network interface
1492  * @param[in] port Port number
1493  * @param[in] address PHY register address
1494  * @param[in] data Register value
1495  **/
1496 
1497 void lan9370WritePhyReg(NetInterface *interface, uint8_t port,
1498  uint8_t address, uint16_t data)
1499 {
1500  uint16_t n;
1501 
1502  //SPI slave mode?
1503  if(interface->spiDriver != NULL)
1504  {
1505  //The SPI interface provides access to all PHY registers
1507 
1508  //Set register address
1510  //Set register value
1512 
1513  //Start a write operation
1516 
1517  //Wait for the write to complete
1518  while((lan9370ReadSwitchReg16(interface, LAN9370_IND_CTRL) &
1519  LAN9370_IND_CTRL_BUSY) != 0)
1520  {
1521  }
1522  }
1523  else if(interface->smiDriver != NULL)
1524  {
1525  //Write the specified PHY register
1526  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1527  }
1528  else
1529  {
1530  //Write the specified PHY register
1531  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1532  }
1533 }
1534 
1535 
1536 /**
1537  * @brief Read PHY register
1538  * @param[in] interface Underlying network interface
1539  * @param[in] port Port number
1540  * @param[in] address PHY register address
1541  * @return Register value
1542  **/
1543 
1544 uint16_t lan9370ReadPhyReg(NetInterface *interface, uint8_t port,
1545  uint8_t address)
1546 {
1547  uint16_t n;
1548  uint16_t data;
1549 
1550  //SPI slave mode?
1551  if(interface->spiDriver != NULL)
1552  {
1553  //The SPI interface provides access to all PHY registers
1555 
1556  //Set register address
1558 
1559  //Start a read operation
1562 
1563  //Wait for the read to complete
1564  while((lan9370ReadSwitchReg16(interface, LAN9370_IND_CTRL) &
1565  LAN9370_IND_CTRL_BUSY) != 0)
1566  {
1567  }
1568 
1569  //Read the 16-bit value
1571  }
1572  else if(interface->smiDriver != NULL)
1573  {
1574  //Read the specified PHY register
1575  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1576  }
1577  else
1578  {
1579  //Read the specified PHY register
1580  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1581  }
1582 
1583  //Return register value
1584  return data;
1585 }
1586 
1587 
1588 /**
1589  * @brief Dump PHY registers for debugging purpose
1590  * @param[in] interface Underlying network interface
1591  * @param[in] port Port number
1592  **/
1593 
1594 void lan9370DumpPhyReg(NetInterface *interface, uint8_t port)
1595 {
1596  uint8_t i;
1597 
1598  //Loop through PHY registers
1599  for(i = 0; i < 32; i++)
1600  {
1601  //Display current PHY register
1602  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1603  lan9370ReadPhyReg(interface, port, i));
1604  }
1605 
1606  //Terminate with a line feed
1607  TRACE_DEBUG("\r\n");
1608 }
1609 
1610 
1611 /**
1612  * @brief Write extended register
1613  * @param[in] interface Underlying network interface
1614  * @param[in] port Port number
1615  * @param[in] bank Register bank
1616  * @param[in] addr Register address
1617  * @param[in] data Extended register value
1618  **/
1619 
1620 void lan9370WriteExtReg(NetInterface *interface, uint8_t port, uint8_t bank,
1621  uint8_t addr, uint16_t data)
1622 {
1623  uint16_t temp;
1624 
1625  //Set up a write operation
1627  //Select register bank
1628  temp |= (bank << 8) & LAN9370_EXT_REG_CTL_REGISTER_BANK;
1629  //Select register address
1631 
1632  //Write the EXT_REG_WR_DATA register with the desired 16-bit data
1634 
1635  //Write the EXT_REG_CTL register
1636  lan9370WritePhyReg(interface, port, LAN9370_EXT_REG_CTL, temp);
1637 }
1638 
1639 
1640 /**
1641  * @brief Read extended register
1642  * @param[in] interface Underlying network interface
1643  * @param[in] port Port number
1644  * @param[in] bank Register bank
1645  * @param[in] addr Register address
1646  * @return Extended register value
1647  **/
1648 
1649 uint16_t lan9370ReadExtReg(NetInterface *interface, uint8_t port, uint8_t bank,
1650  uint8_t addr)
1651 {
1652  uint16_t temp;
1653 
1654  //Set up a read operation
1656  //Select register bank
1657  temp |= (bank << 8) & LAN9370_EXT_REG_CTL_REGISTER_BANK;
1658  //Select register address
1660 
1661  //Write the EXT_REG_CTL register
1662  lan9370WritePhyReg(interface, port, LAN9370_EXT_REG_CTL, temp);
1663 
1664  //Read the EXT_REG_RD_DATA register
1665  return lan9370ReadPhyReg(interface, port, LAN9370_EXT_REG_RD_DATA);
1666 }
1667 
1668 
1669 /**
1670  * @brief Write switch register (8 bits)
1671  * @param[in] interface Underlying network interface
1672  * @param[in] address Switch register address
1673  * @param[in] data Register value
1674  **/
1675 
1676 void lan9370WriteSwitchReg8(NetInterface *interface, uint16_t address,
1677  uint8_t data)
1678 {
1679  uint32_t command;
1680 
1681  //SPI slave mode?
1682  if(interface->spiDriver != NULL)
1683  {
1684  //Set up a write operation
1685  command = LAN9370_SPI_CMD_WRITE;
1686  //Set register address
1687  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1688 
1689  //Pull the CS pin low
1690  interface->spiDriver->assertCs();
1691 
1692  //Write 32-bit command
1693  interface->spiDriver->transfer((command >> 24) & 0xFF);
1694  interface->spiDriver->transfer((command >> 16) & 0xFF);
1695  interface->spiDriver->transfer((command >> 8) & 0xFF);
1696  interface->spiDriver->transfer(command & 0xFF);
1697 
1698  //Write 8-bit data
1699  interface->spiDriver->transfer(data);
1700 
1701  //Terminate the operation by raising the CS pin
1702  interface->spiDriver->deassertCs();
1703  }
1704  else
1705  {
1706  //The MDC/MDIO interface does not have access to all the configuration
1707  //registers. It can only access the standard MIIM registers
1708  }
1709 }
1710 
1711 
1712 /**
1713  * @brief Read switch register (8 bits)
1714  * @param[in] interface Underlying network interface
1715  * @param[in] address Switch register address
1716  * @return Register value
1717  **/
1718 
1719 uint8_t lan9370ReadSwitchReg8(NetInterface *interface, uint16_t address)
1720 {
1721  uint8_t data;
1722  uint32_t command;
1723 
1724  //SPI slave mode?
1725  if(interface->spiDriver != NULL)
1726  {
1727  //Set up a read operation
1728  command = LAN9370_SPI_CMD_READ;
1729  //Set register address
1730  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1731 
1732  //Pull the CS pin low
1733  interface->spiDriver->assertCs();
1734 
1735  //Write 32-bit command
1736  interface->spiDriver->transfer((command >> 24) & 0xFF);
1737  interface->spiDriver->transfer((command >> 16) & 0xFF);
1738  interface->spiDriver->transfer((command >> 8) & 0xFF);
1739  interface->spiDriver->transfer(command & 0xFF);
1740 
1741  //Read 8-bit data
1742  data = interface->spiDriver->transfer(0xFF);
1743 
1744  //Terminate the operation by raising the CS pin
1745  interface->spiDriver->deassertCs();
1746  }
1747  else
1748  {
1749  //The MDC/MDIO interface does not have access to all the configuration
1750  //registers. It can only access the standard MIIM registers
1751  data = 0;
1752  }
1753 
1754  //Return register value
1755  return data;
1756 }
1757 
1758 
1759 /**
1760  * @brief Write switch register (16 bits)
1761  * @param[in] interface Underlying network interface
1762  * @param[in] address Switch register address
1763  * @param[in] data Register value
1764  **/
1765 
1767  uint16_t data)
1768 {
1769  uint32_t command;
1770 
1771  //SPI slave mode?
1772  if(interface->spiDriver != NULL)
1773  {
1774  //Set up a write operation
1775  command = LAN9370_SPI_CMD_WRITE;
1776  //Set register address
1777  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1778 
1779  //Pull the CS pin low
1780  interface->spiDriver->assertCs();
1781 
1782  //Write 32-bit command
1783  interface->spiDriver->transfer((command >> 24) & 0xFF);
1784  interface->spiDriver->transfer((command >> 16) & 0xFF);
1785  interface->spiDriver->transfer((command >> 8) & 0xFF);
1786  interface->spiDriver->transfer(command & 0xFF);
1787 
1788  //Write 16-bit data
1789  interface->spiDriver->transfer((data >> 8) & 0xFF);
1790  interface->spiDriver->transfer(data & 0xFF);
1791 
1792  //Terminate the operation by raising the CS pin
1793  interface->spiDriver->deassertCs();
1794  }
1795  else
1796  {
1797  //The MDC/MDIO interface does not have access to all the configuration
1798  //registers. It can only access the standard MIIM registers
1799  }
1800 }
1801 
1802 
1803 /**
1804  * @brief Read switch register (16 bits)
1805  * @param[in] interface Underlying network interface
1806  * @param[in] address Switch register address
1807  * @return Register value
1808  **/
1809 
1810 uint16_t lan9370ReadSwitchReg16(NetInterface *interface, uint16_t address)
1811 {
1812  uint16_t data;
1813  uint32_t command;
1814 
1815  //SPI slave mode?
1816  if(interface->spiDriver != NULL)
1817  {
1818  //Set up a read operation
1819  command = LAN9370_SPI_CMD_READ;
1820  //Set register address
1821  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1822 
1823  //Pull the CS pin low
1824  interface->spiDriver->assertCs();
1825 
1826  //Write 32-bit command
1827  interface->spiDriver->transfer((command >> 24) & 0xFF);
1828  interface->spiDriver->transfer((command >> 16) & 0xFF);
1829  interface->spiDriver->transfer((command >> 8) & 0xFF);
1830  interface->spiDriver->transfer(command & 0xFF);
1831 
1832  //Read 16-bit data
1833  data = interface->spiDriver->transfer(0xFF) << 8;
1834  data |= interface->spiDriver->transfer(0xFF);
1835 
1836  //Terminate the operation by raising the CS pin
1837  interface->spiDriver->deassertCs();
1838  }
1839  else
1840  {
1841  //The MDC/MDIO interface does not have access to all the configuration
1842  //registers. It can only access the standard MIIM registers
1843  data = 0;
1844  }
1845 
1846  //Return register value
1847  return data;
1848 }
1849 
1850 
1851 /**
1852  * @brief Write switch register (32 bits)
1853  * @param[in] interface Underlying network interface
1854  * @param[in] address Switch register address
1855  * @param[in] data Register value
1856  **/
1857 
1859  uint32_t data)
1860 {
1861  uint32_t command;
1862 
1863  //SPI slave mode?
1864  if(interface->spiDriver != NULL)
1865  {
1866  //Set up a write operation
1867  command = LAN9370_SPI_CMD_WRITE;
1868  //Set register address
1869  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1870 
1871  //Pull the CS pin low
1872  interface->spiDriver->assertCs();
1873 
1874  //Write 32-bit command
1875  interface->spiDriver->transfer((command >> 24) & 0xFF);
1876  interface->spiDriver->transfer((command >> 16) & 0xFF);
1877  interface->spiDriver->transfer((command >> 8) & 0xFF);
1878  interface->spiDriver->transfer(command & 0xFF);
1879 
1880  //Write 32-bit data
1881  interface->spiDriver->transfer((data >> 24) & 0xFF);
1882  interface->spiDriver->transfer((data >> 16) & 0xFF);
1883  interface->spiDriver->transfer((data >> 8) & 0xFF);
1884  interface->spiDriver->transfer(data & 0xFF);
1885 
1886  //Terminate the operation by raising the CS pin
1887  interface->spiDriver->deassertCs();
1888  }
1889  else
1890  {
1891  //The MDC/MDIO interface does not have access to all the configuration
1892  //registers. It can only access the standard MIIM registers
1893  }
1894 }
1895 
1896 
1897 /**
1898  * @brief Read switch register (32 bits)
1899  * @param[in] interface Underlying network interface
1900  * @param[in] address Switch register address
1901  * @return Register value
1902  **/
1903 
1904 uint32_t lan9370ReadSwitchReg32(NetInterface *interface, uint16_t address)
1905 {
1906  uint32_t data;
1907  uint32_t command;
1908 
1909  //SPI slave mode?
1910  if(interface->spiDriver != NULL)
1911  {
1912  //Set up a read operation
1913  command = LAN9370_SPI_CMD_READ;
1914  //Set register address
1915  command |= (address << 5) & LAN9370_SPI_CMD_ADDR;
1916 
1917  //Pull the CS pin low
1918  interface->spiDriver->assertCs();
1919 
1920  //Write 32-bit command
1921  interface->spiDriver->transfer((command >> 24) & 0xFF);
1922  interface->spiDriver->transfer((command >> 16) & 0xFF);
1923  interface->spiDriver->transfer((command >> 8) & 0xFF);
1924  interface->spiDriver->transfer(command & 0xFF);
1925 
1926  //Read 32-bit data
1927  data = interface->spiDriver->transfer(0xFF) << 24;
1928  data |= interface->spiDriver->transfer(0xFF) << 16;
1929  data |= interface->spiDriver->transfer(0xFF) << 8;
1930  data |= interface->spiDriver->transfer(0xFF);
1931 
1932  //Terminate the operation by raising the CS pin
1933  interface->spiDriver->deassertCs();
1934  }
1935  else
1936  {
1937  //The MDC/MDIO interface does not have access to all the configuration
1938  //registers. It can only access the standard MIIM registers
1939  data = 0;
1940  }
1941 
1942  //Return register value
1943  return data;
1944 }
uint8_t type
Definition: coap_common.h:176
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define HTONS(value)
Definition: cpu_endian.h:410
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint16_t port
Definition: dns_common.h:267
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_NOT_FOUND
Definition: error.h:147
@ ERROR_END_OF_TABLE
Definition: error.h:290
@ ERROR_INVALID_ENTRY
Definition: error.h:288
@ ERROR_TABLE_FULL
Definition: error.h:289
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint8_t data[]
Definition: ethernet.h:222
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
EthHeader
Definition: ethernet.h:223
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
Helper functions for Ethernet.
Ipv6Addr address[]
Definition: ipv6.h:316
void lan9370WriteExtReg(NetInterface *interface, uint8_t port, uint8_t bank, uint8_t addr, uint16_t data)
Write extended register.
void lan9370FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
void lan9370EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
uint32_t lan9370ReadSwitchReg32(NetInterface *interface, uint16_t address)
Read switch register (32 bits)
void lan9370SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
uint32_t lan9370GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
uint16_t lan9370ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
__weak_func void lan9370InitHook(NetInterface *interface)
LAN9370 custom configuration.
void lan9370DisableIrq(NetInterface *interface)
Disable interrupts.
error_t lan9370UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
SwitchPortState lan9370GetPortState(NetInterface *interface, uint8_t port)
Get port state.
uint16_t lan9370ReadExtReg(NetInterface *interface, uint8_t port, uint8_t bank, uint8_t addr)
Read extended register.
void lan9370WriteSwitchReg32(NetInterface *interface, uint16_t address, uint32_t data)
Write switch register (32 bits)
error_t lan9370Init(NetInterface *interface)
LAN9370 Ethernet switch initialization.
void lan9370Tick(NetInterface *interface)
LAN9370 timer handler.
void lan9370EventHandler(NetInterface *interface)
LAN9370 event handler.
error_t lan9370TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
void lan9370WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
error_t lan9370GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
void lan9370SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
void lan9370SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
uint8_t lan9370ReadSwitchReg8(NetInterface *interface, uint16_t address)
Read switch register (8 bits)
void lan9370EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
void lan9370EnableIrq(NetInterface *interface)
Enable interrupts.
error_t lan9370AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
void lan9370EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
bool_t lan9370GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
uint16_t lan9370ReadSwitchReg16(NetInterface *interface, uint16_t address)
Read switch register (16 bits)
void lan9370WriteSwitchReg8(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register (8 bits)
NicDuplexMode lan9370GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
error_t lan9370GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
const uint16_t lan9370IngressTailTag[5]
Tail tag rules (host to LAN9370)
void lan9370WriteSwitchReg16(NetInterface *interface, uint16_t address, uint16_t data)
Write switch register (16 bits)
error_t lan9370DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
void lan9370FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
void lan9370DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
const SwitchDriver lan9370SwitchDriver
LAN9370 Ethernet switch driver.
LAN9370 5-port 100Base-T1 Ethernet switch driver.
#define LAN9370_PORT4
#define LAN9370_ALU_TABLE_ENTRY2_PORT5_FORWARD
#define LAN9370_SWITCH_LUE_CTRL3_AGE_PERIOD_7_0_DEFAULT
#define LAN9370_UNKONWN_MULTICAST_CTRL_FWD
#define LAN9370_STATIC_TABLE_ENTRY1
#define LAN9370_STATIC_TABLE_ENTRY2_PORT_FORWARD
#define LAN9370_EXT_REG_WR_DATA
#define LAN9370_PORTn_MSTP_STATE(port)
#define LAN9370_TAIL_TAG_DEST_PORT1
#define LAN9370_PORTn_XMII_CTRL1_RGMII_SPEED_1000
#define LAN9370_ALU_TABLE_ENTRY2_PORT2_FORWARD
#define LAN9370_ALU_TABLE_CTRL_VALID
#define LAN9370_IND_CTRL
#define LAN9370_TAIL_TAG_SRC_PORT
#define LAN9370_PORT5_XMII_CTRL1
#define LAN9370_PORTn_MSTP_STATE_LEARNING_DIS
#define LAN9370_STATIC_MCAST_TABLE_CTRL_START_FINISH
#define LAN9370_STATIC_TABLE_ENTRY1_VALID
#define LAN9370_SWITCH_LUE_CTRL3
#define LAN9370_SWITCH_LUE_CTRL0_HASH_OPTION_CRC
#define LAN9370_SWITCH_LUE_AGE
#define LAN9370_ALU_TABLE_ENTRY2_PORT1_FORWARD
#define LAN9370_SPI_CMD_ADDR
#define LAN9370_PORT5_XMII_CTRL0
#define LAN9370_STATIC_MCAST_TABLE_CTRL_ACTION_READ
#define LAN9370_SWITCH_LUE_CTRL1_FLUSH_ALU_TABLE
#define LAN9370_SPI_CMD_WRITE
#define LAN9370_CHIP_ID1
#define LAN9370_ALU_TABLE_CTRL_ACTION_SEARCH
#define LAN9370_EXT_REG_CTL_READ_CONTROL
#define LAN9370_STATIC_MAC_TABLE_SIZE
#define LAN9370_IND_DATA
#define LAN9370_UNKONWN_MULTICAST_CTRL_FWD_MAP
#define LAN9370_EXT_REG_RD_DATA
#define LAN9370_TAIL_TAG_PORT_BLOCKING_OVERRIDE
#define LAN9370_IND_CTRL_BUSY
#define LAN9370_PORTn_XMII_CTRL0_DUPLEX
#define LAN9370_ALU_TABLE_CTRL
#define LAN9370_ALU_TABLE_ENTRY2_PORT3_FORWARD
#define LAN9370_PORTn_XMII_CTRL1_RGMII_ID_IG
#define LAN9370_UNKONWN_MULTICAST_CTRL
#define LAN9370_UNKONWN_MULTICAST_CTRL_FWD_MAP_PORT5
#define LAN9370_STATIC_TABLE_ENTRY4
#define LAN9370_EXT_REG_CTL_WRITE_CONTROL
#define LAN9370_SWITCH_OP_START_SWITCH
#define LAN9370_SWITCH_LUE_CTRL0
#define LAN9370_STATIC_MCAST_TABLE_CTRL_DIRECT_ACCESS
#define LAN9370_PORTn_MSTP_STATE_RECEIVE_EN
#define LAN9370_PORT3
#define LAN9370_GLOBAL_PORT_MIRROR_SNOOP_CTRL_MLD_SNOOP_EN
#define LAN9370_GLOBAL_PORT_MIRROR_SNOOP_CTRL
#define LAN9370_SWITCH_LUE_CTRL2
#define LAN9370_IND_ADDR
#define LAN9370_GLOBAL_PORT_MIRROR_SNOOP_CTRL_IGMP_SNOOP_EN
#define LAN9370_PORT2
#define LAN9370_EXT_REG_CTL_REGISTER_ADDR
#define LAN9370_PORTn_XMII_CTRL1_RGMII_ID_EG
#define LAN9370_SWITCH_LUE_CTRL2_FLUSH_OPTION
#define LAN9370_GLOBAL_CTRL0
#define LAN9370_PORT5_MAC_CTRL0
#define LAN9370_PORT5
#define LAN9370_SWITCH_LUE_CTRL0_DROP_INVALID_VID
#define LAN9370_PORTn_XMII_CTRL1_MII_INTF_SEL_RGMII
#define LAN9370_ALU_TABLE_ENTRY2_PORT4_FORWARD
#define LAN9370_STATIC_TABLE_ENTRY2
#define LAN9370_ALU_TABLE_ENTRY4
#define LAN9370_PORT1
#define LAN9370_TAIL_TAG_DEST_PORT3
#define LAN9370_TAIL_TAG_DEST_PORT2
#define LAN9370_PORTn_XMII_CTRL0_SPEED_10_100
#define LAN9370_ALU_TABLE_ENTRY2_PORT_FORWARD
#define LAN9370_CHIP_ID1_DEFAULT
#define LAN9370_VPHY_SPECIAL_CTRL
#define LAN9370_PORTn_MAC_CTRL0_FR_LEN_CHK
#define LAN9370_EXT_REG_CTL_REGISTER_BANK
#define LAN9370_IND_CTRL_OP_WRITE
#define LAN9370_SWITCH_LUE_AGE_AGE_PERIOD_19_8_DEFAULT
#define LAN9370_IND_CTRL_OP_READ
#define LAN9370_ALU_TABLE_ENTRY1
#define LAN9370_STATIC_MCAST_TABLE_CTRL_TABLE_SELECT_STATIC
#define LAN9370_EXT_REG_CTL
#define LAN9370_SWITCH_LUE_CTRL2_FLUSH_OPTION_DYNAMIC
#define LAN9370_STATIC_MCAST_TABLE_CTRL_TABLE_INDEX
#define LAN9370_VPHY_SPECIAL_CTRL_SPI_INDIRECT_EN
#define LAN9370_TAIL_TAG_DEST_PORT4
#define LAN9370_TAIL_TAG_NORMAL_ADDR_LOOKUP
#define LAN9370_SWITCH_LUE_AGE_AGE_PERIOD_19_8
#define LAN9370_PORTn_MSTP_STATE_TRANSMIT_EN
#define LAN9370_PORT5_MASK
#define LAN9370_PORT_MASK
#define LAN9370_PORTn_T1_PHY_REG(port, addr)
#define LAN9370_PORTn_XMII_CTRL1_MII_INTF_SEL
#define LAN9370_PORT5_OP_CTRL0
#define LAN9370_STATIC_TABLE_ENTRY3
#define LAN9370_STATIC_MCAST_TABLE_CTRL
#define LAN9370_ALU_TABLE_CTRL_START_FINISH
#define LAN9370_GLOBAL_CTRL0_APB_PHY_REG_BLK
#define LAN9370_STATIC_TABLE_ENTRY2_OVERRIDE
#define LAN9370_SWITCH_LUE_CTRL0_RESERVED_LUE_EN
#define LAN9370_SWITCH_LUE_CTRL1
#define LAN9370_ALU_TABLE_ENTRY3
#define LAN9370_BASIC_STATUS
#define LAN9370_BASIC_STATUS_LINK_STATUS
#define LAN9370_TAIL_TAG_VALID
#define LAN9370_SWITCH_LUE_CTRL3_AGE_PERIOD_7_0
#define LAN9370_ALU_TABLE_CTRL_VALID_ENTRY_OR_SEARCH_END
#define LAN9370_SWITCH_OP
#define LAN9370_SWITCH_LUE_CTRL0_AGE_COUNT_DEFAULT
#define LAN9370_SWITCH_LUE_CTRL1_FLUSH_MSTP_ENTRIES
#define LAN9370_ALU_TABLE_ENTRY2
#define LAN9370_STATIC_MCAST_TABLE_CTRL_ACTION_WRITE
#define LAN9370_PORTn_OP_CTRL0_TAIL_TAG_EN
#define LAN9370_SPI_CMD_READ
#define LAN9370_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL
Ipv4Addr addr
Definition: nbns_common.h:123
TCP/IP stack core.
#define NET_INTERFACE_COUNT
Definition: net.h:113
#define NetInterface
Definition: net.h:36
#define netInterface
Definition: net_legacy.h:199
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:588
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:548
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define SMI_OPCODE_READ
Definition: nic.h:67
NicDuplexMode
Duplex mode.
Definition: nic.h:122
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
SwitchPortState
Switch port state.
Definition: nic.h:134
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
Ethernet switch driver.
Definition: nic.h:322
Forwarding database entry.
Definition: nic.h:149
MacAddr macAddr
Definition: nic.h:150
uint32_t destPorts
Definition: nic.h:152
bool_t override
Definition: nic.h:153
uint8_t srcPort
Definition: nic.h:151
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369