lan9303_driver.c
Go to the documentation of this file.
1 /**
2  * @file lan9303_driver.c
3  * @brief LAN9303 3-port Ethernet switch driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
37 #include "debug.h"
38 
39 
40 /**
41  * @brief LAN9303 Ethernet switch driver
42  **/
43 
45 {
69 };
70 
71 
72 /**
73  * @brief LAN9303 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 LAN9303...\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 != LAN9303_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 = lan9303ReadSysReg(interface, LAN9303_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 & LAN9303_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  lan9303DumpPhyReg(interface, port);
177  }
178 
179  //Perform custom configuration
180  lan9303InitHook(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
185  osSetEvent(&interface->netContext->event);
186 
187  //Successful initialization
188  return NO_ERROR;
189 }
190 
191 
192 /**
193  * @brief LAN9303 custom configuration
194  * @param[in] interface Underlying network interface
195  **/
196 
197 __weak_func void lan9303InitHook(NetInterface *interface)
198 {
199 }
200 
201 
202 /**
203  * @brief LAN9303 timer handler
204  * @param[in] interface Underlying network interface
205  **/
206 
207 __weak_func void lan9303Tick(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  NetContext *context;
218  NetInterface *virtualInterface;
219 
220  //Point to the TCP/IP stack context
221  context = interface->netContext;
222 
223  //Loop through network interfaces
224  for(i = 0; i < context->numInterfaces; i++)
225  {
226  //Point to the current interface
227  virtualInterface = &context->interfaces[i];
228 
229  //Check whether the current virtual interface is attached to the
230  //physical interface
231  if(virtualInterface == interface ||
232  virtualInterface->parent == interface)
233  {
234  //Retrieve current link state
235  linkState = lan9303GetLinkState(interface, virtualInterface->port);
236 
237  //Link up or link down event?
238  if(linkState != virtualInterface->linkState)
239  {
240  //Set event flag
241  interface->phyEvent = TRUE;
242  //Notify the TCP/IP stack of the event
243  osSetEvent(&interface->netContext->event);
244  }
245  }
246  }
247  }
248  else
249 #endif
250  {
251  //Initialize link state
252  linkState = FALSE;
253 
254  //Loop through the ports
256  {
257  //Retrieve current link state
258  if(lan9303GetLinkState(interface, port))
259  {
260  linkState = TRUE;
261  }
262  }
263 
264  //Link up or link down event?
265  if(linkState != interface->linkState)
266  {
267  //Set event flag
268  interface->phyEvent = TRUE;
269  //Notify the TCP/IP stack of the event
270  osSetEvent(&interface->netContext->event);
271  }
272  }
273 }
274 
275 
276 /**
277  * @brief Enable interrupts
278  * @param[in] interface Underlying network interface
279  **/
280 
282 {
283 }
284 
285 
286 /**
287  * @brief Disable interrupts
288  * @param[in] interface Underlying network interface
289  **/
290 
292 {
293 }
294 
295 
296 /**
297  * @brief LAN9303 event handler
298  * @param[in] interface Underlying network interface
299  **/
300 
301 __weak_func void lan9303EventHandler(NetInterface *interface)
302 {
303  uint_t port;
304  bool_t linkState;
305 
306 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
307  //Port separation mode?
308  if(interface->port != 0)
309  {
310  uint_t i;
311  uint16_t status;
312  NetContext *context;
313  NetInterface *virtualInterface;
314 
315  //Point to the TCP/IP stack context
316  context = interface->netContext;
317 
318  //Loop through network interfaces
319  for(i = 0; i < context->numInterfaces; i++)
320  {
321  //Point to the current interface
322  virtualInterface = &context->interfaces[i];
323 
324  //Check whether the current virtual interface is attached to the
325  //physical interface
326  if(virtualInterface == interface ||
327  virtualInterface->parent == interface)
328  {
329  //Get the port number associated with the current interface
330  port = virtualInterface->port;
331 
332  //Valid port?
333  if(port >= LAN9303_PORT1 && port <= LAN9303_PORT2)
334  {
335  //Retrieve current link state
336  linkState = lan9303GetLinkState(interface, port);
337 
338  //Link up event?
339  if(linkState && !virtualInterface->linkState)
340  {
341  //Adjust MAC configuration parameters for proper operation
342  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
343  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
344  interface->nicDriver->updateMacConfig(interface);
345 
346  //Read PHY special control/status register
347  status = lan9303ReadPhyReg(interface, port, LAN9303_PSCSR);
348 
349  //Check current operation mode
350  switch(status & LAN9303_PSCSR_SPEED)
351  {
352  //10BASE-T half-duplex
354  virtualInterface->linkSpeed = NIC_LINK_SPEED_10MBPS;
355  virtualInterface->duplexMode = NIC_HALF_DUPLEX_MODE;
356  break;
357 
358  //10BASE-T full-duplex
360  virtualInterface->linkSpeed = NIC_LINK_SPEED_10MBPS;
361  virtualInterface->duplexMode = NIC_FULL_DUPLEX_MODE;
362  break;
363 
364  //100BASE-TX half-duplex
366  virtualInterface->linkSpeed = NIC_LINK_SPEED_100MBPS;
367  virtualInterface->duplexMode = NIC_HALF_DUPLEX_MODE;
368  break;
369 
370  //100BASE-TX full-duplex
372  virtualInterface->linkSpeed = NIC_LINK_SPEED_100MBPS;
373  virtualInterface->duplexMode = NIC_FULL_DUPLEX_MODE;
374  break;
375 
376  //Unknown operation mode
377  default:
378  //Debug message
379  TRACE_WARNING("Invalid operation mode!\r\n");
380  break;
381  }
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(lan9303GetLinkState(interface, port))
413  {
414  linkState = TRUE;
415  }
416  }
417 
418  //Link up event?
419  if(linkState)
420  {
421  //Adjust MAC configuration parameters for proper operation
422  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
423  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
424  interface->nicDriver->updateMacConfig(interface);
425 
426  //Update link state
427  interface->linkState = TRUE;
428  }
429  else
430  {
431  //Update link state
432  interface->linkState = FALSE;
433  }
434 
435  //Process link state change event
436  nicNotifyLinkChange(interface);
437  }
438 }
439 
440 
441 /**
442  * @brief Add special VLAN tag to Ethernet frame
443  * @param[in] interface Underlying network interface
444  * @param[in] buffer Multi-part buffer containing the payload
445  * @param[in,out] offset Offset to the first payload byte
446  * @param[in] ancillary Additional options passed to the stack along with
447  * the packet
448  * @return Error code
449  **/
450 
452  size_t *offset, NetTxAncillary *ancillary)
453 {
454  error_t error;
455 
456  //Initialize status code
457  error = NO_ERROR;
458 
459 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
460  //Valid port?
461  if(ancillary->port <= LAN9303_PORT2)
462  {
463  //Is there enough space for the VLAN tag?
464  if(*offset >= sizeof(VlanTag))
465  {
466  EthHeader *header;
467  VlanTag *vlanTag;
468 
469  //Make room for the special VLAN tag
470  *offset -= sizeof(VlanTag);
471  //Point to the beginning of the frame
472  header = netBufferAt(buffer, *offset, 0);
473 
474  //Move the Ethernet header to make room for the special VLAN tag
475  osMemmove(header, (uint8_t *) header + sizeof(VlanTag),
476  sizeof(EthHeader));
477 
478  //The special VLAN tag is a normal VLAN tag where the VID field is
479  //used as the destination port indicator
480  vlanTag = (VlanTag *) header->data;
481 
482  //Default port number?
483  if(ancillary->port == 0)
484  {
485  //If VID bit 3 is one, then the normal ALR lookup is performed
486  vlanTag->tci = HTONS(LAN9303_VID_ALR_LOOKUP);
487  }
488  else
489  {
490  //VID bits 0 and 1 specify the destination port
491  vlanTag->tci = htons(LAN9303_VID_STP_OVERRIDE | ancillary->port);
492  }
493 
494  //The EtherType field indicates which protocol is encapsulated in
495  //the payload
496  vlanTag->type = header->type;
497 
498  //A distinct EtherType has been allocated for use in the TPID field
499  header->type = HTONS(ETH_TYPE_VLAN);
500  }
501  else
502  {
503  //Report an error
504  error = ERROR_INVALID_PARAMETER;
505  }
506  }
507  else
508  {
509  //The port number is not valid
510  error = ERROR_INVALID_PORT;
511  }
512 #endif
513 
514  //Return status code
515  return error;
516 }
517 
518 
519 /**
520  * @brief Decode special VLAN tag from incoming Ethernet frame
521  * @param[in] interface Underlying network interface
522  * @param[in,out] frame Pointer to the received Ethernet frame
523  * @param[in,out] length Length of the frame, in bytes
524  * @param[in,out] ancillary Additional options passed to the stack along with
525  * the packet
526  * @return Error code
527  **/
528 
529 error_t lan9303UntagFrame(NetInterface *interface, uint8_t **frame,
530  size_t *length, NetRxAncillary *ancillary)
531 {
532  error_t error;
533 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
534  EthHeader *header;
535  VlanTag *vlanTag;
536 #endif
537 
538  //Initialize status code
539  error = NO_ERROR;
540 
541 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
542  //Point to the beginning of the frame
543  header = (EthHeader *) *frame;
544 
545  //Check whether VLAN tagging is used
546  if(ntohs(header->type) == ETH_TYPE_VLAN)
547  {
548  //Valid Ethernet frame received?
549  if(*length >= (sizeof(EthHeader) + sizeof(VlanTag)))
550  {
551  //The special VLAN tag is a normal VLAN tag where the VID field is
552  //used as a source port indicator
553  vlanTag = (VlanTag *) header->data;
554 
555  //VID bits 0 and 1 specify the source port
556  ancillary->port = ntohs(vlanTag->tci) & LAN9303_VID_SRC_PORT;
557  //Fix the value of the EtherType field
558  header->type = vlanTag->type;
559 
560  //Strip the VLAN tag from the Ethernet frame
561  osMemmove(*frame + sizeof(VlanTag), *frame, sizeof(EthHeader));
562 
563  //Point to the Ethernet frame header
564  *frame += sizeof(VlanTag);
565  //Retrieve the length of the original frame
566  *length -= sizeof(VlanTag);
567  }
568  else
569  {
570  //Drop the received frame
571  error = ERROR_INVALID_LENGTH;
572  }
573  }
574  else
575  {
576  //If the interface is configured to accept VLAN-tagged frames, then
577  //drop the incoming Ethernet frame
578  error = ERROR_WRONG_IDENTIFIER;
579  }
580 #endif
581 
582  //Return status code
583  return error;
584 }
585 
586 
587 /**
588  * @brief Get link state
589  * @param[in] interface Underlying network interface
590  * @param[in] port Port number
591  * @return Link state
592  **/
593 
595 {
596  uint16_t status;
597  bool_t linkState;
598 
599  //Check port number
600  if(port >= LAN9303_PORT1 && port <= LAN9303_PORT2)
601  {
602  //Read status register
603  status = lan9303ReadPhyReg(interface, port, LAN9303_BMSR);
604 
605  //Retrieve current link state
606  linkState = (status & LAN9303_BMSR_LINK_STATUS) ? TRUE : FALSE;
607  }
608  else
609  {
610  //The specified port number is not valid
611  linkState = FALSE;
612  }
613 
614  //Return link status
615  return linkState;
616 }
617 
618 
619 /**
620  * @brief Get link speed
621  * @param[in] interface Underlying network interface
622  * @param[in] port Port number
623  * @return Link speed
624  **/
625 
626 uint32_t lan9303GetLinkSpeed(NetInterface *interface, uint8_t port)
627 {
628  uint16_t status;
629  uint32_t linkSpeed;
630 
631  //Check port number
632  if(port >= LAN9303_PORT1 && port <= LAN9303_PORT2)
633  {
634  //Read PHY special control/status register
635  status = lan9303ReadPhyReg(interface, port, LAN9303_PSCSR);
636 
637  //Check current operation mode
638  switch(status & LAN9303_PSCSR_SPEED)
639  {
640  //10BASE-T
643  linkSpeed = NIC_LINK_SPEED_10MBPS;
644  break;
645 
646  //100BASE-TX
649  linkSpeed = NIC_LINK_SPEED_100MBPS;
650  break;
651 
652  //Unknown operation mode
653  default:
654  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
655  break;
656  }
657  }
658  else
659  {
660  //The specified port number is not valid
661  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
662  }
663 
664  //Return link speed
665  return linkSpeed;
666 }
667 
668 
669 /**
670  * @brief Get duplex mode
671  * @param[in] interface Underlying network interface
672  * @param[in] port Port number
673  * @return Duplex mode
674  **/
675 
677 {
678  uint16_t status;
679  NicDuplexMode duplexMode;
680 
681  //Check port number
682  if(port >= LAN9303_PORT1 && port <= LAN9303_PORT2)
683  {
684  //Read PHY special control/status register
685  status = lan9303ReadPhyReg(interface, port, LAN9303_PSCSR);
686 
687  //Check current operation mode
688  switch(status & LAN9303_PSCSR_SPEED)
689  {
690  //10BASE-T or 100BASE-TX half-duplex
693  duplexMode = NIC_HALF_DUPLEX_MODE;
694  break;
695 
696  //10BASE-T or 100BASE-TX full-duplex
699  duplexMode = NIC_FULL_DUPLEX_MODE;
700  break;
701 
702  //Unknown operation mode
703  default:
704  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
705  break;
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 lan9303SetPortState(NetInterface *interface, uint8_t port,
727  SwitchPortState state)
728 {
729  uint32_t temp;
730 
731  //Read port state register
732  temp = lan9303ReadSwitchReg(interface, LAN9303_SWE_PORT_STATE);
733 
734  //Check port number
735  if(port == LAN9303_PORT1)
736  {
737  //Clear current configuration
739 
740  //Update port 1 state
741  switch(state)
742  {
745  break;
748  break;
751  break;
752  default:
754  break;
755  }
756  }
757  else if(port == LAN9303_PORT2)
758  {
759  //Clear current configuration
761 
762  //Update port 2 state
763  switch(state)
764  {
767  break;
770  break;
773  break;
774  default:
776  break;
777  }
778  }
779  else
780  {
781  //The specified port number is not valid
782  }
783 
784  //Write the value back to port state register
786 }
787 
788 
789 /**
790  * @brief Get port state
791  * @param[in] interface Underlying network interface
792  * @param[in] port Port number
793  * @return Port state
794  **/
795 
797 {
798  uint32_t temp;
799  SwitchPortState state;
800 
801  //Read port state register
802  temp = lan9303ReadSwitchReg(interface, LAN9303_SWE_PORT_STATE);
803 
804  //Check port number
805  if(port == LAN9303_PORT1)
806  {
807  //Check port 1 state
808  switch(temp & LAN9303_SWE_PORT_STATE_PORT1)
809  {
812  break;
815  break;
818  break;
819  default:
821  break;
822  }
823  }
824  else if(port == LAN9303_PORT2)
825  {
826  //Check port 2 state
827  switch(temp & LAN9303_SWE_PORT_STATE_PORT2)
828  {
831  break;
834  break;
837  break;
838  default:
840  break;
841  }
842  }
843  else
844  {
845  //The specified port number is not valid
847  }
848 
849  //Return port state
850  return state;
851 }
852 
853 
854 /**
855  * @brief Set aging time for dynamic filtering entries
856  * @param[in] interface Underlying network interface
857  * @param[in] agingTime Aging time, in seconds
858  **/
859 
860 void lan9303SetAgingTime(NetInterface *interface, uint32_t agingTime)
861 {
862  //The aging period is fixed to 5 minutes
863 }
864 
865 
866 /**
867  * @brief Enable IGMP snooping
868  * @param[in] interface Underlying network interface
869  * @param[in] enable Enable or disable IGMP snooping
870  **/
871 
873 {
874  uint32_t temp;
875 
876  //Read the Switch Engine Global Ingress Configuration register
878 
879  //Enable or disable IGMP monitoring
880  if(enable)
881  {
883  }
884  else
885  {
887  }
888 
889  //Set the port bit map where IGMP packets are sent
892 
893  //Write the value back to Switch Engine Global Ingress Configuration register
895 }
896 
897 
898 /**
899  * @brief Enable MLD snooping
900  * @param[in] interface Underlying network interface
901  * @param[in] enable Enable or disable MLD snooping
902  **/
903 
905 {
906  //Not implemented
907 }
908 
909 
910 /**
911  * @brief Enable reserved multicast table
912  * @param[in] interface Underlying network interface
913  * @param[in] enable Enable or disable reserved group addresses
914  **/
915 
917 {
918  uint_t i;
919  SwitchFdbEntry entry;
920 
921  //The reserved group addresses are in the range of 01-80-C2-00-00-00 to
922  //01-80-C2-00-00-0F
923  for(i = 0; i <= 15; i++)
924  {
925  //Specify the reserved group address to be added or removed
926  entry.macAddr.b[0] = 0x01;
927  entry.macAddr.b[1] = 0x80;
928  entry.macAddr.b[2] = 0xC2;
929  entry.macAddr.b[3] = 0x00;
930  entry.macAddr.b[4] = 0x00;
931  entry.macAddr.b[5] = i;
932 
933  //Format forwarding database entry
934  entry.srcPort = 0;
936  entry.override = TRUE;
937 
938  //Update the static MAC table
939  if(enable)
940  {
941  lan9303AddStaticFdbEntry(interface, &entry);
942  }
943  else
944  {
945  lan9303DeleteStaticFdbEntry(interface, &entry);
946  }
947  }
948 }
949 
950 
951 /**
952  * @brief Add a new entry to the static MAC table
953  * @param[in] interface Underlying network interface
954  * @param[in] entry Pointer to the forwarding database entry
955  * @return Error code
956  **/
957 
959  const SwitchFdbEntry *entry)
960 {
961  uint32_t value;
962  uint32_t ports;
963 
964  //Check whether the forward port is the CPU port
965  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
966  {
967  ports = LAN9303_PORT0_MASK;
968  }
969  else
970  {
971  ports = entry->destPorts & LAN9303_PORT_MASK;
972  }
973 
974  //Valid forward ports?
975  if(ports != 0)
976  {
977  //Write SWE_ALR_WR_DAT_0 and SWE_ALR_WR_DAT_1 with the desired MAC
978  //address and control bits
980 
981  //When the Override bit set, packets received with a destination
982  //address that matches the MAC address in the SWE_ALR_WR_DAT_1 and
983  //SWE_ALR_WR_DAT_0 registers will be forwarded regardless of the port
984  //state
985  if(entry->override)
986  {
988  }
989 
990  //Set the ports associated with this MAC address
991  switch(ports)
992  {
993  case LAN9303_PORT0_MASK:
995  break;
996  case LAN9303_PORT1_MASK:
998  break;
999  case LAN9303_PORT2_MASK:
1001  break;
1002  case LAN9303_PORT0_1_MASK:
1004  break;
1005  case LAN9303_PORT0_2_MASK:
1007  break;
1008  case LAN9303_PORT1_2_MASK:
1010  break;
1011  default:
1013  break;
1014  }
1015  }
1016  else
1017  {
1018  //An entry can be deleted by setting the Valid bit to 0
1020  }
1021 
1022  //Copy MAC address (last 16 bits)
1023  value |= entry->macAddr.b[4] | (entry->macAddr.b[5] << 8);
1024  //Write SWE_ALR_WR_DAT_1 register
1026 
1027  //Copy MAC address (first 32 bits)
1028  value = entry->macAddr.b[0] | (entry->macAddr.b[1] << 8) |
1029  (entry->macAddr.b[2] << 16) | (entry->macAddr.b[3] << 24);
1030 
1031  //Write SWE_ALR_WR_DAT_0 register
1033 
1034  //Write the SWE_ALR_CMD register
1037 
1038  //Poll the Make Pending bit in the SWE_ALR_CMD_STS register until it is
1039  //cleared
1040  do
1041  {
1042  //Read the SWE_ALR_CMD_STS register
1044 
1045  //Check the Make Pending bit
1046  } while((value & LAN9303_SWE_ALR_CMD_STS_MAKE_PENDING) != 0);
1047 
1048  //Clear the SWE_ALR_CMD register
1050 
1051  //Successful processing
1052  return NO_ERROR;
1053 }
1054 
1055 
1056 /**
1057  * @brief Remove an entry from the static MAC table
1058  * @param[in] interface Underlying network interface
1059  * @param[in] entry Forwarding database entry to remove from the table
1060  * @return Error code
1061  **/
1062 
1064  const SwitchFdbEntry *entry)
1065 {
1066  uint32_t value;
1067 
1068  //An entry can be deleted by setting the Valid bit to 0
1070 
1071  //Specify the MAC address to remove (last 16 bits)
1072  value |= entry->macAddr.b[4] | (entry->macAddr.b[5] << 8);
1073  //Write SWE_ALR_WR_DAT_1 register
1075 
1076  //Specify the MAC address to remove (first 32 bits)
1077  value = entry->macAddr.b[0] | (entry->macAddr.b[1] << 8) |
1078  (entry->macAddr.b[2] << 16) | (entry->macAddr.b[3] << 24);
1079 
1080  //Write SWE_ALR_WR_DAT_0 register
1082 
1083  //Write the SWE_ALR_CMD register
1086 
1087  //Poll the Make Pending bit in the SWE_ALR_CMD_STS register until it is
1088  //cleared
1089  do
1090  {
1091  //Read the SWE_ALR_CMD_STS register
1093 
1094  //Check the Make Pending bit
1095  } while((value & LAN9303_SWE_ALR_CMD_STS_MAKE_PENDING) != 0);
1096 
1097  //Clear the SWE_ALR_CMD register
1099 
1100  //Successful processing
1101  return NO_ERROR;
1102 }
1103 
1104 
1105 /**
1106  * @brief Read an entry from the static MAC table
1107  * @param[in] interface Underlying network interface
1108  * @param[in] index Zero-based index of the entry to read
1109  * @param[out] entry Pointer to the forwarding database entry
1110  * @return Error code
1111  **/
1112 
1114  SwitchFdbEntry *entry)
1115 {
1116  uint32_t value;
1117 
1118  //Loop through the ALR table
1119  while(1)
1120  {
1121  //Out of bound index?
1122  if(index >= LAN9303_ALR_TABLE_SIZE)
1123  return ERROR_END_OF_TABLE;
1124 
1125  //First entry?
1126  if(index == 0)
1127  {
1129  }
1130  else
1131  {
1133  }
1134 
1135  //Write the SWE_ALR_CMD register
1137  //Clear the SWE_ALR_CMD register
1139 
1140  //Poll the Valid and End of Table bits in the SWE_ALR_RD_DAT_1 register
1141  //until either is set
1142  while(1)
1143  {
1144  //Read SWE_ALR_RD_DAT_1 register
1146 
1147  //If the End of Table bit is set, then exit
1149  {
1150  return ERROR_END_OF_TABLE;
1151  }
1152 
1153  //If the Valid bit is set, then the entry is valid
1155  {
1156  break;
1157  }
1158  }
1159 
1160  //Static entry?
1162  {
1163  break;
1164  }
1165 
1166  //Skip dynamic entries
1167  index++;
1168  }
1169 
1170  //Store the data from SWE_ALR_RD_DAT_0 and SWE_ALR_RD_DAT_1 registers
1171  entry->srcPort = 0;
1172  entry->override = FALSE;
1173 
1174  //Retrieve the ports associated with this MAC address
1176  {
1178  entry->destPorts = LAN9303_PORT0_MASK;
1179  break;
1181  entry->destPorts = LAN9303_PORT1_MASK;
1182  break;
1184  entry->destPorts = LAN9303_PORT2_MASK;
1185  break;
1188  break;
1191  break;
1194  break;
1197  break;
1198  default:
1199  entry->destPorts = 0;
1200  break;
1201  }
1202 
1203  //Copy MAC address (last 16 bits)
1204  entry->macAddr.b[4] = value & 0xFF;
1205  entry->macAddr.b[5] = (value >> 8) & 0xFF;
1206 
1207  //Read SWE_ALR_RD_DAT_0 register
1209 
1210  //Copy MAC address (first 32 bits)
1211  entry->macAddr.b[0] = value & 0xFF;
1212  entry->macAddr.b[1] = (value >> 8) & 0xFF;
1213  entry->macAddr.b[2] = (value >> 16) & 0xFF;
1214  entry->macAddr.b[3] = (value >> 24) & 0xFF;
1215 
1216  //Successful processing
1217  return NO_ERROR;
1218 }
1219 
1220 
1221 /**
1222  * @brief Flush static MAC table
1223  * @param[in] interface Underlying network interface
1224  **/
1225 
1227 {
1228  error_t error;
1229  uint_t i;
1230  SwitchFdbEntry entry;
1231 
1232  //Loop through the ALR table
1233  for(i = 0; i < LAN9303_ALR_TABLE_SIZE; i++)
1234  {
1235  //Read current entry
1236  error = lan9303GetStaticFdbEntry(interface, i, &entry);
1237 
1238  //Valid entry?
1239  if(!error)
1240  {
1241  //An entry can be deleted by setting the Valid bit to 0
1242  lan9303DeleteStaticFdbEntry(interface, &entry);
1243  }
1244  else
1245  {
1246  //The end of the table has been reached
1247  break;
1248  }
1249  }
1250 }
1251 
1252 
1253 /**
1254  * @brief Read an entry from the dynamic MAC table
1255  * @param[in] interface Underlying network interface
1256  * @param[in] index Zero-based index of the entry to read
1257  * @param[out] entry Pointer to the forwarding database entry
1258  * @return Error code
1259  **/
1260 
1262  SwitchFdbEntry *entry)
1263 {
1264  uint32_t value;
1265 
1266  //Loop through the ALR table
1267  while(1)
1268  {
1269  //Out of bound index?
1270  if(index >= LAN9303_ALR_TABLE_SIZE)
1271  return ERROR_END_OF_TABLE;
1272 
1273  //First entry?
1274  if(index == 0)
1275  {
1277  }
1278  else
1279  {
1281  }
1282 
1283  //Write the SWE_ALR_CMD register
1285  //Clear the SWE_ALR_CMD register
1287 
1288  //Poll the Valid and End of Table bits in the SWE_ALR_RD_DAT_1 register
1289  //until either is set
1290  while(1)
1291  {
1292  //Read SWE_ALR_RD_DAT_1 register
1294 
1295  //If the End of Table bit is set, then exit
1297  {
1298  return ERROR_END_OF_TABLE;
1299  }
1300 
1301  //If the Valid bit is set, then the entry is valid
1303  {
1304  break;
1305  }
1306  }
1307 
1308  //Dynamic entry?
1310  {
1311  break;
1312  }
1313 
1314  //Skip static entries
1315  index++;
1316  }
1317 
1318  //Store the data from SWE_ALR_RD_DAT_0 and SWE_ALR_RD_DAT_1 registers
1319  entry->destPorts = 0;
1320  entry->override = FALSE;
1321 
1322  //Retrieve the port associated with this MAC address
1324  {
1326  entry->srcPort = LAN9303_PORT0;
1327  break;
1329  entry->srcPort = LAN9303_PORT1;
1330  break;
1332  entry->srcPort = LAN9303_PORT2;
1333  break;
1334  default:
1335  entry->srcPort = 0;
1336  break;
1337  }
1338 
1339  //Copy MAC address (last 16 bits)
1340  entry->macAddr.b[4] = value & 0xFF;
1341  entry->macAddr.b[5] = (value >> 8) & 0xFF;
1342 
1343  //Read SWE_ALR_RD_DAT_0 register
1345 
1346  //Copy MAC address (first 32 bits)
1347  entry->macAddr.b[0] = value & 0xFF;
1348  entry->macAddr.b[1] = (value >> 8) & 0xFF;
1349  entry->macAddr.b[2] = (value >> 16) & 0xFF;
1350  entry->macAddr.b[3] = (value >> 24) & 0xFF;
1351 
1352  //Successful processing
1353  return NO_ERROR;
1354 }
1355 
1356 
1357 /**
1358  * @brief Flush dynamic MAC table
1359  * @param[in] interface Underlying network interface
1360  * @param[in] port Port number
1361  **/
1362 
1364 {
1365  error_t error;
1366  uint_t i;
1367  uint32_t value;
1368  SwitchFdbEntry entry;
1369 
1370  //Loop through the ALR table
1371  for(i = 0; i < LAN9303_ALR_TABLE_SIZE; i++)
1372  {
1373  //Read current entry
1374  error = lan9303GetDynamicFdbEntry(interface, i, &entry);
1375 
1376  //Valid entry?
1377  if(!error)
1378  {
1379  //Matching port number?
1380  if(entry.srcPort == port || port == 0)
1381  {
1382  //Specify the MAC address to remove (last 16 bits)
1383  value = entry.macAddr.b[4] | (entry.macAddr.b[5] << 8);
1384  //Write SWE_ALR_WR_DAT_1 register
1386 
1387  //Specify the MAC address to remove (first 32 bits)
1388  value = entry.macAddr.b[0] | (entry.macAddr.b[1] << 8) |
1389  (entry.macAddr.b[2] << 16) | (entry.macAddr.b[3] << 24);
1390 
1391  //Write SWE_ALR_WR_DAT_0 register
1393 
1394  //Write the SWE_ALR_CMD register
1397 
1398  //Poll the Make Pending bit in the SWE_ALR_CMD_STS register until
1399  //it is cleared
1400  do
1401  {
1402  //Read the SWE_ALR_CMD_STS register
1404 
1405  //Check the Make Pending bit
1406  } while((value & LAN9303_SWE_ALR_CMD_STS_MAKE_PENDING) != 0);
1407 
1408  //Clear the SWE_ALR_CMD register
1410  }
1411  }
1412  else
1413  {
1414  //The end of the table has been reached
1415  break;
1416  }
1417  }
1418 }
1419 
1420 
1421 /**
1422  * @brief Set forward ports for unknown multicast packets
1423  * @param[in] interface Underlying network interface
1424  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1425  * @param[in] forwardPorts Port map
1426  **/
1427 
1429  bool_t enable, uint32_t forwardPorts)
1430 {
1431  //Not implemented
1432 }
1433 
1434 
1435 /**
1436  * @brief Write PHY register
1437  * @param[in] interface Underlying network interface
1438  * @param[in] port Port number
1439  * @param[in] address PHY register address
1440  * @param[in] data Register value
1441  **/
1442 
1443 void lan9303WritePhyReg(NetInterface *interface, uint8_t port,
1444  uint8_t address, uint16_t data)
1445 {
1446  //Write the specified PHY register
1447  if(interface->smiDriver != NULL)
1448  {
1449  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1450  }
1451  else
1452  {
1453  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1454  }
1455 }
1456 
1457 
1458 /**
1459  * @brief Read PHY register
1460  * @param[in] interface Underlying network interface
1461  * @param[in] port Port number
1462  * @param[in] address PHY register address
1463  * @return Register value
1464  **/
1465 
1466 uint16_t lan9303ReadPhyReg(NetInterface *interface, uint8_t port,
1467  uint8_t address)
1468 {
1469  uint16_t data;
1470 
1471  //Read the specified PHY register
1472  if(interface->smiDriver != NULL)
1473  {
1474  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1475  }
1476  else
1477  {
1478  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1479  }
1480 
1481  //Return the value of the PHY register
1482  return data;
1483 }
1484 
1485 
1486 /**
1487  * @brief Dump PHY registers for debugging purpose
1488  * @param[in] interface Underlying network interface
1489  * @param[in] port Port number
1490  **/
1491 
1492 void lan9303DumpPhyReg(NetInterface *interface, uint8_t port)
1493 {
1494  uint8_t i;
1495 
1496  //Loop through PHY registers
1497  for(i = 0; i < 32; i++)
1498  {
1499  //Display current PHY register
1500  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1501  lan9303ReadPhyReg(interface, port, i));
1502  }
1503 
1504  //Terminate with a line feed
1505  TRACE_DEBUG("\r\n");
1506 }
1507 
1508 
1509 /**
1510  * @brief Write system CSR register
1511  * @param[in] interface Underlying network interface
1512  * @param[in] address System register address
1513  * @param[in] data Register value
1514  **/
1515 
1516 void lan9303WriteSysReg(NetInterface *interface, uint16_t address,
1517  uint32_t data)
1518 {
1519  uint8_t phyAddr;
1520  uint8_t regAddr;
1521 
1522  //PHY address bit 4 is 1 for SMI commands. PHY address 3:0 form system
1523  //register address bits 9:6
1524  phyAddr = 0x10 | ((address >> 6) & 0x0F);
1525 
1526  //Register address field forms register address bits 5:1
1527  regAddr = (address >> 1) & 0x1F;
1528 
1529  //Write system CSR register
1530  if(interface->smiDriver != NULL)
1531  {
1532  //Write the low word of the SMI register
1533  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr,
1534  data & 0xFFFF);
1535 
1536  //Write the high word of the SMI register
1537  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr + 1,
1538  (data >> 16) & 0xFFFF);
1539  }
1540  else
1541  {
1542  //Write the low word of the SMI register
1543  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr,
1544  data & 0xFFFF);
1545 
1546  //Write the high word of the SMI register
1547  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr + 1,
1548  (data >> 16) & 0xFFFF);
1549  }
1550 }
1551 
1552 
1553 /**
1554  * @brief Read system CSR register
1555  * @param[in] interface Underlying network interface
1556  * @param[in] address System register address
1557  * @return Register value
1558  **/
1559 
1560 uint32_t lan9303ReadSysReg(NetInterface *interface, uint16_t address)
1561 {
1562  uint8_t phyAddr;
1563  uint8_t regAddr;
1564  uint32_t data;
1565 
1566  //PHY address bit 4 is 1 for SMI commands. PHY address 3:0 form system
1567  //register address bits 9:6
1568  phyAddr = 0x10 | ((address >> 6) & 0x0F);
1569 
1570  //Register address field forms register address bits 5:1
1571  regAddr = (address >> 1) & 0x1F;
1572 
1573  //Read system CSR register
1574  if(interface->smiDriver != NULL)
1575  {
1576  //Read the low word of the SMI register
1577  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1578  regAddr);
1579 
1580  //Read the high word of the SMI register
1581  data |= interface->smiDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1582  regAddr + 1) << 16;
1583  }
1584  else
1585  {
1586  //Read the low word of the SMI register
1587  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1588  regAddr);
1589 
1590  //Read the high word of the SMI register
1591  data |= interface->nicDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1592  regAddr + 1) << 16;
1593  }
1594 
1595  //Return register value
1596  return data;
1597 }
1598 
1599 
1600 /**
1601  * @brief Dump system CSR registers for debugging purpose
1602  * @param[in] interface Underlying network interface
1603  **/
1604 
1606 {
1607  uint16_t i;
1608 
1609  //Loop through system registers
1610  for(i = 80; i < 512; i += 4)
1611  {
1612  //Display current system register
1613  TRACE_DEBUG("0x%03" PRIX16 ": 0x%08" PRIX32 "\r\n", i,
1614  lan9303ReadSysReg(interface, i));
1615  }
1616 
1617  //Terminate with a line feed
1618  TRACE_DEBUG("\r\n");
1619 }
1620 
1621 
1622 /**
1623  * @brief Write switch fabric CSR register
1624  * @param[in] interface Underlying network interface
1625  * @param[in] address Switch fabric register address
1626  * @param[in] data Register value
1627  **/
1628 
1629 void lan9303WriteSwitchReg(NetInterface *interface, uint16_t address,
1630  uint32_t data)
1631 {
1632  uint32_t value;
1633 
1634  //To perform a write to an individual switch fabric register, the desired
1635  //data must first be written into the SWITCH_CSR_DATA register
1637 
1638  //Set up a write operation
1641 
1642  //Set register address
1644 
1645  //The write cycle is initiated by performing a single write to the
1646  //SWITCH_CSR_CMD register
1648 
1649  //The completion of the write cycle is indicated by the clearing of the
1650  //CSR_BUSY bit
1651  do
1652  {
1653  //Read SWITCH_CSR_CMD register
1655 
1656  //Poll CSR_BUSY bit
1657  } while((value & LAN9303_SWITCH_CSR_CMD_BUSY) != 0);
1658 }
1659 
1660 
1661 /**
1662  * @brief Read switch fabric CSR register
1663  * @param[in] interface Underlying network interface
1664  * @param[in] address Switch fabric register address
1665  * @return Register value
1666  **/
1667 
1668 uint32_t lan9303ReadSwitchReg(NetInterface *interface, uint16_t address)
1669 {
1670  uint32_t value;
1671 
1672  //Set up a read operation
1675 
1676  //Set register address
1678 
1679  //To perform a read of an individual switch fabric register, the read cycle
1680  //must be initiated by performing a single write to the SWITCH_CSR_CMD
1681  //register
1683 
1684  //Valid data is available for reading when the CSR_BUSY bit is cleared
1685  do
1686  {
1687  //Read SWITCH_CSR_CMD register
1689 
1690  //Poll CSR_BUSY bit
1691  } while((value & LAN9303_SWITCH_CSR_CMD_BUSY) != 0);
1692 
1693  //Read data from the SWITCH_CSR_DATA register
1694  return lan9303ReadSysReg(interface, LAN9303_SWITCH_CSR_DATA);
1695 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:601
#define htons(value)
Definition: cpu_endian.h:413
#define LAN9303_BYTE_TEST
#define NetContext
Definition: net.h:36
#define LAN9303_SWE_ALR_WR_DAT_1_AGE_OVERRIDE
int bool_t
Definition: compiler_port.h:63
#define LAN9303_PSCSR_SPEED_100BTX_FD
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
uint32_t destPorts
Definition: nic.h:152
#define LAN9303_BM_EGRSS_PORT_TYPE_PORT0_TYPE_CPU
#define LAN9303_SWE_GLOBAL_INGRSS_CFG_IGMP_MONITOR_PORT
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define LAN9303_PORT0_1_MASK
#define LAN9303_SWE_PORT_STATE_PORT0_FORWARDING
#define LAN9303_SWE_ALR_WR_DAT_1_PORT_0_1
const SwitchDriver lan9303SwitchDriver
LAN9303 Ethernet switch driver.
#define LAN9303_SWE_ALR_RD_DAT_1_STATIC
#define LAN9303_SWE_ALR_WR_DAT_1_PORT_2
SwitchPortState lan9303GetPortState(NetInterface *interface, uint8_t port)
Get port state.
error_t lan9303AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
#define LAN9303_SWE_ALR_WR_DAT_1_PORT_0_2
#define LAN9303_BYTE_TEST_DEFAULT
@ ERROR_END_OF_TABLE
Definition: error.h:292
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define LAN9303_SWITCH_CSR_CMD_WRITE
error_t lan9303Init(NetInterface *interface)
LAN9303 Ethernet switch initialization.
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
#define LAN9303_PORT0_2_MASK
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
#define LAN9303_SWE_GLOBAL_INGRSS_CFG_IGMP_MONITORING_EN
void lan9303SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
#define LAN9303_MAC_TX_CFG_IFG_CONFIG_DEFAULT
#define LAN9303_VID_STP_OVERRIDE
@ ERROR_INVALID_PORT
Definition: error.h:104
#define LAN9303_SWE_ALR_CMD
#define LAN9303_PSCSR_SPEED_100BTX_HD
bool_t lan9303GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
#define LAN9303_SWE_PORT_STATE_PORT2_DISABLED
#define LAN9303_SWITCH_CSR_CMD_READ
EthHeader
Definition: ethernet.h:225
#define LAN9303_SWE_PORT_STATE_PORT2_FORWARDING
#define LAN9303_PORT2_MASK
#define LAN9303_SWE_ALR_CMD_GET_NEXT_ENTRY
void lan9303DisableIrq(NetInterface *interface)
Disable interrupts.
void lan9303EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
#define LAN9303_SWE_ALR_CMD_STS_MAKE_PENDING
#define LAN9303_PORT0
#define LAN9303_PSCSR_SPEED_10BT_HD
VlanTag
Definition: ethernet.h:248
#define SMI_OPCODE_WRITE
Definition: nic.h:66
void lan9303WriteSysReg(NetInterface *interface, uint16_t address, uint32_t data)
Write system CSR register.
#define LAN9303_SWE_GLOBAL_INGRSS_CFG
#define LAN9303_SWE_PORT_MIRROR_SNIFFER_PORT_0
#define LAN9303_SWITCH_CSR_CMD
#define LAN9303_SWE_INGRSS_PORT_TYP
#define LAN9303_SWE_PORT_MIRROR_RX_MIRRORING_EN
#define LAN9303_PORT0_1_2_MASK
#define LAN9303_HW_CFG_DEVICE_READY
__weak_func void lan9303Tick(NetInterface *interface)
LAN9303 timer handler.
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:43
uint16_t lan9303ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
#define LAN9303_SWE_ALR_RD_DAT_0
#define LAN9303_SWE_ALR_RD_DAT_1_VALID
#define LAN9303_PORT0_MASK
void lan9303WriteSwitchReg(NetInterface *interface, uint16_t address, uint32_t data)
Write switch fabric CSR register.
#define LAN9303_PSCSR
#define LAN9303_PORT1_2_MASK
void lan9303EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
#define NetRxAncillary
Definition: net_misc.h:40
__weak_func void lan9303EventHandler(NetInterface *interface)
LAN9303 event handler.
#define NetInterface
Definition: net.h:40
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
#define LAN9303_MAC_RX_CFG_REJECT_MAC_TYPES
#define LAN9303_SWE_ALR_WR_DAT_0
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define LAN9303_SWE_ALR_RD_DAT_1_PORT_1
#define LAN9303_VID_ALR_LOOKUP
#define LAN9303_BMSR
#define LAN9303_SWE_PORT_STATE_PORT1_LISTENING
#define LAN9303_MAC_TX_CFG_TX_EN
#define LAN9303_SWITCH_CSR_CMD_ADDR
void lan9303DumpSysReg(NetInterface *interface)
Dump system CSR registers for debugging purpose.
#define LAN9303_PSCSR_SPEED
#define NetTxAncillary
Definition: net_misc.h:36
#define LAN9303_HW_CFG
#define LAN9303_SWE_ALR_WR_DAT_1_PORT_1
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
#define LAN9303_SWE_PORT_STATE_PORT1
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
#define LAN9303_BMSR_LINK_STATUS
LAN9303 3-port Ethernet switch driver.
#define LAN9303_SWE_PORT_STATE_PORT1_FORWARDING
#define LAN9303_SWE_ALR_RD_DAT_1_PORT_0_2
@ SWITCH_PORT_STATE_BLOCKING
Definition: nic.h:137
uint32_t lan9303ReadSwitchReg(NetInterface *interface, uint16_t address)
Read switch fabric CSR register.
#define LAN9303_SWE_ALR_WR_DAT_1_PORT_0_1_2
error_t lan9303UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode special VLAN tag from incoming Ethernet frame.
void lan9303SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
#define LAN9303_SWE_ALR_RD_DAT_1_PORT_2
#define LAN9303_SWE_INGRSS_PORT_TYP_PORT0
uint16_t port
Definition: dns_common.h:270
#define ntohs(value)
Definition: cpu_endian.h:421
__weak_func void lan9303InitHook(NetInterface *interface)
LAN9303 custom configuration.
#define TRACE_WARNING(...)
Definition: debug.h:93
@ ETH_TYPE_VLAN
Definition: ethernet.h:167
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define LAN9303_SWITCH_CSR_CMD_BE
error_t lan9303GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
#define LAN9303_MAC_TX_CFG_TX_PAD_EN
uint16_t regAddr
#define LAN9303_SWE_PORT_STATE_PORT1_DISABLED
#define LAN9303_MAC_RX_CFG_RX_EN
uint32_t lan9303GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
#define LAN9303_SWE_PORT_STATE_PORT2
error_t lan9303GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
Ethernet switch driver.
Definition: nic.h:325
#define LAN9303_SWE_ALR_RD_DAT_1_PORT_0_1_2
#define HTONS(value)
Definition: cpu_endian.h:410
void lan9303WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
#define LAN9303_SWE_ALR_RD_DAT_1_PORT_0_1
Ipv6Addr address[]
Definition: ipv6.h:345
NicDuplexMode
Duplex mode.
Definition: nic.h:122
#define LAN9303_BM_EGRSS_PORT_TYPE
MacAddr macAddr
Definition: nic.h:150
error_t lan9303DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
#define LAN9303_PORT2
uint8_t srcPort
Definition: nic.h:151
#define LAN9303_SWITCH_CSR_CMD_BUSY
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
uint8_t value[]
Definition: tcp.h:376
#define LAN9303_SWE_ALR_RD_DAT_1_END_OF_TABLE
#define LAN9303_SWE_ALR_WR_DAT_1_VALID
#define LAN9303_PORT_MASK
#define LAN9303_SWE_PORT_MIRROR_MIRRORED_PORT_2
#define LAN9303_SWE_ALR_WR_DAT_1_PORT_1_2
#define LAN9303_SWE_PORT_STATE_PORT1_LEARNING
#define LAN9303_PORT1
uint32_t lan9303ReadSysReg(NetInterface *interface, uint16_t address)
Read system CSR register.
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
void lan9303FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
#define LAN9303_PORT1_MASK
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define LAN9303_SWE_ALR_RD_DAT_1_PORT
void lan9303EnableIrq(NetInterface *interface)
Enable interrupts.
#define LAN9303_MAC_RX_CFG(port)
#define LAN9303_SWE_PORT_MIRROR_MIRRORED_PORT_1
void lan9303DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
#define LAN9303_SWE_PORT_MIRROR_RX_MIRRORING_FILT_EN
#define LAN9303_SWE_ALR_RD_DAT_1
#define LAN9303_ALR_TABLE_SIZE
NicDuplexMode lan9303GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
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
#define LAN9303_SWE_PORT_MIRROR
#define LAN9303_MAC_TX_CFG(port)
#define LAN9303_SWE_ALR_CMD_GET_FIRST_ENTRY
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
#define LAN9303_SWE_ALR_WR_DAT_1_PORT_0
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define LAN9303_PSCSR_SPEED_10BT_FD
#define LAN9303_SWE_ALR_CMD_STS
#define LAN9303_SWE_PORT_STATE
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
#define LAN9303_SWE_ALR_RD_DAT_1_PORT_0
#define LAN9303_SWE_PORT_STATE_PORT2_LEARNING
#define LAN9303_SWE_GLOBAL_INGRSS_CFG_IGMP_MONITOR_PORT_0
#define LAN9303_SWITCH_CSR_DATA
void lan9303FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
void lan9303EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
#define LAN9303_SWE_ALR_RD_DAT_1_PORT_1_2
error_t lan9303TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add special VLAN tag to Ethernet frame.
#define LAN9303_SWE_ALR_WR_DAT_1_STATIC
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
void lan9303SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
Debugging facilities.
#define osMemmove(dest, src, length)
Definition: os_port.h:150
Forwarding database entry.
Definition: nic.h:149
#define LAN9303_VID_SRC_PORT
#define LAN9303_SWE_ALR_WR_DAT_1
#define LAN9303_SWE_PORT_STATE_PORT2_LISTENING
#define LAN9303_SWE_ALR_CMD_MAKE_ENTRY