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