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-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"
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
197  osSetEvent(&interface->netContext->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 __weak_func 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  NetContext *context;
230  NetInterface *virtualInterface;
231 
232  //Point to the TCP/IP stack context
233  context = interface->netContext;
234 
235  //Loop through network interfaces
236  for(i = 0; i < context->numInterfaces; i++)
237  {
238  //Point to the current interface
239  virtualInterface = &context->interfaces[i];
240 
241  //Check whether the current virtual interface is attached to the
242  //physical interface
243  if(virtualInterface == interface ||
244  virtualInterface->parent == interface)
245  {
246  //Retrieve current link state
247  linkState = ksz8794GetLinkState(interface, virtualInterface->port);
248 
249  //Link up or link down event?
250  if(linkState != virtualInterface->linkState)
251  {
252  //Set event flag
253  interface->phyEvent = TRUE;
254  //Notify the TCP/IP stack of the event
255  osSetEvent(&interface->netContext->event);
256  }
257  }
258  }
259  }
260  else
261 #endif
262  {
263  //Initialize link state
264  linkState = FALSE;
265 
266  //Loop through the ports
268  {
269  //Retrieve current link state
270  if(ksz8794GetLinkState(interface, port))
271  {
272  linkState = TRUE;
273  }
274  }
275 
276  //Link up or link down event?
277  if(linkState != interface->linkState)
278  {
279  //Set event flag
280  interface->phyEvent = TRUE;
281  //Notify the TCP/IP stack of the event
282  osSetEvent(&interface->netContext->event);
283  }
284  }
285 }
286 
287 
288 /**
289  * @brief Enable interrupts
290  * @param[in] interface Underlying network interface
291  **/
292 
294 {
295 }
296 
297 
298 /**
299  * @brief Disable interrupts
300  * @param[in] interface Underlying network interface
301  **/
302 
304 {
305 }
306 
307 
308 /**
309  * @brief KSZ8794 event handler
310  * @param[in] interface Underlying network interface
311  **/
312 
313 __weak_func void ksz8794EventHandler(NetInterface *interface)
314 {
315  uint_t port;
316  bool_t linkState;
317 
318 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
319  //Port separation mode?
320  if(interface->port != 0)
321  {
322  uint_t i;
323  NetContext *context;
324  NetInterface *virtualInterface;
325 
326  //Point to the TCP/IP stack context
327  context = interface->netContext;
328 
329  //Loop through network interfaces
330  for(i = 0; i < context->numInterfaces; i++)
331  {
332  //Point to the current interface
333  virtualInterface = &context->interfaces[i];
334 
335  //Check whether the current virtual interface is attached to the
336  //physical interface
337  if(virtualInterface == interface ||
338  virtualInterface->parent == interface)
339  {
340  //Get the port number associated with the current interface
341  port = virtualInterface->port;
342 
343  //Valid port?
344  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
345  {
346  //Retrieve current link state
347  linkState = ksz8794GetLinkState(interface, port);
348 
349  //Link up event?
350  if(linkState && !virtualInterface->linkState)
351  {
352  //Retrieve host interface speed
353  interface->linkSpeed = ksz8794GetLinkSpeed(interface,
354  KSZ8794_PORT4);
355 
356  //Retrieve host interface duplex mode
357  interface->duplexMode = ksz8794GetDuplexMode(interface,
358  KSZ8794_PORT4);
359 
360  //Adjust MAC configuration parameters for proper operation
361  interface->nicDriver->updateMacConfig(interface);
362 
363  //Check current speed
364  virtualInterface->linkSpeed = ksz8794GetLinkSpeed(interface,
365  port);
366 
367  //Check current duplex mode
368  virtualInterface->duplexMode = ksz8794GetDuplexMode(interface,
369  port);
370 
371  //Update link state
372  virtualInterface->linkState = TRUE;
373 
374  //Process link state change event
375  nicNotifyLinkChange(virtualInterface);
376  }
377  //Link down event
378  else if(!linkState && virtualInterface->linkState)
379  {
380  //Update link state
381  virtualInterface->linkState = FALSE;
382 
383  //Process link state change event
384  nicNotifyLinkChange(virtualInterface);
385  }
386  }
387  }
388  }
389  }
390  else
391 #endif
392  {
393  //Initialize link state
394  linkState = FALSE;
395 
396  //Loop through the ports
398  {
399  //Retrieve current link state
400  if(ksz8794GetLinkState(interface, port))
401  {
402  linkState = TRUE;
403  }
404  }
405 
406  //Link up event?
407  if(linkState)
408  {
409  //Retrieve host interface speed
410  interface->linkSpeed = ksz8794GetLinkSpeed(interface, KSZ8794_PORT4);
411  //Retrieve host interface duplex mode
412  interface->duplexMode = ksz8794GetDuplexMode(interface, KSZ8794_PORT4);
413 
414  //Adjust MAC configuration parameters for proper operation
415  interface->nicDriver->updateMacConfig(interface);
416 
417  //Update link state
418  interface->linkState = TRUE;
419  }
420  else
421  {
422  //Update link state
423  interface->linkState = FALSE;
424  }
425 
426  //Process link state change event
427  nicNotifyLinkChange(interface);
428  }
429 }
430 
431 
432 /**
433  * @brief Add tail tag to Ethernet frame
434  * @param[in] interface Underlying network interface
435  * @param[in] buffer Multi-part buffer containing the payload
436  * @param[in,out] offset Offset to the first payload byte
437  * @param[in] ancillary Additional options passed to the stack along with
438  * the packet
439  * @return Error code
440  **/
441 
443  size_t *offset, NetTxAncillary *ancillary)
444 {
445  error_t error;
446 
447  //Initialize status code
448  error = NO_ERROR;
449 
450 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
451  //SPI slave mode?
452  if(interface->spiDriver != NULL)
453  {
454  //Valid port?
455  if(ancillary->port <= KSZ8794_PORT3)
456  {
457  size_t length;
458  const uint8_t *tailTag;
459 
460  //The one byte tail tagging is used to indicate the destination port
461  tailTag = &ksz8794IngressTailTag[ancillary->port];
462 
463  //Retrieve the length of the Ethernet frame
464  length = netBufferGetLength(buffer) - *offset;
465 
466  //The host controller should manually add padding to the packet before
467  //inserting the tail tag
468  error = ethPadFrame(buffer, &length);
469 
470  //Check status code
471  if(!error)
472  {
473  //The tail tag is inserted at the end of the packet, just before
474  //the CRC
475  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
476  }
477  }
478  else
479  {
480  //The port number is not valid
481  error = ERROR_INVALID_PORT;
482  }
483  }
484 #endif
485 
486  //Return status code
487  return error;
488 }
489 
490 
491 /**
492  * @brief Decode tail tag from incoming Ethernet frame
493  * @param[in] interface Underlying network interface
494  * @param[in,out] frame Pointer to the received Ethernet frame
495  * @param[in,out] length Length of the frame, in bytes
496  * @param[in,out] ancillary Additional options passed to the stack along with
497  * the packet
498  * @return Error code
499  **/
500 
501 error_t ksz8794UntagFrame(NetInterface *interface, uint8_t **frame,
502  size_t *length, NetRxAncillary *ancillary)
503 {
504  error_t error;
505 
506  //Initialize status code
507  error = NO_ERROR;
508 
509 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
510  //SPI slave mode?
511  if(interface->spiDriver != NULL)
512  {
513  //Valid Ethernet frame received?
514  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
515  {
516  uint8_t *tailTag;
517 
518  //The tail tag is inserted at the end of the packet, just before
519  //the CRC
520  tailTag = *frame + *length - sizeof(uint8_t);
521 
522  //The one byte tail tagging is used to indicate the source port
523  ancillary->port = (*tailTag & KSZ8794_TAIL_TAG_SRC_PORT) + 1;
524 
525  //Strip tail tag from Ethernet frame
526  *length -= sizeof(uint8_t);
527  }
528  else
529  {
530  //Drop the received frame
531  error = ERROR_INVALID_LENGTH;
532  }
533  }
534  else
535  {
536  //Tail tagging mode cannot be enabled through MDC/MDIO interface
537  ancillary->port = 0;
538  }
539 #endif
540 
541  //Return status code
542  return error;
543 }
544 
545 
546 /**
547  * @brief Get link state
548  * @param[in] interface Underlying network interface
549  * @param[in] port Port number
550  * @return Link state
551  **/
552 
554 {
555  uint16_t status;
556  bool_t linkState;
557 
558  //Check port number
559  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
560  {
561  //SPI slave mode?
562  if(interface->spiDriver != NULL)
563  {
564  //Read port status 2 register
565  status = ksz8794ReadSwitchReg(interface, KSZ8794_PORTn_STAT2(port));
566 
567  //Retrieve current link state
568  linkState = (status & KSZ8794_PORTn_STAT2_LINK_GOOD) ? TRUE : FALSE;
569  }
570  else
571  {
572  //Read status register
573  status = ksz8794ReadPhyReg(interface, port, KSZ8794_BMSR);
574 
575  //Retrieve current link state
576  linkState = (status & KSZ8794_BMSR_LINK_STATUS) ? TRUE : FALSE;
577  }
578  }
579  else
580  {
581  //The specified port number is not valid
582  linkState = FALSE;
583  }
584 
585  //Return link status
586  return linkState;
587 }
588 
589 
590 /**
591  * @brief Get link speed
592  * @param[in] interface Underlying network interface
593  * @param[in] port Port number
594  * @return Link speed
595  **/
596 
597 uint32_t ksz8794GetLinkSpeed(NetInterface *interface, uint8_t port)
598 {
599  uint8_t type;
600  uint8_t value;
601  uint32_t linkSpeed;
602 
603  //SPI slave mode?
604  if(interface->spiDriver != NULL)
605  {
606  //Check port number
607  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
608  {
609  //Read port status 1 register
611 
612  //Retrieve current link speed
614  {
615  linkSpeed = NIC_LINK_SPEED_100MBPS;
616  }
617  else
618  {
619  linkSpeed = NIC_LINK_SPEED_10MBPS;
620  }
621  }
622  else if(port == KSZ8794_PORT4)
623  {
624  //Read port 4 interface control 6 register
626 
627  //Retrieve host interface type
629 
630  //Gigabit interface?
633  {
634  //1000 Mb/s mode
635  linkSpeed = NIC_LINK_SPEED_1GBPS;
636  }
637  else
638  {
639  //Read global control 4 register
641 
642  //Retrieve host interface speed
644  {
645  //10 Mb/s mode
646  linkSpeed = NIC_LINK_SPEED_10MBPS;
647  }
648  else
649  {
650  //100 Mb/s mode
651  linkSpeed = NIC_LINK_SPEED_100MBPS;
652  }
653  }
654  }
655  else
656  {
657  //The specified port number is not valid
658  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
659  }
660  }
661  else
662  {
663  //The MDC/MDIO interface does not have access to all the configuration
664  //registers. It can only access the standard MIIM registers
665  linkSpeed = NIC_LINK_SPEED_100MBPS;
666  }
667 
668  //Return link speed
669  return linkSpeed;
670 }
671 
672 
673 /**
674  * @brief Get duplex mode
675  * @param[in] interface Underlying network interface
676  * @param[in] port Port number
677  * @return Duplex mode
678  **/
679 
681 {
682  uint8_t value;
683  NicDuplexMode duplexMode;
684 
685  //SPI slave mode?
686  if(interface->spiDriver != NULL)
687  {
688  //Check port number
689  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
690  {
691  //Read port status 1 register
693 
694  //Retrieve current duplex mode
696  {
697  duplexMode = NIC_FULL_DUPLEX_MODE;
698  }
699  else
700  {
701  duplexMode = NIC_HALF_DUPLEX_MODE;
702  }
703  }
704  else if(port == KSZ8794_PORT4)
705  {
706  //Read global control 4 register
708 
709  //Retrieve host interface duplex mode
711  {
712  duplexMode = NIC_HALF_DUPLEX_MODE;
713  }
714  else
715  {
716  duplexMode = NIC_FULL_DUPLEX_MODE;
717  }
718  }
719  else
720  {
721  //The specified port number is not valid
722  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
723  }
724  }
725  else
726  {
727  //The MDC/MDIO interface does not have access to all the configuration
728  //registers. It can only access the standard MIIM registers
729  duplexMode = NIC_FULL_DUPLEX_MODE;
730  }
731 
732  //Return duplex mode
733  return duplexMode;
734 }
735 
736 
737 /**
738  * @brief Set port state
739  * @param[in] interface Underlying network interface
740  * @param[in] port Port number
741  * @param[in] state Port state
742  **/
743 
744 void ksz8794SetPortState(NetInterface *interface, uint8_t port,
745  SwitchPortState state)
746 {
747  uint8_t temp;
748 
749  //Check port number
750  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
751  {
752  //Read port control 2 register
753  temp = ksz8794ReadSwitchReg(interface, KSZ8794_PORTn_CTRL2(port));
754 
755  //Update port state
756  switch(state)
757  {
758  //Listening state
763  break;
764 
765  //Learning state
770  break;
771 
772  //Forwarding state
777  break;
778 
779  //Disabled state
780  default:
784  break;
785  }
786 
787  //Write the value back to port control 2 register
789  }
790 }
791 
792 
793 /**
794  * @brief Get port state
795  * @param[in] interface Underlying network interface
796  * @param[in] port Port number
797  * @return Port state
798  **/
799 
801 {
802  uint8_t temp;
803  SwitchPortState state;
804 
805  //Check port number
806  if(port >= KSZ8794_PORT1 && port <= KSZ8794_PORT3)
807  {
808  //Read port control 2 register
809  temp = ksz8794ReadSwitchReg(interface, KSZ8794_PORTn_CTRL2(port));
810 
811  //Check port state
812  if((temp & KSZ8794_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
813  (temp & KSZ8794_PORTn_CTRL2_RECEIVE_EN) == 0 &&
814  (temp & KSZ8794_PORTn_CTRL2_LEARNING_DIS) != 0)
815  {
816  //Disabled state
818  }
819  else if((temp & KSZ8794_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
820  (temp & KSZ8794_PORTn_CTRL2_RECEIVE_EN) != 0 &&
821  (temp & KSZ8794_PORTn_CTRL2_LEARNING_DIS) != 0)
822  {
823  //Listening state
825  }
826  else if((temp & KSZ8794_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
827  (temp & KSZ8794_PORTn_CTRL2_RECEIVE_EN) == 0 &&
828  (temp & KSZ8794_PORTn_CTRL2_LEARNING_DIS) == 0)
829  {
830  //Learning state
832  }
833  else if((temp & KSZ8794_PORTn_CTRL2_TRANSMIT_EN) != 0 &&
834  (temp & KSZ8794_PORTn_CTRL2_RECEIVE_EN) != 0 &&
835  (temp & KSZ8794_PORTn_CTRL2_LEARNING_DIS) == 0)
836  {
837  //Forwarding state
839  }
840  else
841  {
842  //Unknown state
844  }
845  }
846  else
847  {
848  //The specified port number is not valid
850  }
851 
852  //Return port state
853  return state;
854 }
855 
856 
857 /**
858  * @brief Set aging time for dynamic filtering entries
859  * @param[in] interface Underlying network interface
860  * @param[in] agingTime Aging time, in seconds
861  **/
862 
863 void ksz8794SetAgingTime(NetInterface *interface, uint32_t agingTime)
864 {
865  //The aging period is fixed to 300 seconds
866 }
867 
868 
869 /**
870  * @brief Enable IGMP snooping
871  * @param[in] interface Underlying network interface
872  * @param[in] enable Enable or disable IGMP snooping
873  **/
874 
876 {
877  uint8_t temp;
878 
879  //Read global control 3 register
880  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL3);
881 
882  //Enable or disable IGMP snooping
883  if(enable)
884  {
886  }
887  else
888  {
890  }
891 
892  //Write the value back to global control 3 register
894 }
895 
896 
897 /**
898  * @brief Enable MLD snooping
899  * @param[in] interface Underlying network interface
900  * @param[in] enable Enable or disable MLD snooping
901  **/
902 
904 {
905  uint8_t temp;
906 
907  //Read global control 21 register
908  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL21);
909 
910  //Enable or disable MLD snooping
911  if(enable)
912  {
914  }
915  else
916  {
918  }
919 
920  //Write the value back to global control 21 register
922 }
923 
924 
925 /**
926  * @brief Enable reserved multicast table
927  * @param[in] interface Underlying network interface
928  * @param[in] enable Enable or disable reserved group addresses
929  **/
930 
932 {
933  uint_t i;
934  SwitchFdbEntry entry;
935 
936  //The reserved group addresses are in the range of 01-80-C2-00-00-00 to
937  //01-80-C2-00-00-0F
938  for(i = 0; i <= 15; i++)
939  {
940  //Specify the reserved group address to be added or removed
941  entry.macAddr.b[0] = 0x01;
942  entry.macAddr.b[1] = 0x80;
943  entry.macAddr.b[2] = 0xC2;
944  entry.macAddr.b[3] = 0x00;
945  entry.macAddr.b[4] = 0x00;
946  entry.macAddr.b[5] = i;
947 
948  //Format forwarding database entry
949  entry.srcPort = 0;
951  entry.override = TRUE;
952 
953  //Update the static MAC table
954  if(enable)
955  {
956  ksz8794AddStaticFdbEntry(interface, &entry);
957  }
958  else
959  {
960  ksz8794DeleteStaticFdbEntry(interface, &entry);
961  }
962  }
963 }
964 
965 
966 /**
967  * @brief Add a new entry to the static MAC table
968  * @param[in] interface Underlying network interface
969  * @param[in] entry Pointer to the forwarding database entry
970  * @return Error code
971  **/
972 
974  const SwitchFdbEntry *entry)
975 {
976  error_t error;
977  uint_t i;
978  uint_t j;
979  uint8_t *p;
980  SwitchFdbEntry currentEntry;
981  Ksz8794StaticMacEntryW newEntry;
982 
983  //Keep track of the first free entry
985 
986  //Loop through the static MAC table
987  for(i = 0; i < KSZ8794_STATIC_MAC_TABLE_SIZE; i++)
988  {
989  //Read current entry
990  error = ksz8794GetStaticFdbEntry(interface, i, &currentEntry);
991 
992  //Valid entry?
993  if(!error)
994  {
995  //Check whether the table already contains the specified MAC address
996  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
997  {
998  j = i;
999  break;
1000  }
1001  }
1002  else
1003  {
1004  //Keep track of the first free entry
1006  {
1007  j = i;
1008  }
1009  }
1010  }
1011 
1012  //Any entry available?
1014  {
1015  //Format MAC entry
1016  newEntry.fid = 0;
1017  newEntry.useFid = 0;
1018  newEntry.override = entry->override;
1019  newEntry.valid = TRUE;
1020  newEntry.macAddr = entry->macAddr;
1021 
1022  //Set the relevant forward ports
1023  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1024  {
1025  newEntry.forwardPorts = KSZ8794_PORT4_MASK;
1026  }
1027  else
1028  {
1029  newEntry.forwardPorts = entry->destPorts & KSZ8794_PORT_MASK;
1030  }
1031 
1032  //Select the static MAC address table
1036 
1037  //Point to the MAC entry
1038  p = (uint8_t *) &newEntry;
1039 
1040  //Write indirect data registers
1041  for(i = 0; i < sizeof(Ksz8794StaticMacEntryW); i++)
1042  {
1043  ksz8794WriteSwitchReg(interface, KSZ8794_INDIRECT_DATA7 + i, p[i]);
1044  }
1045 
1046  //Setup a write operation
1050 
1051  //Trigger the write operation
1053 
1054  //Successful processing
1055  error = NO_ERROR;
1056  }
1057  else
1058  {
1059  //The static MAC table is full
1060  error = ERROR_TABLE_FULL;
1061  }
1062 
1063  //Return status code
1064  return error;
1065 }
1066 
1067 
1068 /**
1069  * @brief Remove an entry from the static MAC table
1070  * @param[in] interface Underlying network interface
1071  * @param[in] entry Forwarding database entry to remove from the table
1072  * @return Error code
1073  **/
1074 
1076  const SwitchFdbEntry *entry)
1077 {
1078  error_t error;
1079  uint_t i;
1080  uint_t j;
1081  SwitchFdbEntry currentEntry;
1082 
1083  //Loop through the static MAC table
1084  for(j = 0; j < KSZ8794_STATIC_MAC_TABLE_SIZE; j++)
1085  {
1086  //Read current entry
1087  error = ksz8794GetStaticFdbEntry(interface, j, &currentEntry);
1088 
1089  //Valid entry?
1090  if(!error)
1091  {
1092  //Check whether the table contains the specified MAC address
1093  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1094  {
1095  break;
1096  }
1097  }
1098  }
1099 
1100  //Any matching entry?
1102  {
1103  //Select the static MAC address table
1107 
1108  //Clear indirect data registers
1109  for(i = 0; i < sizeof(Ksz8794StaticMacEntryW); i++)
1110  {
1111  ksz8794WriteSwitchReg(interface, KSZ8794_INDIRECT_DATA7 + i, 0);
1112  }
1113 
1114  //Setup a write operation
1118 
1119  //Trigger the write operation
1121 
1122  //Successful processing
1123  error = NO_ERROR;
1124  }
1125  else
1126  {
1127  //The static MAC table does not contain the specified address
1128  error = ERROR_NOT_FOUND;
1129  }
1130 
1131  //Return status code
1132  return error;
1133 }
1134 
1135 
1136 /**
1137  * @brief Read an entry from the static MAC table
1138  * @param[in] interface Underlying network interface
1139  * @param[in] index Zero-based index of the entry to read
1140  * @param[out] entry Pointer to the forwarding database entry
1141  * @return Error code
1142  **/
1143 
1145  SwitchFdbEntry *entry)
1146 {
1147  error_t error;
1148  uint_t i;
1149  uint8_t *p;
1150  Ksz8794StaticMacEntryR currentEntry;
1151 
1152  //Check index parameter
1153  if(index < KSZ8794_STATIC_MAC_TABLE_SIZE)
1154  {
1155  //Select the static MAC address table
1159 
1160  //Trigger the read operation
1161  ksz8794WriteSwitchReg(interface, KSZ8794_INDIRECT_CTRL1, index);
1162 
1163  //Point to the MAC entry
1164  p = (uint8_t *) &currentEntry;
1165 
1166  //Read indirect data registers
1167  for(i = 0; i < sizeof(Ksz8794StaticMacEntryR); i++)
1168  {
1169  p[i] = ksz8794ReadSwitchReg(interface, KSZ8794_INDIRECT_DATA7 + i);
1170  }
1171 
1172  //Valid entry?
1173  if(currentEntry.valid)
1174  {
1175  //Copy MAC entry
1176  entry->macAddr = currentEntry.macAddr;
1177  entry->srcPort = 0;
1178  entry->destPorts = currentEntry.forwardPorts & KSZ8794_PORT_MASK;
1179  entry->override = currentEntry.override;
1180 
1181  //Successful processing
1182  error = NO_ERROR;
1183  }
1184  else
1185  {
1186  //The entry is not valid
1187  error = ERROR_INVALID_ENTRY;
1188  }
1189  }
1190  else
1191  {
1192  //The end of the table has been reached
1193  error = ERROR_END_OF_TABLE;
1194  }
1195 
1196  //Return status code
1197  return error;
1198 }
1199 
1200 
1201 /**
1202  * @brief Flush static MAC table
1203  * @param[in] interface Underlying network interface
1204  **/
1205 
1207 {
1208  uint_t i;
1209  uint_t temp;
1210  uint8_t state[5];
1211 
1212  //Loop through the ports
1213  for(i = KSZ8794_PORT1; i <= KSZ8794_PORT4; i++)
1214  {
1215  //Valid port?
1216  if(i != KSZ8794_PORT_RESERVED)
1217  {
1218  //Save the current state of the port
1219  state[i - 1] = ksz8794ReadSwitchReg(interface, KSZ8794_PORTn_CTRL2(i));
1220 
1221  //Turn off learning capability
1223  state[i - 1] | KSZ8794_PORTn_CTRL2_LEARNING_DIS);
1224  }
1225  }
1226 
1227  //All the entries associated with a port that has its learning capability
1228  //being turned off will be flushed
1229  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL0);
1231  ksz8794WriteSwitchReg(interface, KSZ8794_GLOBAL_CTRL0, temp);
1232 
1233  //Loop through the ports
1234  for(i = KSZ8794_PORT1; i <= KSZ8794_PORT4; i++)
1235  {
1236  //Valid port?
1237  if(i != KSZ8794_PORT_RESERVED)
1238  {
1239  //Restore the original state of the port
1240  ksz8794WriteSwitchReg(interface, KSZ8794_PORTn_CTRL2(i), state[i - 1]);
1241  }
1242  }
1243 }
1244 
1245 
1246 /**
1247  * @brief Read an entry from the dynamic MAC table
1248  * @param[in] interface Underlying network interface
1249  * @param[in] index Zero-based index of the entry to read
1250  * @param[out] entry Pointer to the forwarding database entry
1251  * @return Error code
1252  **/
1253 
1255  SwitchFdbEntry *entry)
1256 {
1257  error_t error;
1258  uint_t i;
1259  uint_t n;
1260  uint8_t *p;
1261  Ksz8794DynamicMacEntry currentEntry;
1262 
1263  //Check index parameter
1264  if(index < KSZ8794_DYNAMIC_MAC_TABLE_SIZE)
1265  {
1266  //Read the MAC entry at the specified index
1267  do
1268  {
1269  //Select the dynamic MAC address table
1274 
1275  //Trigger the read operation
1276  ksz8794WriteSwitchReg(interface, KSZ8794_INDIRECT_CTRL1, LSB(index));
1277 
1278  //Point to the MAC entry
1279  p = (uint8_t *) &currentEntry;
1280 
1281  //Read indirect data registers
1282  for(i = 0; i < sizeof(Ksz8794DynamicMacEntry); i++)
1283  {
1284  p[i] = ksz8794ReadSwitchReg(interface, KSZ8794_INDIRECT_DATA8 + i);
1285  }
1286 
1287  //Retry until the entry is ready
1288  } while(currentEntry.dataNotReady);
1289 
1290  //Check whether there are valid entries in the table
1291  if(!currentEntry.macEmpty)
1292  {
1293  //Retrieve the number of valid entries
1294  n = ((currentEntry.numValidEntriesH << 3) |
1295  currentEntry.numValidEntriesL) + 1;
1296  }
1297  else
1298  {
1299  //The table is empty
1300  n = 0;
1301  }
1302 
1303  //Valid entry?
1304  if(index < n)
1305  {
1306  //Copy MAC entry
1307  entry->macAddr = currentEntry.macAddr;
1308  entry->srcPort = currentEntry.sourcePort + 1;
1309  entry->destPorts = 0;
1310  entry->override = FALSE;
1311 
1312  //Successful processing
1313  error = NO_ERROR;
1314  }
1315  else
1316  {
1317  //The end of the table has been reached
1318  error = ERROR_END_OF_TABLE;
1319  }
1320  }
1321  else
1322  {
1323  //The end of the table has been reached
1324  error = ERROR_END_OF_TABLE;
1325  }
1326 
1327  //Return status code
1328  return error;
1329 }
1330 
1331 
1332 /**
1333  * @brief Flush dynamic MAC table
1334  * @param[in] interface Underlying network interface
1335  * @param[in] port Port number
1336  **/
1337 
1339 {
1340  uint_t i;
1341  uint_t temp;
1342  uint8_t state[5];
1343 
1344  //Loop through the ports
1345  for(i = KSZ8794_PORT1; i <= KSZ8794_PORT4; i++)
1346  {
1347  //Valid port?
1348  if(i != KSZ8794_PORT_RESERVED)
1349  {
1350  //Matching port number?
1351  if(i == port || port == 0)
1352  {
1353  //Save the current state of the port
1354  state[i - 1] = ksz8794ReadSwitchReg(interface,
1355  KSZ8794_PORTn_CTRL2(i));
1356 
1357  //Turn off learning capability
1359  state[i - 1] | KSZ8794_PORTn_CTRL2_LEARNING_DIS);
1360  }
1361  }
1362  }
1363 
1364  //All the entries associated with a port that has its learning capability
1365  //being turned off will be flushed
1366  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL0);
1368  ksz8794WriteSwitchReg(interface, KSZ8794_GLOBAL_CTRL0, temp);
1369 
1370  //Loop through the ports
1371  for(i = KSZ8794_PORT1; i <= KSZ8794_PORT4; i++)
1372  {
1373  //Valid port?
1374  if(i != KSZ8794_PORT_RESERVED)
1375  {
1376  //Matching port number?
1377  if(i == port || port == 0)
1378  {
1379  //Restore the original state of the port
1381  state[i - 1]);
1382  }
1383  }
1384  }
1385 }
1386 
1387 
1388 /**
1389  * @brief Set forward ports for unknown multicast packets
1390  * @param[in] interface Underlying network interface
1391  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1392  * @param[in] forwardPorts Port map
1393  **/
1394 
1396  bool_t enable, uint32_t forwardPorts)
1397 {
1398  uint8_t temp;
1399 
1400  //Read global control 16 register
1401  temp = ksz8794ReadSwitchReg(interface, KSZ8794_GLOBAL_CTRL16);
1402 
1403  //Clear port map
1405 
1406  //Enable or disable forwarding of unknown multicast packets
1407  if(enable)
1408  {
1409  //Enable forwarding
1411 
1412  //Check whether unknown multicast packets should be forwarded to the CPU port
1413  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1414  {
1416  }
1417 
1418  //Select the desired forward ports
1419  temp |= forwardPorts & KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL;
1420  }
1421  else
1422  {
1423  //Disable forwarding
1425  }
1426 
1427  //Write the value back to global control 16 register
1428  ksz8794WriteSwitchReg(interface, KSZ8794_GLOBAL_CTRL16, temp);
1429 }
1430 
1431 
1432 /**
1433  * @brief Write VLAN entry
1434  * @param[in] interface Underlying network interface
1435  * @param[in] entry VLAN entry
1436  * @return Error code
1437  **/
1438 
1440  const SwitchVlanEntry *entry)
1441 {
1442  error_t error;
1443  uint_t i;
1444  uint8_t *p;
1445  Ksz8794VlanEntrySet vlanSet;
1446 
1447  //The VLAN table supports up to 4096 VLAN entries
1448  if(entry->vlanId < KSZ8794_VLAN_TABLE_SIZE)
1449  {
1450  //Select the VLAN table for reading
1454 
1455  //Trigger the read operation
1457  entry->vlanId / 4);
1458 
1459  //Point to the VLAN set
1460  p = (uint8_t *) &vlanSet;
1461 
1462  //Read indirect data registers
1463  for(i = 0; i < sizeof(Ksz8794VlanEntrySet); i++)
1464  {
1465  p[i] = ksz8794ReadSwitchReg(interface, KSZ8794_INDIRECT_DATA7 + i);
1466  }
1467 
1468  //Each VLAN set consists of 4 VLAN entries
1469  switch(entry->vlanId % 4)
1470  {
1471  case 0:
1472  //Modify the first VLAN entry of the VLAN set
1473  vlanSet.entry0Valid = entry->valid;
1474  vlanSet.entry0MembershipL = entry->ports & 0x01;
1475  vlanSet.entry0MembershipH = (entry->ports >> 1) & 0x0F;
1476  vlanSet.entry0Fid = entry->fid & 0x7F;
1477  break;
1478 
1479  case 1:
1480  //Modify the second VLAN entry of the VLAN set
1481  vlanSet.entry1Valid = entry->valid;
1482  vlanSet.entry1MembershipL = entry->ports & 0x01;
1483  vlanSet.entry1MembershipH = (entry->ports >> 1) & 0x0F;
1484  vlanSet.entry1Fid = entry->fid & 0x7F;
1485  break;
1486 
1487  case 2:
1488  //Modify the third VLAN entry of the VLAN set
1489  vlanSet.entry2Valid = entry->valid;
1490  vlanSet.entry2MembershipL = entry->ports & 0x01;
1491  vlanSet.entry2MembershipH = (entry->ports >> 1) & 0x0F;
1492  vlanSet.entry2Fid = entry->fid & 0x7F;
1493  break;
1494 
1495  default:
1496  //Modify the fourth VLAN entry of the VLAN set
1497  vlanSet.entry3Valid = entry->valid;
1498  vlanSet.entry3MembershipL = entry->ports & 0x01;
1499  vlanSet.entry3MembershipH = (entry->ports >> 1) & 0x0F;
1500  vlanSet.entry3Fid = entry->fid & 0x7F;
1501  break;
1502  }
1503 
1504  //Write indirect data registers
1505  for(i = 0; i < sizeof(Ksz8794VlanEntrySet); i++)
1506  {
1507  ksz8794WriteSwitchReg(interface, KSZ8794_INDIRECT_DATA7 + i, p[i]);
1508  }
1509 
1510  //Select the VLAN table for writing
1514 
1515  //Trigger the write operation
1517  entry->vlanId / 4);
1518 
1519  //Successful processing
1520  error = NO_ERROR;
1521  }
1522  else
1523  {
1524  //The VLAN identifier is invalid
1525  error = ERROR_INVALID_PARAMETER;
1526  }
1527 
1528  //Return status code
1529  return error;
1530 }
1531 
1532 
1533 /**
1534  * @brief Write PHY register
1535  * @param[in] interface Underlying network interface
1536  * @param[in] port Port number
1537  * @param[in] address PHY register address
1538  * @param[in] data Register value
1539  **/
1540 
1541 void ksz8794WritePhyReg(NetInterface *interface, uint8_t port,
1542  uint8_t address, uint16_t data)
1543 {
1544  //Write the specified PHY register
1545  if(interface->smiDriver != NULL)
1546  {
1547  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1548  }
1549  else
1550  {
1551  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1552  }
1553 }
1554 
1555 
1556 /**
1557  * @brief Read PHY register
1558  * @param[in] interface Underlying network interface
1559  * @param[in] port Port number
1560  * @param[in] address PHY register address
1561  * @return Register value
1562  **/
1563 
1564 uint16_t ksz8794ReadPhyReg(NetInterface *interface, uint8_t port,
1565  uint8_t address)
1566 {
1567  uint16_t data;
1568 
1569  //Read the specified PHY register
1570  if(interface->smiDriver != NULL)
1571  {
1572  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1573  }
1574  else
1575  {
1576  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1577  }
1578 
1579  //Return the value of the PHY register
1580  return data;
1581 }
1582 
1583 
1584 /**
1585  * @brief Dump PHY registers for debugging purpose
1586  * @param[in] interface Underlying network interface
1587  * @param[in] port Port number
1588  **/
1589 
1590 void ksz8794DumpPhyReg(NetInterface *interface, uint8_t port)
1591 {
1592  uint8_t i;
1593 
1594  //Loop through PHY registers
1595  for(i = 0; i < 32; i++)
1596  {
1597  //Display current PHY register
1598  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1599  ksz8794ReadPhyReg(interface, port, i));
1600  }
1601 
1602  //Terminate with a line feed
1603  TRACE_DEBUG("\r\n");
1604 }
1605 
1606 
1607 /**
1608  * @brief Write switch register
1609  * @param[in] interface Underlying network interface
1610  * @param[in] address Switch register address
1611  * @param[in] data Register value
1612  **/
1613 
1614 void ksz8794WriteSwitchReg(NetInterface *interface, uint16_t address,
1615  uint8_t data)
1616 {
1617  uint16_t command;
1618 
1619  //SPI slave mode?
1620  if(interface->spiDriver != NULL)
1621  {
1622  //Set up a write operation
1623  command = KSZ8794_SPI_CMD_WRITE;
1624  //Set register address
1625  command |= (address << 1) & KSZ8794_SPI_CMD_ADDR;
1626 
1627  //Pull the CS pin low
1628  interface->spiDriver->assertCs();
1629 
1630  //Write 16-bit command
1631  interface->spiDriver->transfer(MSB(command));
1632  interface->spiDriver->transfer(LSB(command));
1633 
1634  //Write data
1635  interface->spiDriver->transfer(data);
1636 
1637  //Terminate the operation by raising the CS pin
1638  interface->spiDriver->deassertCs();
1639  }
1640  else
1641  {
1642  //The MDC/MDIO interface does not have access to all the configuration
1643  //registers. It can only access the standard MIIM registers
1644  }
1645 }
1646 
1647 
1648 /**
1649  * @brief Read switch register
1650  * @param[in] interface Underlying network interface
1651  * @param[in] address Switch register address
1652  * @return Register value
1653  **/
1654 
1655 uint8_t ksz8794ReadSwitchReg(NetInterface *interface, uint16_t address)
1656 {
1657  uint8_t data;
1658  uint16_t command;
1659 
1660  //SPI slave mode?
1661  if(interface->spiDriver != NULL)
1662  {
1663  //Set up a read operation
1664  command = KSZ8794_SPI_CMD_READ;
1665  //Set register address
1666  command |= (address << 1) & KSZ8794_SPI_CMD_ADDR;
1667 
1668  //Pull the CS pin low
1669  interface->spiDriver->assertCs();
1670 
1671  //Write 16-bit command
1672  interface->spiDriver->transfer(MSB(command));
1673  interface->spiDriver->transfer(LSB(command));
1674 
1675  //Read data
1676  data = interface->spiDriver->transfer(0xFF);
1677 
1678  //Terminate the operation by raising the CS pin
1679  interface->spiDriver->deassertCs();
1680  }
1681  else
1682  {
1683  //The MDC/MDIO interface does not have access to all the configuration
1684  //registers. It can only access the standard MIIM registers
1685  data = 0;
1686  }
1687 
1688  //Return register value
1689  return data;
1690 }
1691 
1692 
1693 /**
1694  * @brief Dump switch registers for debugging purpose
1695  * @param[in] interface Underlying network interface
1696  **/
1697 
1699 {
1700  uint16_t i;
1701 
1702  //Loop through switch registers
1703  for(i = 0; i < 256; i++)
1704  {
1705  //Display current switch register
1706  TRACE_DEBUG("0x%02" PRIX16 " (%02" PRIu16 ") : 0x%02" PRIX8 "\r\n",
1707  i, i, ksz8794ReadSwitchReg(interface, i));
1708  }
1709 
1710  //Terminate with a line feed
1711  TRACE_DEBUG("\r\n");
1712 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:601
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
uint8_t entry0Valid
#define KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP
#define KSZ8794_GLOBAL_CTRL4_SW4_HALF_DUPLEX_MODE
#define NetContext
Definition: net.h:36
uint8_t entry3Fid
uint8_t useFid
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
#define KSZ8794_STATIC_MAC_TABLE_SIZE
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
uint32_t destPorts
Definition: nic.h:152
error_t ksz8794TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
#define KSZ8794_PORT4_IF_CTRL6_IF_MODE_SEL
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
uint32_t ksz8794GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
error_t ksz8794Init(NetInterface *interface)
KSZ8794 Ethernet switch initialization.
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
#define KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_PORT4
__weak_func void ksz8794EventHandler(NetInterface *interface)
KSZ8794 event handler.
#define KSZ8794_GLOBAL_CTRL2
error_t ksz8794UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
@ ERROR_END_OF_TABLE
Definition: error.h:292
#define KSZ8794_SPI_CMD_READ
uint8_t p
Definition: ndp.h:300
#define KSZ8794_GLOBAL_CTRL0_FLUSH_DYNAMIC_MAC_TABLE
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define TRUE
Definition: os_port.h:50
#define KSZ8794_PORTn_STAT2_LINK_GOOD
uint8_t data[]
Definition: ethernet.h:224
#define KSZ8794_PORTn_STAT1_OP_SPEED
uint8_t entry3Valid
#define KSZ8794_TAIL_TAG_PORT_SEL
uint8_t entry1Fid
bool_t valid
Definition: nic.h:164
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
uint8_t type
Definition: coap_common.h:176
uint8_t entry2Valid
@ ERROR_INVALID_PORT
Definition: error.h:104
void ksz8794SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
#define KSZ8794_PORT_RESERVED
uint8_t fid
@ ERROR_TABLE_FULL
Definition: error.h:291
#define KSZ8794_PORT4_MASK
Dynamic MAC table entry.
#define KSZ8794_PORTn_CTRL2_LEARNING_DIS
uint16_t ksz8794ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
EthHeader
Definition: ethernet.h:225
MacAddr macAddr
#define KSZ8794_GLOBAL_CTRL3_SW5_IGMP_SNOOP_EN
error_t ksz8794DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
#define KSZ8794_CHIP_ID0
#define KSZ8794_INDIRECT_CTRL0_ADDR_9_8
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define KSZ8794_INDIRECT_CTRL1
uint8_t entry3MembershipH
#define KSZ8794_TAIL_TAG_SRC_PORT
#define KSZ8794_INDIRECT_CTRL0_WRITE
uint8_t override
uint8_t sourcePort
MacAddr macAddr
void ksz8794EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
VLAN entry.
Definition: nic.h:162
#define KSZ8794_GLOBAL_CTRL0_FLUSH_STATIC_MAC_TABLE
error_t
Error codes.
Definition: error.h:43
#define KSZ8794_PORT4_IF_CTRL6_IF_MODE_SEL_RGMII
uint8_t entry2MembershipL
KSZ8794 4-port Ethernet switch driver.
#define KSZ8794_TAIL_TAG_DEST_PORT2
#define KSZ8794_INDIRECT_CTRL0
#define KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL
#define KSZ8794_GLOBAL_CTRL4
#define KSZ8794_PORTn_CTRL2_RECEIVE_EN
#define KSZ8794_PORT4
#define KSZ8794_CHIP_ID0_FAMILY_ID_DEFAULT
void ksz8794DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
Static MAC table entry (read operation)
#define KSZ8794_PORT_MASK
uint8_t forwardPorts
#define KSZ8794_GLOBAL_CTRL16
#define KSZ8794_PORT3
__weak_func void ksz8794InitHook(NetInterface *interface)
KSZ8794 custom configuration.
#define KSZ8794_BMSR
#define KSZ8794_GLOBAL_CTRL21
uint8_t numValidEntriesH
#define KSZ8794_GLOBAL_CTRL10
#define NetRxAncillary
Definition: net_misc.h:40
MacAddr macAddr
#define NetInterface
Definition: net.h:40
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define KSZ8794_TAIL_TAG_NORMAL_ADDR_LOOKUP
Static MAC table entry (write operation)
const uint8_t ksz8794IngressTailTag[4]
Tail tag rules (host to KSZ8794)
#define KSZ8794_INDIRECT_CTRL0_READ
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
#define KSZ8794_GLOBAL_CTRL0
SwitchPortState ksz8794GetPortState(NetInterface *interface, uint8_t port)
Get port state.
#define NetTxAncillary
Definition: net_misc.h:36
#define MSB(x)
Definition: os_port.h:59
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
#define KSZ8794_GLOBAL_CTRL21_MLD_SNOOP_EN
void ksz8794FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define LSB(x)
Definition: os_port.h:55
#define KSZ8794_SPI_CMD_WRITE
#define KSZ8794_INDIRECT_BYTE
void ksz8794SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
uint8_t dataNotReady
uint8_t valid
uint8_t entry2MembershipH
#define KSZ8794_INDIRECT_DATA7
uint8_t entry1MembershipH
NicDuplexMode ksz8794GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
#define KSZ8794_TAIL_TAG_DEST_PORT1
void ksz8794DisableIrq(NetInterface *interface)
Disable interrupts.
uint16_t port
Definition: dns_common.h:270
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define KSZ8794_GLOBAL_CTRL2_MAX_PKT_SIZE_CHECK_DIS
uint8_t numValidEntriesL
uint16_t fid
Definition: nic.h:165
error_t ksz8794GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
uint8_t entry0MembershipH
error_t ksz8794GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
#define KSZ8794_GLOBAL_CTRL4_SW4_SPEED
Ethernet switch driver.
Definition: nic.h:325
uint16_t vlanId
Definition: nic.h:163
error_t ksz8794AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
uint8_t n
uint8_t entry0Fid
void ksz8794FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
@ ERROR_INVALID_ENTRY
Definition: error.h:290
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:604
Ipv6Addr address[]
Definition: ipv6.h:345
#define KSZ8794_PORTn_STAT1_OP_DUPLEX
#define KSZ8794_BMSR_LINK_STATUS
NicDuplexMode
Duplex mode.
Definition: nic.h:122
MacAddr macAddr
Definition: nic.h:150
error_t ksz8794WriteVlanEntry(NetInterface *interface, const SwitchVlanEntry *entry)
Write VLAN entry.
void ksz8794WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
uint8_t forwardPorts
uint8_t srcPort
Definition: nic.h:151
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
#define KSZ8794_PORT4_IF_CTRL6
#define KSZ8794_PORTn_STAT1(port)
#define KSZ8794_VLAN_TABLE_SIZE
#define KSZ8794_PORTn_STAT2(port)
void ksz8794WriteSwitchReg(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register.
uint8_t value[]
Definition: tcp.h:376
uint8_t macEmpty
uint8_t entry2Fid
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
#define KSZ8794_GLOBAL_CTRL10_TAIL_TAG_EN
#define KSZ8794_GLOBAL_CTRL3
__weak_func void ksz8794Tick(NetInterface *interface)
KSZ8794 timer handler.
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define KSZ8794_INDIRECT_CTRL0_TABLE_SEL_DYNAMIC_MAC
#define KSZ8794_PORT1
bool_t ksz8794GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
uint32_t ports
Definition: nic.h:166
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
uint8_t entry1Valid
Set of VLAN entries.
void ksz8794DumpSwitchReg(NetInterface *interface)
Dump switch registers for debugging purpose.
#define KSZ8794_PORTn_CTRL2_TRANSMIT_EN
#define KSZ8794_INDIRECT_DATA8
#define KSZ8794_INDIRECT_CTRL0_TABLE_SEL_VLAN
uint8_t entry0MembershipL
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
#define KSZ8794_PORTn_CTRL2(port)
void ksz8794EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
void ksz8794EnableIrq(NetInterface *interface)
Enable interrupts.
unsigned int uint_t
Definition: compiler_port.h:57
#define KSZ8794_DYNAMIC_MAC_TABLE_SIZE
TCP/IP stack core.
#define KSZ8794_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD
#define KSZ8794_SPI_CMD_ADDR
uint8_t valid
void ksz8794EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
uint8_t entry3MembershipL
#define KSZ8794_PORT4_IF_CTRL6_IS_1GBPS
void ksz8794SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
const SwitchDriver ksz8794SwitchDriver
KSZ8794 Ethernet switch driver.
Helper functions for Ethernet.
uint8_t ksz8794ReadSwitchReg(NetInterface *interface, uint16_t address)
Read switch register.
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
Debugging facilities.
#define KSZ8794_INDIRECT_CTRL0_TABLE_SEL_STATIC_MAC
Forwarding database entry.
Definition: nic.h:149
uint8_t override
uint8_t entry1MembershipL
#define KSZ8794_TAIL_TAG_DEST_PORT3