ksz8563_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz8563_driver.c
3  * @brief KSZ8563 3-port Ethernet switch driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/ethernet_misc.h"
38 #include "debug.h"
39 
40 
41 /**
42  * @brief KSZ8563 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ8563)
75  **/
76 
77 const uint8_t ksz8563IngressTailTag[3] =
78 {
82 };
83 
84 
85 /**
86  * @brief KSZ8563 Ethernet switch initialization
87  * @param[in] interface Underlying network interface
88  * @return Error code
89  **/
90 
92 {
93  uint_t port;
94  uint8_t temp;
95 
96  //Debug message
97  TRACE_INFO("Initializing KSZ8563...\r\n");
98 
99  //SPI slave mode?
100  if(interface->spiDriver != NULL)
101  {
102  //Initialize SPI interface
103  interface->spiDriver->init();
104 
105  //Wait for the serial interface to be ready
106  do
107  {
108  //Read CHIP_ID1 register
109  temp = ksz8563ReadSwitchReg8(interface, KSZ8563_CHIP_ID1);
110 
111  //The returned data is invalid until the serial interface is ready
112  } while(temp != KSZ8563_CHIP_ID1_DEFAULT);
113 
114  //Reset switch
117 
118  //Wait for the reset to complete
119  do
120  {
121  //Read switch operation register
122  temp = ksz8563ReadSwitchReg8(interface, KSZ8563_SWITCH_OP);
123 
124  //The reset bit is self-clearing
125  } while((temp & KSZ8563_SWITCH_OP_SOFT_HARD_RESET) != 0);
126 
127 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
128  //Enable tail tag feature
132 
133  //Disable frame length check (silicon errata workaround 1)
137 #else
138  //Disable tail tag feature
142 
143  //Enable frame length check
147 #endif
148 
149  //Loop through the ports
151  {
152 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
153  //Port separation mode?
154  if(interface->port != 0)
155  {
156  //Disable packet transmission and address learning
158  }
159  else
160 #endif
161  {
162  //Enable transmission, reception and address learning
164  }
165  }
166 
167  //Restore default age count
171 
172  //Restore default age period
175 
176  //Add internal delay to ingress and egress RGMII clocks
181 
182  //Start switch operation
185  }
186  else if(interface->smiDriver != NULL)
187  {
188  //Initialize serial management interface
189  interface->smiDriver->init();
190  }
191  else
192  {
193  //Just for sanity
194  }
195 
196  //Loop through the ports
198  {
199  //Select single-LED mode
203 
204  //Implement workaround for single-LED mode
205  ksz8563WritePhyReg(interface, port, 0x1E, 0xFA00);
206 
207  //Debug message
208  TRACE_DEBUG("Port %u:\r\n", port);
209  //Dump PHY registers for debugging purpose
210  ksz8563DumpPhyReg(interface, port);
211  }
212 
213  //Perform custom configuration
214  ksz8563InitHook(interface);
215 
216  //Force the TCP/IP stack to poll the link state at startup
217  interface->phyEvent = TRUE;
218  //Notify the TCP/IP stack of the event
220 
221  //Successful initialization
222  return NO_ERROR;
223 }
224 
225 
226 /**
227  * @brief KSZ8563 custom configuration
228  * @param[in] interface Underlying network interface
229  **/
230 
231 __weak_func void ksz8563InitHook(NetInterface *interface)
232 {
233 }
234 
235 
236 /**
237  * @brief KSZ8563 timer handler
238  * @param[in] interface Underlying network interface
239  **/
240 
241 void ksz8563Tick(NetInterface *interface)
242 {
243  uint_t port;
244  bool_t linkState;
245 
246 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
247  //Port separation mode?
248  if(interface->port != 0)
249  {
250  uint_t i;
251  NetInterface *virtualInterface;
252 
253  //Loop through network interfaces
254  for(i = 0; i < NET_INTERFACE_COUNT; i++)
255  {
256  //Point to the current interface
257  virtualInterface = &netInterface[i];
258 
259  //Check whether the current virtual interface is attached to the
260  //physical interface
261  if(virtualInterface == interface ||
262  virtualInterface->parent == interface)
263  {
264  //Retrieve current link state
265  linkState = ksz8563GetLinkState(interface, virtualInterface->port);
266 
267  //Link up or link down event?
268  if(linkState != virtualInterface->linkState)
269  {
270  //Set event flag
271  interface->phyEvent = TRUE;
272  //Notify the TCP/IP stack of the event
274  }
275  }
276  }
277  }
278  else
279 #endif
280  {
281  //Initialize link state
282  linkState = FALSE;
283 
284  //Loop through the ports
286  {
287  //Retrieve current link state
288  if(ksz8563GetLinkState(interface, port))
289  {
290  linkState = TRUE;
291  }
292  }
293 
294  //Link up or link down event?
295  if(linkState != interface->linkState)
296  {
297  //Set event flag
298  interface->phyEvent = TRUE;
299  //Notify the TCP/IP stack of the event
301  }
302  }
303 }
304 
305 
306 /**
307  * @brief Enable interrupts
308  * @param[in] interface Underlying network interface
309  **/
310 
312 {
313 }
314 
315 
316 /**
317  * @brief Disable interrupts
318  * @param[in] interface Underlying network interface
319  **/
320 
322 {
323 }
324 
325 
326 /**
327  * @brief KSZ8563 event handler
328  * @param[in] interface Underlying network interface
329  **/
330 
332 {
333  uint_t port;
334  bool_t linkState;
335 
336 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
337  //Port separation mode?
338  if(interface->port != 0)
339  {
340  uint_t i;
341  NetInterface *virtualInterface;
342 
343  //Loop through network interfaces
344  for(i = 0; i < NET_INTERFACE_COUNT; i++)
345  {
346  //Point to the current interface
347  virtualInterface = &netInterface[i];
348 
349  //Check whether the current virtual interface is attached to the
350  //physical interface
351  if(virtualInterface == interface ||
352  virtualInterface->parent == interface)
353  {
354  //Get the port number associated with the current interface
355  port = virtualInterface->port;
356 
357  //Valid port?
358  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
359  {
360  //Retrieve current link state
361  linkState = ksz8563GetLinkState(interface, port);
362 
363  //Link up event?
364  if(linkState && !virtualInterface->linkState)
365  {
366  //Retrieve host interface speed
367  interface->linkSpeed = ksz8563GetLinkSpeed(interface,
368  KSZ8563_PORT3);
369 
370  //Retrieve host interface duplex mode
371  interface->duplexMode = ksz8563GetDuplexMode(interface,
372  KSZ8563_PORT3);
373 
374  //Adjust MAC configuration parameters for proper operation
375  interface->nicDriver->updateMacConfig(interface);
376 
377  //Check current speed
378  virtualInterface->linkSpeed = ksz8563GetLinkSpeed(interface,
379  port);
380 
381  //Check current duplex mode
382  virtualInterface->duplexMode = ksz8563GetDuplexMode(interface,
383  port);
384 
385  //Update link state
386  virtualInterface->linkState = TRUE;
387 
388  //Process link state change event
389  nicNotifyLinkChange(virtualInterface);
390  }
391  //Link down event
392  else if(!linkState && virtualInterface->linkState)
393  {
394  //Update link state
395  virtualInterface->linkState = FALSE;
396 
397  //Process link state change event
398  nicNotifyLinkChange(virtualInterface);
399  }
400  }
401  }
402  }
403  }
404  else
405 #endif
406  {
407  //Initialize link state
408  linkState = FALSE;
409 
410  //Loop through the ports
412  {
413  //Retrieve current link state
414  if(ksz8563GetLinkState(interface, port))
415  {
416  linkState = TRUE;
417  }
418  }
419 
420  //Link up event?
421  if(linkState)
422  {
423  //Retrieve host interface speed
424  interface->linkSpeed = ksz8563GetLinkSpeed(interface, KSZ8563_PORT3);
425  //Retrieve host interface duplex mode
426  interface->duplexMode = ksz8563GetDuplexMode(interface, KSZ8563_PORT3);
427 
428  //Adjust MAC configuration parameters for proper operation
429  interface->nicDriver->updateMacConfig(interface);
430 
431  //Update link state
432  interface->linkState = TRUE;
433  }
434  else
435  {
436  //Update link state
437  interface->linkState = FALSE;
438  }
439 
440  //Process link state change event
441  nicNotifyLinkChange(interface);
442  }
443 }
444 
445 
446 /**
447  * @brief Add tail tag to Ethernet frame
448  * @param[in] interface Underlying network interface
449  * @param[in] buffer Multi-part buffer containing the payload
450  * @param[in,out] offset Offset to the first payload byte
451  * @param[in] ancillary Additional options passed to the stack along with
452  * the packet
453  * @return Error code
454  **/
455 
457  size_t *offset, NetTxAncillary *ancillary)
458 {
459  error_t error;
460 
461  //Initialize status code
462  error = NO_ERROR;
463 
464 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
465  //SPI slave mode?
466  if(interface->spiDriver != NULL)
467  {
468  //Valid port?
469  if(ancillary->port <= KSZ8563_PORT2)
470  {
471  size_t length;
472  const uint8_t *tailTag;
473 
474  //The one byte tail tagging is used to indicate the destination port
475  tailTag = &ksz8563IngressTailTag[ancillary->port];
476 
477  //Retrieve the length of the Ethernet frame
478  length = netBufferGetLength(buffer) - *offset;
479 
480  //The host controller should manually add padding to the packet before
481  //inserting the tail tag
482  error = ethPadFrame(buffer, &length);
483 
484  //Check status code
485  if(!error)
486  {
487  //The tail tag is inserted at the end of the packet, just before
488  //the CRC
489  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
490  }
491  }
492  else
493  {
494  //The port number is not valid
495  error = ERROR_INVALID_PORT;
496  }
497  }
498 #endif
499 
500  //Return status code
501  return error;
502 }
503 
504 
505 /**
506  * @brief Decode tail tag from incoming Ethernet frame
507  * @param[in] interface Underlying network interface
508  * @param[in,out] frame Pointer to the received Ethernet frame
509  * @param[in,out] length Length of the frame, in bytes
510  * @param[in,out] ancillary Additional options passed to the stack along with
511  * the packet
512  * @return Error code
513  **/
514 
515 error_t ksz8563UntagFrame(NetInterface *interface, uint8_t **frame,
516  size_t *length, NetRxAncillary *ancillary)
517 {
518  error_t error;
519 
520  //Initialize status code
521  error = NO_ERROR;
522 
523 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
524  //SPI slave mode?
525  if(interface->spiDriver != NULL)
526  {
527  //Valid Ethernet frame received?
528  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
529  {
530  uint8_t *tailTag;
531 
532  //The tail tag is inserted at the end of the packet, just before
533  //the CRC
534  tailTag = *frame + *length - sizeof(uint8_t);
535 
536  //The one byte tail tagging is used to indicate the source port
537  ancillary->port = (*tailTag & KSZ8563_TAIL_TAG_SRC_PORT) + 1;
538 
539  //Strip tail tag from Ethernet frame
540  *length -= sizeof(uint8_t);
541  }
542  else
543  {
544  //Drop the received frame
545  error = ERROR_INVALID_LENGTH;
546  }
547  }
548  else
549  {
550  //Tail tagging mode cannot be enabled through MDC/MDIO interface
551  ancillary->port = 0;
552  }
553 #endif
554 
555  //Return status code
556  return error;
557 }
558 
559 
560 /**
561  * @brief Get link state
562  * @param[in] interface Underlying network interface
563  * @param[in] port Port number
564  * @return Link state
565  **/
566 
568 {
569  uint16_t value;
570  bool_t linkState;
571 
572  //Check port number
573  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
574  {
575  //Any link failure condition is latched in the BMSR register. Reading
576  //the register twice will always return the actual link status
577  value = ksz8563ReadPhyReg(interface, port, KSZ8563_BMSR);
578  value = ksz8563ReadPhyReg(interface, port, KSZ8563_BMSR);
579 
580  //Retrieve current link state
581  linkState = (value & KSZ8563_BMSR_LINK_STATUS) ? TRUE : FALSE;
582  }
583  else
584  {
585  //The specified port number is not valid
586  linkState = FALSE;
587  }
588 
589  //Return link status
590  return linkState;
591 }
592 
593 
594 /**
595  * @brief Get link speed
596  * @param[in] interface Underlying network interface
597  * @param[in] port Port number
598  * @return Link speed
599  **/
600 
601 uint32_t ksz8563GetLinkSpeed(NetInterface *interface, uint8_t port)
602 {
603  uint8_t type;
604  uint16_t value;
605  uint32_t linkSpeed;
606 
607  //Check port number
608  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
609  {
610  //Read PHY control register
612 
613  //Retrieve current link speed
615  {
616  //100BASE-TX
617  linkSpeed = NIC_LINK_SPEED_100MBPS;
618  }
619  else if((value & KSZ8563_PHYCON_SPEED_10BT) != 0)
620  {
621  //10BASE-T
622  linkSpeed = NIC_LINK_SPEED_10MBPS;
623  }
624  else
625  {
626  //The link speed is not valid
627  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
628  }
629  }
630  else if(port == KSZ8563_PORT3)
631  {
632  //SPI slave mode?
633  if(interface->spiDriver != NULL)
634  {
635  //Read port 3 XMII control 1 register
637 
638  //Retrieve host interface type
640 
641  //Gigabit interface?
644  {
645  //1000 Mb/s mode
646  linkSpeed = NIC_LINK_SPEED_1GBPS;
647  }
648  else
649  {
650  //Read port 3 XMII control 0 register
652 
653  //Retrieve host interface speed
655  {
656  //100 Mb/s mode
657  linkSpeed = NIC_LINK_SPEED_100MBPS;
658  }
659  else
660  {
661  //10 Mb/s mode
662  linkSpeed = NIC_LINK_SPEED_10MBPS;
663  }
664  }
665  }
666  else
667  {
668  //The MDC/MDIO interface does not have access to all the configuration
669  //registers. It can only access the standard MIIM registers
670  linkSpeed = NIC_LINK_SPEED_100MBPS;
671  }
672  }
673  else
674  {
675  //The specified port number is not valid
676  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
677  }
678 
679  //Return link status
680  return linkSpeed;
681 }
682 
683 
684 /**
685  * @brief Get duplex mode
686  * @param[in] interface Underlying network interface
687  * @param[in] port Port number
688  * @return Duplex mode
689  **/
690 
692 {
693  uint16_t value;
694  NicDuplexMode duplexMode;
695 
696  //Check port number
697  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
698  {
699  //Read PHY control register
701 
702  //Retrieve current duplex mode
704  {
705  duplexMode = NIC_FULL_DUPLEX_MODE;
706  }
707  else
708  {
709  duplexMode = NIC_HALF_DUPLEX_MODE;
710  }
711  }
712  else if(port == KSZ8563_PORT3)
713  {
714  //SPI slave mode?
715  if(interface->spiDriver != NULL)
716  {
717  //Read port 3 XMII control 0 register
719 
720  //Retrieve host interface duplex mode
722  {
723  duplexMode = NIC_FULL_DUPLEX_MODE;
724  }
725  else
726  {
727  duplexMode = NIC_HALF_DUPLEX_MODE;
728  }
729  }
730  else
731  {
732  //The MDC/MDIO interface does not have access to all the configuration
733  //registers. It can only access the standard MIIM registers
734  duplexMode = NIC_FULL_DUPLEX_MODE;
735  }
736  }
737  else
738  {
739  //The specified port number is not valid
740  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
741  }
742 
743  //Return duplex mode
744  return duplexMode;
745 }
746 
747 
748 /**
749  * @brief Set port state
750  * @param[in] interface Underlying network interface
751  * @param[in] port Port number
752  * @param[in] state Port state
753  **/
754 
755 void ksz8563SetPortState(NetInterface *interface, uint8_t port,
756  SwitchPortState state)
757 {
758  uint8_t temp;
759 
760  //Check port number
761  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
762  {
763  //Read MSTP state register
765 
766  //Update port state
767  switch(state)
768  {
769  //Listening state
774  break;
775 
776  //Learning state
781  break;
782 
783  //Forwarding state
788  break;
789 
790  //Disabled state
791  default:
795  break;
796  }
797 
798  //Write the value back to MSTP state register
800  }
801 }
802 
803 
804 /**
805  * @brief Get port state
806  * @param[in] interface Underlying network interface
807  * @param[in] port Port number
808  * @return Port state
809  **/
810 
812 {
813  uint8_t temp;
814  SwitchPortState state;
815 
816  //Check port number
817  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
818  {
819  //Read MSTP state register
821 
822  //Check port state
823  if((temp & KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
824  (temp & KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
826  {
827  //Disabled state
829  }
830  else if((temp & KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
831  (temp & KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
833  {
834  //Listening state
836  }
837  else if((temp & KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
838  (temp & KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
840  {
841  //Learning state
843  }
844  else if((temp & KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN) != 0 &&
845  (temp & KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
847  {
848  //Forwarding state
850  }
851  else
852  {
853  //Unknown state
855  }
856  }
857  else
858  {
859  //The specified port number is not valid
861  }
862 
863  //Return port state
864  return state;
865 }
866 
867 
868 /**
869  * @brief Set aging time for dynamic filtering entries
870  * @param[in] interface Underlying network interface
871  * @param[in] agingTime Aging time, in seconds
872  **/
873 
874 void ksz8563SetAgingTime(NetInterface *interface, uint32_t agingTime)
875 {
876  //The Age Period in combination with the Age Count field determines the
877  //aging time of dynamic entries in the address lookup table
878  agingTime = (agingTime + 3) / 4;
879 
880  //Limit the range of the parameter
881  agingTime = MIN(agingTime, 255);
882 
883  //Write the value to Switch Lookup Engine Control 3 register
885  (uint8_t) agingTime);
886 }
887 
888 
889 /**
890  * @brief Enable IGMP snooping
891  * @param[in] interface Underlying network interface
892  * @param[in] enable Enable or disable IGMP snooping
893  **/
894 
896 {
897  uint8_t temp;
898 
899  //Read the Global Port Mirroring and Snooping Control register
900  temp = ksz8563ReadSwitchReg8(interface,
902 
903  //Enable or disable IGMP snooping
904  if(enable)
905  {
907  }
908  else
909  {
911  }
912 
913  //Write the value back to Global Port Mirroring and Snooping Control register
915  temp);
916 }
917 
918 
919 /**
920  * @brief Enable MLD snooping
921  * @param[in] interface Underlying network interface
922  * @param[in] enable Enable or disable MLD snooping
923  **/
924 
926 {
927  uint8_t temp;
928 
929  //Read the Global Port Mirroring and Snooping Control register
930  temp = ksz8563ReadSwitchReg8(interface,
932 
933  //Enable or disable MLD snooping
934  if(enable)
935  {
937  }
938  else
939  {
941  }
942 
943  //Write the value back to Global Port Mirroring and Snooping Control register
945  temp);
946 }
947 
948 
949 /**
950  * @brief Enable reserved multicast table
951  * @param[in] interface Underlying network interface
952  * @param[in] enable Enable or disable reserved group addresses
953  **/
954 
956 {
957  uint8_t temp;
958 
959  //Read the Switch Lookup Engine Control 0 register
961 
962  //Enable or disable the reserved multicast table
963  if(enable)
964  {
966  }
967  else
968  {
970  }
971 
972  //Write the value back to Switch Lookup Engine Control 0 register
974 }
975 
976 
977 /**
978  * @brief Add a new entry to the static MAC table
979  * @param[in] interface Underlying network interface
980  * @param[in] entry Pointer to the forwarding database entry
981  * @return Error code
982  **/
983 
985  const SwitchFdbEntry *entry)
986 {
987  error_t error;
988  uint_t i;
989  uint_t j;
990  uint32_t value;
991  SwitchFdbEntry currentEntry;
992 
993  //Keep track of the first free entry
995 
996  //Loop through the static MAC table
997  for(i = 0; i < KSZ8563_STATIC_MAC_TABLE_SIZE; i++)
998  {
999  //Read current entry
1000  error = ksz8563GetStaticFdbEntry(interface, i, &currentEntry);
1001 
1002  //Valid entry?
1003  if(!error)
1004  {
1005  //Check whether the table already contains the specified MAC address
1006  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1007  {
1008  j = i;
1009  break;
1010  }
1011  }
1012  else
1013  {
1014  //Keep track of the first free entry
1016  {
1017  j = i;
1018  }
1019  }
1020  }
1021 
1022  //Any entry available?
1024  {
1025  //Write the Static Address Table Entry 1 register
1028 
1029  //Set the relevant forward ports
1030  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1031  {
1033  }
1034  else
1035  {
1036  value = entry->destPorts & KSZ8563_PORT_MASK;
1037  }
1038 
1039  //Enable overriding of port state
1040  if(entry->override)
1041  {
1043  }
1044 
1045  //Write the Static Address Table Entry 2 register
1047 
1048  //Copy MAC address (first 16 bits)
1049  value = (entry->macAddr.b[0] << 8) | entry->macAddr.b[1];
1050 
1051  //Write the Static Address Table Entry 3 register
1053 
1054  //Copy MAC address (last 32 bits)
1055  value = (entry->macAddr.b[2] << 24) | (entry->macAddr.b[3] << 16) |
1056  (entry->macAddr.b[4] << 8) | entry->macAddr.b[5];
1057 
1058  //Write the Static Address Table Entry 4 register
1060 
1061  //Write the TABLE_INDEX field with the 4-bit index value
1063  //Set the TABLE_SELECT bit to 0 to select the static address table
1065  //Set the ACTION bit to 0 to indicate a write operation
1067  //Set the START_FINISH bit to 1 to initiate the operation
1069 
1070  //Start the write operation
1072  value);
1073 
1074  //When the operation is complete, the START_FINISH bit will be cleared
1075  //automatically
1076  do
1077  {
1078  //Read the Static Address and Reserved Multicast Table Control register
1079  value = ksz8563ReadSwitchReg32(interface,
1081 
1082  //Poll the START_FINISH bit
1084 
1085  //Successful processing
1086  error = NO_ERROR;
1087  }
1088  else
1089  {
1090  //The static MAC table is full
1091  error = ERROR_TABLE_FULL;
1092  }
1093 
1094  //Return status code
1095  return error;
1096 }
1097 
1098 
1099 /**
1100  * @brief Remove an entry from the static MAC table
1101  * @param[in] interface Underlying network interface
1102  * @param[in] entry Forwarding database entry to remove from the table
1103  * @return Error code
1104  **/
1105 
1107  const SwitchFdbEntry *entry)
1108 {
1109  error_t error;
1110  uint_t j;
1111  uint32_t value;
1112  SwitchFdbEntry currentEntry;
1113 
1114  //Loop through the static MAC table
1115  for(j = 0; j < KSZ8563_STATIC_MAC_TABLE_SIZE; j++)
1116  {
1117  //Read current entry
1118  error = ksz8563GetStaticFdbEntry(interface, j, &currentEntry);
1119 
1120  //Valid entry?
1121  if(!error)
1122  {
1123  //Check whether the table contains the specified MAC address
1124  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1125  {
1126  break;
1127  }
1128  }
1129  }
1130 
1131  //Any matching entry?
1133  {
1134  //Clear Static Address Table Entry registers
1139 
1140  //Write the TABLE_INDEX field with the 4-bit index value
1142  //Set the TABLE_SELECT bit to 0 to select the static address table
1144  //Set the ACTION bit to 0 to indicate a write operation
1146  //Set the START_FINISH bit to 1 to initiate the operation
1148 
1149  //Start the write operation
1151  value);
1152 
1153  //When the operation is complete, the START_FINISH bit will be cleared
1154  //automatically
1155  do
1156  {
1157  //Read the Static Address and Reserved Multicast Table Control register
1158  value = ksz8563ReadSwitchReg32(interface,
1160 
1161  //Poll the START_FINISH bit
1163 
1164  //Successful processing
1165  error = NO_ERROR;
1166  }
1167  else
1168  {
1169  //The static MAC table does not contain the specified address
1170  error = ERROR_NOT_FOUND;
1171  }
1172 
1173  //Return status code
1174  return error;
1175 }
1176 
1177 
1178 /**
1179  * @brief Read an entry from the static MAC table
1180  * @param[in] interface Underlying network interface
1181  * @param[in] index Zero-based index of the entry to read
1182  * @param[out] entry Pointer to the forwarding database entry
1183  * @return Error code
1184  **/
1185 
1187  SwitchFdbEntry *entry)
1188 {
1189  error_t error;
1190  uint32_t value;
1191 
1192  //Check index parameter
1193  if(index < KSZ8563_STATIC_MAC_TABLE_SIZE)
1194  {
1195  //Write the TABLE_INDEX field with the 4-bit index value
1197  //Set the TABLE_SELECT bit to 0 to select the static address table
1199  //Set the ACTION bit to 1 to indicate a read operation
1201  //Set the START_FINISH bit to 1 to initiate the operation
1203 
1204  //Start the read operation
1206  value);
1207 
1208  //When the operation is complete, the START_FINISH bit will be cleared
1209  //automatically
1210  do
1211  {
1212  //Read the Static Address and Reserved Multicast Table Control register
1213  value = ksz8563ReadSwitchReg32(interface,
1215 
1216  //Poll the START_FINISH bit
1218 
1219  //Read the Static Address Table Entry 1 register
1221 
1222  //Valid entry?
1224  {
1225  //Read the Static Address Table Entry 2 register
1227 
1228  //Retrieve the ports associated with this MAC address
1229  entry->srcPort = 0;
1231 
1232  //Check the value of the OVERRIDE bit
1234  {
1235  entry->override = TRUE;
1236  }
1237  else
1238  {
1239  entry->override = FALSE;
1240  }
1241 
1242  //Read the Static Address Table Entry 3 register
1244 
1245  //Copy MAC address (first 16 bits)
1246  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1247  entry->macAddr.b[1] = value & 0xFF;
1248 
1249  //Read the Static Address Table Entry 4 register
1251 
1252  //Copy MAC address (last 32 bits)
1253  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1254  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1255  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1256  entry->macAddr.b[5] = value & 0xFF;
1257 
1258  //Successful processing
1259  error = NO_ERROR;
1260  }
1261  else
1262  {
1263  //The entry is not valid
1264  error = ERROR_INVALID_ENTRY;
1265  }
1266  }
1267  else
1268  {
1269  //The end of the table has been reached
1270  error = ERROR_END_OF_TABLE;
1271  }
1272 
1273  //Return status code
1274  return error;
1275 }
1276 
1277 
1278 /**
1279  * @brief Flush static MAC table
1280  * @param[in] interface Underlying network interface
1281  **/
1282 
1284 {
1285  uint_t i;
1286  uint32_t value;
1287 
1288  //Loop through the static MAC table
1289  for(i = 0; i < KSZ8563_STATIC_MAC_TABLE_SIZE; i++)
1290  {
1291  //Clear Static Address Table Entry registers
1296 
1297  //Write the TABLE_INDEX field with the 4-bit index value
1299  //Set the TABLE_SELECT bit to 0 to select the static address table
1301  //Set the ACTION bit to 0 to indicate a write operation
1303  //Set the START_FINISH bit to 1 to initiate the operation
1305 
1306  //Start the write operation
1308  value);
1309 
1310  //When the operation is complete, the START_FINISH bit will be cleared
1311  //automatically
1312  do
1313  {
1314  //Read the Static Address and Reserved Multicast Table Control register
1315  value = ksz8563ReadSwitchReg32(interface,
1317 
1318  //Poll the START_FINISH bit
1320  }
1321 }
1322 
1323 
1324 /**
1325  * @brief Read an entry from the dynamic MAC table
1326  * @param[in] interface Underlying network interface
1327  * @param[in] index Zero-based index of the entry to read
1328  * @param[out] entry Pointer to the forwarding database entry
1329  * @return Error code
1330  **/
1331 
1333  SwitchFdbEntry *entry)
1334 {
1335  error_t error;
1336  uint32_t value;
1337 
1338  //First entry?
1339  if(index == 0)
1340  {
1341  //Clear the ALU Table Access Control register to stop any operation
1343 
1344  //Start the search operation
1348  }
1349 
1350  //Poll the VALID_ENTRY_OR_SEARCH_END bit until it is set
1351  do
1352  {
1353  //Read the ALU Table Access Control register
1355 
1356  //This bit goes high to indicate either a new valid entry is returned or
1357  //the search is complete
1359 
1360  //Check whether the next valid entry is ready
1361  if((value & KSZ8563_ALU_TABLE_CTRL_VALID) != 0)
1362  {
1363  //Store the data from the ALU table entry
1364  entry->destPorts = 0;
1365  entry->override = FALSE;
1366 
1367  //Read the ALU Table Entry 1 and 2 registers
1370 
1371  //Retrieve the port associated with this MAC address
1373  {
1375  entry->srcPort = KSZ8563_PORT1;
1376  break;
1378  entry->srcPort = KSZ8563_PORT2;
1379  break;
1381  entry->srcPort = KSZ8563_PORT3;
1382  break;
1383  default:
1384  entry->srcPort = 0;
1385  break;
1386  }
1387 
1388  //Read the ALU Table Entry 3 register
1390 
1391  //Copy MAC address (first 16 bits)
1392  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1393  entry->macAddr.b[1] = value & 0xFF;
1394 
1395  //Read the ALU Table Entry 4 register
1397 
1398  //Copy MAC address (last 32 bits)
1399  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1400  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1401  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1402  entry->macAddr.b[5] = value & 0xFF;
1403 
1404  //Successful processing
1405  error = NO_ERROR;
1406  }
1407  else
1408  {
1409  //The search can be stopped any time by setting the START_FINISH bit to 0
1411 
1412  //The end of the table has been reached
1413  error = ERROR_END_OF_TABLE;
1414  }
1415 
1416  //Return status code
1417  return error;
1418 }
1419 
1420 
1421 /**
1422  * @brief Flush dynamic MAC table
1423  * @param[in] interface Underlying network interface
1424  * @param[in] port Port number
1425  **/
1426 
1428 {
1429  uint_t temp;
1430  uint8_t state;
1431 
1432  //Flush only dynamic table entries
1437 
1438  //Valid port number?
1439  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT3)
1440  {
1441  //Save the current state of the port
1443 
1444  //Turn off learning capability
1447 
1448  //All the entries associated with a port that has its learning capability
1449  //being turned off will be flushed
1453 
1454  //Restore the original state of the port
1456  }
1457  else
1458  {
1459  //Trigger a flush of the entire address lookup table
1463  }
1464 }
1465 
1466 
1467 /**
1468  * @brief Set forward ports for unknown multicast packets
1469  * @param[in] interface Underlying network interface
1470  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1471  * @param[in] forwardPorts Port map
1472  **/
1473 
1475  bool_t enable, uint32_t forwardPorts)
1476 {
1477  uint32_t temp;
1478 
1479  //Read Unknown Multicast Control register
1481 
1482  //Clear port map
1484 
1485  //Enable or disable forwarding of unknown multicast packets
1486  if(enable)
1487  {
1488  //Enable forwarding
1490 
1491  //Check whether unknown multicast packets should be forwarded to the CPU port
1492  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1493  {
1495  }
1496 
1497  //Select the desired forward ports
1498  temp |= forwardPorts & KSZ8563_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL;
1499  }
1500  else
1501  {
1502  //Disable forwarding
1504  }
1505 
1506  //Write the value back to Unknown Multicast Control register
1508 }
1509 
1510 
1511 /**
1512  * @brief Write PHY register
1513  * @param[in] interface Underlying network interface
1514  * @param[in] port Port number
1515  * @param[in] address PHY register address
1516  * @param[in] data Register value
1517  **/
1518 
1519 void ksz8563WritePhyReg(NetInterface *interface, uint8_t port,
1520  uint8_t address, uint16_t data)
1521 {
1522  uint16_t n;
1523 
1524  //SPI slave mode?
1525  if(interface->spiDriver != NULL)
1526  {
1527  //The SPI interface provides access to all PHY registers
1529  //Write the 16-bit value
1530  ksz8563WriteSwitchReg16(interface, n, data);
1531  }
1532  else if(interface->smiDriver != NULL)
1533  {
1534  //Write the specified PHY register
1535  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1536  }
1537  else
1538  {
1539  //Write the specified PHY register
1540  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1541  }
1542 }
1543 
1544 
1545 /**
1546  * @brief Read PHY register
1547  * @param[in] interface Underlying network interface
1548  * @param[in] port Port number
1549  * @param[in] address PHY register address
1550  * @return Register value
1551  **/
1552 
1553 uint16_t ksz8563ReadPhyReg(NetInterface *interface, uint8_t port,
1554  uint8_t address)
1555 {
1556  uint16_t n;
1557  uint16_t data;
1558 
1559  //SPI slave mode?
1560  if(interface->spiDriver != NULL)
1561  {
1562  //The SPI interface provides access to all PHY registers
1564  //Read the 16-bit value
1565  data = ksz8563ReadSwitchReg16(interface, n);
1566  }
1567  else if(interface->smiDriver != NULL)
1568  {
1569  //Read the specified PHY register
1570  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1571  }
1572  else
1573  {
1574  //Read the specified PHY register
1575  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1576  }
1577 
1578  //Return register value
1579  return data;
1580 }
1581 
1582 
1583 /**
1584  * @brief Dump PHY registers for debugging purpose
1585  * @param[in] interface Underlying network interface
1586  * @param[in] port Port number
1587  **/
1588 
1589 void ksz8563DumpPhyReg(NetInterface *interface, uint8_t port)
1590 {
1591  uint8_t i;
1592 
1593  //Loop through PHY registers
1594  for(i = 0; i < 32; i++)
1595  {
1596  //Display current PHY register
1597  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1598  ksz8563ReadPhyReg(interface, port, i));
1599  }
1600 
1601  //Terminate with a line feed
1602  TRACE_DEBUG("\r\n");
1603 }
1604 
1605 
1606 /**
1607  * @brief Write MMD register
1608  * @param[in] interface Underlying network interface
1609  * @param[in] port Port number
1610  * @param[in] devAddr Device address
1611  * @param[in] regAddr Register address
1612  * @param[in] data Register value
1613  **/
1614 
1615 void ksz8563WriteMmdReg(NetInterface *interface, uint8_t port,
1616  uint8_t devAddr, uint16_t regAddr, uint16_t data)
1617 {
1618  //Select register operation
1621 
1622  //Write MMD register address
1624 
1625  //Select data operation
1628 
1629  //Write the content of the MMD register
1631 }
1632 
1633 
1634 /**
1635  * @brief Read MMD register
1636  * @param[in] interface Underlying network interface
1637  * @param[in] port Port number
1638  * @param[in] devAddr Device address
1639  * @param[in] regAddr Register address
1640  * @return Register value
1641  **/
1642 
1643 uint16_t ksz8563ReadMmdReg(NetInterface *interface, uint8_t port,
1644  uint8_t devAddr, uint16_t regAddr)
1645 {
1646  //Select register operation
1649 
1650  //Write MMD register address
1652 
1653  //Select data operation
1656 
1657  //Read the content of the MMD register
1658  return ksz8563ReadPhyReg(interface, port, KSZ8563_MMDAADR);
1659 }
1660 
1661 
1662 /**
1663  * @brief Write switch register (8 bits)
1664  * @param[in] interface Underlying network interface
1665  * @param[in] address Switch register address
1666  * @param[in] data Register value
1667  **/
1668 
1669 void ksz8563WriteSwitchReg8(NetInterface *interface, uint16_t address,
1670  uint8_t data)
1671 {
1672  uint32_t command;
1673 
1674  //SPI slave mode?
1675  if(interface->spiDriver != NULL)
1676  {
1677  //Set up a write operation
1678  command = KSZ8563_SPI_CMD_WRITE;
1679  //Set register address
1680  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1681 
1682  //Pull the CS pin low
1683  interface->spiDriver->assertCs();
1684 
1685  //Write 32-bit command
1686  interface->spiDriver->transfer((command >> 24) & 0xFF);
1687  interface->spiDriver->transfer((command >> 16) & 0xFF);
1688  interface->spiDriver->transfer((command >> 8) & 0xFF);
1689  interface->spiDriver->transfer(command & 0xFF);
1690 
1691  //Write 8-bit data
1692  interface->spiDriver->transfer(data);
1693 
1694  //Terminate the operation by raising the CS pin
1695  interface->spiDriver->deassertCs();
1696  }
1697  else
1698  {
1699  //The MDC/MDIO interface does not have access to all the configuration
1700  //registers. It can only access the standard MIIM registers
1701  }
1702 }
1703 
1704 
1705 /**
1706  * @brief Read switch register (8 bits)
1707  * @param[in] interface Underlying network interface
1708  * @param[in] address Switch register address
1709  * @return Register value
1710  **/
1711 
1712 uint8_t ksz8563ReadSwitchReg8(NetInterface *interface, uint16_t address)
1713 {
1714  uint8_t data;
1715  uint32_t command;
1716 
1717  //SPI slave mode?
1718  if(interface->spiDriver != NULL)
1719  {
1720  //Set up a read operation
1721  command = KSZ8563_SPI_CMD_READ;
1722  //Set register address
1723  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1724 
1725  //Pull the CS pin low
1726  interface->spiDriver->assertCs();
1727 
1728  //Write 32-bit command
1729  interface->spiDriver->transfer((command >> 24) & 0xFF);
1730  interface->spiDriver->transfer((command >> 16) & 0xFF);
1731  interface->spiDriver->transfer((command >> 8) & 0xFF);
1732  interface->spiDriver->transfer(command & 0xFF);
1733 
1734  //Read 8-bit data
1735  data = interface->spiDriver->transfer(0xFF);
1736 
1737  //Terminate the operation by raising the CS pin
1738  interface->spiDriver->deassertCs();
1739  }
1740  else
1741  {
1742  //The MDC/MDIO interface does not have access to all the configuration
1743  //registers. It can only access the standard MIIM registers
1744  data = 0;
1745  }
1746 
1747  //Return register value
1748  return data;
1749 }
1750 
1751 
1752 /**
1753  * @brief Write switch register (16 bits)
1754  * @param[in] interface Underlying network interface
1755  * @param[in] address Switch register address
1756  * @param[in] data Register value
1757  **/
1758 
1760  uint16_t data)
1761 {
1762  uint32_t command;
1763 
1764  //SPI slave mode?
1765  if(interface->spiDriver != NULL)
1766  {
1767  //Set up a write operation
1768  command = KSZ8563_SPI_CMD_WRITE;
1769  //Set register address
1770  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1771 
1772  //Pull the CS pin low
1773  interface->spiDriver->assertCs();
1774 
1775  //Write 32-bit command
1776  interface->spiDriver->transfer((command >> 24) & 0xFF);
1777  interface->spiDriver->transfer((command >> 16) & 0xFF);
1778  interface->spiDriver->transfer((command >> 8) & 0xFF);
1779  interface->spiDriver->transfer(command & 0xFF);
1780 
1781  //Write 16-bit data
1782  interface->spiDriver->transfer((data >> 8) & 0xFF);
1783  interface->spiDriver->transfer(data & 0xFF);
1784 
1785  //Terminate the operation by raising the CS pin
1786  interface->spiDriver->deassertCs();
1787  }
1788  else
1789  {
1790  //The MDC/MDIO interface does not have access to all the configuration
1791  //registers. It can only access the standard MIIM registers
1792  }
1793 }
1794 
1795 
1796 /**
1797  * @brief Read switch register (16 bits)
1798  * @param[in] interface Underlying network interface
1799  * @param[in] address Switch register address
1800  * @return Register value
1801  **/
1802 
1803 uint16_t ksz8563ReadSwitchReg16(NetInterface *interface, uint16_t address)
1804 {
1805  uint16_t data;
1806  uint32_t command;
1807 
1808  //SPI slave mode?
1809  if(interface->spiDriver != NULL)
1810  {
1811  //Set up a read operation
1812  command = KSZ8563_SPI_CMD_READ;
1813  //Set register address
1814  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1815 
1816  //Pull the CS pin low
1817  interface->spiDriver->assertCs();
1818 
1819  //Write 32-bit command
1820  interface->spiDriver->transfer((command >> 24) & 0xFF);
1821  interface->spiDriver->transfer((command >> 16) & 0xFF);
1822  interface->spiDriver->transfer((command >> 8) & 0xFF);
1823  interface->spiDriver->transfer(command & 0xFF);
1824 
1825  //Read 16-bit data
1826  data = interface->spiDriver->transfer(0xFF) << 8;
1827  data |= interface->spiDriver->transfer(0xFF);
1828 
1829  //Terminate the operation by raising the CS pin
1830  interface->spiDriver->deassertCs();
1831  }
1832  else
1833  {
1834  //The MDC/MDIO interface does not have access to all the configuration
1835  //registers. It can only access the standard MIIM registers
1836  data = 0;
1837  }
1838 
1839  //Return register value
1840  return data;
1841 }
1842 
1843 
1844 /**
1845  * @brief Write switch register (32 bits)
1846  * @param[in] interface Underlying network interface
1847  * @param[in] address Switch register address
1848  * @param[in] data Register value
1849  **/
1850 
1852  uint32_t data)
1853 {
1854  uint32_t command;
1855 
1856  //SPI slave mode?
1857  if(interface->spiDriver != NULL)
1858  {
1859  //Set up a write operation
1860  command = KSZ8563_SPI_CMD_WRITE;
1861  //Set register address
1862  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1863 
1864  //Pull the CS pin low
1865  interface->spiDriver->assertCs();
1866 
1867  //Write 32-bit command
1868  interface->spiDriver->transfer((command >> 24) & 0xFF);
1869  interface->spiDriver->transfer((command >> 16) & 0xFF);
1870  interface->spiDriver->transfer((command >> 8) & 0xFF);
1871  interface->spiDriver->transfer(command & 0xFF);
1872 
1873  //Write 32-bit data
1874  interface->spiDriver->transfer((data >> 24) & 0xFF);
1875  interface->spiDriver->transfer((data >> 16) & 0xFF);
1876  interface->spiDriver->transfer((data >> 8) & 0xFF);
1877  interface->spiDriver->transfer(data & 0xFF);
1878 
1879  //Terminate the operation by raising the CS pin
1880  interface->spiDriver->deassertCs();
1881  }
1882  else
1883  {
1884  //The MDC/MDIO interface does not have access to all the configuration
1885  //registers. It can only access the standard MIIM registers
1886  }
1887 }
1888 
1889 
1890 /**
1891  * @brief Read switch register (32 bits)
1892  * @param[in] interface Underlying network interface
1893  * @param[in] address Switch register address
1894  * @return Register value
1895  **/
1896 
1897 uint32_t ksz8563ReadSwitchReg32(NetInterface *interface, uint16_t address)
1898 {
1899  uint32_t data;
1900  uint32_t command;
1901 
1902  //SPI slave mode?
1903  if(interface->spiDriver != NULL)
1904  {
1905  //Set up a read operation
1906  command = KSZ8563_SPI_CMD_READ;
1907  //Set register address
1908  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1909 
1910  //Pull the CS pin low
1911  interface->spiDriver->assertCs();
1912 
1913  //Write 32-bit command
1914  interface->spiDriver->transfer((command >> 24) & 0xFF);
1915  interface->spiDriver->transfer((command >> 16) & 0xFF);
1916  interface->spiDriver->transfer((command >> 8) & 0xFF);
1917  interface->spiDriver->transfer(command & 0xFF);
1918 
1919  //Read 32-bit data
1920  data = interface->spiDriver->transfer(0xFF) << 24;
1921  data |= interface->spiDriver->transfer(0xFF) << 16;
1922  data |= interface->spiDriver->transfer(0xFF) << 8;
1923  data |= interface->spiDriver->transfer(0xFF);
1924 
1925  //Terminate the operation by raising the CS pin
1926  interface->spiDriver->deassertCs();
1927  }
1928  else
1929  {
1930  //The MDC/MDIO interface does not have access to all the configuration
1931  //registers. It can only access the standard MIIM registers
1932  data = 0;
1933  }
1934 
1935  //Return register value
1936  return data;
1937 }
uint8_t type
Definition: coap_common.h:176
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint16_t port
Definition: dns_common.h:267
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_NOT_FOUND
Definition: error.h:147
@ ERROR_END_OF_TABLE
Definition: error.h:290
@ ERROR_INVALID_ENTRY
Definition: error.h:288
@ ERROR_TABLE_FULL
Definition: error.h:289
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint8_t data[]
Definition: ethernet.h:222
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
EthHeader
Definition: ethernet.h:223
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
Helper functions for Ethernet.
Ipv6Addr address[]
Definition: ipv6.h:316
void ksz8563DisableIrq(NetInterface *interface)
Disable interrupts.
void ksz8563Tick(NetInterface *interface)
KSZ8563 timer handler.
error_t ksz8563Init(NetInterface *interface)
KSZ8563 Ethernet switch initialization.
error_t ksz8563AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
const uint8_t ksz8563IngressTailTag[3]
Tail tag rules (host to KSZ8563)
SwitchPortState ksz8563GetPortState(NetInterface *interface, uint8_t port)
Get port state.
void ksz8563EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
void ksz8563EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
error_t ksz8563TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
void ksz8563WriteSwitchReg16(NetInterface *interface, uint16_t address, uint16_t data)
Write switch register (16 bits)
uint16_t ksz8563ReadMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr)
Read MMD register.
uint32_t ksz8563GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
void ksz8563SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
void ksz8563WriteSwitchReg8(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register (8 bits)
void ksz8563WriteMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr, uint16_t data)
Write MMD register.
void ksz8563EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
uint8_t ksz8563ReadSwitchReg8(NetInterface *interface, uint16_t address)
Read switch register (8 bits)
void ksz8563SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
void ksz8563EventHandler(NetInterface *interface)
KSZ8563 event handler.
const SwitchDriver ksz8563SwitchDriver
KSZ8563 Ethernet switch driver.
void ksz8563SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
uint16_t ksz8563ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
uint32_t ksz8563ReadSwitchReg32(NetInterface *interface, uint16_t address)
Read switch register (32 bits)
void ksz8563EnableIrq(NetInterface *interface)
Enable interrupts.
error_t ksz8563GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
uint16_t ksz8563ReadSwitchReg16(NetInterface *interface, uint16_t address)
Read switch register (16 bits)
error_t ksz8563DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
error_t ksz8563GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
void ksz8563FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
NicDuplexMode ksz8563GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
bool_t ksz8563GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
void ksz8563DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
void ksz8563WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
__weak_func void ksz8563InitHook(NetInterface *interface)
KSZ8563 custom configuration.
void ksz8563FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
error_t ksz8563UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
void ksz8563WriteSwitchReg32(NetInterface *interface, uint16_t address, uint32_t data)
Write switch register (32 bits)
KSZ8563 3-port Ethernet switch driver.
#define KSZ8563_UNKONWN_MULTICAST_CTRL_FWD_MAP
#define KSZ8563_PORTn_XMII_CTRL0_SPEED_10_100
#define KSZ8563_ALU_TABLE_CTRL_ACTION_SEARCH
#define KSZ8563_PHYCON_SPEED_10BT
#define KSZ8563_ALU_TABLE_ENTRY1
#define KSZ8563_MMD_LED_MODE_RESERVED_DEFAULT
#define KSZ8563_CHIP_ID1
#define KSZ8563_SWITCH_LUE_CTRL3
#define KSZ8563_SWITCH_LUE_CTRL0
#define KSZ8563_PORTn_MSTP_STATE(port)
#define KSZ8563_TAIL_TAG_NORMAL_ADDR_LOOKUP
#define KSZ8563_ALU_TABLE_ENTRY2_PORT3_FORWARD
#define KSZ8563_PORTn_XMII_CTRL1_SPEED_1000
#define KSZ8563_STATIC_TABLE_ENTRY3
#define KSZ8563_STATIC_TABLE_ENTRY2
#define KSZ8563_PORT3_XMII_CTRL0
#define KSZ8563_STATIC_TABLE_ENTRY2_OVERRIDE
#define KSZ8563_UNKONWN_MULTICAST_CTRL_FWD_MAP_PORT3
#define KSZ8563_PORTn_MSTP_STATE_LEARNING_DIS
#define KSZ8563_STATIC_MCAST_TABLE_CTRL_START_FINISH
#define KSZ8563_PORTn_XMII_CTRL1_IF_TYPE
#define KSZ8563_STATIC_TABLE_ENTRY1
#define KSZ8563_SWITCH_OP_SOFT_HARD_RESET
#define KSZ8563_SWITCH_LUE_CTRL1_FLUSH_MSTP_ENTRIES
#define KSZ8563_SWITCH_OP_START_SWITCH
#define KSZ8563_MMDACR_FUNC_ADDR
#define KSZ8563_SPI_CMD_WRITE
#define KSZ8563_MMDACR_DEVAD
#define KSZ8563_PORT2
#define KSZ8563_SWITCH_LUE_CTRL2
#define KSZ8563_ALU_TABLE_CTRL_VALID_ENTRY_OR_SEARCH_END
#define KSZ8563_CHIP_ID1_DEFAULT
#define KSZ8563_SPI_CMD_READ
#define KSZ8563_SWITCH_LUE_CTRL0_HASH_OPTION_CRC
#define KSZ8563_MMDACR_FUNC_DATA_NO_POST_INC
#define KSZ8563_PORT3_OP_CTRL0
#define KSZ8563_PORTn_XMII_CTRL1_IF_TYPE_RGMII
#define KSZ8563_ALU_TABLE_ENTRY2
#define KSZ8563_ALU_TABLE_ENTRY3
#define KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN
#define KSZ8563_MMD_LED_MODE_LED_MODE_SINGLE
#define KSZ8563_ALU_TABLE_CTRL_START_FINISH
#define KSZ8563_UNKONWN_MULTICAST_CTRL_FWD
#define KSZ8563_PHYCON_DUPLEX_STATUS
#define KSZ8563_PORT3_MASK
#define KSZ8563_STATIC_MAC_TABLE_SIZE
#define KSZ8563_TAIL_TAG_DEST_PORT1
#define KSZ8563_MMDACR
#define KSZ8563_TAIL_TAG_PORT_BLOCKING_OVERRIDE
#define KSZ8563_PORTn_XMII_CTRL0_DUPLEX
#define KSZ8563_SWITCH_LUE_CTRL3_AGE_PERIOD_DEFAULT
#define KSZ8563_TAIL_TAG_DEST_PORT2
#define KSZ8563_PORT3_XMII_CTRL1
#define KSZ8563_SWITCH_LUE_CTRL0_RESERVED_MCAST_LOOKUP_EN
#define KSZ8563_SWITCH_LUE_CTRL2_FLUSH_OPTION
#define KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN
#define KSZ8563_ALU_TABLE_ENTRY2_PORT2_FORWARD
#define KSZ8563_STATIC_MCAST_TABLE_CTRL
#define KSZ8563_MMDAADR
#define KSZ8563_STATIC_MCAST_TABLE_CTRL_TABLE_INDEX
#define KSZ8563_MMD_LED_MODE
#define KSZ8563_STATIC_TABLE_ENTRY2_PORT_FORWARD
#define KSZ8563_ALU_TABLE_ENTRY2_PORT_FORWARD
#define KSZ8563_PHYCON_SPEED_100BTX
#define KSZ8563_PORT3
#define KSZ8563_SPI_CMD_ADDR
#define KSZ8563_GLOBAL_PORT_MIRROR_SNOOP_CTRL_IGMP_SNOOP_EN
#define KSZ8563_PHYCON
#define KSZ8563_STATIC_TABLE_ENTRY4
#define KSZ8563_PORTn_XMII_CTRL1_RGMII_ID_IG
#define KSZ8563_PORTn_OP_CTRL0_TAIL_TAG_EN
#define KSZ8563_PORTn_ETH_PHY_REG(port, addr)
#define KSZ8563_ALU_TABLE_CTRL
#define KSZ8563_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL
#define KSZ8563_PORT1
#define KSZ8563_SWITCH_LUE_CTRL1_FLUSH_ALU_TABLE
#define KSZ8563_PORT_MASK
#define KSZ8563_STATIC_TABLE_ENTRY1_VALID
#define KSZ8563_STATIC_MCAST_TABLE_CTRL_TABLE_SELECT
#define KSZ8563_SWITCH_LUE_CTRL2_FLUSH_OPTION_DYNAMIC
#define KSZ8563_GLOBAL_PORT_MIRROR_SNOOP_CTRL
#define KSZ8563_SWITCH_LUE_CTRL1
#define KSZ8563_BMSR_LINK_STATUS
#define KSZ8563_SWITCH_LUE_CTRL0_AGE_COUNT_DEFAULT
#define KSZ8563_PORTn_XMII_CTRL1_RGMII_ID_EG
#define KSZ8563_STATIC_MCAST_TABLE_CTRL_ACTION
#define KSZ8563_GLOBAL_PORT_MIRROR_SNOOP_CTRL_MLD_SNOOP_EN
#define KSZ8563_ALU_TABLE_ENTRY4
#define KSZ8563_SWITCH_MAC_CTRL0
#define KSZ8563_TAIL_TAG_SRC_PORT
#define KSZ8563_BMSR
#define KSZ8563_ALU_TABLE_CTRL_VALID
#define KSZ8563_ALU_TABLE_ENTRY2_PORT1_FORWARD
#define KSZ8563_SWITCH_OP
#define KSZ8563_SWITCH_MAC_CTRL0_FRAME_LEN_CHECK_EN
#define KSZ8563_UNKONWN_MULTICAST_CTRL
uint16_t regAddr
TCP/IP stack core.
#define NET_INTERFACE_COUNT
Definition: net.h:113
#define NetInterface
Definition: net.h:36
#define netInterface
Definition: net_legacy.h:199
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:588
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:548
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define SMI_OPCODE_READ
Definition: nic.h:67
NicDuplexMode
Duplex mode.
Definition: nic.h:122
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
SwitchPortState
Switch port state.
Definition: nic.h:134
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
Ethernet switch driver.
Definition: nic.h:322
Forwarding database entry.
Definition: nic.h:149
MacAddr macAddr
Definition: nic.h:150
uint32_t destPorts
Definition: nic.h:152
bool_t override
Definition: nic.h:153
uint8_t srcPort
Definition: nic.h:151
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369