ksz8795_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz8795_driver.c
3  * @brief KSZ8795 5-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 KSZ8795 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ8795)
75  **/
76 
77 const uint8_t ksz8795IngressTailTag[5] =
78 {
84 };
85 
86 
87 /**
88  * @brief KSZ8795 Ethernet switch initialization
89  * @param[in] interface Underlying network interface
90  * @return Error code
91  **/
92 
94 {
95  uint_t port;
96  uint8_t temp;
97 
98  //Debug message
99  TRACE_INFO("Initializing KSZ8795...\r\n");
100 
101  //SPI slave mode?
102  if(interface->spiDriver != NULL)
103  {
104  //Initialize SPI interface
105  interface->spiDriver->init();
106 
107  //Wait for the serial interface to be ready
108  do
109  {
110  //Read CHIP_ID0 register
111  temp = ksz8795ReadSwitchReg(interface, KSZ8795_CHIP_ID0);
112 
113  //The returned data is invalid until the serial interface is ready
114  } while(temp != KSZ8795_CHIP_ID0_FAMILY_ID_DEFAULT);
115 
116 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
117  //Enable tail tag feature
118  temp = ksz8795ReadSwitchReg(interface, KSZ8795_GLOBAL_CTRL10);
121 
122  //Disable packet size check
123  temp = ksz8795ReadSwitchReg(interface, KSZ8795_GLOBAL_CTRL2);
126 #else
127  //Disable tail tag feature
128  temp = ksz8795ReadSwitchReg(interface, KSZ8795_GLOBAL_CTRL10);
131 
132  //Enable packet size check
133  temp = ksz8795ReadSwitchReg(interface, KSZ8795_GLOBAL_CTRL2);
136 #endif
137 
138  //Loop through the ports
140  {
141 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
142  //Port separation mode?
143  if(interface->port != 0)
144  {
145  //Disable packet transmission and address learning
147  }
148  else
149 #endif
150  {
151  //Enable transmission, reception and address learning
153  }
154  }
155 
156  //Disable EEE next page exchange (silicon errata workaround 2)
160 
161  //Improve receiver settings (silicon errata workaround 3)
165 
166  //Improve transmitter settings (silicon errata workaround 4)
170 
171  //Dump switch registers for debugging purpose
172  ksz8795DumpSwitchReg(interface);
173  }
174  else
175  {
176  //Initialize serial management interface
177  if(interface->smiDriver != NULL)
178  {
179  interface->smiDriver->init();
180  }
181 
182  //Loop through the ports
184  {
185  //Debug message
186  TRACE_DEBUG("Port %u:\r\n", port);
187  //Dump PHY registers for debugging purpose
188  ksz8795DumpPhyReg(interface, port);
189  }
190  }
191 
192  //Perform custom configuration
193  ksz8795InitHook(interface);
194 
195  //Force the TCP/IP stack to poll the link state at startup
196  interface->phyEvent = TRUE;
197  //Notify the TCP/IP stack of the event
199 
200  //Successful initialization
201  return NO_ERROR;
202 }
203 
204 
205 /**
206  * @brief KSZ8795 custom configuration
207  * @param[in] interface Underlying network interface
208  **/
209 
210 __weak_func void ksz8795InitHook(NetInterface *interface)
211 {
212 }
213 
214 
215 /**
216  * @brief KSZ8795 timer handler
217  * @param[in] interface Underlying network interface
218  **/
219 
220 void ksz8795Tick(NetInterface *interface)
221 {
222  uint_t port;
223  bool_t linkState;
224 
225 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
226  //Port separation mode?
227  if(interface->port != 0)
228  {
229  uint_t i;
230  NetInterface *virtualInterface;
231 
232  //Loop through network interfaces
233  for(i = 0; i < NET_INTERFACE_COUNT; i++)
234  {
235  //Point to the current interface
236  virtualInterface = &netInterface[i];
237 
238  //Check whether the current virtual interface is attached to the
239  //physical interface
240  if(virtualInterface == interface ||
241  virtualInterface->parent == interface)
242  {
243  //Retrieve current link state
244  linkState = ksz8795GetLinkState(interface, virtualInterface->port);
245 
246  //Link up or link down event?
247  if(linkState != virtualInterface->linkState)
248  {
249  //Set event flag
250  interface->phyEvent = TRUE;
251  //Notify the TCP/IP stack of the event
253  }
254  }
255  }
256  }
257  else
258 #endif
259  {
260  //Initialize link state
261  linkState = FALSE;
262 
263  //Loop through the ports
265  {
266  //Retrieve current link state
267  if(ksz8795GetLinkState(interface, port))
268  {
269  linkState = TRUE;
270  }
271  }
272 
273  //Link up or link down event?
274  if(linkState != interface->linkState)
275  {
276  //Set event flag
277  interface->phyEvent = TRUE;
278  //Notify the TCP/IP stack of the event
280  }
281  }
282 }
283 
284 
285 /**
286  * @brief Enable interrupts
287  * @param[in] interface Underlying network interface
288  **/
289 
291 {
292 }
293 
294 
295 /**
296  * @brief Disable interrupts
297  * @param[in] interface Underlying network interface
298  **/
299 
301 {
302 }
303 
304 
305 /**
306  * @brief KSZ8795 event handler
307  * @param[in] interface Underlying network interface
308  **/
309 
311 {
312  uint_t port;
313  bool_t linkState;
314 
315 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
316  //Port separation mode?
317  if(interface->port != 0)
318  {
319  uint_t i;
320  NetInterface *virtualInterface;
321 
322  //Loop through network interfaces
323  for(i = 0; i < NET_INTERFACE_COUNT; i++)
324  {
325  //Point to the current interface
326  virtualInterface = &netInterface[i];
327 
328  //Check whether the current virtual interface is attached to the
329  //physical interface
330  if(virtualInterface == interface ||
331  virtualInterface->parent == interface)
332  {
333  //Get the port number associated with the current interface
334  port = virtualInterface->port;
335 
336  //Valid port?
337  if(port >= KSZ8795_PORT1 && port <= KSZ8795_PORT4)
338  {
339  //Retrieve current link state
340  linkState = ksz8795GetLinkState(interface, port);
341 
342  //Link up event?
343  if(linkState && !virtualInterface->linkState)
344  {
345  //Retrieve host interface speed
346  interface->linkSpeed = ksz8795GetLinkSpeed(interface,
347  KSZ8795_PORT5);
348 
349  //Retrieve host interface duplex mode
350  interface->duplexMode = ksz8795GetDuplexMode(interface,
351  KSZ8795_PORT5);
352 
353  //Adjust MAC configuration parameters for proper operation
354  interface->nicDriver->updateMacConfig(interface);
355 
356  //Check current speed
357  virtualInterface->linkSpeed = ksz8795GetLinkSpeed(interface,
358  port);
359 
360  //Check current duplex mode
361  virtualInterface->duplexMode = ksz8795GetDuplexMode(interface,
362  port);
363 
364  //Update link state
365  virtualInterface->linkState = TRUE;
366 
367  //Process link state change event
368  nicNotifyLinkChange(virtualInterface);
369  }
370  //Link down event
371  else if(!linkState && virtualInterface->linkState)
372  {
373  //Update link state
374  virtualInterface->linkState = FALSE;
375 
376  //Process link state change event
377  nicNotifyLinkChange(virtualInterface);
378  }
379  }
380  }
381  }
382  }
383  else
384 #endif
385  {
386  //Initialize link state
387  linkState = FALSE;
388 
389  //Loop through the ports
391  {
392  //Retrieve current link state
393  if(ksz8795GetLinkState(interface, port))
394  {
395  linkState = TRUE;
396  }
397  }
398 
399  //Link up event?
400  if(linkState)
401  {
402  //Retrieve host interface speed
403  interface->linkSpeed = ksz8795GetLinkSpeed(interface, KSZ8795_PORT5);
404  //Retrieve host interface duplex mode
405  interface->duplexMode = ksz8795GetDuplexMode(interface, KSZ8795_PORT5);
406 
407  //Adjust MAC configuration parameters for proper operation
408  interface->nicDriver->updateMacConfig(interface);
409 
410  //Update link state
411  interface->linkState = TRUE;
412  }
413  else
414  {
415  //Update link state
416  interface->linkState = FALSE;
417  }
418 
419  //Process link state change event
420  nicNotifyLinkChange(interface);
421  }
422 }
423 
424 
425 /**
426  * @brief Add tail tag to Ethernet frame
427  * @param[in] interface Underlying network interface
428  * @param[in] buffer Multi-part buffer containing the payload
429  * @param[in,out] offset Offset to the first payload byte
430  * @param[in] ancillary Additional options passed to the stack along with
431  * the packet
432  * @return Error code
433  **/
434 
436  size_t *offset, NetTxAncillary *ancillary)
437 {
438  error_t error;
439 
440  //Initialize status code
441  error = NO_ERROR;
442 
443 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
444  //SPI slave mode?
445  if(interface->spiDriver != NULL)
446  {
447  //Valid port?
448  if(ancillary->port <= KSZ8795_PORT4)
449  {
450  size_t length;
451  const uint8_t *tailTag;
452 
453  //The one byte tail tagging is used to indicate the destination port
454  tailTag = &ksz8795IngressTailTag[ancillary->port];
455 
456  //Retrieve the length of the Ethernet frame
457  length = netBufferGetLength(buffer) - *offset;
458 
459  //The host controller should manually add padding to the packet before
460  //inserting the tail tag
461  error = ethPadFrame(buffer, &length);
462 
463  //Check status code
464  if(!error)
465  {
466  //The tail tag is inserted at the end of the packet, just before
467  //the CRC
468  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
469  }
470  }
471  else
472  {
473  //The port number is not valid
474  error = ERROR_INVALID_PORT;
475  }
476  }
477 #endif
478 
479  //Return status code
480  return error;
481 }
482 
483 
484 /**
485  * @brief Decode tail tag from incoming Ethernet frame
486  * @param[in] interface Underlying network interface
487  * @param[in,out] frame Pointer to the received Ethernet frame
488  * @param[in,out] length Length of the frame, in bytes
489  * @param[in,out] ancillary Additional options passed to the stack along with
490  * the packet
491  * @return Error code
492  **/
493 
494 error_t ksz8795UntagFrame(NetInterface *interface, uint8_t **frame,
495  size_t *length, NetRxAncillary *ancillary)
496 {
497  error_t error;
498 
499  //Initialize status code
500  error = NO_ERROR;
501 
502 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
503  //SPI slave mode?
504  if(interface->spiDriver != NULL)
505  {
506  //Valid Ethernet frame received?
507  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
508  {
509  uint8_t *tailTag;
510 
511  //The tail tag is inserted at the end of the packet, just before
512  //the CRC
513  tailTag = *frame + *length - sizeof(uint8_t);
514 
515  //The one byte tail tagging is used to indicate the source port
516  ancillary->port = (*tailTag & KSZ8795_TAIL_TAG_SRC_PORT) + 1;
517 
518  //Strip tail tag from Ethernet frame
519  *length -= sizeof(uint8_t);
520  }
521  else
522  {
523  //Drop the received frame
524  error = ERROR_INVALID_LENGTH;
525  }
526  }
527  else
528  {
529  //Tail tagging mode cannot be enabled through MDC/MDIO interface
530  ancillary->port = 0;
531  }
532 #endif
533 
534  //Return status code
535  return error;
536 }
537 
538 
539 /**
540  * @brief Get link state
541  * @param[in] interface Underlying network interface
542  * @param[in] port Port number
543  * @return Link state
544  **/
545 
547 {
548  uint16_t status;
549  bool_t linkState;
550 
551  //Check port number
552  if(port >= KSZ8795_PORT1 && port <= KSZ8795_PORT4)
553  {
554  //SPI slave mode?
555  if(interface->spiDriver != NULL)
556  {
557  //Read port status 2 register
558  status = ksz8795ReadSwitchReg(interface, KSZ8795_PORTn_STAT2(port));
559 
560  //Retrieve current link state
561  linkState = (status & KSZ8795_PORTn_STAT2_LINK_GOOD) ? TRUE : FALSE;
562  }
563  else
564  {
565  //Read status register
566  status = ksz8795ReadPhyReg(interface, port, KSZ8795_BMSR);
567 
568  //Retrieve current link state
569  linkState = (status & KSZ8795_BMSR_LINK_STATUS) ? TRUE : FALSE;
570  }
571  }
572  else
573  {
574  //The specified port number is not valid
575  linkState = FALSE;
576  }
577 
578  //Return link status
579  return linkState;
580 }
581 
582 
583 /**
584  * @brief Get link speed
585  * @param[in] interface Underlying network interface
586  * @param[in] port Port number
587  * @return Link speed
588  **/
589 
590 uint32_t ksz8795GetLinkSpeed(NetInterface *interface, uint8_t port)
591 {
592  uint8_t type;
593  uint8_t value;
594  uint32_t linkSpeed;
595 
596  //SPI slave mode?
597  if(interface->spiDriver != NULL)
598  {
599  //Check port number
600  if(port >= KSZ8795_PORT1 && port <= KSZ8795_PORT4)
601  {
602  //Read port status 1 register
604 
605  //Retrieve current link speed
607  {
608  linkSpeed = NIC_LINK_SPEED_100MBPS;
609  }
610  else
611  {
612  linkSpeed = NIC_LINK_SPEED_10MBPS;
613  }
614  }
615  else if(port == KSZ8795_PORT5)
616  {
617  //Read port 5 interface control 6 register
619 
620  //Retrieve host interface type
622 
623  //Gigabit interface?
627  {
628  //1000 Mb/s mode
629  linkSpeed = NIC_LINK_SPEED_1GBPS;
630  }
631  else
632  {
633  //Read global control 4 register
635 
636  //Retrieve host interface speed
638  {
639  //10 Mb/s mode
640  linkSpeed = NIC_LINK_SPEED_10MBPS;
641  }
642  else
643  {
644  //100 Mb/s mode
645  linkSpeed = NIC_LINK_SPEED_100MBPS;
646  }
647  }
648  }
649  else
650  {
651  //The specified port number is not valid
652  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
653  }
654  }
655  else
656  {
657  //The MDC/MDIO interface does not have access to all the configuration
658  //registers. It can only access the standard MIIM registers
659  linkSpeed = NIC_LINK_SPEED_100MBPS;
660  }
661 
662  //Return link status
663  return linkSpeed;
664 }
665 
666 
667 /**
668  * @brief Get duplex mode
669  * @param[in] interface Underlying network interface
670  * @param[in] port Port number
671  * @return Duplex mode
672  **/
673 
675 {
676  uint8_t value;
677  NicDuplexMode duplexMode;
678 
679  //SPI slave mode?
680  if(interface->spiDriver != NULL)
681  {
682  //Check port number
683  if(port >= KSZ8795_PORT1 && port <= KSZ8795_PORT4)
684  {
685  //Read port status 1 register
687 
688  //Retrieve current duplex mode
690  {
691  duplexMode = NIC_FULL_DUPLEX_MODE;
692  }
693  else
694  {
695  duplexMode = NIC_HALF_DUPLEX_MODE;
696  }
697  }
698  else if(port == KSZ8795_PORT5)
699  {
700  //Read global control 4 register
702 
703  //Retrieve host interface duplex mode
705  {
706  duplexMode = NIC_HALF_DUPLEX_MODE;
707  }
708  else
709  {
710  duplexMode = NIC_FULL_DUPLEX_MODE;
711  }
712  }
713  else
714  {
715  //The specified port number is not valid
716  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
717  }
718  }
719  else
720  {
721  //The MDC/MDIO interface does not have access to all the configuration
722  //registers. It can only access the standard MIIM registers
723  duplexMode = NIC_FULL_DUPLEX_MODE;
724  }
725 
726  //Return duplex mode
727  return duplexMode;
728 }
729 
730 
731 /**
732  * @brief Set port state
733  * @param[in] interface Underlying network interface
734  * @param[in] port Port number
735  * @param[in] state Port state
736  **/
737 
738 void ksz8795SetPortState(NetInterface *interface, uint8_t port,
739  SwitchPortState state)
740 {
741  uint8_t temp;
742 
743  //Check port number
744  if(port >= KSZ8795_PORT1 && port <= KSZ8795_PORT4)
745  {
746  //Read port control 2 register
747  temp = ksz8795ReadSwitchReg(interface, KSZ8795_PORTn_CTRL2(port));
748 
749  //Update port state
750  switch(state)
751  {
752  //Listening state
757  break;
758 
759  //Learning state
764  break;
765 
766  //Forwarding state
771  break;
772 
773  //Disabled state
774  default:
778  break;
779  }
780 
781  //Write the value back to port control 2 register
783  }
784 }
785 
786 
787 /**
788  * @brief Get port state
789  * @param[in] interface Underlying network interface
790  * @param[in] port Port number
791  * @return Port state
792  **/
793 
795 {
796  uint8_t temp;
797  SwitchPortState state;
798 
799  //Check port number
800  if(port >= KSZ8795_PORT1 && port <= KSZ8795_PORT4)
801  {
802  //Read port control 2 register
803  temp = ksz8795ReadSwitchReg(interface, KSZ8795_PORTn_CTRL2(port));
804 
805  //Check port state
806  if((temp & KSZ8795_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
807  (temp & KSZ8795_PORTn_CTRL2_RECEIVE_EN) == 0 &&
808  (temp & KSZ8795_PORTn_CTRL2_LEARNING_DIS) != 0)
809  {
810  //Disabled state
812  }
813  else if((temp & KSZ8795_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
814  (temp & KSZ8795_PORTn_CTRL2_RECEIVE_EN) != 0 &&
815  (temp & KSZ8795_PORTn_CTRL2_LEARNING_DIS) != 0)
816  {
817  //Listening state
819  }
820  else if((temp & KSZ8795_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
821  (temp & KSZ8795_PORTn_CTRL2_RECEIVE_EN) == 0 &&
822  (temp & KSZ8795_PORTn_CTRL2_LEARNING_DIS) == 0)
823  {
824  //Learning state
826  }
827  else if((temp & KSZ8795_PORTn_CTRL2_TRANSMIT_EN) != 0 &&
828  (temp & KSZ8795_PORTn_CTRL2_RECEIVE_EN) != 0 &&
829  (temp & KSZ8795_PORTn_CTRL2_LEARNING_DIS) == 0)
830  {
831  //Forwarding state
833  }
834  else
835  {
836  //Unknown state
838  }
839  }
840  else
841  {
842  //The specified port number is not valid
844  }
845 
846  //Return port state
847  return state;
848 }
849 
850 
851 /**
852  * @brief Set aging time for dynamic filtering entries
853  * @param[in] interface Underlying network interface
854  * @param[in] agingTime Aging time, in seconds
855  **/
856 
857 void ksz8795SetAgingTime(NetInterface *interface, uint32_t agingTime)
858 {
859  //The aging period is fixed to 300 seconds
860 }
861 
862 
863 /**
864  * @brief Enable IGMP snooping
865  * @param[in] interface Underlying network interface
866  * @param[in] enable Enable or disable IGMP snooping
867  **/
868 
870 {
871  uint8_t temp;
872 
873  //Read global control 3 register
874  temp = ksz8795ReadSwitchReg(interface, KSZ8795_GLOBAL_CTRL3);
875 
876  //Enable or disable IGMP snooping
877  if(enable)
878  {
880  }
881  else
882  {
884  }
885 
886  //Write the value back to global control 3 register
888 }
889 
890 
891 /**
892  * @brief Enable MLD snooping
893  * @param[in] interface Underlying network interface
894  * @param[in] enable Enable or disable MLD snooping
895  **/
896 
898 {
899  uint8_t temp;
900 
901  //Read global control 21 register
902  temp = ksz8795ReadSwitchReg(interface, KSZ8795_GLOBAL_CTRL21);
903 
904  //Enable or disable MLD snooping
905  if(enable)
906  {
908  }
909  else
910  {
912  }
913 
914  //Write the value back to global control 21 register
916 }
917 
918 
919 /**
920  * @brief Enable reserved multicast table
921  * @param[in] interface Underlying network interface
922  * @param[in] enable Enable or disable reserved group addresses
923  **/
924 
926 {
927  uint_t i;
928  SwitchFdbEntry entry;
929 
930  //The reserved group addresses are in the range of 01-80-C2-00-00-00 to
931  //01-80-C2-00-00-0F
932  for(i = 0; i <= 15; i++)
933  {
934  //Specify the reserved group address to be added or removed
935  entry.macAddr.b[0] = 0x01;
936  entry.macAddr.b[1] = 0x80;
937  entry.macAddr.b[2] = 0xC2;
938  entry.macAddr.b[3] = 0x00;
939  entry.macAddr.b[4] = 0x00;
940  entry.macAddr.b[5] = i;
941 
942  //Format forwarding database entry
943  entry.srcPort = 0;
945  entry.override = TRUE;
946 
947  //Update the static MAC table
948  if(enable)
949  {
950  ksz8795AddStaticFdbEntry(interface, &entry);
951  }
952  else
953  {
954  ksz8795DeleteStaticFdbEntry(interface, &entry);
955  }
956  }
957 }
958 
959 
960 /**
961  * @brief Add a new entry to the static MAC table
962  * @param[in] interface Underlying network interface
963  * @param[in] entry Pointer to the forwarding database entry
964  * @return Error code
965  **/
966 
968  const SwitchFdbEntry *entry)
969 {
970  error_t error;
971  uint_t i;
972  uint_t j;
973  uint8_t *p;
974  SwitchFdbEntry currentEntry;
975  Ksz8795StaticMacEntryW newEntry;
976 
977  //Keep track of the first free entry
979 
980  //Loop through the static MAC table
981  for(i = 0; i < KSZ8795_STATIC_MAC_TABLE_SIZE; i++)
982  {
983  //Read current entry
984  error = ksz8795GetStaticFdbEntry(interface, i, &currentEntry);
985 
986  //Valid entry?
987  if(!error)
988  {
989  //Check whether the table already contains the specified MAC address
990  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
991  {
992  j = i;
993  break;
994  }
995  }
996  else
997  {
998  //Keep track of the first free entry
1000  {
1001  j = i;
1002  }
1003  }
1004  }
1005 
1006  //Any entry available?
1008  {
1009  //Format MAC entry
1010  newEntry.fid = 0;
1011  newEntry.useFid = 0;
1012  newEntry.override = entry->override;
1013  newEntry.valid = TRUE;
1014  newEntry.macAddr = entry->macAddr;
1015 
1016  //Set the relevant forward ports
1017  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1018  {
1019  newEntry.forwardPorts = KSZ8795_PORT5_MASK;
1020  }
1021  else
1022  {
1023  newEntry.forwardPorts = entry->destPorts & KSZ8795_PORT_MASK;
1024  }
1025 
1026  //Select the static MAC address table
1030 
1031  //Point to the MAC entry
1032  p = (uint8_t *) &newEntry;
1033 
1034  //Write indirect data registers
1035  for(i = 0; i < sizeof(Ksz8795StaticMacEntryW); i++)
1036  {
1037  ksz8795WriteSwitchReg(interface, KSZ8795_INDIRECT_DATA7 + i, p[i]);
1038  }
1039 
1040  //Setup a write operation
1044 
1045  //Trigger the write operation
1047 
1048  //Successful processing
1049  error = NO_ERROR;
1050  }
1051  else
1052  {
1053  //The static MAC table is full
1054  error = ERROR_TABLE_FULL;
1055  }
1056 
1057  //Return status code
1058  return error;
1059 }
1060 
1061 
1062 /**
1063  * @brief Remove an entry from the static MAC table
1064  * @param[in] interface Underlying network interface
1065  * @param[in] entry Forwarding database entry to remove from the table
1066  * @return Error code
1067  **/
1068 
1070  const SwitchFdbEntry *entry)
1071 {
1072  error_t error;
1073  uint_t i;
1074  uint_t j;
1075  SwitchFdbEntry currentEntry;
1076 
1077  //Loop through the static MAC table
1078  for(j = 0; j < KSZ8795_STATIC_MAC_TABLE_SIZE; j++)
1079  {
1080  //Read current entry
1081  error = ksz8795GetStaticFdbEntry(interface, j, &currentEntry);
1082 
1083  //Valid entry?
1084  if(!error)
1085  {
1086  //Check whether the table contains the specified MAC address
1087  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1088  {
1089  break;
1090  }
1091  }
1092  }
1093 
1094  //Any matching entry?
1096  {
1097  //Select the static MAC address table
1101 
1102  //Clear indirect data registers
1103  for(i = 0; i < sizeof(Ksz8795StaticMacEntryW); i++)
1104  {
1105  ksz8795WriteSwitchReg(interface, KSZ8795_INDIRECT_DATA7 + i, 0);
1106  }
1107 
1108  //Setup a write operation
1112 
1113  //Trigger the write operation
1115 
1116  //Successful processing
1117  error = NO_ERROR;
1118  }
1119  else
1120  {
1121  //The static MAC table does not contain the specified address
1122  error = ERROR_NOT_FOUND;
1123  }
1124 
1125  //Return status code
1126  return error;
1127 }
1128 
1129 
1130 /**
1131  * @brief Read an entry from the static MAC table
1132  * @param[in] interface Underlying network interface
1133  * @param[in] index Zero-based index of the entry to read
1134  * @param[out] entry Pointer to the forwarding database entry
1135  * @return Error code
1136  **/
1137 
1139  SwitchFdbEntry *entry)
1140 {
1141  error_t error;
1142  uint_t i;
1143  uint8_t *p;
1144  Ksz8795StaticMacEntryR currentEntry;
1145 
1146  //Check index parameter
1147  if(index < KSZ8795_STATIC_MAC_TABLE_SIZE)
1148  {
1149  //Select the static MAC address table
1153 
1154  //Trigger the read operation
1155  ksz8795WriteSwitchReg(interface, KSZ8795_INDIRECT_CTRL1, index);
1156 
1157  //Point to the MAC entry
1158  p = (uint8_t *) &currentEntry;
1159 
1160  //Read indirect data registers
1161  for(i = 0; i < sizeof(Ksz8795StaticMacEntryR); i++)
1162  {
1163  p[i] = ksz8795ReadSwitchReg(interface, KSZ8795_INDIRECT_DATA7 + i);
1164  }
1165 
1166  //Valid entry?
1167  if(currentEntry.valid)
1168  {
1169  //Copy MAC entry
1170  entry->macAddr = currentEntry.macAddr;
1171  entry->srcPort = 0;
1172  entry->destPorts = currentEntry.forwardPorts & KSZ8795_PORT_MASK;
1173  entry->override = currentEntry.override;
1174 
1175  //Successful processing
1176  error = NO_ERROR;
1177  }
1178  else
1179  {
1180  //The entry is not valid
1181  error = ERROR_INVALID_ENTRY;
1182  }
1183  }
1184  else
1185  {
1186  //The end of the table has been reached
1187  error = ERROR_END_OF_TABLE;
1188  }
1189 
1190  //Return status code
1191  return error;
1192 }
1193 
1194 
1195 /**
1196  * @brief Flush static MAC table
1197  * @param[in] interface Underlying network interface
1198  **/
1199 
1201 {
1202  uint_t i;
1203  uint_t temp;
1204  uint8_t state[5];
1205 
1206  //Loop through the ports
1207  for(i = KSZ8795_PORT1; i <= KSZ8795_PORT5; i++)
1208  {
1209  //Save the current state of the port
1210  state[i - 1] = ksz8795ReadSwitchReg(interface, KSZ8795_PORTn_CTRL2(i));
1211 
1212  //Turn off learning capability
1214  state[i - 1] | KSZ8795_PORTn_CTRL2_LEARNING_DIS);
1215  }
1216 
1217  //All the entries associated with a port that has its learning capability
1218  //being turned off will be flushed
1219  temp = ksz8795ReadSwitchReg(interface, KSZ8795_GLOBAL_CTRL0);
1221  ksz8795WriteSwitchReg(interface, KSZ8795_GLOBAL_CTRL0, temp);
1222 
1223  //Loop through the ports
1224  for(i = KSZ8795_PORT1; i <= KSZ8795_PORT5; i++)
1225  {
1226  //Restore the original state of the port
1227  ksz8795WriteSwitchReg(interface, KSZ8795_PORTn_CTRL2(i), state[i - 1]);
1228  }
1229 }
1230 
1231 
1232 /**
1233  * @brief Read an entry from the dynamic MAC table
1234  * @param[in] interface Underlying network interface
1235  * @param[in] index Zero-based index of the entry to read
1236  * @param[out] entry Pointer to the forwarding database entry
1237  * @return Error code
1238  **/
1239 
1241  SwitchFdbEntry *entry)
1242 {
1243  error_t error;
1244  uint_t i;
1245  uint_t n;
1246  uint8_t *p;
1247  Ksz8795DynamicMacEntry currentEntry;
1248 
1249  //Check index parameter
1250  if(index < KSZ8795_DYNAMIC_MAC_TABLE_SIZE)
1251  {
1252  //Read the MAC entry at the specified index
1253  do
1254  {
1255  //Select the dynamic MAC address table
1260 
1261  //Trigger the read operation
1262  ksz8795WriteSwitchReg(interface, KSZ8795_INDIRECT_CTRL1, LSB(index));
1263 
1264  //Point to the MAC entry
1265  p = (uint8_t *) &currentEntry;
1266 
1267  //Read indirect data registers
1268  for(i = 0; i < sizeof(Ksz8795DynamicMacEntry); i++)
1269  {
1270  p[i] = ksz8795ReadSwitchReg(interface, KSZ8795_INDIRECT_DATA8 + i);
1271  }
1272 
1273  //Retry until the entry is ready
1274  } while(currentEntry.dataNotReady);
1275 
1276  //Check whether there are valid entries in the table
1277  if(!currentEntry.macEmpty)
1278  {
1279  //Retrieve the number of valid entries
1280  n = ((currentEntry.numValidEntriesH << 3) |
1281  currentEntry.numValidEntriesL) + 1;
1282  }
1283  else
1284  {
1285  //The table is empty
1286  n = 0;
1287  }
1288 
1289  //Valid entry?
1290  if(index < n)
1291  {
1292  //Copy MAC entry
1293  entry->macAddr = currentEntry.macAddr;
1294  entry->srcPort = currentEntry.sourcePort + 1;
1295  entry->destPorts = 0;
1296  entry->override = FALSE;
1297 
1298  //Successful processing
1299  error = NO_ERROR;
1300  }
1301  else
1302  {
1303  //The end of the table has been reached
1304  error = ERROR_END_OF_TABLE;
1305  }
1306  }
1307  else
1308  {
1309  //The end of the table has been reached
1310  error = ERROR_END_OF_TABLE;
1311  }
1312 
1313  //Return status code
1314  return error;
1315 }
1316 
1317 
1318 /**
1319  * @brief Flush dynamic MAC table
1320  * @param[in] interface Underlying network interface
1321  * @param[in] port Port number
1322  **/
1323 
1325 {
1326  uint_t i;
1327  uint_t temp;
1328  uint8_t state[5];
1329 
1330  //Loop through the ports
1331  for(i = KSZ8795_PORT1; i <= KSZ8795_PORT5; i++)
1332  {
1333  //Matching port number?
1334  if(i == port || port == 0)
1335  {
1336  //Save the current state of the port
1337  state[i - 1] = ksz8795ReadSwitchReg(interface, KSZ8795_PORTn_CTRL2(i));
1338 
1339  //Turn off learning capability
1341  state[i - 1] | KSZ8795_PORTn_CTRL2_LEARNING_DIS);
1342  }
1343  }
1344 
1345  //All the entries associated with a port that has its learning capability
1346  //being turned off will be flushed
1347  temp = ksz8795ReadSwitchReg(interface, KSZ8795_GLOBAL_CTRL0);
1349  ksz8795WriteSwitchReg(interface, KSZ8795_GLOBAL_CTRL0, temp);
1350 
1351  //Loop through the ports
1352  for(i = KSZ8795_PORT1; i <= KSZ8795_PORT5; i++)
1353  {
1354  //Matching port number?
1355  if(i == port || port == 0)
1356  {
1357  //Restore the original state of the port
1358  ksz8795WriteSwitchReg(interface, KSZ8795_PORTn_CTRL2(i), state[i - 1]);
1359  }
1360  }
1361 }
1362 
1363 
1364 /**
1365  * @brief Set forward ports for unknown multicast packets
1366  * @param[in] interface Underlying network interface
1367  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1368  * @param[in] forwardPorts Port map
1369  **/
1370 
1372  bool_t enable, uint32_t forwardPorts)
1373 {
1374  uint8_t temp;
1375 
1376  //Read global control 16 register
1377  temp = ksz8795ReadSwitchReg(interface, KSZ8795_GLOBAL_CTRL16);
1378 
1379  //Clear port map
1381 
1382  //Enable or disable forwarding of unknown multicast packets
1383  if(enable)
1384  {
1385  //Enable forwarding
1387 
1388  //Check whether unknown multicast packets should be forwarded to the CPU port
1389  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1390  {
1392  }
1393 
1394  //Select the desired forward ports
1395  temp |= forwardPorts & KSZ8795_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL;
1396  }
1397  else
1398  {
1399  //Disable forwarding
1401  }
1402 
1403  //Write the value back to global control 16 register
1404  ksz8795WriteSwitchReg(interface, KSZ8795_GLOBAL_CTRL16, temp);
1405 }
1406 
1407 
1408 /**
1409  * @brief Write PHY register
1410  * @param[in] interface Underlying network interface
1411  * @param[in] port Port number
1412  * @param[in] address PHY register address
1413  * @param[in] data Register value
1414  **/
1415 
1416 void ksz8795WritePhyReg(NetInterface *interface, uint8_t port,
1417  uint8_t address, uint16_t data)
1418 {
1419  //Write the specified PHY register
1420  if(interface->smiDriver != NULL)
1421  {
1422  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1423  }
1424  else
1425  {
1426  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1427  }
1428 }
1429 
1430 
1431 /**
1432  * @brief Read PHY register
1433  * @param[in] interface Underlying network interface
1434  * @param[in] port Port number
1435  * @param[in] address PHY register address
1436  * @return Register value
1437  **/
1438 
1439 uint16_t ksz8795ReadPhyReg(NetInterface *interface, uint8_t port,
1440  uint8_t address)
1441 {
1442  uint16_t data;
1443 
1444  //Read the specified PHY register
1445  if(interface->smiDriver != NULL)
1446  {
1447  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1448  }
1449  else
1450  {
1451  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1452  }
1453 
1454  //Return the value of the PHY register
1455  return data;
1456 }
1457 
1458 
1459 /**
1460  * @brief Dump PHY registers for debugging purpose
1461  * @param[in] interface Underlying network interface
1462  * @param[in] port Port number
1463  **/
1464 
1465 void ksz8795DumpPhyReg(NetInterface *interface, uint8_t port)
1466 {
1467  uint8_t i;
1468 
1469  //Loop through PHY registers
1470  for(i = 0; i < 32; i++)
1471  {
1472  //Display current PHY register
1473  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1474  ksz8795ReadPhyReg(interface, port, i));
1475  }
1476 
1477  //Terminate with a line feed
1478  TRACE_DEBUG("\r\n");
1479 }
1480 
1481 
1482 /**
1483  * @brief Write switch register
1484  * @param[in] interface Underlying network interface
1485  * @param[in] address Switch register address
1486  * @param[in] data Register value
1487  **/
1488 
1489 void ksz8795WriteSwitchReg(NetInterface *interface, uint16_t address,
1490  uint8_t data)
1491 {
1492  uint16_t command;
1493 
1494  //SPI slave mode?
1495  if(interface->spiDriver != NULL)
1496  {
1497  //Set up a write operation
1498  command = KSZ8795_SPI_CMD_WRITE;
1499  //Set register address
1500  command |= (address << 1) & KSZ8795_SPI_CMD_ADDR;
1501 
1502  //Pull the CS pin low
1503  interface->spiDriver->assertCs();
1504 
1505  //Write 16-bit command
1506  interface->spiDriver->transfer(MSB(command));
1507  interface->spiDriver->transfer(LSB(command));
1508 
1509  //Write data
1510  interface->spiDriver->transfer(data);
1511 
1512  //Terminate the operation by raising the CS pin
1513  interface->spiDriver->deassertCs();
1514  }
1515  else
1516  {
1517  //The MDC/MDIO interface does not have access to all the configuration
1518  //registers. It can only access the standard MIIM registers
1519  }
1520 }
1521 
1522 
1523 /**
1524  * @brief Read switch register
1525  * @param[in] interface Underlying network interface
1526  * @param[in] address Switch register address
1527  * @return Register value
1528  **/
1529 
1530 uint8_t ksz8795ReadSwitchReg(NetInterface *interface, uint16_t address)
1531 {
1532  uint8_t data;
1533  uint16_t command;
1534 
1535  //SPI slave mode?
1536  if(interface->spiDriver != NULL)
1537  {
1538  //Set up a read operation
1539  command = KSZ8795_SPI_CMD_READ;
1540  //Set register address
1541  command |= (address << 1) & KSZ8795_SPI_CMD_ADDR;
1542 
1543  //Pull the CS pin low
1544  interface->spiDriver->assertCs();
1545 
1546  //Write 16-bit command
1547  interface->spiDriver->transfer(MSB(command));
1548  interface->spiDriver->transfer(LSB(command));
1549 
1550  //Read data
1551  data = interface->spiDriver->transfer(0xFF);
1552 
1553  //Terminate the operation by raising the CS pin
1554  interface->spiDriver->deassertCs();
1555  }
1556  else
1557  {
1558  //The MDC/MDIO interface does not have access to all the configuration
1559  //registers. It can only access the standard MIIM registers
1560  data = 0;
1561  }
1562 
1563  //Return register value
1564  return data;
1565 }
1566 
1567 
1568 /**
1569  * @brief Dump switch registers for debugging purpose
1570  * @param[in] interface Underlying network interface
1571  **/
1572 
1574 {
1575  uint16_t i;
1576 
1577  //Loop through switch registers
1578  for(i = 0; i < 256; i++)
1579  {
1580  //Display current switch register
1581  TRACE_DEBUG("0x%02" PRIX16 " (%02" PRIu16 ") : 0x%02" PRIX8 "\r\n",
1582  i, i, ksz8795ReadSwitchReg(interface, i));
1583  }
1584 
1585  //Terminate with a line feed
1586  TRACE_DEBUG("\r\n");
1587 }
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 ksz8795SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
void ksz8795DumpSwitchReg(NetInterface *interface)
Dump switch registers for debugging purpose.
error_t ksz8795Init(NetInterface *interface)
KSZ8795 Ethernet switch initialization.
uint32_t ksz8795GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
void ksz8795Tick(NetInterface *interface)
KSZ8795 timer handler.
void ksz8795FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
void ksz8795EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
error_t ksz8795GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
uint16_t ksz8795ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
error_t ksz8795AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
void ksz8795EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
error_t ksz8795GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
void ksz8795DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
void ksz8795EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
void ksz8795SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
SwitchPortState ksz8795GetPortState(NetInterface *interface, uint8_t port)
Get port state.
error_t ksz8795UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
error_t ksz8795DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
void ksz8795WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
NicDuplexMode ksz8795GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
void ksz8795EventHandler(NetInterface *interface)
KSZ8795 event handler.
error_t ksz8795TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
void ksz8795DisableIrq(NetInterface *interface)
Disable interrupts.
const SwitchDriver ksz8795SwitchDriver
KSZ8795 Ethernet switch driver.
bool_t ksz8795GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
void ksz8795WriteSwitchReg(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register.
void ksz8795SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
uint8_t ksz8795ReadSwitchReg(NetInterface *interface, uint16_t address)
Read switch register.
void ksz8795FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
const uint8_t ksz8795IngressTailTag[5]
Tail tag rules (host to KSZ8795)
__weak_func void ksz8795InitHook(NetInterface *interface)
KSZ8795 custom configuration.
void ksz8795EnableIrq(NetInterface *interface)
Enable interrupts.
KSZ8795 5-port Ethernet switch driver.
#define KSZ8795_PORTn_STAT2(port)
#define KSZ8795_PORT5_IF_CTRL6_IF_MODE_SEL
#define KSZ8795_INDIRECT_DATA7
#define KSZ8795_GLOBAL_CTRL4_SW5_HALF_DUPLEX_MODE
#define KSZ8795_PORT5_IF_CTRL6_IS_1GBPS
#define KSZ8795_INDIRECT_CTRL0_WRITE
#define KSZ8795_INDIRECT_BYTE
#define KSZ8795_PORT5_IF_CTRL6_IF_MODE_SEL_RGMII
#define KSZ8795_TAIL_TAG_DEST_PORT1
#define KSZ8795_TAIL_TAG_SRC_PORT
#define KSZ8795_INDIRECT_CTRL0_TABLE_SEL_STATIC_MAC
#define KSZ8795_PORT5
#define KSZ8795_GLOBAL_CTRL0_FLUSH_STATIC_MAC_TABLE
#define KSZ8795_GLOBAL_CTRL4_SW5_SPEED
#define KSZ8795_GLOBAL_CTRL0
#define KSZ8795_PORTn_STAT1_OP_SPEED
#define KSZ8795_TAIL_TAG_NORMAL_ADDR_LOOKUP
#define KSZ8795_TAIL_TAG_PORT_SEL
#define KSZ8795_GLOBAL_CTRL2_MAX_PKT_SIZE_CHECK_DIS
#define KSZ8795_PORT4
#define KSZ8795_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL
#define KSZ8795_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD
#define KSZ8795_PORTn_STAT1_OP_DUPLEX
#define KSZ8795_BMSR_LINK_STATUS
#define KSZ8795_GLOBAL_CTRL3
#define KSZ8795_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_PORT5
#define KSZ8795_INDIRECT_CTRL0_ADDR_9_8
#define KSZ8795_SPI_CMD_ADDR
#define KSZ8795_INDIRECT_DATA8
#define KSZ8795_PORT5_MASK
#define KSZ8795_PORTn_STAT2_LINK_GOOD
#define KSZ8795_TAIL_TAG_DEST_PORT4
#define KSZ8795_TAIL_TAG_DEST_PORT2
#define KSZ8795_GLOBAL_CTRL10
#define KSZ8795_TAIL_TAG_DEST_PORT3
#define KSZ8795_PORTn_CTRL2_RECEIVE_EN
#define KSZ8795_GLOBAL_CTRL4
#define KSZ8795_CHIP_ID0
#define KSZ8795_DYNAMIC_MAC_TABLE_SIZE
#define KSZ8795_PORTn_CTRL2(port)
#define KSZ8795_GLOBAL_CTRL16
#define KSZ8795_GLOBAL_CTRL2
#define KSZ8795_GLOBAL_CTRL0_FLUSH_DYNAMIC_MAC_TABLE
#define KSZ8795_PORT1
#define KSZ8795_GLOBAL_CTRL21_MLD_SNOOP_EN
#define KSZ8795_STATIC_MAC_TABLE_SIZE
#define KSZ8795_INDIRECT_CTRL0_TABLE_SEL_DYNAMIC_MAC
#define KSZ8795_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP
#define KSZ8795_BMSR
#define KSZ8795_PORTn_STAT1(port)
#define KSZ8795_GLOBAL_CTRL10_TAIL_TAG_EN
#define KSZ8795_GLOBAL_CTRL21
#define KSZ8795_SPI_CMD_READ
#define KSZ8795_SPI_CMD_WRITE
#define KSZ8795_INDIRECT_CTRL0_READ
#define KSZ8795_GLOBAL_CTRL3_SW5_IGMP_SNOOP_EN
#define KSZ8795_CHIP_ID0_FAMILY_ID_DEFAULT
#define KSZ8795_PORT5_IF_CTRL6
#define KSZ8795_PORT_MASK
#define KSZ8795_INDIRECT_CTRL1
#define KSZ8795_PORTn_CTRL2_LEARNING_DIS
#define KSZ8795_PORT5_IF_CTRL6_IF_MODE_SEL_GMII
#define KSZ8795_PORTn_CTRL2_TRANSMIT_EN
#define KSZ8795_INDIRECT_CTRL0
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