ksz8794_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz8794_driver.c
3  * @brief KSZ8794 4-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.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/ethernet_misc.h"
38 #include "debug.h"
39 
40 
41 /**
42  * @brief KSZ8794 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ8794)
75  **/
76 
77 const uint8_t ksz8794IngressTailTag[4] =
78 {
83 };
84 
85 
86 /**
87  * @brief KSZ8794 Ethernet switch initialization
88  * @param[in] interface Underlying network interface
89  * @return Error code
90  **/
91 
93 {
94  uint_t port;
95  uint8_t temp;
96 
97  //Debug message
98  TRACE_INFO("Initializing KSZ8794...\r\n");
99 
100  //SPI slave mode?
101  if(interface->spiDriver != NULL)
102  {
103  //Initialize SPI interface
104  interface->spiDriver->init();
105 
106  //Wait for the serial interface to be ready
107  do
108  {
109  //Read CHIP_ID0 register
110  temp = ksz8794ReadSwitchReg(interface, KSZ8794_CHIP_ID0);
111 
112  //The returned data is invalid until the serial interface is ready
113  } while(temp != KSZ8794_CHIP_ID0_FAMILY_ID_DEFAULT);
114 
115 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
116  //Enable tail tag feature
117  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL10);
120 
121  //Disable packet size check
122  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL2);
125 #else
126  //Disable tail tag feature
127  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL10);
130 
131  //Enable packet size check
132  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL2);
135 #endif
136 
137  //Loop through the ports
139  {
140 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
141  //Port separation mode?
142  if(interface->port != 0)
143  {
144  //Disable packet transmission and address learning
146  }
147  else
148 #endif
149  {
150  //Enable transmission, reception and address learning
152  }
153  }
154 
155  //Disable EEE next page exchange (silicon errata workaround 2)
159 
160  //Improve receiver settings (silicon errata workaround 3)
164 
165  //Improve transmitter settings (silicon errata workaround 4)
169 
170  //Dump switch registers for debugging purpose
171  ksz8794DumpSwitchReg(interface);
172  }
173  else
174  {
175  //Initialize serial management interface
176  if(interface->smiDriver != NULL)
177  {
178  interface->smiDriver->init();
179  }
180 
181  //Loop through the ports
183  {
184  //Debug message
185  TRACE_DEBUG("Port %u:\r\n", port);
186  //Dump PHY registers for debugging purpose
187  ksz8794DumpPhyReg(interface, port);
188  }
189  }
190 
191  //Perform custom configuration
192  ksz8794InitHook(interface);
193 
194  //Force the TCP/IP stack to poll the link state at startup
195  interface->phyEvent = TRUE;
196  //Notify the TCP/IP stack of the event
198 
199  //Successful initialization
200  return NO_ERROR;
201 }
202 
203 
204 /**
205  * @brief KSZ8794 custom configuration
206  * @param[in] interface Underlying network interface
207  **/
208 
209 __weak_func void ksz8794InitHook(NetInterface *interface)
210 {
211 }
212 
213 
214 /**
215  * @brief KSZ8794 timer handler
216  * @param[in] interface Underlying network interface
217  **/
218 
219 void ksz8794Tick(NetInterface *interface)
220 {
221  uint_t port;
222  bool_t linkState;
223 
224 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
225  //Port separation mode?
226  if(interface->port != 0)
227  {
228  uint_t i;
229  NetInterface *virtualInterface;
230 
231  //Loop through network interfaces
232  for(i = 0; i < NET_INTERFACE_COUNT; i++)
233  {
234  //Point to the current interface
235  virtualInterface = &netInterface[i];
236 
237  //Check whether the current virtual interface is attached to the
238  //physical interface
239  if(virtualInterface == interface ||
240  virtualInterface->parent == interface)
241  {
242  //Retrieve current link state
243  linkState = ksz8794GetLinkState(interface, virtualInterface->port);
244 
245  //Link up or link down event?
246  if(linkState != virtualInterface->linkState)
247  {
248  //Set event flag
249  interface->phyEvent = TRUE;
250  //Notify the TCP/IP stack of the event
252  }
253  }
254  }
255  }
256  else
257 #endif
258  {
259  //Initialize link state
260  linkState = FALSE;
261 
262  //Loop through the ports
264  {
265  //Retrieve current link state
266  if(ksz8794GetLinkState(interface, port))
267  {
268  linkState = TRUE;
269  }
270  }
271 
272  //Link up or link down event?
273  if(linkState != interface->linkState)
274  {
275  //Set event flag
276  interface->phyEvent = TRUE;
277  //Notify the TCP/IP stack of the event
279  }
280  }
281 }
282 
283 
284 /**
285  * @brief Enable interrupts
286  * @param[in] interface Underlying network interface
287  **/
288 
290 {
291 }
292 
293 
294 /**
295  * @brief Disable interrupts
296  * @param[in] interface Underlying network interface
297  **/
298 
300 {
301 }
302 
303 
304 /**
305  * @brief KSZ8794 event handler
306  * @param[in] interface Underlying network interface
307  **/
308 
310 {
311  uint_t port;
312  bool_t linkState;
313 
314 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
315  //Port separation mode?
316  if(interface->port != 0)
317  {
318  uint_t i;
319  NetInterface *virtualInterface;
320 
321  //Loop through network interfaces
322  for(i = 0; i < NET_INTERFACE_COUNT; i++)
323  {
324  //Point to the current interface
325  virtualInterface = &netInterface[i];
326 
327  //Check whether the current virtual interface is attached to the
328  //physical interface
329  if(virtualInterface == interface ||
330  virtualInterface->parent == interface)
331  {
332  //Get the port number associated with the current interface
333  port = virtualInterface->port;
334 
335  //Valid port?
336  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
337  {
338  //Retrieve current link state
339  linkState = ksz8794GetLinkState(interface, port);
340 
341  //Link up event?
342  if(linkState && !virtualInterface->linkState)
343  {
344  //Retrieve host interface speed
345  interface->linkSpeed = ksz8794GetLinkSpeed(interface,
346  KSZ8794_PORT4);
347 
348  //Retrieve host interface duplex mode
349  interface->duplexMode = ksz8794GetDuplexMode(interface,
350  KSZ8794_PORT4);
351 
352  //Adjust MAC configuration parameters for proper operation
353  interface->nicDriver->updateMacConfig(interface);
354 
355  //Check current speed
356  virtualInterface->linkSpeed = ksz8794GetLinkSpeed(interface,
357  port);
358 
359  //Check current duplex mode
360  virtualInterface->duplexMode = ksz8794GetDuplexMode(interface,
361  port);
362 
363  //Update link state
364  virtualInterface->linkState = TRUE;
365 
366  //Process link state change event
367  nicNotifyLinkChange(virtualInterface);
368  }
369  //Link down event
370  else if(!linkState && virtualInterface->linkState)
371  {
372  //Update link state
373  virtualInterface->linkState = FALSE;
374 
375  //Process link state change event
376  nicNotifyLinkChange(virtualInterface);
377  }
378  }
379  }
380  }
381  }
382  else
383 #endif
384  {
385  //Initialize link state
386  linkState = FALSE;
387 
388  //Loop through the ports
390  {
391  //Retrieve current link state
392  if(ksz8794GetLinkState(interface, port))
393  {
394  linkState = TRUE;
395  }
396  }
397 
398  //Link up event?
399  if(linkState)
400  {
401  //Retrieve host interface speed
402  interface->linkSpeed = ksz8794GetLinkSpeed(interface, KSZ8794_PORT4);
403  //Retrieve host interface duplex mode
404  interface->duplexMode = ksz8794GetDuplexMode(interface, KSZ8794_PORT4);
405 
406  //Adjust MAC configuration parameters for proper operation
407  interface->nicDriver->updateMacConfig(interface);
408 
409  //Update link state
410  interface->linkState = TRUE;
411  }
412  else
413  {
414  //Update link state
415  interface->linkState = FALSE;
416  }
417 
418  //Process link state change event
419  nicNotifyLinkChange(interface);
420  }
421 }
422 
423 
424 /**
425  * @brief Add tail tag to Ethernet frame
426  * @param[in] interface Underlying network interface
427  * @param[in] buffer Multi-part buffer containing the payload
428  * @param[in,out] offset Offset to the first payload byte
429  * @param[in] ancillary Additional options passed to the stack along with
430  * the packet
431  * @return Error code
432  **/
433 
435  size_t *offset, NetTxAncillary *ancillary)
436 {
437  error_t error;
438 
439  //Initialize status code
440  error = NO_ERROR;
441 
442 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
443  //SPI slave mode?
444  if(interface->spiDriver != NULL)
445  {
446  //Valid port?
447  if(ancillary->port <= KSZ8794_PORT3)
448  {
449  size_t length;
450  const uint8_t *tailTag;
451 
452  //The one byte tail tagging is used to indicate the destination port
453  tailTag = &ksz8794IngressTailTag[ancillary->port];
454 
455  //Retrieve the length of the Ethernet frame
456  length = netBufferGetLength(buffer) - *offset;
457 
458  //The host controller should manually add padding to the packet before
459  //inserting the tail tag
460  error = ethPadFrame(buffer, &length);
461 
462  //Check status code
463  if(!error)
464  {
465  //The tail tag is inserted at the end of the packet, just before
466  //the CRC
467  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
468  }
469  }
470  else
471  {
472  //The port number is not valid
473  error = ERROR_INVALID_PORT;
474  }
475  }
476 #endif
477 
478  //Return status code
479  return error;
480 }
481 
482 
483 /**
484  * @brief Decode tail tag from incoming Ethernet frame
485  * @param[in] interface Underlying network interface
486  * @param[in,out] frame Pointer to the received Ethernet frame
487  * @param[in,out] length Length of the frame, in bytes
488  * @param[in,out] ancillary Additional options passed to the stack along with
489  * the packet
490  * @return Error code
491  **/
492 
493 error_t ksz8794UntagFrame(NetInterface *interface, uint8_t **frame,
494  size_t *length, NetRxAncillary *ancillary)
495 {
496  error_t error;
497 
498  //Initialize status code
499  error = NO_ERROR;
500 
501 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
502  //SPI slave mode?
503  if(interface->spiDriver != NULL)
504  {
505  //Valid Ethernet frame received?
506  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
507  {
508  uint8_t *tailTag;
509 
510  //The tail tag is inserted at the end of the packet, just before
511  //the CRC
512  tailTag = *frame + *length - sizeof(uint8_t);
513 
514  //The one byte tail tagging is used to indicate the source port
515  ancillary->port = (*tailTag & KSZ8794_TAIL_TAG_SRC_PORT) + 1;
516 
517  //Strip tail tag from Ethernet frame
518  *length -= sizeof(uint8_t);
519  }
520  else
521  {
522  //Drop the received frame
523  error = ERROR_INVALID_LENGTH;
524  }
525  }
526  else
527  {
528  //Tail tagging mode cannot be enabled through MDC/MDIO interface
529  ancillary->port = 0;
530  }
531 #endif
532 
533  //Return status code
534  return error;
535 }
536 
537 
538 /**
539  * @brief Get link state
540  * @param[in] interface Underlying network interface
541  * @param[in] port Port number
542  * @return Link state
543  **/
544 
546 {
547  uint16_t status;
548  bool_t linkState;
549 
550  //Check port number
551  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
552  {
553  //SPI slave mode?
554  if(interface->spiDriver != NULL)
555  {
556  //Read port status 2 register
557  status = ksz8794ReadSwitchReg(interface, KSZ8794_PORTn_STAT2(port));
558 
559  //Retrieve current link state
560  linkState = (status & KSZ8794_PORTn_STAT2_LINK_GOOD) ? TRUE : FALSE;
561  }
562  else
563  {
564  //Read status register
565  status = ksz8794ReadPhyReg(interface, port, KSZ8794_BMSR);
566 
567  //Retrieve current link state
568  linkState = (status & KSZ8794_BMSR_LINK_STATUS) ? TRUE : FALSE;
569  }
570  }
571  else
572  {
573  //The specified port number is not valid
574  linkState = FALSE;
575  }
576 
577  //Return link status
578  return linkState;
579 }
580 
581 
582 /**
583  * @brief Get link speed
584  * @param[in] interface Underlying network interface
585  * @param[in] port Port number
586  * @return Link speed
587  **/
588 
589 uint32_t ksz8794GetLinkSpeed(NetInterface *interface, uint8_t port)
590 {
591  uint8_t type;
592  uint8_t value;
593  uint32_t linkSpeed;
594 
595  //SPI slave mode?
596  if(interface->spiDriver != NULL)
597  {
598  //Check port number
599  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
600  {
601  //Read port status 1 register
603 
604  //Retrieve current link speed
606  {
607  linkSpeed = NIC_LINK_SPEED_100MBPS;
608  }
609  else
610  {
611  linkSpeed = NIC_LINK_SPEED_10MBPS;
612  }
613  }
614  else if(port == KSZ8794_PORT4)
615  {
616  //Read port 4 interface control 6 register
618 
619  //Retrieve host interface type
621 
622  //Gigabit interface?
625  {
626  //1000 Mb/s mode
627  linkSpeed = NIC_LINK_SPEED_1GBPS;
628  }
629  else
630  {
631  //Read global control 4 register
633 
634  //Retrieve host interface speed
636  {
637  //10 Mb/s mode
638  linkSpeed = NIC_LINK_SPEED_10MBPS;
639  }
640  else
641  {
642  //100 Mb/s mode
643  linkSpeed = NIC_LINK_SPEED_100MBPS;
644  }
645  }
646  }
647  else
648  {
649  //The specified port number is not valid
650  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
651  }
652  }
653  else
654  {
655  //The MDC/MDIO interface does not have access to all the configuration
656  //registers. It can only access the standard MIIM registers
657  linkSpeed = NIC_LINK_SPEED_100MBPS;
658  }
659 
660  //Return link status
661  return linkSpeed;
662 }
663 
664 
665 /**
666  * @brief Get duplex mode
667  * @param[in] interface Underlying network interface
668  * @param[in] port Port number
669  * @return Duplex mode
670  **/
671 
673 {
674  uint8_t value;
675  NicDuplexMode duplexMode;
676 
677  //SPI slave mode?
678  if(interface->spiDriver != NULL)
679  {
680  //Check port number
681  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
682  {
683  //Read port status 1 register
685 
686  //Retrieve current duplex mode
688  {
689  duplexMode = NIC_FULL_DUPLEX_MODE;
690  }
691  else
692  {
693  duplexMode = NIC_HALF_DUPLEX_MODE;
694  }
695  }
696  else if(port == KSZ8794_PORT4)
697  {
698  //Read global control 4 register
700 
701  //Retrieve host interface duplex mode
703  {
704  duplexMode = NIC_HALF_DUPLEX_MODE;
705  }
706  else
707  {
708  duplexMode = NIC_FULL_DUPLEX_MODE;
709  }
710  }
711  else
712  {
713  //The specified port number is not valid
714  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
715  }
716  }
717  else
718  {
719  //The MDC/MDIO interface does not have access to all the configuration
720  //registers. It can only access the standard MIIM registers
721  duplexMode = NIC_FULL_DUPLEX_MODE;
722  }
723 
724  //Return duplex mode
725  return duplexMode;
726 }
727 
728 
729 /**
730  * @brief Set port state
731  * @param[in] interface Underlying network interface
732  * @param[in] port Port number
733  * @param[in] state Port state
734  **/
735 
736 void ksz8794SetPortState(NetInterface *interface, uint8_t port,
737  SwitchPortState state)
738 {
739  uint8_t temp;
740 
741  //Check port number
742  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
743  {
744  //Read port control 2 register
745  temp = ksz8794ReadSwitchReg(interface, KSZ8794_PORTn_CTRL2(port));
746 
747  //Update port state
748  switch(state)
749  {
750  //Listening state
755  break;
756 
757  //Learning state
762  break;
763 
764  //Forwarding state
769  break;
770 
771  //Disabled state
772  default:
776  break;
777  }
778 
779  //Write the value back to port control 2 register
781  }
782 }
783 
784 
785 /**
786  * @brief Get port state
787  * @param[in] interface Underlying network interface
788  * @param[in] port Port number
789  * @return Port state
790  **/
791 
793 {
794  uint8_t temp;
795  SwitchPortState state;
796 
797  //Check port number
798  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
799  {
800  //Read port control 2 register
801  temp = ksz8794ReadSwitchReg(interface, KSZ8794_PORTn_CTRL2(port));
802 
803  //Check port state
804  if((temp & KSZ8794_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
805  (temp & KSZ8794_PORTn_CTRL2_RECEIVE_EN) == 0 &&
806  (temp & KSZ8794_PORTn_CTRL2_LEARNING_DIS) != 0)
807  {
808  //Disabled state
810  }
811  else if((temp & KSZ8794_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
812  (temp & KSZ8794_PORTn_CTRL2_RECEIVE_EN) != 0 &&
813  (temp & KSZ8794_PORTn_CTRL2_LEARNING_DIS) != 0)
814  {
815  //Listening state
817  }
818  else if((temp & KSZ8794_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
819  (temp & KSZ8794_PORTn_CTRL2_RECEIVE_EN) == 0 &&
820  (temp & KSZ8794_PORTn_CTRL2_LEARNING_DIS) == 0)
821  {
822  //Learning state
824  }
825  else if((temp & KSZ8794_PORTn_CTRL2_TRANSMIT_EN) != 0 &&
826  (temp & KSZ8794_PORTn_CTRL2_RECEIVE_EN) != 0 &&
827  (temp & KSZ8794_PORTn_CTRL2_LEARNING_DIS) == 0)
828  {
829  //Forwarding state
831  }
832  else
833  {
834  //Unknown state
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 ksz8794SetAgingTime(NetInterface *interface, uint32_t agingTime)
856 {
857  //The aging period is fixed to 300 seconds
858 }
859 
860 
861 /**
862  * @brief Enable IGMP snooping
863  * @param[in] interface Underlying network interface
864  * @param[in] enable Enable or disable IGMP snooping
865  **/
866 
868 {
869  uint8_t temp;
870 
871  //Read global control 3 register
872  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL3);
873 
874  //Enable or disable IGMP snooping
875  if(enable)
876  {
878  }
879  else
880  {
882  }
883 
884  //Write the value back to global control 3 register
886 }
887 
888 
889 /**
890  * @brief Enable MLD snooping
891  * @param[in] interface Underlying network interface
892  * @param[in] enable Enable or disable MLD snooping
893  **/
894 
896 {
897  uint8_t temp;
898 
899  //Read global control 21 register
900  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL21);
901 
902  //Enable or disable MLD snooping
903  if(enable)
904  {
906  }
907  else
908  {
910  }
911 
912  //Write the value back to global control 21 register
914 }
915 
916 
917 /**
918  * @brief Enable reserved multicast table
919  * @param[in] interface Underlying network interface
920  * @param[in] enable Enable or disable reserved group addresses
921  **/
922 
924 {
925  uint_t i;
926  SwitchFdbEntry entry;
927 
928  //The reserved group addresses are in the range of 01-80-C2-00-00-00 to
929  //01-80-C2-00-00-0F
930  for(i = 0; i <= 15; i++)
931  {
932  //Specify the reserved group address to be added or removed
933  entry.macAddr.b[0] = 0x01;
934  entry.macAddr.b[1] = 0x80;
935  entry.macAddr.b[2] = 0xC2;
936  entry.macAddr.b[3] = 0x00;
937  entry.macAddr.b[4] = 0x00;
938  entry.macAddr.b[5] = i;
939 
940  //Format forwarding database entry
941  entry.srcPort = 0;
943  entry.override = TRUE;
944 
945  //Update the static MAC table
946  if(enable)
947  {
948  ksz8794AddStaticFdbEntry(interface, &entry);
949  }
950  else
951  {
952  ksz8794DeleteStaticFdbEntry(interface, &entry);
953  }
954  }
955 }
956 
957 
958 /**
959  * @brief Add a new entry to the static MAC table
960  * @param[in] interface Underlying network interface
961  * @param[in] entry Pointer to the forwarding database entry
962  * @return Error code
963  **/
964 
966  const SwitchFdbEntry *entry)
967 {
968  error_t error;
969  uint_t i;
970  uint_t j;
971  uint8_t *p;
972  SwitchFdbEntry currentEntry;
973  Ksz8794StaticMacEntryW newEntry;
974 
975  //Keep track of the first free entry
977 
978  //Loop through the static MAC table
979  for(i = 0; i < KSZ8794_STATIC_MAC_TABLE_SIZE; i++)
980  {
981  //Read current entry
982  error = ksz8794GetStaticFdbEntry(interface, i, &currentEntry);
983 
984  //Valid entry?
985  if(!error)
986  {
987  //Check whether the table already contains the specified MAC address
988  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
989  {
990  j = i;
991  break;
992  }
993  }
994  else
995  {
996  //Keep track of the first free entry
998  {
999  j = i;
1000  }
1001  }
1002  }
1003 
1004  //Any entry available?
1006  {
1007  //Format MAC entry
1008  newEntry.fid = 0;
1009  newEntry.useFid = 0;
1010  newEntry.override = entry->override;
1011  newEntry.valid = TRUE;
1012  newEntry.macAddr = entry->macAddr;
1013 
1014  //Set the relevant forward ports
1015  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1016  {
1017  newEntry.forwardPorts = KSZ8794_PORT4_MASK;
1018  }
1019  else
1020  {
1021  newEntry.forwardPorts = entry->destPorts & KSZ8794_PORT_MASK;
1022  }
1023 
1024  //Select the static MAC address table
1028 
1029  //Point to the MAC entry
1030  p = (uint8_t *) &newEntry;
1031 
1032  //Write indirect data registers
1033  for(i = 0; i < sizeof(Ksz8794StaticMacEntryW); i++)
1034  {
1035  ksz8794WriteSwitchReg(interface, KSZ8794_INDIRECT_DATA7 + i, p[i]);
1036  }
1037 
1038  //Setup a write operation
1042 
1043  //Trigger the write operation
1045 
1046  //Successful processing
1047  error = NO_ERROR;
1048  }
1049  else
1050  {
1051  //The static MAC table is full
1052  error = ERROR_TABLE_FULL;
1053  }
1054 
1055  //Return status code
1056  return error;
1057 }
1058 
1059 
1060 /**
1061  * @brief Remove an entry from the static MAC table
1062  * @param[in] interface Underlying network interface
1063  * @param[in] entry Forwarding database entry to remove from the table
1064  * @return Error code
1065  **/
1066 
1068  const SwitchFdbEntry *entry)
1069 {
1070  error_t error;
1071  uint_t i;
1072  uint_t j;
1073  SwitchFdbEntry currentEntry;
1074 
1075  //Loop through the static MAC table
1076  for(j = 0; j < KSZ8794_STATIC_MAC_TABLE_SIZE; j++)
1077  {
1078  //Read current entry
1079  error = ksz8794GetStaticFdbEntry(interface, j, &currentEntry);
1080 
1081  //Valid entry?
1082  if(!error)
1083  {
1084  //Check whether the table contains the specified MAC address
1085  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1086  {
1087  break;
1088  }
1089  }
1090  }
1091 
1092  //Any matching entry?
1094  {
1095  //Select the static MAC address table
1099 
1100  //Clear indirect data registers
1101  for(i = 0; i < sizeof(Ksz8794StaticMacEntryW); i++)
1102  {
1103  ksz8794WriteSwitchReg(interface, KSZ8794_INDIRECT_DATA7 + i, 0);
1104  }
1105 
1106  //Setup a write operation
1110 
1111  //Trigger the write operation
1113 
1114  //Successful processing
1115  error = NO_ERROR;
1116  }
1117  else
1118  {
1119  //The static MAC table does not contain the specified address
1120  error = ERROR_NOT_FOUND;
1121  }
1122 
1123  //Return status code
1124  return error;
1125 }
1126 
1127 
1128 /**
1129  * @brief Read an entry from the static MAC table
1130  * @param[in] interface Underlying network interface
1131  * @param[in] index Zero-based index of the entry to read
1132  * @param[out] entry Pointer to the forwarding database entry
1133  * @return Error code
1134  **/
1135 
1137  SwitchFdbEntry *entry)
1138 {
1139  error_t error;
1140  uint_t i;
1141  uint8_t *p;
1142  Ksz8794StaticMacEntryR currentEntry;
1143 
1144  //Check index parameter
1145  if(index < KSZ8794_STATIC_MAC_TABLE_SIZE)
1146  {
1147  //Select the static MAC address table
1151 
1152  //Trigger the read operation
1153  ksz8794WriteSwitchReg(interface, KSZ8794_INDIRECT_CTRL1, index);
1154 
1155  //Point to the MAC entry
1156  p = (uint8_t *) &currentEntry;
1157 
1158  //Read indirect data registers
1159  for(i = 0; i < sizeof(Ksz8794StaticMacEntryR); i++)
1160  {
1161  p[i] = ksz8794ReadSwitchReg(interface, KSZ8794_INDIRECT_DATA7 + i);
1162  }
1163 
1164  //Valid entry?
1165  if(currentEntry.valid)
1166  {
1167  //Copy MAC entry
1168  entry->macAddr = currentEntry.macAddr;
1169  entry->srcPort = 0;
1170  entry->destPorts = currentEntry.forwardPorts & KSZ8794_PORT_MASK;
1171  entry->override = currentEntry.override;
1172 
1173  //Successful processing
1174  error = NO_ERROR;
1175  }
1176  else
1177  {
1178  //The entry is not valid
1179  error = ERROR_INVALID_ENTRY;
1180  }
1181  }
1182  else
1183  {
1184  //The end of the table has been reached
1185  error = ERROR_END_OF_TABLE;
1186  }
1187 
1188  //Return status code
1189  return error;
1190 }
1191 
1192 
1193 /**
1194  * @brief Flush static MAC table
1195  * @param[in] interface Underlying network interface
1196  **/
1197 
1199 {
1200  uint_t i;
1201  uint_t temp;
1202  uint8_t state[5];
1203 
1204  //Loop through the ports
1205  for(i = KSZ8794_PORT1; i <= KSZ8794_PORT4; i++)
1206  {
1207  //Valid port?
1208  if(i != KSZ8794_PORT_RESERVED)
1209  {
1210  //Save the current state of the port
1211  state[i - 1] = ksz8794ReadSwitchReg(interface, KSZ8794_PORTn_CTRL2(i));
1212 
1213  //Turn off learning capability
1215  state[i - 1] | KSZ8794_PORTn_CTRL2_LEARNING_DIS);
1216  }
1217  }
1218 
1219  //All the entries associated with a port that has its learning capability
1220  //being turned off will be flushed
1221  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL0);
1223  ksz8794WriteSwitchReg(interface, KSZ8794_GLOBAL_CTRL0, temp);
1224 
1225  //Loop through the ports
1226  for(i = KSZ8794_PORT1; i <= KSZ8794_PORT4; i++)
1227  {
1228  //Valid port?
1229  if(i != KSZ8794_PORT_RESERVED)
1230  {
1231  //Restore the original state of the port
1232  ksz8794WriteSwitchReg(interface, KSZ8794_PORTn_CTRL2(i), state[i - 1]);
1233  }
1234  }
1235 }
1236 
1237 
1238 /**
1239  * @brief Read an entry from the dynamic MAC table
1240  * @param[in] interface Underlying network interface
1241  * @param[in] index Zero-based index of the entry to read
1242  * @param[out] entry Pointer to the forwarding database entry
1243  * @return Error code
1244  **/
1245 
1247  SwitchFdbEntry *entry)
1248 {
1249  error_t error;
1250  uint_t i;
1251  uint_t n;
1252  uint8_t *p;
1253  Ksz8794DynamicMacEntry currentEntry;
1254 
1255  //Check index parameter
1256  if(index < KSZ8794_DYNAMIC_MAC_TABLE_SIZE)
1257  {
1258  //Read the MAC entry at the specified index
1259  do
1260  {
1261  //Select the dynamic MAC address table
1266 
1267  //Trigger the read operation
1268  ksz8794WriteSwitchReg(interface, KSZ8794_INDIRECT_CTRL1, LSB(index));
1269 
1270  //Point to the MAC entry
1271  p = (uint8_t *) &currentEntry;
1272 
1273  //Read indirect data registers
1274  for(i = 0; i < sizeof(Ksz8794DynamicMacEntry); i++)
1275  {
1276  p[i] = ksz8794ReadSwitchReg(interface, KSZ8794_INDIRECT_DATA8 + i);
1277  }
1278 
1279  //Retry until the entry is ready
1280  } while(currentEntry.dataNotReady);
1281 
1282  //Check whether there are valid entries in the table
1283  if(!currentEntry.macEmpty)
1284  {
1285  //Retrieve the number of valid entries
1286  n = ((currentEntry.numValidEntriesH << 3) |
1287  currentEntry.numValidEntriesL) + 1;
1288  }
1289  else
1290  {
1291  //The table is empty
1292  n = 0;
1293  }
1294 
1295  //Valid entry?
1296  if(index < n)
1297  {
1298  //Copy MAC entry
1299  entry->macAddr = currentEntry.macAddr;
1300  entry->srcPort = currentEntry.sourcePort + 1;
1301  entry->destPorts = 0;
1302  entry->override = FALSE;
1303 
1304  //Successful processing
1305  error = NO_ERROR;
1306  }
1307  else
1308  {
1309  //The end of the table has been reached
1310  error = ERROR_END_OF_TABLE;
1311  }
1312  }
1313  else
1314  {
1315  //The end of the table has been reached
1316  error = ERROR_END_OF_TABLE;
1317  }
1318 
1319  //Return status code
1320  return error;
1321 }
1322 
1323 
1324 /**
1325  * @brief Flush dynamic MAC table
1326  * @param[in] interface Underlying network interface
1327  * @param[in] port Port number
1328  **/
1329 
1331 {
1332  uint_t i;
1333  uint_t temp;
1334  uint8_t state[5];
1335 
1336  //Loop through the ports
1337  for(i = KSZ8794_PORT1; i <= KSZ8794_PORT4; i++)
1338  {
1339  //Valid port?
1340  if(i != KSZ8794_PORT_RESERVED)
1341  {
1342  //Matching port number?
1343  if(i == port || port == 0)
1344  {
1345  //Save the current state of the port
1346  state[i - 1] = ksz8794ReadSwitchReg(interface,
1347  KSZ8794_PORTn_CTRL2(i));
1348 
1349  //Turn off learning capability
1351  state[i - 1] | KSZ8794_PORTn_CTRL2_LEARNING_DIS);
1352  }
1353  }
1354  }
1355 
1356  //All the entries associated with a port that has its learning capability
1357  //being turned off will be flushed
1358  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL0);
1360  ksz8794WriteSwitchReg(interface, KSZ8794_GLOBAL_CTRL0, temp);
1361 
1362  //Loop through the ports
1363  for(i = KSZ8794_PORT1; i <= KSZ8794_PORT4; i++)
1364  {
1365  //Valid port?
1366  if(i != KSZ8794_PORT_RESERVED)
1367  {
1368  //Matching port number?
1369  if(i == port || port == 0)
1370  {
1371  //Restore the original state of the port
1373  state[i - 1]);
1374  }
1375  }
1376  }
1377 }
1378 
1379 
1380 /**
1381  * @brief Set forward ports for unknown multicast packets
1382  * @param[in] interface Underlying network interface
1383  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1384  * @param[in] forwardPorts Port map
1385  **/
1386 
1388  bool_t enable, uint32_t forwardPorts)
1389 {
1390  uint8_t temp;
1391 
1392  //Read global control 16 register
1393  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL16);
1394 
1395  //Clear port map
1397 
1398  //Enable or disable forwarding of unknown multicast packets
1399  if(enable)
1400  {
1401  //Enable forwarding
1403 
1404  //Check whether unknown multicast packets should be forwarded to the CPU port
1405  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1406  {
1408  }
1409 
1410  //Select the desired forward ports
1411  temp |= forwardPorts & KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL;
1412  }
1413  else
1414  {
1415  //Disable forwarding
1417  }
1418 
1419  //Write the value back to global control 16 register
1420  ksz8794WriteSwitchReg(interface, KSZ8794_GLOBAL_CTRL16, temp);
1421 }
1422 
1423 
1424 /**
1425  * @brief Write PHY register
1426  * @param[in] interface Underlying network interface
1427  * @param[in] port Port number
1428  * @param[in] address PHY register address
1429  * @param[in] data Register value
1430  **/
1431 
1432 void ksz8794WritePhyReg(NetInterface *interface, uint8_t port,
1433  uint8_t address, uint16_t data)
1434 {
1435  //Write the specified PHY register
1436  if(interface->smiDriver != NULL)
1437  {
1438  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1439  }
1440  else
1441  {
1442  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1443  }
1444 }
1445 
1446 
1447 /**
1448  * @brief Read PHY register
1449  * @param[in] interface Underlying network interface
1450  * @param[in] port Port number
1451  * @param[in] address PHY register address
1452  * @return Register value
1453  **/
1454 
1455 uint16_t ksz8794ReadPhyReg(NetInterface *interface, uint8_t port,
1456  uint8_t address)
1457 {
1458  uint16_t data;
1459 
1460  //Read the specified PHY register
1461  if(interface->smiDriver != NULL)
1462  {
1463  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1464  }
1465  else
1466  {
1467  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1468  }
1469 
1470  //Return the value of the PHY register
1471  return data;
1472 }
1473 
1474 
1475 /**
1476  * @brief Dump PHY registers for debugging purpose
1477  * @param[in] interface Underlying network interface
1478  * @param[in] port Port number
1479  **/
1480 
1481 void ksz8794DumpPhyReg(NetInterface *interface, uint8_t port)
1482 {
1483  uint8_t i;
1484 
1485  //Loop through PHY registers
1486  for(i = 0; i < 32; i++)
1487  {
1488  //Display current PHY register
1489  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1490  ksz8794ReadPhyReg(interface, port, i));
1491  }
1492 
1493  //Terminate with a line feed
1494  TRACE_DEBUG("\r\n");
1495 }
1496 
1497 
1498 /**
1499  * @brief Write switch register
1500  * @param[in] interface Underlying network interface
1501  * @param[in] address Switch register address
1502  * @param[in] data Register value
1503  **/
1504 
1505 void ksz8794WriteSwitchReg(NetInterface *interface, uint16_t address,
1506  uint8_t data)
1507 {
1508  uint16_t command;
1509 
1510  //SPI slave mode?
1511  if(interface->spiDriver != NULL)
1512  {
1513  //Set up a write operation
1514  command = KSZ8794_SPI_CMD_WRITE;
1515  //Set register address
1516  command |= (address << 1) & KSZ8794_SPI_CMD_ADDR;
1517 
1518  //Pull the CS pin low
1519  interface->spiDriver->assertCs();
1520 
1521  //Write 16-bit command
1522  interface->spiDriver->transfer(MSB(command));
1523  interface->spiDriver->transfer(LSB(command));
1524 
1525  //Write data
1526  interface->spiDriver->transfer(data);
1527 
1528  //Terminate the operation by raising the CS pin
1529  interface->spiDriver->deassertCs();
1530  }
1531  else
1532  {
1533  //The MDC/MDIO interface does not have access to all the configuration
1534  //registers. It can only access the standard MIIM registers
1535  }
1536 }
1537 
1538 
1539 /**
1540  * @brief Read switch register
1541  * @param[in] interface Underlying network interface
1542  * @param[in] address Switch register address
1543  * @return Register value
1544  **/
1545 
1546 uint8_t ksz8794ReadSwitchReg(NetInterface *interface, uint16_t address)
1547 {
1548  uint8_t data;
1549  uint16_t command;
1550 
1551  //SPI slave mode?
1552  if(interface->spiDriver != NULL)
1553  {
1554  //Set up a read operation
1555  command = KSZ8794_SPI_CMD_READ;
1556  //Set register address
1557  command |= (address << 1) & KSZ8794_SPI_CMD_ADDR;
1558 
1559  //Pull the CS pin low
1560  interface->spiDriver->assertCs();
1561 
1562  //Write 16-bit command
1563  interface->spiDriver->transfer(MSB(command));
1564  interface->spiDriver->transfer(LSB(command));
1565 
1566  //Read data
1567  data = interface->spiDriver->transfer(0xFF);
1568 
1569  //Terminate the operation by raising the CS pin
1570  interface->spiDriver->deassertCs();
1571  }
1572  else
1573  {
1574  //The MDC/MDIO interface does not have access to all the configuration
1575  //registers. It can only access the standard MIIM registers
1576  data = 0;
1577  }
1578 
1579  //Return register value
1580  return data;
1581 }
1582 
1583 
1584 /**
1585  * @brief Dump switch registers for debugging purpose
1586  * @param[in] interface Underlying network interface
1587  **/
1588 
1590 {
1591  uint16_t i;
1592 
1593  //Loop through switch registers
1594  for(i = 0; i < 256; i++)
1595  {
1596  //Display current switch register
1597  TRACE_DEBUG("0x%02" PRIX16 " (%02" PRIu16 ") : 0x%02" PRIX8 "\r\n",
1598  i, i, ksz8794ReadSwitchReg(interface, i));
1599  }
1600 
1601  //Terminate with a line feed
1602  TRACE_DEBUG("\r\n");
1603 }
uint8_t type
Definition: coap_common.h:176
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint16_t port
Definition: dns_common.h:267
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_NOT_FOUND
Definition: error.h:147
@ ERROR_END_OF_TABLE
Definition: error.h:290
@ ERROR_INVALID_ENTRY
Definition: error.h:288
@ ERROR_TABLE_FULL
Definition: error.h:289
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint8_t data[]
Definition: ethernet.h:222
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
EthHeader
Definition: ethernet.h:223
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
Helper functions for Ethernet.
Ipv6Addr address[]
Definition: ipv6.h:316
void ksz8794DisableIrq(NetInterface *interface)
Disable interrupts.
uint8_t ksz8794ReadSwitchReg(NetInterface *interface, uint16_t address)
Read switch register.
uint32_t ksz8794GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
void ksz8794EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
error_t ksz8794DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
error_t ksz8794UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
error_t ksz8794GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
error_t ksz8794GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
const uint8_t ksz8794IngressTailTag[4]
Tail tag rules (host to KSZ8794)
void ksz8794DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
__weak_func void ksz8794InitHook(NetInterface *interface)
KSZ8794 custom configuration.
void ksz8794EnableIrq(NetInterface *interface)
Enable interrupts.
void ksz8794EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
void ksz8794WriteSwitchReg(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register.
error_t ksz8794AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
SwitchPortState ksz8794GetPortState(NetInterface *interface, uint8_t port)
Get port state.
uint16_t ksz8794ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
void ksz8794FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
bool_t ksz8794GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
NicDuplexMode ksz8794GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
void ksz8794SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
void ksz8794SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
error_t ksz8794Init(NetInterface *interface)
KSZ8794 Ethernet switch initialization.
void ksz8794FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
void ksz8794WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
void ksz8794EventHandler(NetInterface *interface)
KSZ8794 event handler.
const SwitchDriver ksz8794SwitchDriver
KSZ8794 Ethernet switch driver.
void ksz8794Tick(NetInterface *interface)
KSZ8794 timer handler.
void ksz8794EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
void ksz8794DumpSwitchReg(NetInterface *interface)
Dump switch registers for debugging purpose.
error_t ksz8794TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
void ksz8794SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
KSZ8794 4-port Ethernet switch driver.
#define KSZ8794_GLOBAL_CTRL3
#define KSZ8794_GLOBAL_CTRL2
#define KSZ8794_TAIL_TAG_DEST_PORT3
#define KSZ8794_PORT4_IF_CTRL6_IS_1GBPS
#define KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL
#define KSZ8794_PORTn_STAT1(port)
#define KSZ8794_INDIRECT_CTRL0_READ
#define KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD
#define KSZ8794_PORT3
#define KSZ8794_INDIRECT_CTRL0_ADDR_9_8
#define KSZ8794_PORTn_CTRL2(port)
#define KSZ8794_PORTn_STAT2(port)
#define KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP
#define KSZ8794_GLOBAL_CTRL10
#define KSZ8794_INDIRECT_CTRL0
#define KSZ8794_INDIRECT_CTRL0_TABLE_SEL_DYNAMIC_MAC
#define KSZ8794_INDIRECT_DATA7
#define KSZ8794_PORTn_STAT2_LINK_GOOD
#define KSZ8794_PORTn_STAT1_OP_SPEED
#define KSZ8794_PORT4_IF_CTRL6_IF_MODE_SEL_RGMII
#define KSZ8794_PORTn_CTRL2_RECEIVE_EN
#define KSZ8794_PORT4_IF_CTRL6
#define KSZ8794_GLOBAL_CTRL4
#define KSZ8794_GLOBAL_CTRL10_TAIL_TAG_EN
#define KSZ8794_GLOBAL_CTRL0
#define KSZ8794_PORT_RESERVED
#define KSZ8794_SPI_CMD_READ
#define KSZ8794_INDIRECT_CTRL0_WRITE
#define KSZ8794_GLOBAL_CTRL3_SW5_IGMP_SNOOP_EN
#define KSZ8794_PORT4_MASK
#define KSZ8794_SPI_CMD_ADDR
#define KSZ8794_TAIL_TAG_SRC_PORT
#define KSZ8794_GLOBAL_CTRL21
#define KSZ8794_BMSR_LINK_STATUS
#define KSZ8794_PORTn_CTRL2_LEARNING_DIS
#define KSZ8794_PORT4_IF_CTRL6_IF_MODE_SEL
#define KSZ8794_PORT1
#define KSZ8794_INDIRECT_CTRL1
#define KSZ8794_GLOBAL_CTRL2_MAX_PKT_SIZE_CHECK_DIS
#define KSZ8794_TAIL_TAG_DEST_PORT2
#define KSZ8794_CHIP_ID0
#define KSZ8794_GLOBAL_CTRL16
#define KSZ8794_PORTn_STAT1_OP_DUPLEX
#define KSZ8794_CHIP_ID0_FAMILY_ID_DEFAULT
#define KSZ8794_INDIRECT_CTRL0_TABLE_SEL_STATIC_MAC
#define KSZ8794_PORT_MASK
#define KSZ8794_INDIRECT_BYTE
#define KSZ8794_PORTn_CTRL2_TRANSMIT_EN
#define KSZ8794_GLOBAL_CTRL4_SW4_HALF_DUPLEX_MODE
#define KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_PORT4
#define KSZ8794_GLOBAL_CTRL0_FLUSH_DYNAMIC_MAC_TABLE
#define KSZ8794_PORT4
#define KSZ8794_GLOBAL_CTRL4_SW4_SPEED
#define KSZ8794_INDIRECT_DATA8
#define KSZ8794_TAIL_TAG_DEST_PORT1
#define KSZ8794_GLOBAL_CTRL0_FLUSH_STATIC_MAC_TABLE
#define KSZ8794_SPI_CMD_WRITE
#define KSZ8794_TAIL_TAG_NORMAL_ADDR_LOOKUP
#define KSZ8794_DYNAMIC_MAC_TABLE_SIZE
#define KSZ8794_BMSR
#define KSZ8794_TAIL_TAG_PORT_SEL
#define KSZ8794_GLOBAL_CTRL21_MLD_SNOOP_EN
#define KSZ8794_STATIC_MAC_TABLE_SIZE
uint8_t p
Definition: ndp.h:300
TCP/IP stack core.
#define NET_INTERFACE_COUNT
Definition: net.h:113
#define NetInterface
Definition: net.h:36
#define netInterface
Definition: net_legacy.h:199
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:588
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:548
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define SMI_OPCODE_READ
Definition: nic.h:67
NicDuplexMode
Duplex mode.
Definition: nic.h:122
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
SwitchPortState
Switch port state.
Definition: nic.h:134
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define LSB(x)
Definition: os_port.h:55
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define MSB(x)
Definition: os_port.h:59
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
Dynamic MAC table entry.
uint8_t numValidEntriesH
uint8_t sourcePort
MacAddr macAddr
uint8_t macEmpty
uint8_t numValidEntriesL
uint8_t dataNotReady
Static MAC table entry (read operation)
uint8_t forwardPorts
MacAddr macAddr
uint8_t valid
uint8_t override
Static MAC table entry (write operation)
uint8_t forwardPorts
MacAddr macAddr
uint8_t valid
uint8_t useFid
uint8_t override
uint8_t fid
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
Ethernet switch driver.
Definition: nic.h:322
Forwarding database entry.
Definition: nic.h:149
MacAddr macAddr
Definition: nic.h:150
uint32_t destPorts
Definition: nic.h:152
bool_t override
Definition: nic.h:153
uint8_t srcPort
Definition: nic.h:151
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369