ksz8775_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz8775_driver.c
3  * @brief KSZ8775 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 KSZ8775 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ8775)
75  **/
76 
77 const uint8_t ksz8775IngressTailTag[5] =
78 {
84 };
85 
86 
87 /**
88  * @brief KSZ8775 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 KSZ8775...\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 = ksz8775ReadSwitchReg(interface, KSZ8775_CHIP_ID0);
112 
113  //The returned data is invalid until the serial interface is ready
114  } while(temp != KSZ8775_CHIP_ID0_FAMILY_ID_DEFAULT);
115 
116 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
117  //Enable tail tag feature
118  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL10);
121 
122  //Disable packet size check
123  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL2);
126 #else
127  //Disable tail tag feature
128  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL10);
131 
132  //Enable packet size check
133  temp = ksz8775ReadSwitchReg(interface, KSZ8775_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  ksz8775DumpSwitchReg(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  ksz8775DumpPhyReg(interface, port);
189  }
190  }
191 
192  //Perform custom configuration
193  ksz8775InitHook(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 KSZ8775 custom configuration
207  * @param[in] interface Underlying network interface
208  **/
209 
210 __weak_func void ksz8775InitHook(NetInterface *interface)
211 {
212 }
213 
214 
215 /**
216  * @brief KSZ8775 timer handler
217  * @param[in] interface Underlying network interface
218  **/
219 
220 __weak_func void ksz8775Tick(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 = ksz8775GetLinkState(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(ksz8775GetLinkState(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 KSZ8775 event handler
311  * @param[in] interface Underlying network interface
312  **/
313 
314 __weak_func void ksz8775EventHandler(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 >= KSZ8775_PORT1 && port <= KSZ8775_PORT4)
346  {
347  //Retrieve current link state
348  linkState = ksz8775GetLinkState(interface, port);
349 
350  //Link up event?
351  if(linkState && !virtualInterface->linkState)
352  {
353  //Retrieve host interface speed
354  interface->linkSpeed = ksz8775GetLinkSpeed(interface,
355  KSZ8775_PORT5);
356 
357  //Retrieve host interface duplex mode
358  interface->duplexMode = ksz8775GetDuplexMode(interface,
359  KSZ8775_PORT5);
360 
361  //Adjust MAC configuration parameters for proper operation
362  interface->nicDriver->updateMacConfig(interface);
363 
364  //Check current speed
365  virtualInterface->linkSpeed = ksz8775GetLinkSpeed(interface,
366  port);
367 
368  //Check current duplex mode
369  virtualInterface->duplexMode = ksz8775GetDuplexMode(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(ksz8775GetLinkState(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 = ksz8775GetLinkSpeed(interface, KSZ8775_PORT5);
412  //Retrieve host interface duplex mode
413  interface->duplexMode = ksz8775GetDuplexMode(interface, KSZ8775_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 <= KSZ8775_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 = &ksz8775IngressTailTag[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 ksz8775UntagFrame(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 & KSZ8775_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 >= KSZ8775_PORT1 && port <= KSZ8775_PORT3)
561  {
562  //SPI slave mode?
563  if(interface->spiDriver != NULL)
564  {
565  //Read port status 2 register
566  status = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_STAT2(port));
567 
568  //Retrieve current link state
569  linkState = (status & KSZ8775_PORTn_STAT2_LINK_GOOD) ? TRUE : FALSE;
570  }
571  else
572  {
573  //Read status register
574  status = ksz8775ReadPhyReg(interface, port, KSZ8775_BMSR);
575 
576  //Retrieve current link state
577  linkState = (status & KSZ8775_BMSR_LINK_STATUS) ? TRUE : FALSE;
578  }
579  }
580  else if(port == KSZ8775_PORT4)
581  {
582  //Port 4 is always up
583  linkState = TRUE;
584  }
585  else
586  {
587  //The specified port number is not valid
588  linkState = FALSE;
589  }
590 
591  //Return link status
592  return linkState;
593 }
594 
595 
596 /**
597  * @brief Get link speed
598  * @param[in] interface Underlying network interface
599  * @param[in] port Port number
600  * @return Link speed
601  **/
602 
603 uint32_t ksz8775GetLinkSpeed(NetInterface *interface, uint8_t port)
604 {
605  uint8_t type;
606  uint8_t value;
607  uint32_t linkSpeed;
608 
609  //SPI slave mode?
610  if(interface->spiDriver != NULL)
611  {
612  //Check port number
613  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT3)
614  {
615  //Read port status 1 register
617 
618  //Retrieve current link speed
620  {
621  linkSpeed = NIC_LINK_SPEED_100MBPS;
622  }
623  else
624  {
625  linkSpeed = NIC_LINK_SPEED_10MBPS;
626  }
627  }
628  else if(port == KSZ8775_PORT4)
629  {
630  //Read port 4 control 9 register
632 
633  //Retrieve current link speed
635  {
636  linkSpeed = NIC_LINK_SPEED_100MBPS;
637  }
638  else
639  {
640  linkSpeed = NIC_LINK_SPEED_10MBPS;
641  }
642  }
643  else if(port == KSZ8775_PORT5)
644  {
645  //Read port 5 interface control 6 register
647 
648  //Retrieve host interface type
650 
651  //Gigabit interface?
654  {
655  //1000 Mb/s mode
656  linkSpeed = NIC_LINK_SPEED_1GBPS;
657  }
658  else
659  {
660  //Read global control 4 register
662 
663  //Retrieve host interface speed
665  {
666  //10 Mb/s mode
667  linkSpeed = NIC_LINK_SPEED_10MBPS;
668  }
669  else
670  {
671  //100 Mb/s mode
672  linkSpeed = NIC_LINK_SPEED_100MBPS;
673  }
674  }
675  }
676  else
677  {
678  //The specified port number is not valid
679  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
680  }
681  }
682  else
683  {
684  //The MDC/MDIO interface does not have access to all the configuration
685  //registers. It can only access the standard MIIM registers
686  linkSpeed = NIC_LINK_SPEED_100MBPS;
687  }
688 
689  //Return link speed
690  return linkSpeed;
691 }
692 
693 
694 /**
695  * @brief Get duplex mode
696  * @param[in] interface Underlying network interface
697  * @param[in] port Port number
698  * @return Duplex mode
699  **/
700 
702 {
703  uint8_t value;
704  NicDuplexMode duplexMode;
705 
706  //SPI slave mode?
707  if(interface->spiDriver != NULL)
708  {
709  //Check port number
710  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT3)
711  {
712  //Read port status 1 register
714 
715  //Retrieve current duplex mode
717  {
718  duplexMode = NIC_FULL_DUPLEX_MODE;
719  }
720  else
721  {
722  duplexMode = NIC_HALF_DUPLEX_MODE;
723  }
724  }
725  else if(port == KSZ8775_PORT4)
726  {
727  //Read port status 1 register
729 
730  //Retrieve current duplex mode
732  {
733  duplexMode = NIC_FULL_DUPLEX_MODE;
734  }
735  else
736  {
737  duplexMode = NIC_HALF_DUPLEX_MODE;
738  }
739  }
740  else if(port == KSZ8775_PORT5)
741  {
742  //Read global control 4 register
744 
745  //Retrieve host interface duplex mode
747  {
748  duplexMode = NIC_HALF_DUPLEX_MODE;
749  }
750  else
751  {
752  duplexMode = NIC_FULL_DUPLEX_MODE;
753  }
754  }
755  else
756  {
757  //The specified port number is not valid
758  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
759  }
760  }
761  else
762  {
763  //The MDC/MDIO interface does not have access to all the configuration
764  //registers. It can only access the standard MIIM registers
765  duplexMode = NIC_FULL_DUPLEX_MODE;
766  }
767 
768  //Return duplex mode
769  return duplexMode;
770 }
771 
772 
773 /**
774  * @brief Set port state
775  * @param[in] interface Underlying network interface
776  * @param[in] port Port number
777  * @param[in] state Port state
778  **/
779 
780 void ksz8775SetPortState(NetInterface *interface, uint8_t port,
781  SwitchPortState state)
782 {
783  uint8_t temp;
784 
785  //Check port number
786  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT4)
787  {
788  //Read port control 2 register
789  temp = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_CTRL2(port));
790 
791  //Update port state
792  switch(state)
793  {
794  //Listening state
799  break;
800 
801  //Learning state
806  break;
807 
808  //Forwarding state
813  break;
814 
815  //Disabled state
816  default:
820  break;
821  }
822 
823  //Write the value back to port control 2 register
825  }
826 }
827 
828 
829 /**
830  * @brief Get port state
831  * @param[in] interface Underlying network interface
832  * @param[in] port Port number
833  * @return Port state
834  **/
835 
837 {
838  uint8_t temp;
839  SwitchPortState state;
840 
841  //Check port number
842  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT4)
843  {
844  //Read port control 2 register
845  temp = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_CTRL2(port));
846 
847  //Check port state
848  if((temp & KSZ8775_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
849  (temp & KSZ8775_PORTn_CTRL2_RECEIVE_EN) == 0 &&
850  (temp & KSZ8775_PORTn_CTRL2_LEARNING_DIS) != 0)
851  {
852  //Disabled state
854  }
855  else if((temp & KSZ8775_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
856  (temp & KSZ8775_PORTn_CTRL2_RECEIVE_EN) != 0 &&
857  (temp & KSZ8775_PORTn_CTRL2_LEARNING_DIS) != 0)
858  {
859  //Listening state
861  }
862  else if((temp & KSZ8775_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
863  (temp & KSZ8775_PORTn_CTRL2_RECEIVE_EN) == 0 &&
864  (temp & KSZ8775_PORTn_CTRL2_LEARNING_DIS) == 0)
865  {
866  //Learning state
868  }
869  else if((temp & KSZ8775_PORTn_CTRL2_TRANSMIT_EN) != 0 &&
870  (temp & KSZ8775_PORTn_CTRL2_RECEIVE_EN) != 0 &&
871  (temp & KSZ8775_PORTn_CTRL2_LEARNING_DIS) == 0)
872  {
873  //Forwarding state
875  }
876  else
877  {
878  //Unknown state
880  }
881  }
882  else
883  {
884  //The specified port number is not valid
886  }
887 
888  //Return port state
889  return state;
890 }
891 
892 
893 /**
894  * @brief Set aging time for dynamic filtering entries
895  * @param[in] interface Underlying network interface
896  * @param[in] agingTime Aging time, in seconds
897  **/
898 
899 void ksz8775SetAgingTime(NetInterface *interface, uint32_t agingTime)
900 {
901  //The aging period is fixed to 300 seconds
902 }
903 
904 
905 /**
906  * @brief Enable IGMP snooping
907  * @param[in] interface Underlying network interface
908  * @param[in] enable Enable or disable IGMP snooping
909  **/
910 
912 {
913  uint8_t temp;
914 
915  //Read global control 3 register
916  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL3);
917 
918  //Enable or disable IGMP snooping
919  if(enable)
920  {
922  }
923  else
924  {
926  }
927 
928  //Write the value back to global control 3 register
930 }
931 
932 
933 /**
934  * @brief Enable MLD snooping
935  * @param[in] interface Underlying network interface
936  * @param[in] enable Enable or disable MLD snooping
937  **/
938 
940 {
941  uint8_t temp;
942 
943  //Read global control 21 register
944  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL21);
945 
946  //Enable or disable MLD snooping
947  if(enable)
948  {
950  }
951  else
952  {
954  }
955 
956  //Write the value back to global control 21 register
958 }
959 
960 
961 /**
962  * @brief Enable reserved multicast table
963  * @param[in] interface Underlying network interface
964  * @param[in] enable Enable or disable reserved group addresses
965  **/
966 
968 {
969  uint_t i;
970  SwitchFdbEntry entry;
971 
972  //The reserved group addresses are in the range of 01-80-C2-00-00-00 to
973  //01-80-C2-00-00-0F
974  for(i = 0; i <= 15; i++)
975  {
976  //Specify the reserved group address to be added or removed
977  entry.macAddr.b[0] = 0x01;
978  entry.macAddr.b[1] = 0x80;
979  entry.macAddr.b[2] = 0xC2;
980  entry.macAddr.b[3] = 0x00;
981  entry.macAddr.b[4] = 0x00;
982  entry.macAddr.b[5] = i;
983 
984  //Format forwarding database entry
985  entry.srcPort = 0;
987  entry.override = TRUE;
988 
989  //Update the static MAC table
990  if(enable)
991  {
992  ksz8775AddStaticFdbEntry(interface, &entry);
993  }
994  else
995  {
996  ksz8775DeleteStaticFdbEntry(interface, &entry);
997  }
998  }
999 }
1000 
1001 
1002 /**
1003  * @brief Add a new entry to the static MAC table
1004  * @param[in] interface Underlying network interface
1005  * @param[in] entry Pointer to the forwarding database entry
1006  * @return Error code
1007  **/
1008 
1010  const SwitchFdbEntry *entry)
1011 {
1012  error_t error;
1013  uint_t i;
1014  uint_t j;
1015  uint8_t *p;
1016  SwitchFdbEntry currentEntry;
1017  Ksz8775StaticMacEntryW newEntry;
1018 
1019  //Keep track of the first free entry
1021 
1022  //Loop through the static MAC table
1023  for(i = 0; i < KSZ8775_STATIC_MAC_TABLE_SIZE; i++)
1024  {
1025  //Read current entry
1026  error = ksz8775GetStaticFdbEntry(interface, i, &currentEntry);
1027 
1028  //Valid entry?
1029  if(!error)
1030  {
1031  //Check whether the table already contains the specified MAC address
1032  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1033  {
1034  j = i;
1035  break;
1036  }
1037  }
1038  else
1039  {
1040  //Keep track of the first free entry
1042  {
1043  j = i;
1044  }
1045  }
1046  }
1047 
1048  //Any entry available?
1050  {
1051  //Format MAC entry
1052  newEntry.fid = 0;
1053  newEntry.useFid = 0;
1054  newEntry.override = entry->override;
1055  newEntry.valid = TRUE;
1056  newEntry.macAddr = entry->macAddr;
1057 
1058  //Set the relevant forward ports
1059  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1060  {
1061  newEntry.forwardPorts = KSZ8775_PORT5_MASK;
1062  }
1063  else
1064  {
1065  newEntry.forwardPorts = entry->destPorts & KSZ8775_PORT_MASK;
1066  }
1067 
1068  //Select the static MAC address table
1072 
1073  //Point to the MAC entry
1074  p = (uint8_t *) &newEntry;
1075 
1076  //Write indirect data registers
1077  for(i = 0; i < sizeof(Ksz8775StaticMacEntryW); i++)
1078  {
1079  ksz8775WriteSwitchReg(interface, KSZ8775_INDIRECT_DATA7 + i, p[i]);
1080  }
1081 
1082  //Setup a write operation
1086 
1087  //Trigger the write operation
1089 
1090  //Successful processing
1091  error = NO_ERROR;
1092  }
1093  else
1094  {
1095  //The static MAC table is full
1096  error = ERROR_TABLE_FULL;
1097  }
1098 
1099  //Return status code
1100  return error;
1101 }
1102 
1103 
1104 /**
1105  * @brief Remove an entry from the static MAC table
1106  * @param[in] interface Underlying network interface
1107  * @param[in] entry Forwarding database entry to remove from the table
1108  * @return Error code
1109  **/
1110 
1112  const SwitchFdbEntry *entry)
1113 {
1114  error_t error;
1115  uint_t i;
1116  uint_t j;
1117  SwitchFdbEntry currentEntry;
1118 
1119  //Loop through the static MAC table
1120  for(j = 0; j < KSZ8775_STATIC_MAC_TABLE_SIZE; j++)
1121  {
1122  //Read current entry
1123  error = ksz8775GetStaticFdbEntry(interface, j, &currentEntry);
1124 
1125  //Valid entry?
1126  if(!error)
1127  {
1128  //Check whether the table contains the specified MAC address
1129  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1130  {
1131  break;
1132  }
1133  }
1134  }
1135 
1136  //Any matching entry?
1138  {
1139  //Select the static MAC address table
1143 
1144  //Clear indirect data registers
1145  for(i = 0; i < sizeof(Ksz8775StaticMacEntryW); i++)
1146  {
1147  ksz8775WriteSwitchReg(interface, KSZ8775_INDIRECT_DATA7 + i, 0);
1148  }
1149 
1150  //Setup a write operation
1154 
1155  //Trigger the write operation
1157 
1158  //Successful processing
1159  error = NO_ERROR;
1160  }
1161  else
1162  {
1163  //The static MAC table does not contain the specified address
1164  error = ERROR_NOT_FOUND;
1165  }
1166 
1167  //Return status code
1168  return error;
1169 }
1170 
1171 
1172 /**
1173  * @brief Read an entry from the static MAC table
1174  * @param[in] interface Underlying network interface
1175  * @param[in] index Zero-based index of the entry to read
1176  * @param[out] entry Pointer to the forwarding database entry
1177  * @return Error code
1178  **/
1179 
1181  SwitchFdbEntry *entry)
1182 {
1183  error_t error;
1184  uint_t i;
1185  uint8_t *p;
1186  Ksz8775StaticMacEntryR currentEntry;
1187 
1188  //Check index parameter
1189  if(index < KSZ8775_STATIC_MAC_TABLE_SIZE)
1190  {
1191  //Select the static MAC address table
1195 
1196  //Trigger the read operation
1197  ksz8775WriteSwitchReg(interface, KSZ8775_INDIRECT_CTRL1, index);
1198 
1199  //Point to the MAC entry
1200  p = (uint8_t *) &currentEntry;
1201 
1202  //Read indirect data registers
1203  for(i = 0; i < sizeof(Ksz8775StaticMacEntryR); i++)
1204  {
1205  p[i] = ksz8775ReadSwitchReg(interface, KSZ8775_INDIRECT_DATA7 + i);
1206  }
1207 
1208  //Valid entry?
1209  if(currentEntry.valid)
1210  {
1211  //Copy MAC entry
1212  entry->macAddr = currentEntry.macAddr;
1213  entry->srcPort = 0;
1214  entry->destPorts = currentEntry.forwardPorts & KSZ8775_PORT_MASK;
1215  entry->override = currentEntry.override;
1216 
1217  //Successful processing
1218  error = NO_ERROR;
1219  }
1220  else
1221  {
1222  //The entry is not valid
1223  error = ERROR_INVALID_ENTRY;
1224  }
1225  }
1226  else
1227  {
1228  //The end of the table has been reached
1229  error = ERROR_END_OF_TABLE;
1230  }
1231 
1232  //Return status code
1233  return error;
1234 }
1235 
1236 
1237 /**
1238  * @brief Flush static MAC table
1239  * @param[in] interface Underlying network interface
1240  **/
1241 
1243 {
1244  uint_t i;
1245  uint_t temp;
1246  uint8_t state[5];
1247 
1248  //Loop through the ports
1249  for(i = KSZ8775_PORT1; i <= KSZ8775_PORT5; i++)
1250  {
1251  //Save the current state of the port
1252  state[i - 1] = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_CTRL2(i));
1253 
1254  //Turn off learning capability
1256  state[i - 1] | KSZ8775_PORTn_CTRL2_LEARNING_DIS);
1257  }
1258 
1259  //All the entries associated with a port that has its learning capability
1260  //being turned off will be flushed
1261  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL0);
1263  ksz8775WriteSwitchReg(interface, KSZ8775_GLOBAL_CTRL0, temp);
1264 
1265  //Loop through the ports
1266  for(i = KSZ8775_PORT1; i <= KSZ8775_PORT5; i++)
1267  {
1268  //Restore the original state of the port
1269  ksz8775WriteSwitchReg(interface, KSZ8775_PORTn_CTRL2(i), state[i - 1]);
1270  }
1271 }
1272 
1273 
1274 /**
1275  * @brief Read an entry from the dynamic MAC table
1276  * @param[in] interface Underlying network interface
1277  * @param[in] index Zero-based index of the entry to read
1278  * @param[out] entry Pointer to the forwarding database entry
1279  * @return Error code
1280  **/
1281 
1283  SwitchFdbEntry *entry)
1284 {
1285  error_t error;
1286  uint_t i;
1287  uint_t n;
1288  uint8_t *p;
1289  Ksz8775DynamicMacEntry currentEntry;
1290 
1291  //Check index parameter
1292  if(index < KSZ8775_DYNAMIC_MAC_TABLE_SIZE)
1293  {
1294  //Read the MAC entry at the specified index
1295  do
1296  {
1297  //Select the dynamic MAC address table
1302 
1303  //Trigger the read operation
1304  ksz8775WriteSwitchReg(interface, KSZ8775_INDIRECT_CTRL1, LSB(index));
1305 
1306  //Point to the MAC entry
1307  p = (uint8_t *) &currentEntry;
1308 
1309  //Read indirect data registers
1310  for(i = 0; i < sizeof(Ksz8775DynamicMacEntry); i++)
1311  {
1312  p[i] = ksz8775ReadSwitchReg(interface, KSZ8775_INDIRECT_DATA8 + i);
1313  }
1314 
1315  //Retry until the entry is ready
1316  } while(currentEntry.dataNotReady);
1317 
1318  //Check whether there are valid entries in the table
1319  if(!currentEntry.macEmpty)
1320  {
1321  //Retrieve the number of valid entries
1322  n = ((currentEntry.numValidEntriesH << 3) |
1323  currentEntry.numValidEntriesL) + 1;
1324  }
1325  else
1326  {
1327  //The table is empty
1328  n = 0;
1329  }
1330 
1331  //Valid entry?
1332  if(index < n)
1333  {
1334  //Copy MAC entry
1335  entry->macAddr = currentEntry.macAddr;
1336  entry->srcPort = currentEntry.sourcePort + 1;
1337  entry->destPorts = 0;
1338  entry->override = FALSE;
1339 
1340  //Successful processing
1341  error = NO_ERROR;
1342  }
1343  else
1344  {
1345  //The end of the table has been reached
1346  error = ERROR_END_OF_TABLE;
1347  }
1348  }
1349  else
1350  {
1351  //The end of the table has been reached
1352  error = ERROR_END_OF_TABLE;
1353  }
1354 
1355  //Return status code
1356  return error;
1357 }
1358 
1359 
1360 /**
1361  * @brief Flush dynamic MAC table
1362  * @param[in] interface Underlying network interface
1363  * @param[in] port Port number
1364  **/
1365 
1367 {
1368  uint_t i;
1369  uint_t temp;
1370  uint8_t state[5];
1371 
1372  //Loop through the ports
1373  for(i = KSZ8775_PORT1; i <= KSZ8775_PORT5; i++)
1374  {
1375  //Matching port number?
1376  if(i == port || port == 0)
1377  {
1378  //Save the current state of the port
1379  state[i - 1] = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_CTRL2(i));
1380 
1381  //Turn off learning capability
1383  state[i - 1] | KSZ8775_PORTn_CTRL2_LEARNING_DIS);
1384  }
1385  }
1386 
1387  //All the entries associated with a port that has its learning capability
1388  //being turned off will be flushed
1389  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL0);
1391  ksz8775WriteSwitchReg(interface, KSZ8775_GLOBAL_CTRL0, temp);
1392 
1393  //Loop through the ports
1394  for(i = KSZ8775_PORT1; i <= KSZ8775_PORT5; i++)
1395  {
1396  //Matching port number?
1397  if(i == port || port == 0)
1398  {
1399  //Restore the original state of the port
1400  ksz8775WriteSwitchReg(interface, KSZ8775_PORTn_CTRL2(i), state[i - 1]);
1401  }
1402  }
1403 }
1404 
1405 
1406 /**
1407  * @brief Set forward ports for unknown multicast packets
1408  * @param[in] interface Underlying network interface
1409  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1410  * @param[in] forwardPorts Port map
1411  **/
1412 
1414  bool_t enable, uint32_t forwardPorts)
1415 {
1416  uint8_t temp;
1417 
1418  //Read global control 16 register
1419  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL16);
1420 
1421  //Clear port map
1423 
1424  //Enable or disable forwarding of unknown multicast packets
1425  if(enable)
1426  {
1427  //Enable forwarding
1429 
1430  //Check whether unknown multicast packets should be forwarded to the CPU port
1431  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1432  {
1434  }
1435 
1436  //Select the desired forward ports
1437  temp |= forwardPorts & KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL;
1438  }
1439  else
1440  {
1441  //Disable forwarding
1443  }
1444 
1445  //Write the value back to global control 16 register
1446  ksz8775WriteSwitchReg(interface, KSZ8775_GLOBAL_CTRL16, temp);
1447 }
1448 
1449 
1450 /**
1451  * @brief Write VLAN entry
1452  * @param[in] interface Underlying network interface
1453  * @param[in] entry VLAN entry
1454  * @return Error code
1455  **/
1456 
1458  const SwitchVlanEntry *entry)
1459 {
1460  error_t error;
1461  uint_t i;
1462  uint8_t *p;
1463  Ksz8775VlanEntrySet vlanSet;
1464 
1465  //The VLAN table supports up to 4096 VLAN entries
1466  if(entry->vlanId < KSZ8775_VLAN_TABLE_SIZE)
1467  {
1468  //Select the VLAN table for reading
1472 
1473  //Trigger the read operation
1475  entry->vlanId / 4);
1476 
1477  //Point to the VLAN set
1478  p = (uint8_t *) &vlanSet;
1479 
1480  //Read indirect data registers
1481  for(i = 0; i < sizeof(Ksz8775VlanEntrySet); i++)
1482  {
1483  p[i] = ksz8775ReadSwitchReg(interface, KSZ8775_INDIRECT_DATA7 + i);
1484  }
1485 
1486  //Each VLAN set consists of 4 VLAN entries
1487  switch(entry->vlanId % 4)
1488  {
1489  case 0:
1490  //Modify the first VLAN entry of the VLAN set
1491  vlanSet.entry0Valid = entry->valid;
1492  vlanSet.entry0MembershipL = entry->ports & 0x01;
1493  vlanSet.entry0MembershipH = (entry->ports >> 1) & 0x0F;
1494  vlanSet.entry0Fid = entry->fid & 0x7F;
1495  break;
1496 
1497  case 1:
1498  //Modify the second VLAN entry of the VLAN set
1499  vlanSet.entry1Valid = entry->valid;
1500  vlanSet.entry1MembershipL = entry->ports & 0x01;
1501  vlanSet.entry1MembershipH = (entry->ports >> 1) & 0x0F;
1502  vlanSet.entry1Fid = entry->fid & 0x7F;
1503  break;
1504 
1505  case 2:
1506  //Modify the third VLAN entry of the VLAN set
1507  vlanSet.entry2Valid = entry->valid;
1508  vlanSet.entry2MembershipL = entry->ports & 0x01;
1509  vlanSet.entry2MembershipH = (entry->ports >> 1) & 0x0F;
1510  vlanSet.entry2Fid = entry->fid & 0x7F;
1511  break;
1512 
1513  default:
1514  //Modify the fourth VLAN entry of the VLAN set
1515  vlanSet.entry3Valid = entry->valid;
1516  vlanSet.entry3MembershipL = entry->ports & 0x01;
1517  vlanSet.entry3MembershipH = (entry->ports >> 1) & 0x0F;
1518  vlanSet.entry3Fid = entry->fid & 0x7F;
1519  break;
1520  }
1521 
1522  //Write indirect data registers
1523  for(i = 0; i < sizeof(Ksz8775VlanEntrySet); i++)
1524  {
1525  ksz8775WriteSwitchReg(interface, KSZ8775_INDIRECT_DATA7 + i, p[i]);
1526  }
1527 
1528  //Select the VLAN table for writing
1532 
1533  //Trigger the write operation
1535  entry->vlanId / 4);
1536 
1537  //Successful processing
1538  error = NO_ERROR;
1539  }
1540  else
1541  {
1542  //The VLAN identifier is invalid
1543  error = ERROR_INVALID_PARAMETER;
1544  }
1545 
1546  //Return status code
1547  return error;
1548 }
1549 
1550 
1551 /**
1552  * @brief Write PHY register
1553  * @param[in] interface Underlying network interface
1554  * @param[in] port Port number
1555  * @param[in] address PHY register address
1556  * @param[in] data Register value
1557  **/
1558 
1559 void ksz8775WritePhyReg(NetInterface *interface, uint8_t port,
1560  uint8_t address, uint16_t data)
1561 {
1562  //Write the specified PHY register
1563  if(interface->smiDriver != NULL)
1564  {
1565  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1566  }
1567  else
1568  {
1569  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1570  }
1571 }
1572 
1573 
1574 /**
1575  * @brief Read PHY register
1576  * @param[in] interface Underlying network interface
1577  * @param[in] port Port number
1578  * @param[in] address PHY register address
1579  * @return Register value
1580  **/
1581 
1582 uint16_t ksz8775ReadPhyReg(NetInterface *interface, uint8_t port,
1583  uint8_t address)
1584 {
1585  uint16_t data;
1586 
1587  //Read the specified PHY register
1588  if(interface->smiDriver != NULL)
1589  {
1590  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1591  }
1592  else
1593  {
1594  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1595  }
1596 
1597  //Return the value of the PHY register
1598  return data;
1599 }
1600 
1601 
1602 /**
1603  * @brief Dump PHY registers for debugging purpose
1604  * @param[in] interface Underlying network interface
1605  * @param[in] port Port number
1606  **/
1607 
1608 void ksz8775DumpPhyReg(NetInterface *interface, uint8_t port)
1609 {
1610  uint8_t i;
1611 
1612  //Loop through PHY registers
1613  for(i = 0; i < 32; i++)
1614  {
1615  //Display current PHY register
1616  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1617  ksz8775ReadPhyReg(interface, port, i));
1618  }
1619 
1620  //Terminate with a line feed
1621  TRACE_DEBUG("\r\n");
1622 }
1623 
1624 
1625 /**
1626  * @brief Write switch register
1627  * @param[in] interface Underlying network interface
1628  * @param[in] address Switch register address
1629  * @param[in] data Register value
1630  **/
1631 
1632 void ksz8775WriteSwitchReg(NetInterface *interface, uint16_t address,
1633  uint8_t data)
1634 {
1635  uint16_t command;
1636 
1637  //SPI slave mode?
1638  if(interface->spiDriver != NULL)
1639  {
1640  //Set up a write operation
1641  command = KSZ8775_SPI_CMD_WRITE;
1642  //Set register address
1643  command |= (address << 1) & KSZ8775_SPI_CMD_ADDR;
1644 
1645  //Pull the CS pin low
1646  interface->spiDriver->assertCs();
1647 
1648  //Write 16-bit command
1649  interface->spiDriver->transfer(MSB(command));
1650  interface->spiDriver->transfer(LSB(command));
1651 
1652  //Write data
1653  interface->spiDriver->transfer(data);
1654 
1655  //Terminate the operation by raising the CS pin
1656  interface->spiDriver->deassertCs();
1657  }
1658  else
1659  {
1660  //The MDC/MDIO interface does not have access to all the configuration
1661  //registers. It can only access the standard MIIM registers
1662  }
1663 }
1664 
1665 
1666 /**
1667  * @brief Read switch register
1668  * @param[in] interface Underlying network interface
1669  * @param[in] address Switch register address
1670  * @return Register value
1671  **/
1672 
1673 uint8_t ksz8775ReadSwitchReg(NetInterface *interface, uint16_t address)
1674 {
1675  uint8_t data;
1676  uint16_t command;
1677 
1678  //SPI slave mode?
1679  if(interface->spiDriver != NULL)
1680  {
1681  //Set up a read operation
1682  command = KSZ8775_SPI_CMD_READ;
1683  //Set register address
1684  command |= (address << 1) & KSZ8775_SPI_CMD_ADDR;
1685 
1686  //Pull the CS pin low
1687  interface->spiDriver->assertCs();
1688 
1689  //Write 16-bit command
1690  interface->spiDriver->transfer(MSB(command));
1691  interface->spiDriver->transfer(LSB(command));
1692 
1693  //Read data
1694  data = interface->spiDriver->transfer(0xFF);
1695 
1696  //Terminate the operation by raising the CS pin
1697  interface->spiDriver->deassertCs();
1698  }
1699  else
1700  {
1701  //The MDC/MDIO interface does not have access to all the configuration
1702  //registers. It can only access the standard MIIM registers
1703  data = 0;
1704  }
1705 
1706  //Return register value
1707  return data;
1708 }
1709 
1710 
1711 /**
1712  * @brief Dump switch registers for debugging purpose
1713  * @param[in] interface Underlying network interface
1714  **/
1715 
1717 {
1718  uint16_t i;
1719 
1720  //Loop through switch registers
1721  for(i = 0; i < 256; i++)
1722  {
1723  //Display current switch register
1724  TRACE_DEBUG("0x%02" PRIX16 " (%02" PRIu16 ") : 0x%02" PRIX8 "\r\n",
1725  i, i, ksz8775ReadSwitchReg(interface, i));
1726  }
1727 
1728  //Terminate with a line feed
1729  TRACE_DEBUG("\r\n");
1730 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:601
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
uint8_t entry0Fid
#define KSZ8775_STATIC_MAC_TABLE_SIZE
#define KSZ8775_PORT5_IF_CTRL6
#define NetContext
Definition: net.h:36
void ksz8775EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
#define KSZ8775_GLOBAL_CTRL3_SW5_IGMP_SNOOP_EN
error_t ksz8775DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
MacAddr macAddr
uint8_t entry3MembershipH
void ksz8775FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
uint32_t destPorts
Definition: nic.h:152
uint8_t valid
void ksz8775DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
#define KSZ8775_SPI_CMD_WRITE
void ksz8775EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
#define KSZ8775_PORTn_STAT2_LINK_GOOD
uint8_t entry3Valid
#define KSZ8775_PORTn_CTRL9(port)
#define KSZ8775_GLOBAL_CTRL21
@ 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
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
bool_t valid
Definition: nic.h:164
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
uint8_t entry3MembershipL
__weak_func void ksz8775InitHook(NetInterface *interface)
KSZ8775 custom configuration.
const SwitchDriver ksz8775SwitchDriver
KSZ8775 Ethernet switch driver.
uint16_t ksz8775ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
#define KSZ8775_PORT5_MASK
uint8_t type
Definition: coap_common.h:176
#define KSZ8775_PORTn_CTRL2_LEARNING_DIS
#define KSZ8775_INDIRECT_CTRL0_READ
#define KSZ8775_PORT4_CTRL9
#define KSZ8775_PORTn_IF_CTRL6_IF_MODE_SEL_RGMII
uint8_t forwardPorts
@ ERROR_INVALID_PORT
Definition: error.h:104
uint8_t ksz8775ReadSwitchReg(NetInterface *interface, uint16_t address)
Read switch register.
#define KSZ8775_TAIL_TAG_DEST_PORT2
void ksz8775SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
@ ERROR_TABLE_FULL
Definition: error.h:291
#define KSZ8775_GLOBAL_CTRL10
void ksz8775WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
#define KSZ8775_PORTn_CTRL2_TRANSMIT_EN
#define KSZ8775_SPI_CMD_ADDR
uint8_t override
EthHeader
Definition: ethernet.h:225
uint8_t entry2MembershipL
#define KSZ8775_INDIRECT_CTRL1
#define KSZ8775_PORTn_STAT1_OP_SPEED
#define KSZ8775_TAIL_TAG_DEST_PORT1
#define SMI_OPCODE_WRITE
Definition: nic.h:66
void ksz8775SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
#define KSZ8775_PORT5
uint8_t numValidEntriesL
#define KSZ8775_SPI_CMD_READ
error_t ksz8775GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
#define KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
#define FALSE
Definition: os_port.h:46
uint8_t dataNotReady
#define KSZ8775_TAIL_TAG_NORMAL_ADDR_LOOKUP
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
KSZ8775 5-port Ethernet switch driver.
#define KSZ8775_GLOBAL_CTRL4_SW5_SPEED
uint8_t entry0Valid
void ksz8775SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
const uint8_t ksz8775IngressTailTag[5]
Tail tag rules (host to KSZ8775)
VLAN entry.
Definition: nic.h:162
#define KSZ8775_DYNAMIC_MAC_TABLE_SIZE
#define KSZ8775_GLOBAL_CTRL4
error_t
Error codes.
Definition: error.h:43
uint8_t entry1Valid
NicDuplexMode ksz8775GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
error_t ksz8775Init(NetInterface *interface)
KSZ8775 Ethernet switch initialization.
SwitchPortState ksz8775GetPortState(NetInterface *interface, uint8_t port)
Get port state.
#define KSZ8775_PORTn_CTRL2(port)
MacAddr macAddr
#define KSZ8775_PORTn_STAT1(port)
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:40
#define KSZ8775_GLOBAL_CTRL2_MAX_PKT_SIZE_CHECK_DIS
uint8_t sourcePort
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
uint8_t macEmpty
Set of VLAN entries.
__weak_func void ksz8775EventHandler(NetInterface *interface)
KSZ8775 event handler.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define KSZ8775_BMSR
uint8_t fid
uint8_t entry3Fid
#define KSZ8775_GLOBAL_CTRL4_SW5_HALF_DUPLEX_MODE
#define KSZ8775_BMSR_LINK_STATUS
void ksz8775DumpSwitchReg(NetInterface *interface)
Dump switch registers for debugging purpose.
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
#define NetTxAncillary
Definition: net_misc.h:36
#define KSZ8775_INDIRECT_CTRL0_TABLE_SEL_VLAN
#define KSZ8775_TAIL_TAG_DEST_PORT3
void ksz8775EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
#define MSB(x)
Definition: os_port.h:59
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
uint8_t forwardPorts
#define TRACE_INFO(...)
Definition: debug.h:105
#define KSZ8775_GLOBAL_CTRL2
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
uint8_t entry0MembershipL
uint8_t entry1MembershipL
#define KSZ8775_PORT3
MacAddr macAddr
#define KSZ8775_PORTn_STAT2(port)
#define KSZ8775_INDIRECT_DATA7
uint32_t ksz8775GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
#define KSZ8775_GLOBAL_CTRL3
#define KSZ8775_PORTn_STAT1_OP_DUPLEX
#define KSZ8775_PORTn_CTRL9_FORCED_DUPLEX
#define KSZ8775_PORT1
error_t ksz8775UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
#define KSZ8775_VLAN_TABLE_SIZE
#define KSZ8775_CHIP_ID0
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
uint16_t port
Definition: dns_common.h:270
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define KSZ8775_TAIL_TAG_PORT_SEL
#define KSZ8775_TAIL_TAG_DEST_PORT4
error_t ksz8775WriteVlanEntry(NetInterface *interface, const SwitchVlanEntry *entry)
Write VLAN entry.
uint16_t fid
Definition: nic.h:165
uint8_t entry2Valid
error_t ksz8775GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
#define KSZ8775_PORT4
Ethernet switch driver.
Definition: nic.h:325
uint8_t entry2Fid
uint8_t entry2MembershipH
bool_t ksz8775GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
uint16_t vlanId
Definition: nic.h:163
uint8_t n
#define KSZ8775_INDIRECT_CTRL0_TABLE_SEL_DYNAMIC_MAC
Static MAC table entry (read operation)
#define KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL
@ 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
#define KSZ8775_CHIP_ID0_FAMILY_ID_DEFAULT
Ipv6Addr address[]
Definition: ipv6.h:345
#define KSZ8775_PORT_MASK
#define KSZ8775_INDIRECT_CTRL0_TABLE_SEL_STATIC_MAC
__weak_func void ksz8775Tick(NetInterface *interface)
KSZ8775 timer handler.
NicDuplexMode
Duplex mode.
Definition: nic.h:122
#define KSZ8775_INDIRECT_CTRL0_WRITE
MacAddr macAddr
Definition: nic.h:150
#define KSZ8775_PORTn_CTRL2_RECEIVE_EN
uint8_t valid
uint8_t srcPort
Definition: nic.h:151
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
#define KSZ8775_INDIRECT_DATA8
Static MAC table entry (write operation)
uint8_t value[]
Definition: tcp.h:376
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
#define KSZ8775_PORTn_IF_CTRL6_IS_1GBPS
#define KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
uint8_t entry1MembershipH
void ksz8775EnableIrq(NetInterface *interface)
Enable interrupts.
#define KSZ8775_GLOBAL_CTRL0_FLUSH_STATIC_MAC_TABLE
uint32_t ports
Definition: nic.h:166
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define KSZ8775_GLOBAL_CTRL21_MLD_SNOOP_EN
Dynamic MAC table entry.
error_t ksz8775TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
#define KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_PORT5
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define KSZ8775_TAIL_TAG_SRC_PORT
uint8_t entry1Fid
uint8_t numValidEntriesH
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
#define KSZ8775_GLOBAL_CTRL0_FLUSH_DYNAMIC_MAC_TABLE
#define KSZ8775_PORTn_CTRL9_FORCED_SPEED
#define KSZ8775_GLOBAL_CTRL16
error_t ksz8775AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
#define KSZ8775_GLOBAL_CTRL0
uint8_t useFid
uint8_t override
#define KSZ8775_PORTn_IF_CTRL6_IF_MODE_SEL
#define KSZ8775_INDIRECT_CTRL0
#define KSZ8775_GLOBAL_CTRL10_TAIL_TAG_EN
Helper functions for Ethernet.
#define KSZ8775_INDIRECT_CTRL0_ADDR_9_8
void ksz8775FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
void ksz8775DisableIrq(NetInterface *interface)
Disable interrupts.
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
Debugging facilities.
Forwarding database entry.
Definition: nic.h:149
#define KSZ8775_INDIRECT_BYTE
uint8_t entry0MembershipH
void ksz8775WriteSwitchReg(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register.