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-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 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
219  osSetEvent(&interface->netContext->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 __weak_func 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  NetContext *context;
252  NetInterface *virtualInterface;
253 
254  //Point to the TCP/IP stack context
255  context = interface->netContext;
256 
257  //Loop through network interfaces
258  for(i = 0; i < context->numInterfaces; i++)
259  {
260  //Point to the current interface
261  virtualInterface = &context->interfaces[i];
262 
263  //Check whether the current virtual interface is attached to the
264  //physical interface
265  if(virtualInterface == interface ||
266  virtualInterface->parent == interface)
267  {
268  //Retrieve current link state
269  linkState = ksz8563GetLinkState(interface, virtualInterface->port);
270 
271  //Link up or link down event?
272  if(linkState != virtualInterface->linkState)
273  {
274  //Set event flag
275  interface->phyEvent = TRUE;
276  //Notify the TCP/IP stack of the event
277  osSetEvent(&interface->netContext->event);
278  }
279  }
280  }
281  }
282  else
283 #endif
284  {
285  //Initialize link state
286  linkState = FALSE;
287 
288  //Loop through the ports
290  {
291  //Retrieve current link state
292  if(ksz8563GetLinkState(interface, port))
293  {
294  linkState = TRUE;
295  }
296  }
297 
298  //Link up or link down event?
299  if(linkState != interface->linkState)
300  {
301  //Set event flag
302  interface->phyEvent = TRUE;
303  //Notify the TCP/IP stack of the event
304  osSetEvent(&interface->netContext->event);
305  }
306  }
307 }
308 
309 
310 /**
311  * @brief Enable interrupts
312  * @param[in] interface Underlying network interface
313  **/
314 
316 {
317 }
318 
319 
320 /**
321  * @brief Disable interrupts
322  * @param[in] interface Underlying network interface
323  **/
324 
326 {
327 }
328 
329 
330 /**
331  * @brief KSZ8563 event handler
332  * @param[in] interface Underlying network interface
333  **/
334 
335 __weak_func void ksz8563EventHandler(NetInterface *interface)
336 {
337  uint_t port;
338  bool_t linkState;
339 
340 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
341  //Port separation mode?
342  if(interface->port != 0)
343  {
344  uint_t i;
345  NetContext *context;
346  NetInterface *virtualInterface;
347 
348  //Point to the TCP/IP stack context
349  context = interface->netContext;
350 
351  //Loop through network interfaces
352  for(i = 0; i < context->numInterfaces; i++)
353  {
354  //Point to the current interface
355  virtualInterface = &context->interfaces[i];
356 
357  //Check whether the current virtual interface is attached to the
358  //physical interface
359  if(virtualInterface == interface ||
360  virtualInterface->parent == interface)
361  {
362  //Get the port number associated with the current interface
363  port = virtualInterface->port;
364 
365  //Valid port?
366  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
367  {
368  //Retrieve current link state
369  linkState = ksz8563GetLinkState(interface, port);
370 
371  //Link up event?
372  if(linkState && !virtualInterface->linkState)
373  {
374  //Retrieve host interface speed
375  interface->linkSpeed = ksz8563GetLinkSpeed(interface,
376  KSZ8563_PORT3);
377 
378  //Retrieve host interface duplex mode
379  interface->duplexMode = ksz8563GetDuplexMode(interface,
380  KSZ8563_PORT3);
381 
382  //Adjust MAC configuration parameters for proper operation
383  interface->nicDriver->updateMacConfig(interface);
384 
385  //Check current speed
386  virtualInterface->linkSpeed = ksz8563GetLinkSpeed(interface,
387  port);
388 
389  //Check current duplex mode
390  virtualInterface->duplexMode = ksz8563GetDuplexMode(interface,
391  port);
392 
393  //Update link state
394  virtualInterface->linkState = TRUE;
395 
396  //Process link state change event
397  nicNotifyLinkChange(virtualInterface);
398  }
399  //Link down event
400  else if(!linkState && virtualInterface->linkState)
401  {
402  //Update link state
403  virtualInterface->linkState = FALSE;
404 
405  //Process link state change event
406  nicNotifyLinkChange(virtualInterface);
407  }
408  }
409  }
410  }
411  }
412  else
413 #endif
414  {
415  //Initialize link state
416  linkState = FALSE;
417 
418  //Loop through the ports
420  {
421  //Retrieve current link state
422  if(ksz8563GetLinkState(interface, port))
423  {
424  linkState = TRUE;
425  }
426  }
427 
428  //Link up event?
429  if(linkState)
430  {
431  //Retrieve host interface speed
432  interface->linkSpeed = ksz8563GetLinkSpeed(interface, KSZ8563_PORT3);
433  //Retrieve host interface duplex mode
434  interface->duplexMode = ksz8563GetDuplexMode(interface, KSZ8563_PORT3);
435 
436  //Adjust MAC configuration parameters for proper operation
437  interface->nicDriver->updateMacConfig(interface);
438 
439  //Update link state
440  interface->linkState = TRUE;
441  }
442  else
443  {
444  //Update link state
445  interface->linkState = FALSE;
446  }
447 
448  //Process link state change event
449  nicNotifyLinkChange(interface);
450  }
451 }
452 
453 
454 /**
455  * @brief Add tail tag to Ethernet frame
456  * @param[in] interface Underlying network interface
457  * @param[in] buffer Multi-part buffer containing the payload
458  * @param[in,out] offset Offset to the first payload byte
459  * @param[in] ancillary Additional options passed to the stack along with
460  * the packet
461  * @return Error code
462  **/
463 
465  size_t *offset, NetTxAncillary *ancillary)
466 {
467  error_t error;
468 
469  //Initialize status code
470  error = NO_ERROR;
471 
472 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
473  //SPI slave mode?
474  if(interface->spiDriver != NULL)
475  {
476  //Valid port?
477  if(ancillary->port <= KSZ8563_PORT2)
478  {
479  size_t length;
480  const uint8_t *tailTag;
481 
482  //The one byte tail tagging is used to indicate the destination port
483  tailTag = &ksz8563IngressTailTag[ancillary->port];
484 
485  //Retrieve the length of the Ethernet frame
486  length = netBufferGetLength(buffer) - *offset;
487 
488  //The host controller should manually add padding to the packet before
489  //inserting the tail tag
490  error = ethPadFrame(buffer, &length);
491 
492  //Check status code
493  if(!error)
494  {
495  //The tail tag is inserted at the end of the packet, just before
496  //the CRC
497  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
498  }
499  }
500  else
501  {
502  //The port number is not valid
503  error = ERROR_INVALID_PORT;
504  }
505  }
506 #endif
507 
508  //Return status code
509  return error;
510 }
511 
512 
513 /**
514  * @brief Decode tail tag from incoming Ethernet frame
515  * @param[in] interface Underlying network interface
516  * @param[in,out] frame Pointer to the received Ethernet frame
517  * @param[in,out] length Length of the frame, in bytes
518  * @param[in,out] ancillary Additional options passed to the stack along with
519  * the packet
520  * @return Error code
521  **/
522 
523 error_t ksz8563UntagFrame(NetInterface *interface, uint8_t **frame,
524  size_t *length, NetRxAncillary *ancillary)
525 {
526  error_t error;
527 
528  //Initialize status code
529  error = NO_ERROR;
530 
531 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
532  //SPI slave mode?
533  if(interface->spiDriver != NULL)
534  {
535  //Valid Ethernet frame received?
536  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
537  {
538  uint8_t *tailTag;
539 
540  //The tail tag is inserted at the end of the packet, just before
541  //the CRC
542  tailTag = *frame + *length - sizeof(uint8_t);
543 
544  //The one byte tail tagging is used to indicate the source port
545  ancillary->port = (*tailTag & KSZ8563_TAIL_TAG_SRC_PORT) + 1;
546 
547  //Strip tail tag from Ethernet frame
548  *length -= sizeof(uint8_t);
549  }
550  else
551  {
552  //Drop the received frame
553  error = ERROR_INVALID_LENGTH;
554  }
555  }
556  else
557  {
558  //Tail tagging mode cannot be enabled through MDC/MDIO interface
559  ancillary->port = 0;
560  }
561 #endif
562 
563  //Return status code
564  return error;
565 }
566 
567 
568 /**
569  * @brief Get link state
570  * @param[in] interface Underlying network interface
571  * @param[in] port Port number
572  * @return Link state
573  **/
574 
576 {
577  uint16_t value;
578  bool_t linkState;
579 
580  //Check port number
581  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
582  {
583  //Any link failure condition is latched in the BMSR register. Reading
584  //the register twice will always return the actual link status
585  value = ksz8563ReadPhyReg(interface, port, KSZ8563_BMSR);
586  value = ksz8563ReadPhyReg(interface, port, KSZ8563_BMSR);
587 
588  //Retrieve current link state
589  linkState = (value & KSZ8563_BMSR_LINK_STATUS) ? TRUE : FALSE;
590  }
591  else
592  {
593  //The specified port number is not valid
594  linkState = FALSE;
595  }
596 
597  //Return link status
598  return linkState;
599 }
600 
601 
602 /**
603  * @brief Get link speed
604  * @param[in] interface Underlying network interface
605  * @param[in] port Port number
606  * @return Link speed
607  **/
608 
609 uint32_t ksz8563GetLinkSpeed(NetInterface *interface, uint8_t port)
610 {
611  uint8_t type;
612  uint16_t value;
613  uint32_t linkSpeed;
614 
615  //Check port number
616  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
617  {
618  //Read PHY control register
620 
621  //Retrieve current link speed
623  {
624  //100BASE-TX
625  linkSpeed = NIC_LINK_SPEED_100MBPS;
626  }
627  else if((value & KSZ8563_PHYCON_SPEED_10BT) != 0)
628  {
629  //10BASE-T
630  linkSpeed = NIC_LINK_SPEED_10MBPS;
631  }
632  else
633  {
634  //The link speed is not valid
635  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
636  }
637  }
638  else if(port == KSZ8563_PORT3)
639  {
640  //SPI slave mode?
641  if(interface->spiDriver != NULL)
642  {
643  //Read port 3 XMII control 1 register
645 
646  //Retrieve host interface type
648 
649  //Gigabit interface?
652  {
653  //1000 Mb/s mode
654  linkSpeed = NIC_LINK_SPEED_1GBPS;
655  }
656  else
657  {
658  //Read port 3 XMII control 0 register
660 
661  //Retrieve host interface speed
663  {
664  //100 Mb/s mode
665  linkSpeed = NIC_LINK_SPEED_100MBPS;
666  }
667  else
668  {
669  //10 Mb/s mode
670  linkSpeed = NIC_LINK_SPEED_10MBPS;
671  }
672  }
673  }
674  else
675  {
676  //The MDC/MDIO interface does not have access to all the configuration
677  //registers. It can only access the standard MIIM registers
678  linkSpeed = NIC_LINK_SPEED_100MBPS;
679  }
680  }
681  else
682  {
683  //The specified port number is not valid
684  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
685  }
686 
687  //Return link speed
688  return linkSpeed;
689 }
690 
691 
692 /**
693  * @brief Get duplex mode
694  * @param[in] interface Underlying network interface
695  * @param[in] port Port number
696  * @return Duplex mode
697  **/
698 
700 {
701  uint16_t value;
702  NicDuplexMode duplexMode;
703 
704  //Check port number
705  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
706  {
707  //Read PHY control register
709 
710  //Retrieve current duplex mode
712  {
713  duplexMode = NIC_FULL_DUPLEX_MODE;
714  }
715  else
716  {
717  duplexMode = NIC_HALF_DUPLEX_MODE;
718  }
719  }
720  else if(port == KSZ8563_PORT3)
721  {
722  //SPI slave mode?
723  if(interface->spiDriver != NULL)
724  {
725  //Read port 3 XMII control 0 register
727 
728  //Retrieve host interface duplex mode
730  {
731  duplexMode = NIC_FULL_DUPLEX_MODE;
732  }
733  else
734  {
735  duplexMode = NIC_HALF_DUPLEX_MODE;
736  }
737  }
738  else
739  {
740  //The MDC/MDIO interface does not have access to all the configuration
741  //registers. It can only access the standard MIIM registers
742  duplexMode = NIC_FULL_DUPLEX_MODE;
743  }
744  }
745  else
746  {
747  //The specified port number is not valid
748  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
749  }
750 
751  //Return duplex mode
752  return duplexMode;
753 }
754 
755 
756 /**
757  * @brief Set port state
758  * @param[in] interface Underlying network interface
759  * @param[in] port Port number
760  * @param[in] state Port state
761  **/
762 
763 void ksz8563SetPortState(NetInterface *interface, uint8_t port,
764  SwitchPortState state)
765 {
766  uint8_t temp;
767 
768  //Check port number
769  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
770  {
771  //Read MSTP state register
773 
774  //Update port state
775  switch(state)
776  {
777  //Listening state
782  break;
783 
784  //Learning state
789  break;
790 
791  //Forwarding state
796  break;
797 
798  //Disabled state
799  default:
803  break;
804  }
805 
806  //Write the value back to MSTP state register
808  }
809 }
810 
811 
812 /**
813  * @brief Get port state
814  * @param[in] interface Underlying network interface
815  * @param[in] port Port number
816  * @return Port state
817  **/
818 
820 {
821  uint8_t temp;
822  SwitchPortState state;
823 
824  //Check port number
825  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT2)
826  {
827  //Read MSTP state register
829 
830  //Check port state
831  if((temp & KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
832  (temp & KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
834  {
835  //Disabled state
837  }
838  else if((temp & KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
839  (temp & KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
841  {
842  //Listening state
844  }
845  else if((temp & KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
846  (temp & KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
848  {
849  //Learning state
851  }
852  else if((temp & KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN) != 0 &&
853  (temp & KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
855  {
856  //Forwarding state
858  }
859  else
860  {
861  //Unknown state
863  }
864  }
865  else
866  {
867  //The specified port number is not valid
869  }
870 
871  //Return port state
872  return state;
873 }
874 
875 
876 /**
877  * @brief Set aging time for dynamic filtering entries
878  * @param[in] interface Underlying network interface
879  * @param[in] agingTime Aging time, in seconds
880  **/
881 
882 void ksz8563SetAgingTime(NetInterface *interface, uint32_t agingTime)
883 {
884  //The Age Period in combination with the Age Count field determines the
885  //aging time of dynamic entries in the address lookup table
886  agingTime = (agingTime + 3) / 4;
887 
888  //Limit the range of the parameter
889  agingTime = MIN(agingTime, 255);
890 
891  //Write the value to Switch Lookup Engine Control 3 register
893  (uint8_t) agingTime);
894 }
895 
896 
897 /**
898  * @brief Enable IGMP snooping
899  * @param[in] interface Underlying network interface
900  * @param[in] enable Enable or disable IGMP snooping
901  **/
902 
904 {
905  uint8_t temp;
906 
907  //Read the Global Port Mirroring and Snooping Control register
908  temp = ksz8563ReadSwitchReg8(interface,
910 
911  //Enable or disable IGMP snooping
912  if(enable)
913  {
915  }
916  else
917  {
919  }
920 
921  //Write the value back to Global Port Mirroring and Snooping Control register
923  temp);
924 }
925 
926 
927 /**
928  * @brief Enable MLD snooping
929  * @param[in] interface Underlying network interface
930  * @param[in] enable Enable or disable MLD snooping
931  **/
932 
934 {
935  uint8_t temp;
936 
937  //Read the Global Port Mirroring and Snooping Control register
938  temp = ksz8563ReadSwitchReg8(interface,
940 
941  //Enable or disable MLD snooping
942  if(enable)
943  {
945  }
946  else
947  {
949  }
950 
951  //Write the value back to Global Port Mirroring and Snooping Control register
953  temp);
954 }
955 
956 
957 /**
958  * @brief Enable reserved multicast table
959  * @param[in] interface Underlying network interface
960  * @param[in] enable Enable or disable reserved group addresses
961  **/
962 
964 {
965  uint8_t temp;
966 
967  //Read the Switch Lookup Engine Control 0 register
969 
970  //Enable or disable the reserved multicast table
971  if(enable)
972  {
974  }
975  else
976  {
978  }
979 
980  //Write the value back to Switch Lookup Engine Control 0 register
982 }
983 
984 
985 /**
986  * @brief Add a new entry to the static MAC table
987  * @param[in] interface Underlying network interface
988  * @param[in] entry Pointer to the forwarding database entry
989  * @return Error code
990  **/
991 
993  const SwitchFdbEntry *entry)
994 {
995  error_t error;
996  uint_t i;
997  uint_t j;
998  uint32_t value;
999  SwitchFdbEntry currentEntry;
1000 
1001  //Keep track of the first free entry
1003 
1004  //Loop through the static MAC table
1005  for(i = 0; i < KSZ8563_STATIC_MAC_TABLE_SIZE; i++)
1006  {
1007  //Read current entry
1008  error = ksz8563GetStaticFdbEntry(interface, i, &currentEntry);
1009 
1010  //Valid entry?
1011  if(!error)
1012  {
1013  //Check whether the table already contains the specified MAC address
1014  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1015  {
1016  j = i;
1017  break;
1018  }
1019  }
1020  else
1021  {
1022  //Keep track of the first free entry
1024  {
1025  j = i;
1026  }
1027  }
1028  }
1029 
1030  //Any entry available?
1032  {
1033  //Write the Static Address Table Entry 1 register
1036 
1037  //Set the relevant forward ports
1038  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1039  {
1041  }
1042  else
1043  {
1044  value = entry->destPorts & KSZ8563_PORT_MASK;
1045  }
1046 
1047  //Enable overriding of port state
1048  if(entry->override)
1049  {
1051  }
1052 
1053  //Write the Static Address Table Entry 2 register
1055 
1056  //Copy MAC address (first 16 bits)
1057  value = (entry->macAddr.b[0] << 8) | entry->macAddr.b[1];
1058 
1059  //Write the Static Address Table Entry 3 register
1061 
1062  //Copy MAC address (last 32 bits)
1063  value = (entry->macAddr.b[2] << 24) | (entry->macAddr.b[3] << 16) |
1064  (entry->macAddr.b[4] << 8) | entry->macAddr.b[5];
1065 
1066  //Write the Static Address Table Entry 4 register
1068 
1069  //Write the TABLE_INDEX field with the 4-bit index value
1071  //Set the TABLE_SELECT bit to 0 to select the static address table
1073  //Set the ACTION bit to 0 to indicate a write operation
1075  //Set the START_FINISH bit to 1 to initiate the operation
1077 
1078  //Start the write operation
1080  value);
1081 
1082  //When the operation is complete, the START_FINISH bit will be cleared
1083  //automatically
1084  do
1085  {
1086  //Read the Static Address and Reserved Multicast Table Control register
1087  value = ksz8563ReadSwitchReg32(interface,
1089 
1090  //Poll the START_FINISH bit
1092 
1093  //Successful processing
1094  error = NO_ERROR;
1095  }
1096  else
1097  {
1098  //The static MAC table is full
1099  error = ERROR_TABLE_FULL;
1100  }
1101 
1102  //Return status code
1103  return error;
1104 }
1105 
1106 
1107 /**
1108  * @brief Remove an entry from the static MAC table
1109  * @param[in] interface Underlying network interface
1110  * @param[in] entry Forwarding database entry to remove from the table
1111  * @return Error code
1112  **/
1113 
1115  const SwitchFdbEntry *entry)
1116 {
1117  error_t error;
1118  uint_t j;
1119  uint32_t value;
1120  SwitchFdbEntry currentEntry;
1121 
1122  //Loop through the static MAC table
1123  for(j = 0; j < KSZ8563_STATIC_MAC_TABLE_SIZE; j++)
1124  {
1125  //Read current entry
1126  error = ksz8563GetStaticFdbEntry(interface, j, &currentEntry);
1127 
1128  //Valid entry?
1129  if(!error)
1130  {
1131  //Check whether the table contains the specified MAC address
1132  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1133  {
1134  break;
1135  }
1136  }
1137  }
1138 
1139  //Any matching entry?
1141  {
1142  //Clear Static Address Table Entry registers
1147 
1148  //Write the TABLE_INDEX field with the 4-bit index value
1150  //Set the TABLE_SELECT bit to 0 to select the static address table
1152  //Set the ACTION bit to 0 to indicate a write operation
1154  //Set the START_FINISH bit to 1 to initiate the operation
1156 
1157  //Start the write operation
1159  value);
1160 
1161  //When the operation is complete, the START_FINISH bit will be cleared
1162  //automatically
1163  do
1164  {
1165  //Read the Static Address and Reserved Multicast Table Control register
1166  value = ksz8563ReadSwitchReg32(interface,
1168 
1169  //Poll the START_FINISH bit
1171 
1172  //Successful processing
1173  error = NO_ERROR;
1174  }
1175  else
1176  {
1177  //The static MAC table does not contain the specified address
1178  error = ERROR_NOT_FOUND;
1179  }
1180 
1181  //Return status code
1182  return error;
1183 }
1184 
1185 
1186 /**
1187  * @brief Read an entry from the static MAC table
1188  * @param[in] interface Underlying network interface
1189  * @param[in] index Zero-based index of the entry to read
1190  * @param[out] entry Pointer to the forwarding database entry
1191  * @return Error code
1192  **/
1193 
1195  SwitchFdbEntry *entry)
1196 {
1197  error_t error;
1198  uint32_t value;
1199 
1200  //Check index parameter
1201  if(index < KSZ8563_STATIC_MAC_TABLE_SIZE)
1202  {
1203  //Write the TABLE_INDEX field with the 4-bit index value
1205  //Set the TABLE_SELECT bit to 0 to select the static address table
1207  //Set the ACTION bit to 1 to indicate a read operation
1209  //Set the START_FINISH bit to 1 to initiate the operation
1211 
1212  //Start the read operation
1214  value);
1215 
1216  //When the operation is complete, the START_FINISH bit will be cleared
1217  //automatically
1218  do
1219  {
1220  //Read the Static Address and Reserved Multicast Table Control register
1221  value = ksz8563ReadSwitchReg32(interface,
1223 
1224  //Poll the START_FINISH bit
1226 
1227  //Read the Static Address Table Entry 1 register
1229 
1230  //Valid entry?
1232  {
1233  //Read the Static Address Table Entry 2 register
1235 
1236  //Retrieve the ports associated with this MAC address
1237  entry->srcPort = 0;
1239 
1240  //Check the value of the OVERRIDE bit
1242  {
1243  entry->override = TRUE;
1244  }
1245  else
1246  {
1247  entry->override = FALSE;
1248  }
1249 
1250  //Read the Static Address Table Entry 3 register
1252 
1253  //Copy MAC address (first 16 bits)
1254  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1255  entry->macAddr.b[1] = value & 0xFF;
1256 
1257  //Read the Static Address Table Entry 4 register
1259 
1260  //Copy MAC address (last 32 bits)
1261  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1262  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1263  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1264  entry->macAddr.b[5] = value & 0xFF;
1265 
1266  //Successful processing
1267  error = NO_ERROR;
1268  }
1269  else
1270  {
1271  //The entry is not valid
1272  error = ERROR_INVALID_ENTRY;
1273  }
1274  }
1275  else
1276  {
1277  //The end of the table has been reached
1278  error = ERROR_END_OF_TABLE;
1279  }
1280 
1281  //Return status code
1282  return error;
1283 }
1284 
1285 
1286 /**
1287  * @brief Flush static MAC table
1288  * @param[in] interface Underlying network interface
1289  **/
1290 
1292 {
1293  uint_t i;
1294  uint32_t value;
1295 
1296  //Loop through the static MAC table
1297  for(i = 0; i < KSZ8563_STATIC_MAC_TABLE_SIZE; i++)
1298  {
1299  //Clear Static Address Table Entry registers
1304 
1305  //Write the TABLE_INDEX field with the 4-bit index value
1307  //Set the TABLE_SELECT bit to 0 to select the static address table
1309  //Set the ACTION bit to 0 to indicate a write operation
1311  //Set the START_FINISH bit to 1 to initiate the operation
1313 
1314  //Start the write operation
1316  value);
1317 
1318  //When the operation is complete, the START_FINISH bit will be cleared
1319  //automatically
1320  do
1321  {
1322  //Read the Static Address and Reserved Multicast Table Control register
1323  value = ksz8563ReadSwitchReg32(interface,
1325 
1326  //Poll the START_FINISH bit
1328  }
1329 }
1330 
1331 
1332 /**
1333  * @brief Read an entry from the dynamic MAC table
1334  * @param[in] interface Underlying network interface
1335  * @param[in] index Zero-based index of the entry to read
1336  * @param[out] entry Pointer to the forwarding database entry
1337  * @return Error code
1338  **/
1339 
1341  SwitchFdbEntry *entry)
1342 {
1343  error_t error;
1344  uint32_t value;
1345 
1346  //First entry?
1347  if(index == 0)
1348  {
1349  //Clear the ALU Table Access Control register to stop any operation
1351 
1352  //Start the search operation
1356  }
1357 
1358  //Poll the VALID_ENTRY_OR_SEARCH_END bit until it is set
1359  do
1360  {
1361  //Read the ALU Table Access Control register
1363 
1364  //This bit goes high to indicate either a new valid entry is returned or
1365  //the search is complete
1367 
1368  //Check whether the next valid entry is ready
1369  if((value & KSZ8563_ALU_TABLE_CTRL_VALID) != 0)
1370  {
1371  //Store the data from the ALU table entry
1372  entry->destPorts = 0;
1373  entry->override = FALSE;
1374 
1375  //Read the ALU Table Entry 1 and 2 registers
1378 
1379  //Retrieve the port associated with this MAC address
1381  {
1383  entry->srcPort = KSZ8563_PORT1;
1384  break;
1386  entry->srcPort = KSZ8563_PORT2;
1387  break;
1389  entry->srcPort = KSZ8563_PORT3;
1390  break;
1391  default:
1392  entry->srcPort = 0;
1393  break;
1394  }
1395 
1396  //Read the ALU Table Entry 3 register
1398 
1399  //Copy MAC address (first 16 bits)
1400  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1401  entry->macAddr.b[1] = value & 0xFF;
1402 
1403  //Read the ALU Table Entry 4 register
1405 
1406  //Copy MAC address (last 32 bits)
1407  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1408  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1409  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1410  entry->macAddr.b[5] = value & 0xFF;
1411 
1412  //Successful processing
1413  error = NO_ERROR;
1414  }
1415  else
1416  {
1417  //The search can be stopped any time by setting the START_FINISH bit to 0
1419 
1420  //The end of the table has been reached
1421  error = ERROR_END_OF_TABLE;
1422  }
1423 
1424  //Return status code
1425  return error;
1426 }
1427 
1428 
1429 /**
1430  * @brief Flush dynamic MAC table
1431  * @param[in] interface Underlying network interface
1432  * @param[in] port Port number
1433  **/
1434 
1436 {
1437  uint_t temp;
1438  uint8_t state;
1439 
1440  //Flush only dynamic table entries
1445 
1446  //Valid port number?
1447  if(port >= KSZ8563_PORT1 && port <= KSZ8563_PORT3)
1448  {
1449  //Save the current state of the port
1451 
1452  //Turn off learning capability
1455 
1456  //All the entries associated with a port that has its learning capability
1457  //being turned off will be flushed
1461 
1462  //Restore the original state of the port
1464  }
1465  else
1466  {
1467  //Trigger a flush of the entire address lookup table
1471  }
1472 }
1473 
1474 
1475 /**
1476  * @brief Set forward ports for unknown multicast packets
1477  * @param[in] interface Underlying network interface
1478  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1479  * @param[in] forwardPorts Port map
1480  **/
1481 
1483  bool_t enable, uint32_t forwardPorts)
1484 {
1485  uint32_t temp;
1486 
1487  //Read Unknown Multicast Control register
1489 
1490  //Clear port map
1492 
1493  //Enable or disable forwarding of unknown multicast packets
1494  if(enable)
1495  {
1496  //Enable forwarding
1498 
1499  //Check whether unknown multicast packets should be forwarded to the CPU port
1500  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1501  {
1503  }
1504 
1505  //Select the desired forward ports
1506  temp |= forwardPorts & KSZ8563_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL;
1507  }
1508  else
1509  {
1510  //Disable forwarding
1512  }
1513 
1514  //Write the value back to Unknown Multicast Control register
1516 }
1517 
1518 
1519 /**
1520  * @brief Write PHY register
1521  * @param[in] interface Underlying network interface
1522  * @param[in] port Port number
1523  * @param[in] address PHY register address
1524  * @param[in] data Register value
1525  **/
1526 
1527 void ksz8563WritePhyReg(NetInterface *interface, uint8_t port,
1528  uint8_t address, uint16_t data)
1529 {
1530  uint16_t n;
1531 
1532  //SPI slave mode?
1533  if(interface->spiDriver != NULL)
1534  {
1535  //The SPI interface provides access to all PHY registers
1537  //Write the 16-bit value
1538  ksz8563WriteSwitchReg16(interface, n, data);
1539  }
1540  else if(interface->smiDriver != NULL)
1541  {
1542  //Write the specified PHY register
1543  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1544  }
1545  else
1546  {
1547  //Write the specified PHY register
1548  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1549  }
1550 }
1551 
1552 
1553 /**
1554  * @brief Read PHY register
1555  * @param[in] interface Underlying network interface
1556  * @param[in] port Port number
1557  * @param[in] address PHY register address
1558  * @return Register value
1559  **/
1560 
1561 uint16_t ksz8563ReadPhyReg(NetInterface *interface, uint8_t port,
1562  uint8_t address)
1563 {
1564  uint16_t n;
1565  uint16_t data;
1566 
1567  //SPI slave mode?
1568  if(interface->spiDriver != NULL)
1569  {
1570  //The SPI interface provides access to all PHY registers
1572  //Read the 16-bit value
1573  data = ksz8563ReadSwitchReg16(interface, n);
1574  }
1575  else if(interface->smiDriver != NULL)
1576  {
1577  //Read the specified PHY register
1578  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1579  }
1580  else
1581  {
1582  //Read the specified PHY register
1583  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1584  }
1585 
1586  //Return register value
1587  return data;
1588 }
1589 
1590 
1591 /**
1592  * @brief Dump PHY registers for debugging purpose
1593  * @param[in] interface Underlying network interface
1594  * @param[in] port Port number
1595  **/
1596 
1597 void ksz8563DumpPhyReg(NetInterface *interface, uint8_t port)
1598 {
1599  uint8_t i;
1600 
1601  //Loop through PHY registers
1602  for(i = 0; i < 32; i++)
1603  {
1604  //Display current PHY register
1605  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1606  ksz8563ReadPhyReg(interface, port, i));
1607  }
1608 
1609  //Terminate with a line feed
1610  TRACE_DEBUG("\r\n");
1611 }
1612 
1613 
1614 /**
1615  * @brief Write MMD register
1616  * @param[in] interface Underlying network interface
1617  * @param[in] port Port number
1618  * @param[in] devAddr Device address
1619  * @param[in] regAddr Register address
1620  * @param[in] data Register value
1621  **/
1622 
1623 void ksz8563WriteMmdReg(NetInterface *interface, uint8_t port,
1624  uint8_t devAddr, uint16_t regAddr, uint16_t data)
1625 {
1626  //Select register operation
1629 
1630  //Write MMD register address
1632 
1633  //Select data operation
1636 
1637  //Write the content of the MMD register
1639 }
1640 
1641 
1642 /**
1643  * @brief Read MMD register
1644  * @param[in] interface Underlying network interface
1645  * @param[in] port Port number
1646  * @param[in] devAddr Device address
1647  * @param[in] regAddr Register address
1648  * @return Register value
1649  **/
1650 
1651 uint16_t ksz8563ReadMmdReg(NetInterface *interface, uint8_t port,
1652  uint8_t devAddr, uint16_t regAddr)
1653 {
1654  //Select register operation
1657 
1658  //Write MMD register address
1660 
1661  //Select data operation
1664 
1665  //Read the content of the MMD register
1666  return ksz8563ReadPhyReg(interface, port, KSZ8563_MMDAADR);
1667 }
1668 
1669 
1670 /**
1671  * @brief Write switch register (8 bits)
1672  * @param[in] interface Underlying network interface
1673  * @param[in] address Switch register address
1674  * @param[in] data Register value
1675  **/
1676 
1677 void ksz8563WriteSwitchReg8(NetInterface *interface, uint16_t address,
1678  uint8_t data)
1679 {
1680  uint32_t command;
1681 
1682  //SPI slave mode?
1683  if(interface->spiDriver != NULL)
1684  {
1685  //Set up a write operation
1686  command = KSZ8563_SPI_CMD_WRITE;
1687  //Set register address
1688  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1689 
1690  //Pull the CS pin low
1691  interface->spiDriver->assertCs();
1692 
1693  //Write 32-bit command
1694  interface->spiDriver->transfer((command >> 24) & 0xFF);
1695  interface->spiDriver->transfer((command >> 16) & 0xFF);
1696  interface->spiDriver->transfer((command >> 8) & 0xFF);
1697  interface->spiDriver->transfer(command & 0xFF);
1698 
1699  //Write 8-bit data
1700  interface->spiDriver->transfer(data);
1701 
1702  //Terminate the operation by raising the CS pin
1703  interface->spiDriver->deassertCs();
1704  }
1705  else
1706  {
1707  //The MDC/MDIO interface does not have access to all the configuration
1708  //registers. It can only access the standard MIIM registers
1709  }
1710 }
1711 
1712 
1713 /**
1714  * @brief Read switch register (8 bits)
1715  * @param[in] interface Underlying network interface
1716  * @param[in] address Switch register address
1717  * @return Register value
1718  **/
1719 
1720 uint8_t ksz8563ReadSwitchReg8(NetInterface *interface, uint16_t address)
1721 {
1722  uint8_t data;
1723  uint32_t command;
1724 
1725  //SPI slave mode?
1726  if(interface->spiDriver != NULL)
1727  {
1728  //Set up a read operation
1729  command = KSZ8563_SPI_CMD_READ;
1730  //Set register address
1731  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1732 
1733  //Pull the CS pin low
1734  interface->spiDriver->assertCs();
1735 
1736  //Write 32-bit command
1737  interface->spiDriver->transfer((command >> 24) & 0xFF);
1738  interface->spiDriver->transfer((command >> 16) & 0xFF);
1739  interface->spiDriver->transfer((command >> 8) & 0xFF);
1740  interface->spiDriver->transfer(command & 0xFF);
1741 
1742  //Read 8-bit data
1743  data = interface->spiDriver->transfer(0xFF);
1744 
1745  //Terminate the operation by raising the CS pin
1746  interface->spiDriver->deassertCs();
1747  }
1748  else
1749  {
1750  //The MDC/MDIO interface does not have access to all the configuration
1751  //registers. It can only access the standard MIIM registers
1752  data = 0;
1753  }
1754 
1755  //Return register value
1756  return data;
1757 }
1758 
1759 
1760 /**
1761  * @brief Write switch register (16 bits)
1762  * @param[in] interface Underlying network interface
1763  * @param[in] address Switch register address
1764  * @param[in] data Register value
1765  **/
1766 
1768  uint16_t data)
1769 {
1770  uint32_t command;
1771 
1772  //SPI slave mode?
1773  if(interface->spiDriver != NULL)
1774  {
1775  //Set up a write operation
1776  command = KSZ8563_SPI_CMD_WRITE;
1777  //Set register address
1778  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1779 
1780  //Pull the CS pin low
1781  interface->spiDriver->assertCs();
1782 
1783  //Write 32-bit command
1784  interface->spiDriver->transfer((command >> 24) & 0xFF);
1785  interface->spiDriver->transfer((command >> 16) & 0xFF);
1786  interface->spiDriver->transfer((command >> 8) & 0xFF);
1787  interface->spiDriver->transfer(command & 0xFF);
1788 
1789  //Write 16-bit data
1790  interface->spiDriver->transfer((data >> 8) & 0xFF);
1791  interface->spiDriver->transfer(data & 0xFF);
1792 
1793  //Terminate the operation by raising the CS pin
1794  interface->spiDriver->deassertCs();
1795  }
1796  else
1797  {
1798  //The MDC/MDIO interface does not have access to all the configuration
1799  //registers. It can only access the standard MIIM registers
1800  }
1801 }
1802 
1803 
1804 /**
1805  * @brief Read switch register (16 bits)
1806  * @param[in] interface Underlying network interface
1807  * @param[in] address Switch register address
1808  * @return Register value
1809  **/
1810 
1811 uint16_t ksz8563ReadSwitchReg16(NetInterface *interface, uint16_t address)
1812 {
1813  uint16_t data;
1814  uint32_t command;
1815 
1816  //SPI slave mode?
1817  if(interface->spiDriver != NULL)
1818  {
1819  //Set up a read operation
1820  command = KSZ8563_SPI_CMD_READ;
1821  //Set register address
1822  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1823 
1824  //Pull the CS pin low
1825  interface->spiDriver->assertCs();
1826 
1827  //Write 32-bit command
1828  interface->spiDriver->transfer((command >> 24) & 0xFF);
1829  interface->spiDriver->transfer((command >> 16) & 0xFF);
1830  interface->spiDriver->transfer((command >> 8) & 0xFF);
1831  interface->spiDriver->transfer(command & 0xFF);
1832 
1833  //Read 16-bit data
1834  data = interface->spiDriver->transfer(0xFF) << 8;
1835  data |= interface->spiDriver->transfer(0xFF);
1836 
1837  //Terminate the operation by raising the CS pin
1838  interface->spiDriver->deassertCs();
1839  }
1840  else
1841  {
1842  //The MDC/MDIO interface does not have access to all the configuration
1843  //registers. It can only access the standard MIIM registers
1844  data = 0;
1845  }
1846 
1847  //Return register value
1848  return data;
1849 }
1850 
1851 
1852 /**
1853  * @brief Write switch register (32 bits)
1854  * @param[in] interface Underlying network interface
1855  * @param[in] address Switch register address
1856  * @param[in] data Register value
1857  **/
1858 
1860  uint32_t data)
1861 {
1862  uint32_t command;
1863 
1864  //SPI slave mode?
1865  if(interface->spiDriver != NULL)
1866  {
1867  //Set up a write operation
1868  command = KSZ8563_SPI_CMD_WRITE;
1869  //Set register address
1870  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1871 
1872  //Pull the CS pin low
1873  interface->spiDriver->assertCs();
1874 
1875  //Write 32-bit command
1876  interface->spiDriver->transfer((command >> 24) & 0xFF);
1877  interface->spiDriver->transfer((command >> 16) & 0xFF);
1878  interface->spiDriver->transfer((command >> 8) & 0xFF);
1879  interface->spiDriver->transfer(command & 0xFF);
1880 
1881  //Write 32-bit data
1882  interface->spiDriver->transfer((data >> 24) & 0xFF);
1883  interface->spiDriver->transfer((data >> 16) & 0xFF);
1884  interface->spiDriver->transfer((data >> 8) & 0xFF);
1885  interface->spiDriver->transfer(data & 0xFF);
1886 
1887  //Terminate the operation by raising the CS pin
1888  interface->spiDriver->deassertCs();
1889  }
1890  else
1891  {
1892  //The MDC/MDIO interface does not have access to all the configuration
1893  //registers. It can only access the standard MIIM registers
1894  }
1895 }
1896 
1897 
1898 /**
1899  * @brief Read switch register (32 bits)
1900  * @param[in] interface Underlying network interface
1901  * @param[in] address Switch register address
1902  * @return Register value
1903  **/
1904 
1905 uint32_t ksz8563ReadSwitchReg32(NetInterface *interface, uint16_t address)
1906 {
1907  uint32_t data;
1908  uint32_t command;
1909 
1910  //SPI slave mode?
1911  if(interface->spiDriver != NULL)
1912  {
1913  //Set up a read operation
1914  command = KSZ8563_SPI_CMD_READ;
1915  //Set register address
1916  command |= (address << 5) & KSZ8563_SPI_CMD_ADDR;
1917 
1918  //Pull the CS pin low
1919  interface->spiDriver->assertCs();
1920 
1921  //Write 32-bit command
1922  interface->spiDriver->transfer((command >> 24) & 0xFF);
1923  interface->spiDriver->transfer((command >> 16) & 0xFF);
1924  interface->spiDriver->transfer((command >> 8) & 0xFF);
1925  interface->spiDriver->transfer(command & 0xFF);
1926 
1927  //Read 32-bit data
1928  data = interface->spiDriver->transfer(0xFF) << 24;
1929  data |= interface->spiDriver->transfer(0xFF) << 16;
1930  data |= interface->spiDriver->transfer(0xFF) << 8;
1931  data |= interface->spiDriver->transfer(0xFF);
1932 
1933  //Terminate the operation by raising the CS pin
1934  interface->spiDriver->deassertCs();
1935  }
1936  else
1937  {
1938  //The MDC/MDIO interface does not have access to all the configuration
1939  //registers. It can only access the standard MIIM registers
1940  data = 0;
1941  }
1942 
1943  //Return register value
1944  return data;
1945 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:601
KSZ8563 3-port Ethernet switch driver.
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define KSZ8563_PHYCON_SPEED_100BTX
void ksz8563EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
#define KSZ8563_PORT2
#define NetContext
Definition: net.h:36
bool_t ksz8563GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
#define KSZ8563_STATIC_TABLE_ENTRY2
#define KSZ8563_GLOBAL_PORT_MIRROR_SNOOP_CTRL_IGMP_SNOOP_EN
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
uint32_t destPorts
Definition: nic.h:152
#define KSZ8563_MMDACR_DEVAD
#define KSZ8563_ALU_TABLE_ENTRY3
#define KSZ8563_PORTn_XMII_CTRL1_RGMII_ID_EG
#define KSZ8563_TAIL_TAG_NORMAL_ADDR_LOOKUP
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define KSZ8563_SWITCH_LUE_CTRL2_FLUSH_OPTION
#define KSZ8563_SPI_CMD_READ
void ksz8563WriteSwitchReg32(NetInterface *interface, uint16_t address, uint32_t data)
Write switch register (32 bits)
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
#define KSZ8563_PORTn_XMII_CTRL0_DUPLEX
#define KSZ8563_STATIC_TABLE_ENTRY2_PORT_FORWARD
@ ERROR_END_OF_TABLE
Definition: error.h:292
error_t ksz8563AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
void ksz8563WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
#define KSZ8563_GLOBAL_PORT_MIRROR_SNOOP_CTRL_MLD_SNOOP_EN
#define TRUE
Definition: os_port.h:50
void ksz8563WriteSwitchReg16(NetInterface *interface, uint16_t address, uint16_t data)
Write switch register (16 bits)
uint8_t data[]
Definition: ethernet.h:224
#define KSZ8563_GLOBAL_PORT_MIRROR_SNOOP_CTRL
#define KSZ8563_SWITCH_LUE_CTRL2
#define KSZ8563_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
#define KSZ8563_PORTn_MSTP_STATE(port)
#define KSZ8563_PORTn_XMII_CTRL0_SPEED_10_100
#define KSZ8563_CHIP_ID1_DEFAULT
uint8_t type
Definition: coap_common.h:176
#define KSZ8563_ALU_TABLE_CTRL_START_FINISH
#define KSZ8563_STATIC_MCAST_TABLE_CTRL_ACTION
#define KSZ8563_TAIL_TAG_SRC_PORT
#define KSZ8563_SWITCH_LUE_CTRL0_HASH_OPTION_CRC
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_TABLE_FULL
Definition: error.h:291
#define KSZ8563_ALU_TABLE_ENTRY2_PORT3_FORWARD
EthHeader
Definition: ethernet.h:225
#define KSZ8563_UNKONWN_MULTICAST_CTRL_FWD
#define KSZ8563_STATIC_MCAST_TABLE_CTRL_TABLE_INDEX
#define KSZ8563_PORT3_OP_CTRL0
#define KSZ8563_STATIC_MCAST_TABLE_CTRL_START_FINISH
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define KSZ8563_UNKONWN_MULTICAST_CTRL
#define KSZ8563_SWITCH_MAC_CTRL0_FRAME_LEN_CHECK_EN
#define KSZ8563_CHIP_ID1
#define KSZ8563_STATIC_TABLE_ENTRY1_VALID
void ksz8563WriteSwitchReg8(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register (8 bits)
#define KSZ8563_TAIL_TAG_PORT_BLOCKING_OVERRIDE
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
#define KSZ8563_ALU_TABLE_ENTRY1
error_t ksz8563TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
#define FALSE
Definition: os_port.h:46
#define KSZ8563_ALU_TABLE_CTRL_VALID
#define KSZ8563_PORT3
#define KSZ8563_STATIC_TABLE_ENTRY3
#define KSZ8563_ALU_TABLE_ENTRY2_PORT2_FORWARD
error_t
Error codes.
Definition: error.h:43
void ksz8563WriteMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr, uint16_t data)
Write MMD register.
#define KSZ8563_ALU_TABLE_CTRL
#define KSZ8563_PORTn_XMII_CTRL1_IF_TYPE_RGMII
__weak_func void ksz8563Tick(NetInterface *interface)
KSZ8563 timer handler.
uint16_t ksz8563ReadMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr)
Read MMD register.
__weak_func void ksz8563EventHandler(NetInterface *interface)
KSZ8563 event handler.
#define KSZ8563_BMSR
error_t ksz8563DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
#define KSZ8563_PORT_MASK
#define KSZ8563_ALU_TABLE_CTRL_VALID_ENTRY_OR_SEARCH_END
#define KSZ8563_PHYCON_SPEED_10BT
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:40
error_t ksz8563GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define KSZ8563_STATIC_MAC_TABLE_SIZE
#define KSZ8563_SWITCH_LUE_CTRL3_AGE_PERIOD_DEFAULT
error_t ksz8563Init(NetInterface *interface)
KSZ8563 Ethernet switch initialization.
uint32_t ksz8563ReadSwitchReg32(NetInterface *interface, uint16_t address)
Read switch register (32 bits)
#define KSZ8563_ALU_TABLE_ENTRY2_PORT1_FORWARD
#define KSZ8563_ALU_TABLE_ENTRY2
#define KSZ8563_BMSR_LINK_STATUS
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
#define NetTxAncillary
Definition: net_misc.h:36
#define KSZ8563_MMDAADR
void ksz8563FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
#define KSZ8563_SWITCH_MAC_CTRL0
void ksz8563DisableIrq(NetInterface *interface)
Disable interrupts.
#define KSZ8563_PORT3_XMII_CTRL1
void ksz8563SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
uint8_t ksz8563ReadSwitchReg8(NetInterface *interface, uint16_t address)
Read switch register (8 bits)
#define MIN(a, b)
Definition: os_port.h:63
#define KSZ8563_PORTn_XMII_CTRL1_RGMII_ID_IG
#define KSZ8563_PORT3_XMII_CTRL0
#define KSZ8563_SWITCH_LUE_CTRL3
#define KSZ8563_MMDACR_FUNC_ADDR
#define KSZ8563_UNKONWN_MULTICAST_CTRL_FWD_MAP
#define KSZ8563_SWITCH_OP
#define KSZ8563_SWITCH_LUE_CTRL1_FLUSH_ALU_TABLE
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
#define KSZ8563_PORTn_OP_CTRL0_TAIL_TAG_EN
#define KSZ8563_SWITCH_OP_START_SWITCH
uint16_t port
Definition: dns_common.h:270
void ksz8563DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
#define KSZ8563_PORTn_MSTP_STATE_TRANSMIT_EN
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define KSZ8563_STATIC_MCAST_TABLE_CTRL_TABLE_SELECT
__weak_func void ksz8563InitHook(NetInterface *interface)
KSZ8563 custom configuration.
uint16_t regAddr
#define KSZ8563_MMDACR
#define KSZ8563_PORTn_XMII_CTRL1_SPEED_1000
Ethernet switch driver.
Definition: nic.h:325
#define KSZ8563_MMD_LED_MODE_RESERVED_DEFAULT
uint8_t n
#define KSZ8563_STATIC_TABLE_ENTRY2_OVERRIDE
#define KSZ8563_SWITCH_LUE_CTRL1
@ 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 KSZ8563_MMD_LED_MODE_LED_MODE_SINGLE
#define KSZ8563_UNKONWN_MULTICAST_CTRL_FWD_MAP_PORT3
uint16_t ksz8563ReadSwitchReg16(NetInterface *interface, uint16_t address)
Read switch register (16 bits)
Ipv6Addr address[]
Definition: ipv6.h:345
void ksz8563EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
const uint8_t ksz8563IngressTailTag[3]
Tail tag rules (host to KSZ8563)
#define KSZ8563_MMDACR_FUNC_DATA_NO_POST_INC
#define KSZ8563_TAIL_TAG_DEST_PORT1
#define KSZ8563_PORT3_MASK
NicDuplexMode
Duplex mode.
Definition: nic.h:122
const SwitchDriver ksz8563SwitchDriver
KSZ8563 Ethernet switch driver.
#define KSZ8563_STATIC_TABLE_ENTRY1
MacAddr macAddr
Definition: nic.h:150
#define KSZ8563_PORTn_XMII_CTRL1_IF_TYPE
#define KSZ8563_PORTn_MSTP_STATE_LEARNING_DIS
#define KSZ8563_SWITCH_LUE_CTRL2_FLUSH_OPTION_DYNAMIC
uint8_t srcPort
Definition: nic.h:151
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
#define KSZ8563_ALU_TABLE_ENTRY2_PORT_FORWARD
void ksz8563SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
uint8_t value[]
Definition: tcp.h:376
#define KSZ8563_SPI_CMD_WRITE
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
NicDuplexMode ksz8563GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
error_t ksz8563GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
uint16_t ksz8563ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
SwitchPortState ksz8563GetPortState(NetInterface *interface, uint8_t port)
Get port state.
void ksz8563EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
error_t ksz8563UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
#define KSZ8563_SWITCH_OP_SOFT_HARD_RESET
#define KSZ8563_STATIC_MCAST_TABLE_CTRL
#define KSZ8563_STATIC_TABLE_ENTRY4
#define KSZ8563_MMD_LED_MODE
#define KSZ8563_SWITCH_LUE_CTRL0
uint32_t ksz8563GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define KSZ8563_PORTn_MSTP_STATE_RECEIVE_EN
#define KSZ8563_PORTn_ETH_PHY_REG(port, addr)
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
#define KSZ8563_PHYCON
#define KSZ8563_PHYCON_DUPLEX_STATUS
void ksz8563SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
#define KSZ8563_SWITCH_LUE_CTRL0_AGE_COUNT_DEFAULT
#define KSZ8563_SPI_CMD_ADDR
#define KSZ8563_SWITCH_LUE_CTRL0_RESERVED_MCAST_LOOKUP_EN
Helper functions for Ethernet.
void ksz8563EnableIrq(NetInterface *interface)
Enable interrupts.
#define KSZ8563_ALU_TABLE_ENTRY4
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
Debugging facilities.
Forwarding database entry.
Definition: nic.h:149
#define KSZ8563_TAIL_TAG_DEST_PORT2
#define KSZ8563_ALU_TABLE_CTRL_ACTION_SEARCH
void ksz8563FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
#define KSZ8563_SWITCH_LUE_CTRL1_FLUSH_MSTP_ENTRIES
#define KSZ8563_PORT1