lan9354_driver.c
Go to the documentation of this file.
1 /**
2  * @file lan9354_driver.c
3  * @brief LAN9354 3-port 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.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
37 #include "debug.h"
38 
39 
40 /**
41  * @brief LAN9354 Ethernet switch driver
42  **/
43 
45 {
69 };
70 
71 
72 /**
73  * @brief LAN9354 Ethernet switch initialization
74  * @param[in] interface Underlying network interface
75  * @return Error code
76  **/
77 
79 {
80  uint_t port;
81  uint32_t value;
82 
83  //Debug message
84  TRACE_INFO("Initializing LAN9354...\r\n");
85 
86  //Initialize serial management interface
87  if(interface->smiDriver != NULL)
88  {
89  interface->smiDriver->init();
90  }
91 
92  //Chip-level reset/configuration completion can be determined by first
93  //polling the BYTE_TEST register
94  do
95  {
96  //Read BYTE_TEST register
98 
99  //The returned data is invalid until the serial interface reset is
100  //complete
101  } while(value != LAN9354_BYTE_TEST_DEFAULT);
102 
103  //The completion of the entire chip-level reset must then be determined
104  //by polling the READY bit of the HW_CFG register
105  do
106  {
107  //Read HW_CFG register
108  value = lan9354ReadSysReg(interface, LAN9354_HW_CFG);
109 
110  //When set, the READY bit indicates that the reset has completed and
111  //the device is ready to be accessed
112  } while((value & LAN9354_HW_CFG_DEVICE_READY) == 0);
113 
114 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
115  //Enable special VLAN tagging mode
118 
119  //Configure egress VLAN tagging rules
122 #else
123  //Disable special VLAN tagging mode
125 
126  //Revert to default configuration
128 #endif
129 
130 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
131  //Port separation mode?
132  if(interface->port != 0)
133  {
134  //Enable port mirroring
141 
142  //Configure port state
147  }
148  else
149 #endif
150  {
151  //Disable port mirroring
153 
154  //Configure port state
159  }
160 
161  //Configure port 0 receive parameters
164 
165  //Configure port 0 transmit parameters
169 
170  //Loop through the ports
172  {
173  //Debug message
174  TRACE_DEBUG("Port %u:\r\n", port);
175  //Dump PHY registers for debugging purpose
176  lan9354DumpPhyReg(interface, port);
177  }
178 
179  //Perform custom configuration
180  lan9354InitHook(interface);
181 
182  //Force the TCP/IP stack to poll the link state at startup
183  interface->phyEvent = TRUE;
184  //Notify the TCP/IP stack of the event
186 
187  //Successful initialization
188  return NO_ERROR;
189 }
190 
191 
192 /**
193  * @brief LAN9354 custom configuration
194  * @param[in] interface Underlying network interface
195  **/
196 
197 __weak_func void lan9354InitHook(NetInterface *interface)
198 {
199 }
200 
201 
202 /**
203  * @brief LAN9354 timer handler
204  * @param[in] interface Underlying network interface
205  **/
206 
207 void lan9354Tick(NetInterface *interface)
208 {
209  uint_t port;
210  bool_t linkState;
211 
212 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
213  //Port separation mode?
214  if(interface->port != 0)
215  {
216  uint_t i;
217  NetInterface *virtualInterface;
218 
219  //Loop through network interfaces
220  for(i = 0; i < NET_INTERFACE_COUNT; i++)
221  {
222  //Point to the current interface
223  virtualInterface = &netInterface[i];
224 
225  //Check whether the current virtual interface is attached to the
226  //physical interface
227  if(virtualInterface == interface ||
228  virtualInterface->parent == interface)
229  {
230  //Retrieve current link state
231  linkState = lan9354GetLinkState(interface, virtualInterface->port);
232 
233  //Link up or link down event?
234  if(linkState != virtualInterface->linkState)
235  {
236  //Set event flag
237  interface->phyEvent = TRUE;
238  //Notify the TCP/IP stack of the event
240  }
241  }
242  }
243  }
244  else
245 #endif
246  {
247  //Initialize link state
248  linkState = FALSE;
249 
250  //Loop through the ports
252  {
253  //Retrieve current link state
254  if(lan9354GetLinkState(interface, port))
255  {
256  linkState = TRUE;
257  }
258  }
259 
260  //Link up or link down event?
261  if(linkState != interface->linkState)
262  {
263  //Set event flag
264  interface->phyEvent = TRUE;
265  //Notify the TCP/IP stack of the event
267  }
268  }
269 }
270 
271 
272 /**
273  * @brief Enable interrupts
274  * @param[in] interface Underlying network interface
275  **/
276 
278 {
279 }
280 
281 
282 /**
283  * @brief Disable interrupts
284  * @param[in] interface Underlying network interface
285  **/
286 
288 {
289 }
290 
291 
292 /**
293  * @brief LAN9354 event handler
294  * @param[in] interface Underlying network interface
295  **/
296 
298 {
299  uint_t port;
300  bool_t linkState;
301 
302 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
303  //Port separation mode?
304  if(interface->port != 0)
305  {
306  uint_t i;
307  uint16_t status;
308  NetInterface *virtualInterface;
309 
310  //Loop through network interfaces
311  for(i = 0; i < NET_INTERFACE_COUNT; i++)
312  {
313  //Point to the current interface
314  virtualInterface = &netInterface[i];
315 
316  //Check whether the current virtual interface is attached to the
317  //physical interface
318  if(virtualInterface == interface ||
319  virtualInterface->parent == interface)
320  {
321  //Get the port number associated with the current interface
322  port = virtualInterface->port;
323 
324  //Valid port?
325  if(port >= LAN9354_PORT1 && port <= LAN9354_PORT2)
326  {
327  //Retrieve current link state
328  linkState = lan9354GetLinkState(interface, port);
329 
330  //Link up event?
331  if(linkState && !virtualInterface->linkState)
332  {
333  //Adjust MAC configuration parameters for proper operation
334  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
335  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
336  interface->nicDriver->updateMacConfig(interface);
337 
338  //Read PHY special control/status register
339  status = lan9354ReadPhyReg(interface, port, LAN9354_PSCSR);
340 
341  //Check current operation mode
342  switch(status & LAN9354_PSCSR_SPEED)
343  {
344  //10BASE-T half-duplex
346  virtualInterface->linkSpeed = NIC_LINK_SPEED_10MBPS;
347  virtualInterface->duplexMode = NIC_HALF_DUPLEX_MODE;
348  break;
349 
350  //10BASE-T full-duplex
352  virtualInterface->linkSpeed = NIC_LINK_SPEED_10MBPS;
353  virtualInterface->duplexMode = NIC_FULL_DUPLEX_MODE;
354  break;
355 
356  //100BASE-TX half-duplex
358  virtualInterface->linkSpeed = NIC_LINK_SPEED_100MBPS;
359  virtualInterface->duplexMode = NIC_HALF_DUPLEX_MODE;
360  break;
361 
362  //100BASE-TX full-duplex
364  virtualInterface->linkSpeed = NIC_LINK_SPEED_100MBPS;
365  virtualInterface->duplexMode = NIC_FULL_DUPLEX_MODE;
366  break;
367 
368  //Unknown operation mode
369  default:
370  //Debug message
371  TRACE_WARNING("Invalid operation mode!\r\n");
372  break;
373  }
374 
375  //Update link state
376  virtualInterface->linkState = TRUE;
377 
378  //Process link state change event
379  nicNotifyLinkChange(virtualInterface);
380  }
381  //Link down event
382  else if(!linkState && virtualInterface->linkState)
383  {
384  //Update link state
385  virtualInterface->linkState = FALSE;
386 
387  //Process link state change event
388  nicNotifyLinkChange(virtualInterface);
389  }
390  }
391  }
392  }
393  }
394  else
395 #endif
396  {
397  //Initialize link state
398  linkState = FALSE;
399 
400  //Loop through the ports
402  {
403  //Retrieve current link state
404  if(lan9354GetLinkState(interface, port))
405  {
406  linkState = TRUE;
407  }
408  }
409 
410  //Link up event?
411  if(linkState)
412  {
413  //Adjust MAC configuration parameters for proper operation
414  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
415  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
416  interface->nicDriver->updateMacConfig(interface);
417 
418  //Update link state
419  interface->linkState = TRUE;
420  }
421  else
422  {
423  //Update link state
424  interface->linkState = FALSE;
425  }
426 
427  //Process link state change event
428  nicNotifyLinkChange(interface);
429  }
430 }
431 
432 
433 /**
434  * @brief Add special VLAN tag to Ethernet frame
435  * @param[in] interface Underlying network interface
436  * @param[in] buffer Multi-part buffer containing the payload
437  * @param[in,out] offset Offset to the first payload byte
438  * @param[in] ancillary Additional options passed to the stack along with
439  * the packet
440  * @return Error code
441  **/
442 
444  size_t *offset, NetTxAncillary *ancillary)
445 {
446  error_t error;
447 
448  //Initialize status code
449  error = NO_ERROR;
450 
451 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
452  //Valid port?
453  if(ancillary->port <= LAN9354_PORT2)
454  {
455  //Is there enough space for the VLAN tag?
456  if(*offset >= sizeof(VlanTag))
457  {
458  EthHeader *header;
459  VlanTag *vlanTag;
460 
461  //Make room for the special VLAN tag
462  *offset -= sizeof(VlanTag);
463  //Point to the beginning of the frame
464  header = netBufferAt(buffer, *offset, 0);
465 
466  //Move the Ethernet header to make room for the special VLAN tag
467  osMemmove(header, (uint8_t *) header + sizeof(VlanTag),
468  sizeof(EthHeader));
469 
470  //The special VLAN tag is a normal VLAN tag where the VID field is
471  //used as the destination port indicator
472  vlanTag = (VlanTag *) header->data;
473 
474  //Default port number?
475  if(ancillary->port == 0)
476  {
477  //If VID bit 3 is one, then the normal ALR lookup is performed
478  vlanTag->tci = htons(LAN9354_VID_ALR_LOOKUP);
479  }
480  else
481  {
482  //VID bits 0 and 1 specify the destination port
483  vlanTag->tci = htons(LAN9354_VID_STP_OVERRIDE | ancillary->port);
484  }
485 
486  //The EtherType field indicates which protocol is encapsulated in
487  //the payload
488  vlanTag->type = header->type;
489 
490  //A distinct Ethertype has been allocated for use in the TPID field
491  header->type = HTONS(ETH_TYPE_VLAN);
492  }
493  else
494  {
495  //Report an error
496  error = ERROR_INVALID_PARAMETER;
497  }
498  }
499  else
500  {
501  //The port number is not valid
502  error = ERROR_INVALID_PORT;
503  }
504 #endif
505 
506  //Return status code
507  return error;
508 }
509 
510 
511 /**
512  * @brief Decode special VLAN 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 lan9354UntagFrame(NetInterface *interface, uint8_t **frame,
522  size_t *length, NetRxAncillary *ancillary)
523 {
524  error_t error;
525 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
526  EthHeader *header;
527  VlanTag *vlanTag;
528 #endif
529 
530  //Initialize status code
531  error = NO_ERROR;
532 
533 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
534  //Point to the beginning of the frame
535  header = (EthHeader *) *frame;
536 
537  //Check whether VLAN tagging is used
538  if(ntohs(header->type) == ETH_TYPE_VLAN)
539  {
540  //Valid Ethernet frame received?
541  if(*length >= (sizeof(EthHeader) + sizeof(VlanTag)))
542  {
543  //The special VLAN tag is a normal VLAN tag where the VID field is
544  //used as a source port indicator
545  vlanTag = (VlanTag *) header->data;
546 
547  //VID bits 0 and 1 specify the source port
548  ancillary->port = ntohs(vlanTag->tci) & LAN9354_VID_SRC_PORT;
549  //Fix the value of the EtherType field
550  header->type = vlanTag->type;
551 
552  //Strip the VLAN tag from the Ethernet frame
553  osMemmove(*frame + sizeof(VlanTag), *frame, sizeof(EthHeader));
554 
555  //Point to the Ethernet frame header
556  *frame += sizeof(VlanTag);
557  //Retrieve the length of the original frame
558  *length -= sizeof(VlanTag);
559 
560  //Successful processing
561  error = NO_ERROR;
562  }
563  else
564  {
565  //Drop the received frame
566  error = ERROR_INVALID_LENGTH;
567  }
568  }
569  else
570  {
571  //If the interface is configured to accept VLAN-tagged frames, then
572  //drop the incoming Ethernet frame
573  error = ERROR_WRONG_IDENTIFIER;
574  }
575 #endif
576 
577  //Return status code
578  return error;
579 }
580 
581 
582 /**
583  * @brief Get link state
584  * @param[in] interface Underlying network interface
585  * @param[in] port Port number
586  * @return Link state
587  **/
588 
590 {
591  uint16_t status;
592  bool_t linkState;
593 
594  //Check port number
595  if(port >= LAN9354_PORT1 && port <= LAN9354_PORT2)
596  {
597  //Read status register
598  status = lan9354ReadPhyReg(interface, port, LAN9354_BMSR);
599 
600  //Retrieve current link state
601  linkState = (status & LAN9354_BMSR_LINK_STATUS) ? TRUE : FALSE;
602  }
603  else
604  {
605  //The specified port number is not valid
606  linkState = FALSE;
607  }
608 
609  //Return link status
610  return linkState;
611 }
612 
613 
614 /**
615  * @brief Get link speed
616  * @param[in] interface Underlying network interface
617  * @param[in] port Port number
618  * @return Link speed
619  **/
620 
621 uint32_t lan9354GetLinkSpeed(NetInterface *interface, uint8_t port)
622 {
623  uint16_t status;
624  uint32_t linkSpeed;
625 
626  //Check port number
627  if(port >= LAN9354_PORT1 && port <= LAN9354_PORT2)
628  {
629  //Read PHY special control/status register
630  status = lan9354ReadPhyReg(interface, port, LAN9354_PSCSR);
631 
632  //Check current operation mode
633  switch(status & LAN9354_PSCSR_SPEED)
634  {
635  //10BASE-T
638  linkSpeed = NIC_LINK_SPEED_10MBPS;
639  break;
640 
641  //100BASE-TX
644  linkSpeed = NIC_LINK_SPEED_100MBPS;
645  break;
646 
647  //Unknown operation mode
648  default:
649  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
650  break;
651  }
652  }
653  else
654  {
655  //The specified port number is not valid
656  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
657  }
658 
659  //Return link status
660  return linkSpeed;
661 }
662 
663 
664 /**
665  * @brief Get duplex mode
666  * @param[in] interface Underlying network interface
667  * @param[in] port Port number
668  * @return Duplex mode
669  **/
670 
672 {
673  uint16_t status;
674  NicDuplexMode duplexMode;
675 
676  //Check port number
677  if(port >= LAN9354_PORT1 && port <= LAN9354_PORT2)
678  {
679  //Read PHY special control/status register
680  status = lan9354ReadPhyReg(interface, port, LAN9354_PSCSR);
681 
682  //Check current operation mode
683  switch(status & LAN9354_PSCSR_SPEED)
684  {
685  //10BASE-T or 100BASE-TX half-duplex
688  duplexMode = NIC_HALF_DUPLEX_MODE;
689  break;
690 
691  //10BASE-T or 100BASE-TX full-duplex
694  duplexMode = NIC_FULL_DUPLEX_MODE;
695  break;
696 
697  //Unknown operation mode
698  default:
699  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
700  break;
701  }
702  }
703  else
704  {
705  //The specified port number is not valid
706  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
707  }
708 
709  //Return duplex mode
710  return duplexMode;
711 }
712 
713 
714 /**
715  * @brief Set port state
716  * @param[in] interface Underlying network interface
717  * @param[in] port Port number
718  * @param[in] state Port state
719  **/
720 
721 void lan9354SetPortState(NetInterface *interface, uint8_t port,
722  SwitchPortState state)
723 {
724  uint32_t temp;
725 
726  //Read port state register
727  temp = lan9354ReadSwitchReg(interface, LAN9354_SWE_PORT_STATE);
728 
729  //Check port number
730  if(port == LAN9354_PORT1)
731  {
732  //Clear current configuration
734 
735  //Update port 1 state
736  switch(state)
737  {
740  break;
743  break;
746  break;
747  default:
749  break;
750  }
751  }
752  else if(port == LAN9354_PORT2)
753  {
754  //Clear current configuration
756 
757  //Update port 2 state
758  switch(state)
759  {
762  break;
765  break;
768  break;
769  default:
771  break;
772  }
773  }
774  else
775  {
776  //The specified port number is not valid
777  }
778 
779  //Write the value back to port state register
781 }
782 
783 
784 /**
785  * @brief Get port state
786  * @param[in] interface Underlying network interface
787  * @param[in] port Port number
788  * @return Port state
789  **/
790 
792 {
793  uint32_t temp;
794  SwitchPortState state;
795 
796  //Read port state register
797  temp = lan9354ReadSwitchReg(interface, LAN9354_SWE_PORT_STATE);
798 
799  //Check port number
800  if(port == LAN9354_PORT1)
801  {
802  //Check port 1 state
803  switch(temp & LAN9354_SWE_PORT_STATE_PORT1)
804  {
807  break;
810  break;
813  break;
814  default:
816  break;
817  }
818  }
819  else if(port == LAN9354_PORT2)
820  {
821  //Check port 2 state
822  switch(temp & LAN9354_SWE_PORT_STATE_PORT2)
823  {
826  break;
829  break;
832  break;
833  default:
835  break;
836  }
837  }
838  else
839  {
840  //The specified port number is not valid
842  }
843 
844  //Return port state
845  return state;
846 }
847 
848 
849 /**
850  * @brief Set aging time for dynamic filtering entries
851  * @param[in] interface Underlying network interface
852  * @param[in] agingTime Aging time, in seconds
853  **/
854 
855 void lan9354SetAgingTime(NetInterface *interface, uint32_t agingTime)
856 {
857  uint32_t temp;
858 
859  //The maximum value is approximately 69 minutes
860  agingTime = MAX(agingTime, 1);
861  agingTime = MIN(agingTime, 4096);
862 
863  //The time is specified in 1 second increments plus 1 second
864  temp = ((agingTime - 1) << 16) & LAN9354_SWE_ALR_CFG_AGING_TIME;
865 
866  //Write the value to the Switch Engine ALR Configuration register
867  lan9354WriteSwitchReg(interface, LAN9354_SWE_ALR_CFG, temp |
869 }
870 
871 
872 /**
873  * @brief Enable IGMP snooping
874  * @param[in] interface Underlying network interface
875  * @param[in] enable Enable or disable IGMP snooping
876  **/
877 
879 {
880  uint32_t temp;
881 
882  //Read the Switch Engine Global Ingress Configuration register
884 
885  //Enable or disable IGMP monitoring
886  if(enable)
887  {
889  }
890  else
891  {
893  }
894 
895  //Set the port bit map where IGMP packets are sent
898 
899  //Write the value back to Switch Engine Global Ingress Configuration register
901 }
902 
903 
904 /**
905  * @brief Enable MLD snooping
906  * @param[in] interface Underlying network interface
907  * @param[in] enable Enable or disable MLD snooping
908  **/
909 
911 {
912  uint32_t temp;
913 
914  //Read the Switch Engine Global Ingress Configuration register
916 
917  //Enable or disable MLD monitoring
918  if(enable)
919  {
921  }
922  else
923  {
925  }
926 
927  //Set the port bit map where MLD packets are sent
930 
931  //Write the value back to Switch Engine Global Ingress Configuration register
933 }
934 
935 
936 /**
937  * @brief Enable reserved multicast table
938  * @param[in] interface Underlying network interface
939  * @param[in] enable Enable or disable reserved group addresses
940  **/
941 
943 {
944  uint_t i;
945  SwitchFdbEntry entry;
946 
947  //The reserved group addresses are in the range of 01-80-C2-00-00-00 to
948  //01-80-C2-00-00-0F
949  for(i = 0; i <= 15; i++)
950  {
951  //Specify the reserved group address to be added or removed
952  entry.macAddr.b[0] = 0x01;
953  entry.macAddr.b[1] = 0x80;
954  entry.macAddr.b[2] = 0xC2;
955  entry.macAddr.b[3] = 0x00;
956  entry.macAddr.b[4] = 0x00;
957  entry.macAddr.b[5] = i;
958 
959  //Format forwarding database entry
960  entry.srcPort = 0;
962  entry.override = TRUE;
963 
964  //Update the static MAC table
965  if(enable)
966  {
967  lan9354AddStaticFdbEntry(interface, &entry);
968  }
969  else
970  {
971  lan9354DeleteStaticFdbEntry(interface, &entry);
972  }
973  }
974 }
975 
976 
977 /**
978  * @brief Add a new entry to the static MAC table
979  * @param[in] interface Underlying network interface
980  * @param[in] entry Pointer to the forwarding database entry
981  * @return Error code
982  **/
983 
985  const SwitchFdbEntry *entry)
986 {
987  uint32_t value;
988  uint32_t ports;
989 
990  //Check whether the forward port is the CPU port
991  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
992  {
993  ports = LAN9354_PORT0_MASK;
994  }
995  else
996  {
997  ports = entry->destPorts & LAN9354_PORT_MASK;
998  }
999 
1000  //Valid forward ports?
1001  if(ports != 0)
1002  {
1003  //Write SWE_ALR_WR_DAT_0 and SWE_ALR_WR_DAT_1 with the desired MAC
1004  //address and control bits
1006 
1007  //When the Override bit set, packets received with a destination
1008  //address that matches the MAC address in the SWE_ALR_WR_DAT_1 and
1009  //SWE_ALR_WR_DAT_0 registers will be forwarded regardless of the port
1010  //state
1011  if(entry->override)
1012  {
1014  }
1015 
1016  //Set the ports associated with this MAC address
1017  switch(ports)
1018  {
1019  case LAN9354_PORT0_MASK:
1021  break;
1022  case LAN9354_PORT1_MASK:
1024  break;
1025  case LAN9354_PORT2_MASK:
1027  break;
1028  case LAN9354_PORT0_1_MASK:
1030  break;
1031  case LAN9354_PORT0_2_MASK:
1033  break;
1034  case LAN9354_PORT1_2_MASK:
1036  break;
1037  default:
1039  break;
1040  }
1041  }
1042  else
1043  {
1044  //An entry can be deleted by setting the Valid bit to 0
1046  }
1047 
1048  //Copy MAC address (last 16 bits)
1049  value |= entry->macAddr.b[4] | (entry->macAddr.b[5] << 8);
1050  //Write SWE_ALR_WR_DAT_1 register
1052 
1053  //Copy MAC address (first 32 bits)
1054  value = entry->macAddr.b[0] | (entry->macAddr.b[1] << 8) |
1055  (entry->macAddr.b[2] << 16) | (entry->macAddr.b[3] << 24);
1056 
1057  //Write SWE_ALR_WR_DAT_0 register
1059 
1060  //Write the SWE_ALR_CMD register
1063 
1064  //Poll the Make Pending bit in the SWE_ALR_CMD_STS register until it is
1065  //cleared
1066  do
1067  {
1068  //Read the SWE_ALR_CMD_STS register
1070 
1071  //Check the Make Pending bit
1073 
1074  //Clear the SWE_ALR_CMD register
1076 
1077  //Successful processing
1078  return NO_ERROR;
1079 }
1080 
1081 
1082 /**
1083  * @brief Remove an entry from the static MAC table
1084  * @param[in] interface Underlying network interface
1085  * @param[in] entry Forwarding database entry to remove from the table
1086  * @return Error code
1087  **/
1088 
1090  const SwitchFdbEntry *entry)
1091 {
1092  uint32_t value;
1093 
1094  //An entry can be deleted by setting the Valid bit to 0
1096 
1097  //Specify the MAC address to remove (last 16 bits)
1098  value |= entry->macAddr.b[4] | (entry->macAddr.b[5] << 8);
1099  //Write SWE_ALR_WR_DAT_1 register
1101 
1102  //Specify the MAC address to remove (first 32 bits)
1103  value = entry->macAddr.b[0] | (entry->macAddr.b[1] << 8) |
1104  (entry->macAddr.b[2] << 16) | (entry->macAddr.b[3] << 24);
1105 
1106  //Write SWE_ALR_WR_DAT_0 register
1108 
1109  //Write the SWE_ALR_CMD register
1112 
1113  //Poll the Make Pending bit in the SWE_ALR_CMD_STS register until it is
1114  //cleared
1115  do
1116  {
1117  //Read the SWE_ALR_CMD_STS register
1119 
1120  //Check the Make Pending bit
1122 
1123  //Clear the SWE_ALR_CMD register
1125 
1126  //Successful processing
1127  return NO_ERROR;
1128 }
1129 
1130 
1131 /**
1132  * @brief Read an entry from the static MAC table
1133  * @param[in] interface Underlying network interface
1134  * @param[in] index Zero-based index of the entry to read
1135  * @param[out] entry Pointer to the forwarding database entry
1136  * @return Error code
1137  **/
1138 
1140  SwitchFdbEntry *entry)
1141 {
1142  uint32_t value;
1143 
1144  //Loop through the ALR table
1145  while(1)
1146  {
1147  //Out of bound index?
1148  if(index >= LAN9354_ALR_TABLE_SIZE)
1149  return ERROR_END_OF_TABLE;
1150 
1151  //First entry?
1152  if(index == 0)
1153  {
1155  }
1156  else
1157  {
1159  }
1160 
1161  //Write the SWE_ALR_CMD register
1163  //Clear the SWE_ALR_CMD register
1165 
1166  //Poll the Valid and End of Table bits in the SWE_ALR_RD_DAT_1 register
1167  //until either is set
1168  while(1)
1169  {
1170  //Read SWE_ALR_RD_DAT_1 register
1172 
1173  //If the End of Table bit is set, then exit
1175  {
1176  return ERROR_END_OF_TABLE;
1177  }
1178 
1179  //If the Valid bit is set, then the entry is valid
1181  {
1182  break;
1183  }
1184  }
1185 
1186  //Static entry?
1188  {
1189  break;
1190  }
1191 
1192  //Skip dynamic entries
1193  index++;
1194  }
1195 
1196  //Store the data from SWE_ALR_RD_DAT_0 and SWE_ALR_RD_DAT_1 registers
1197  entry->srcPort = 0;
1198  entry->override = FALSE;
1199 
1200  //Retrieve the ports associated with this MAC address
1202  {
1204  entry->destPorts = LAN9354_PORT0_MASK;
1205  break;
1207  entry->destPorts = LAN9354_PORT1_MASK;
1208  break;
1210  entry->destPorts = LAN9354_PORT2_MASK;
1211  break;
1214  break;
1217  break;
1220  break;
1223  break;
1224  default:
1225  entry->destPorts = 0;
1226  break;
1227  }
1228 
1229  //Copy MAC address (last 16 bits)
1230  entry->macAddr.b[4] = value & 0xFF;
1231  entry->macAddr.b[5] = (value >> 8) & 0xFF;
1232 
1233  //Read SWE_ALR_RD_DAT_0 register
1235 
1236  //Copy MAC address (first 32 bits)
1237  entry->macAddr.b[0] = value & 0xFF;
1238  entry->macAddr.b[1] = (value >> 8) & 0xFF;
1239  entry->macAddr.b[2] = (value >> 16) & 0xFF;
1240  entry->macAddr.b[3] = (value >> 24) & 0xFF;
1241 
1242  //Successful processing
1243  return NO_ERROR;
1244 }
1245 
1246 
1247 /**
1248  * @brief Flush static MAC table
1249  * @param[in] interface Underlying network interface
1250  **/
1251 
1253 {
1254  error_t error;
1255  uint_t i;
1256  SwitchFdbEntry entry;
1257 
1258  //Loop through the ALR table
1259  for(i = 0; i < LAN9354_ALR_TABLE_SIZE; i++)
1260  {
1261  //Read current entry
1262  error = lan9354GetStaticFdbEntry(interface, i, &entry);
1263 
1264  //Valid entry?
1265  if(!error)
1266  {
1267  //An entry can be deleted by setting the Valid bit to 0
1268  lan9354DeleteStaticFdbEntry(interface, &entry);
1269  }
1270  else
1271  {
1272  //The end of the table has been reached
1273  break;
1274  }
1275  }
1276 }
1277 
1278 
1279 /**
1280  * @brief Read an entry from the dynamic MAC table
1281  * @param[in] interface Underlying network interface
1282  * @param[in] index Zero-based index of the entry to read
1283  * @param[out] entry Pointer to the forwarding database entry
1284  * @return Error code
1285  **/
1286 
1288  SwitchFdbEntry *entry)
1289 {
1290  uint32_t value;
1291 
1292  //Loop through the ALR table
1293  while(1)
1294  {
1295  //Out of bound index?
1296  if(index >= LAN9354_ALR_TABLE_SIZE)
1297  return ERROR_END_OF_TABLE;
1298 
1299  //First entry?
1300  if(index == 0)
1301  {
1303  }
1304  else
1305  {
1307  }
1308 
1309  //Write the SWE_ALR_CMD register
1311  //Clear the SWE_ALR_CMD register
1313 
1314  //Poll the Valid and End of Table bits in the SWE_ALR_RD_DAT_1 register
1315  //until either is set
1316  while(1)
1317  {
1318  //Read SWE_ALR_RD_DAT_1 register
1320 
1321  //If the End of Table bit is set, then exit
1323  {
1324  return ERROR_END_OF_TABLE;
1325  }
1326 
1327  //If the Valid bit is set, then the entry is valid
1329  {
1330  break;
1331  }
1332  }
1333 
1334  //Dynamic entry?
1336  {
1337  break;
1338  }
1339 
1340  //Skip static entries
1341  index++;
1342  }
1343 
1344  //Store the data from SWE_ALR_RD_DAT_0 and SWE_ALR_RD_DAT_1 registers
1345  entry->destPorts = 0;
1346  entry->override = FALSE;
1347 
1348  //Retrieve the port associated with this MAC address
1350  {
1352  entry->srcPort = LAN9354_PORT0;
1353  break;
1355  entry->srcPort = LAN9354_PORT1;
1356  break;
1358  entry->srcPort = LAN9354_PORT2;
1359  break;
1360  default:
1361  entry->srcPort = 0;
1362  break;
1363  }
1364 
1365  //Copy MAC address (last 16 bits)
1366  entry->macAddr.b[4] = value & 0xFF;
1367  entry->macAddr.b[5] = (value >> 8) & 0xFF;
1368 
1369  //Read SWE_ALR_RD_DAT_0 register
1371 
1372  //Copy MAC address (first 32 bits)
1373  entry->macAddr.b[0] = value & 0xFF;
1374  entry->macAddr.b[1] = (value >> 8) & 0xFF;
1375  entry->macAddr.b[2] = (value >> 16) & 0xFF;
1376  entry->macAddr.b[3] = (value >> 24) & 0xFF;
1377 
1378  //Successful processing
1379  return NO_ERROR;
1380 }
1381 
1382 
1383 /**
1384  * @brief Flush dynamic MAC table
1385  * @param[in] interface Underlying network interface
1386  * @param[in] port Port number
1387  **/
1388 
1390 {
1391  error_t error;
1392  uint_t i;
1393  uint32_t value;
1394  SwitchFdbEntry entry;
1395 
1396  //Loop through the ALR table
1397  for(i = 0; i < LAN9354_ALR_TABLE_SIZE; i++)
1398  {
1399  //Read current entry
1400  error = lan9354GetDynamicFdbEntry(interface, i, &entry);
1401 
1402  //Valid entry?
1403  if(!error)
1404  {
1405  //Matching port number?
1406  if(entry.srcPort == port || port == 0)
1407  {
1408  //Specify the MAC address to remove (last 16 bits)
1409  value = entry.macAddr.b[4] | (entry.macAddr.b[5] << 8);
1410  //Write SWE_ALR_WR_DAT_1 register
1412 
1413  //Specify the MAC address to remove (first 32 bits)
1414  value = entry.macAddr.b[0] | (entry.macAddr.b[1] << 8) |
1415  (entry.macAddr.b[2] << 16) | (entry.macAddr.b[3] << 24);
1416 
1417  //Write SWE_ALR_WR_DAT_0 register
1419 
1420  //Write the SWE_ALR_CMD register
1423 
1424  //Poll the Make Pending bit in the SWE_ALR_CMD_STS register until
1425  //it is cleared
1426  do
1427  {
1428  //Read the SWE_ALR_CMD_STS register
1430 
1431  //Check the Make Pending bit
1433 
1434  //Clear the SWE_ALR_CMD register
1436  }
1437  }
1438  else
1439  {
1440  //The end of the table has been reached
1441  break;
1442  }
1443  }
1444 }
1445 
1446 
1447 /**
1448  * @brief Set forward ports for unknown multicast packets
1449  * @param[in] interface Underlying network interface
1450  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1451  * @param[in] forwardPorts Port map
1452  **/
1453 
1455  bool_t enable, uint32_t forwardPorts)
1456 {
1457  //Not implemented
1458 }
1459 
1460 
1461 /**
1462  * @brief Write PHY register
1463  * @param[in] interface Underlying network interface
1464  * @param[in] port Port number
1465  * @param[in] address PHY register address
1466  * @param[in] data Register value
1467  **/
1468 
1469 void lan9354WritePhyReg(NetInterface *interface, uint8_t port,
1470  uint8_t address, uint16_t data)
1471 {
1472  //Write the specified PHY register
1473  if(interface->smiDriver != NULL)
1474  {
1475  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1476  }
1477  else
1478  {
1479  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1480  }
1481 }
1482 
1483 
1484 /**
1485  * @brief Read PHY register
1486  * @param[in] interface Underlying network interface
1487  * @param[in] port Port number
1488  * @param[in] address PHY register address
1489  * @return Register value
1490  **/
1491 
1492 uint16_t lan9354ReadPhyReg(NetInterface *interface, uint8_t port,
1493  uint8_t address)
1494 {
1495  uint16_t data;
1496 
1497  //Read the specified PHY register
1498  if(interface->smiDriver != NULL)
1499  {
1500  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1501  }
1502  else
1503  {
1504  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1505  }
1506 
1507  //Return the value of the PHY register
1508  return data;
1509 }
1510 
1511 
1512 /**
1513  * @brief Dump PHY registers for debugging purpose
1514  * @param[in] interface Underlying network interface
1515  * @param[in] port Port number
1516  **/
1517 
1518 void lan9354DumpPhyReg(NetInterface *interface, uint8_t port)
1519 {
1520  uint8_t i;
1521 
1522  //Loop through PHY registers
1523  for(i = 0; i < 32; i++)
1524  {
1525  //Display current PHY register
1526  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1527  lan9354ReadPhyReg(interface, port, i));
1528  }
1529 
1530  //Terminate with a line feed
1531  TRACE_DEBUG("\r\n");
1532 }
1533 
1534 
1535 /**
1536  * @brief Write system CSR register
1537  * @param[in] interface Underlying network interface
1538  * @param[in] address System register address
1539  * @param[in] data Register value
1540  **/
1541 
1542 void lan9354WriteSysReg(NetInterface *interface, uint16_t address,
1543  uint32_t data)
1544 {
1545  uint8_t phyAddr;
1546  uint8_t regAddr;
1547 
1548  //PHY address bit 4 is 1 for SMI commands. PHY address 3:0 form system
1549  //register address bits 9:6
1550  phyAddr = 0x10 | ((address >> 6) & 0x0F);
1551 
1552  //Register address field forms register address bits 5:1
1553  regAddr = (address >> 1) & 0x1F;
1554 
1555  //Write system CSR register
1556  if(interface->smiDriver != NULL)
1557  {
1558  //Write the low word of the SMI register
1559  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr,
1560  data & 0xFFFF);
1561 
1562  //Write the high word of the SMI register
1563  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr + 1,
1564  (data >> 16) & 0xFFFF);
1565  }
1566  else
1567  {
1568  //Write the low word of the SMI register
1569  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr,
1570  data & 0xFFFF);
1571 
1572  //Write the high word of the SMI register
1573  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr + 1,
1574  (data >> 16) & 0xFFFF);
1575  }
1576 }
1577 
1578 
1579 /**
1580  * @brief Read system CSR register
1581  * @param[in] interface Underlying network interface
1582  * @param[in] address System register address
1583  * @return Register value
1584  **/
1585 
1586 uint32_t lan9354ReadSysReg(NetInterface *interface, uint16_t address)
1587 {
1588  uint8_t phyAddr;
1589  uint8_t regAddr;
1590  uint32_t data;
1591 
1592  //PHY address bit 4 is 1 for SMI commands. PHY address 3:0 form system
1593  //register address bits 9:6
1594  phyAddr = 0x10 | ((address >> 6) & 0x0F);
1595 
1596  //Register address field forms register address bits 5:1
1597  regAddr = (address >> 1) & 0x1F;
1598 
1599  //Read system CSR register
1600  if(interface->smiDriver != NULL)
1601  {
1602  //Read the low word of the SMI register
1603  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1604  regAddr);
1605 
1606  //Read the high word of the SMI register
1607  data |= interface->smiDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1608  regAddr + 1) << 16;
1609  }
1610  else
1611  {
1612  //Read the low word of the SMI register
1613  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1614  regAddr);
1615 
1616  //Read the high word of the SMI register
1617  data |= interface->nicDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1618  regAddr + 1) << 16;
1619  }
1620 
1621  //Return register value
1622  return data;
1623 }
1624 
1625 
1626 /**
1627  * @brief Dump system CSR registers for debugging purpose
1628  * @param[in] interface Underlying network interface
1629  **/
1630 
1632 {
1633  uint16_t i;
1634 
1635  //Loop through system registers
1636  for(i = 80; i < 512; i += 4)
1637  {
1638  //Display current system register
1639  TRACE_DEBUG("0x%03" PRIX16 ": 0x%08" PRIX32 "\r\n", i,
1640  lan9354ReadSysReg(interface, i));
1641  }
1642 
1643  //Terminate with a line feed
1644  TRACE_DEBUG("\r\n");
1645 }
1646 
1647 
1648 /**
1649  * @brief Write switch fabric CSR register
1650  * @param[in] interface Underlying network interface
1651  * @param[in] address Switch fabric register address
1652  * @param[in] data Register value
1653  **/
1654 
1655 void lan9354WriteSwitchReg(NetInterface *interface, uint16_t address,
1656  uint32_t data)
1657 {
1658  uint32_t value;
1659 
1660  //To perform a write to an individual switch fabric register, the desired
1661  //data must first be written into the SWITCH_CSR_DATA register
1663 
1664  //Set up a write operation
1667 
1668  //Set register address
1670 
1671  //The write cycle is initiated by performing a single write to the
1672  //SWITCH_CSR_CMD register
1674 
1675  //The completion of the write cycle is indicated by the clearing of the
1676  //CSR_BUSY bit
1677  do
1678  {
1679  //Read SWITCH_CSR_CMD register
1681 
1682  //Poll CSR_BUSY bit
1683  } while((value & LAN9354_SWITCH_CSR_CMD_BUSY) != 0);
1684 }
1685 
1686 
1687 /**
1688  * @brief Read switch fabric CSR register
1689  * @param[in] interface Underlying network interface
1690  * @param[in] address Switch fabric register address
1691  * @return Register value
1692  **/
1693 
1694 uint32_t lan9354ReadSwitchReg(NetInterface *interface, uint16_t address)
1695 {
1696  uint32_t value;
1697 
1698  //Set up a read operation
1701 
1702  //Set register address
1704 
1705  //To perform a read of an individual switch fabric register, the read cycle
1706  //must be initiated by performing a single write to the SWITCH_CSR_CMD
1707  //register
1709 
1710  //Valid data is available for reading when the CSR_BUSY bit is cleared
1711  do
1712  {
1713  //Read SWITCH_CSR_CMD register
1715 
1716  //Poll CSR_BUSY bit
1717  } while((value & LAN9354_SWITCH_CSR_CMD_BUSY) != 0);
1718 
1719  //Read data from the SWITCH_CSR_DATA register
1720  return lan9354ReadSysReg(interface, LAN9354_SWITCH_CSR_DATA);
1721 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:559
error_t lan9354Init(NetInterface *interface)
LAN9354 Ethernet switch initialization.
#define LAN9354_SWE_PORT_STATE
#define htons(value)
Definition: cpu_endian.h:413
#define LAN9354_MAC_RX_CFG_RX_EN
#define LAN9354_SWE_ALR_CMD_GET_NEXT_ENTRY
#define LAN9354_SWE_ALR_WR_DAT_1_PORT_2
#define LAN9354_SWE_ALR_RD_DAT_1_PORT_1
#define LAN9354_PORT0
#define LAN9354_SWITCH_CSR_CMD_ADDR
#define LAN9354_SWE_PORT_STATE_PORT0_FORWARDING
#define LAN9354_VID_ALR_LOOKUP
#define LAN9354_SWE_ALR_RD_DAT_1_PORT
#define LAN9354_SWE_ALR_WR_DAT_1_VALID
#define LAN9354_SWE_PORT_STATE_PORT1_LEARNING
int bool_t
Definition: compiler_port.h:53
void lan9354WriteSwitchReg(NetInterface *interface, uint16_t address, uint32_t data)
Write switch fabric CSR register.
#define LAN9354_SWE_ALR_RD_DAT_1_PORT_1_2
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
uint32_t destPorts
Definition: nic.h:152
#define netEvent
Definition: net_legacy.h:196
void lan9354SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define LAN9354_SWE_ALR_RD_DAT_1_PORT_0_1
#define LAN9354_HW_CFG_DEVICE_READY
#define LAN9354_SWE_ALR_CMD
void lan9354WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
void lan9354EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
#define LAN9354_PSCSR_SPEED_10BT_HD
#define LAN9354_SWE_PORT_STATE_PORT1_FORWARDING
@ ERROR_END_OF_TABLE
Definition: error.h:291
@ 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
void lan9354WriteSysReg(NetInterface *interface, uint16_t address, uint32_t data)
Write system CSR register.
uint8_t data[]
Definition: ethernet.h:222
void lan9354DisableIrq(NetInterface *interface)
Disable interrupts.
#define LAN9354_SWE_ALR_CFG_AGING_TIME
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
#define LAN9354_SWE_ALR_RD_DAT_1_PORT_0_1_2
#define LAN9354_SWE_ALR_WR_DAT_1_AGE1_OVERRIDE
void lan9354EnableIrq(NetInterface *interface)
Enable interrupts.
#define LAN9354_SWE_ALR_RD_DAT_1_STATIC
#define LAN9354_SWE_GLOBAL_INGRSS_CFG_MLD_IGMP_MONITOR_PORT
#define LAN9354_SWE_ALR_WR_DAT_1_PORT_0_2
#define NET_INTERFACE_COUNT
Definition: net.h:114
#define LAN9354_SWE_GLOBAL_INGRSS_CFG
#define LAN9354_SWE_ALR_WR_DAT_1_PORT_0_1_2
#define LAN9354_SWE_ALR_CFG_ALR_AGE_EN
#define LAN9354_HW_CFG
#define LAN9354_BMSR_LINK_STATUS
@ ERROR_INVALID_PORT
Definition: error.h:104
void lan9354EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
#define LAN9354_VID_STP_OVERRIDE
#define LAN9354_PSCSR_SPEED_10BT_FD
#define LAN9354_SWE_GLOBAL_INGRSS_CFG_MLD_MONITORING_EN
#define LAN9354_SWE_PORT_MIRROR
EthHeader
Definition: ethernet.h:223
#define LAN9354_PSCSR
#define LAN9354_SWITCH_CSR_CMD_BUSY
#define LAN9354_PORT1
VlanTag
Definition: ethernet.h:246
#define LAN9354_SWE_ALR_RD_DAT_1_VALID
void lan9354SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define LAN9354_SWE_ALR_RD_DAT_1_PORT_0
#define LAN9354_SWE_ALR_RD_DAT_1
#define LAN9354_SWE_ALR_WR_DAT_1_PORT_0
#define LAN9354_SWE_GLOBAL_INGRSS_CFG_MLD_IGMP_MONITOR_PORT_0
#define LAN9354_MAC_TX_CFG_TX_PAD_EN
#define FALSE
Definition: os_port.h:46
uint32_t lan9354ReadSysReg(NetInterface *interface, uint16_t address)
Read system CSR register.
#define LAN9354_SWE_ALR_WR_DAT_1_PORT_1_2
#define LAN9354_SWE_ALR_WR_DAT_0
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define LAN9354_SWE_PORT_MIRROR_RX_MIRRORING_EN
error_t
Error codes.
Definition: error.h:43
#define netInterface
Definition: net_legacy.h:199
#define LAN9354_PORT0_1_2_MASK
#define LAN9354_SWE_PORT_MIRROR_MIRRORED_PORT_2
#define LAN9354_SWITCH_CSR_CMD
#define LAN9354_SWE_PORT_STATE_PORT2_FORWARDING
#define LAN9354_PORT2
__weak_func void lan9354InitHook(NetInterface *interface)
LAN9354 custom configuration.
#define LAN9354_PSCSR_SPEED_100BTX_FD
#define LAN9354_MAC_TX_CFG_TX_EN
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
#define LAN9354_MAC_TX_CFG(port)
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
#define LAN9354_MAC_TX_CFG_IFG_CONFIG_DEFAULT
@ ERROR_INVALID_LENGTH
Definition: error.h:111
error_t lan9354GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
#define LAN9354_SWE_ALR_CFG
#define LAN9354_SWE_ALR_RD_DAT_0
#define LAN9354_PORT1_2_MASK
void lan9354FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
#define NetTxAncillary
Definition: net_misc.h:36
uint16_t lan9354ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
#define LAN9354_SWE_ALR_WR_DAT_1
#define LAN9354_SWE_PORT_STATE_PORT2_DISABLED
#define LAN9354_ALR_TABLE_SIZE
#define LAN9354_SWE_PORT_STATE_PORT2_LISTENING
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
uint32_t lan9354ReadSwitchReg(NetInterface *interface, uint16_t address)
Read switch fabric CSR register.
#define MIN(a, b)
Definition: os_port.h:63
#define LAN9354_MAC_RX_CFG_REJECT_MAC_TYPES
#define LAN9354_BM_EGRSS_PORT_TYPE
#define LAN9354_SWE_ALR_WR_DAT_1_STATIC
#define LAN9354_SWITCH_CSR_DATA
NicDuplexMode lan9354GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
void lan9354Tick(NetInterface *interface)
LAN9354 timer handler.
@ SWITCH_PORT_STATE_BLOCKING
Definition: nic.h:137
void lan9354EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
#define LAN9354_SWE_PORT_MIRROR_SNIFFER_PORT_0
error_t lan9354GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
#define LAN9354_SWE_ALR_CMD_STS
#define LAN9354_SWE_PORT_STATE_PORT1
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
uint16_t port
Definition: dns_common.h:267
#define ntohs(value)
Definition: cpu_endian.h:421
#define LAN9354_SWE_ALR_RD_DAT_1_END_OF_TABLE
#define TRACE_WARNING(...)
Definition: debug.h:85
@ ETH_TYPE_VLAN
Definition: ethernet.h:167
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define LAN9354_PORT0_2_MASK
#define MAX(a, b)
Definition: os_port.h:67
#define LAN9354_SWE_ALR_RD_DAT_1_PORT_0_2
#define LAN9354_SWE_INGRSS_PORT_TYP
#define LAN9354_SWE_ALR_RD_DAT_1_PORT_2
#define LAN9354_PORT0_1_MASK
SwitchPortState lan9354GetPortState(NetInterface *interface, uint8_t port)
Get port state.
uint16_t regAddr
LAN9354 3-port Ethernet switch driver.
void lan9354SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
#define LAN9354_SWE_PORT_MIRROR_MIRRORED_PORT_1
Ethernet switch driver.
Definition: nic.h:325
const SwitchDriver lan9354SwitchDriver
LAN9354 Ethernet switch driver.
#define HTONS(value)
Definition: cpu_endian.h:410
bool_t lan9354GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
Ipv6Addr address[]
Definition: ipv6.h:325
#define LAN9354_SWE_PORT_STATE_PORT2
void lan9354DumpSysReg(NetInterface *interface)
Dump system CSR registers for debugging purpose.
NicDuplexMode
Duplex mode.
Definition: nic.h:122
MacAddr macAddr
Definition: nic.h:150
#define LAN9354_SWE_PORT_MIRROR_RX_MIRRORING_FILT_EN
#define LAN9354_SWE_ALR_CMD_STS_OPERATION_PENDING
uint8_t srcPort
Definition: nic.h:151
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
#define LAN9354_SWE_ALR_CMD_MAKE_ENTRY
uint32_t lan9354GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
#define LAN9354_PORT_MASK
uint8_t value[]
Definition: tcp.h:369
#define LAN9354_SWE_INGRSS_PORT_TYP_PORT0
#define LAN9354_BYTE_TEST_DEFAULT
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
#define LAN9354_SWITCH_CSR_CMD_READ
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define LAN9354_PORT0_MASK
#define LAN9354_SWE_ALR_WR_DAT_1_PORT_1
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void * netBufferAt(const NetBuffer *buffer, size_t offset, size_t length)
Returns a pointer to a data segment.
Definition: net_mem.c:418
error_t lan9354DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
#define LAN9354_BYTE_TEST
#define LAN9354_PORT1_MASK
#define LAN9354_MAC_RX_CFG(port)
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define LAN9354_SWE_PORT_STATE_PORT1_DISABLED
error_t lan9354TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add special VLAN tag to Ethernet frame.
#define LAN9354_SWITCH_CSR_CMD_BE
void lan9354EventHandler(NetInterface *interface)
LAN9354 event handler.
#define LAN9354_VID_SRC_PORT
#define LAN9354_SWE_ALR_WR_DAT_1_PORT_0_1
unsigned int uint_t
Definition: compiler_port.h:50
error_t lan9354UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode special VLAN tag from incoming Ethernet frame.
#define LAN9354_PSCSR_SPEED_100BTX_HD
TCP/IP stack core.
#define LAN9354_SWITCH_CSR_CMD_WRITE
void lan9354FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
void lan9354DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
#define LAN9354_SWE_PORT_STATE_PORT1_LISTENING
#define LAN9354_SWE_PORT_STATE_PORT2_LEARNING
#define LAN9354_BMSR
#define LAN9354_SWE_GLOBAL_INGRSS_CFG_IGMP_MONITORING_EN
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
Debugging facilities.
#define LAN9354_BM_EGRSS_PORT_TYPE_PORT0_TYPE_CPU
#define osMemmove(dest, src, length)
Definition: os_port.h:147
#define LAN9354_PORT2_MASK
Forwarding database entry.
Definition: nic.h:149
#define LAN9354_SWE_ALR_CMD_GET_FIRST_ENTRY
#define LAN9354_PSCSR_SPEED
error_t lan9354AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.