ksz9563_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz9563_driver.c
3  * @brief KSZ9563 3-port Gigabit 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 KSZ9563 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ9563)
75  **/
76 
77 const uint8_t ksz9563IngressTailTag[3] =
78 {
82 };
83 
84 
85 /**
86  * @brief KSZ9563 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 KSZ9563...\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 = ksz9563ReadSwitchReg8(interface, KSZ9563_CHIP_ID1);
110 
111  //The returned data is invalid until the serial interface is ready
112  } while(temp != KSZ9563_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 = ksz9563ReadSwitchReg8(interface, KSZ9563_SWITCH_OP);
123 
124  //The reset bit is self-clearing
125  } while((temp & KSZ9563_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  //Adjust EEE refresh time (silicon errata workaround 3)
201  0x0021);
202 
203  //Select tri-color dual-LED mode (silicon errata workaround 8)
207 
208  //Debug message
209  TRACE_DEBUG("Port %u:\r\n", port);
210  //Dump PHY registers for debugging purpose
211  ksz9563DumpPhyReg(interface, port);
212  }
213 
214  //Perform custom configuration
215  ksz9563InitHook(interface);
216 
217  //Force the TCP/IP stack to poll the link state at startup
218  interface->phyEvent = TRUE;
219  //Notify the TCP/IP stack of the event
220  osSetEvent(&interface->netContext->event);
221 
222  //Successful initialization
223  return NO_ERROR;
224 }
225 
226 
227 /**
228  * @brief KSZ9563 custom configuration
229  * @param[in] interface Underlying network interface
230  **/
231 
232 __weak_func void ksz9563InitHook(NetInterface *interface)
233 {
234 }
235 
236 
237 /**
238  * @brief KSZ9563 timer handler
239  * @param[in] interface Underlying network interface
240  **/
241 
242 __weak_func void ksz9563Tick(NetInterface *interface)
243 {
244  uint_t port;
245  bool_t linkState;
246 
247 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
248  //Port separation mode?
249  if(interface->port != 0)
250  {
251  uint_t i;
252  NetContext *context;
253  NetInterface *virtualInterface;
254 
255  //Point to the TCP/IP stack context
256  context = interface->netContext;
257 
258  //Loop through network interfaces
259  for(i = 0; i < context->numInterfaces; i++)
260  {
261  //Point to the current interface
262  virtualInterface = &context->interfaces[i];
263 
264  //Check whether the current virtual interface is attached to the
265  //physical interface
266  if(virtualInterface == interface ||
267  virtualInterface->parent == interface)
268  {
269  //Retrieve current link state
270  linkState = ksz9563GetLinkState(interface, virtualInterface->port);
271 
272  //Link up or link down event?
273  if(linkState != virtualInterface->linkState)
274  {
275  //Set event flag
276  interface->phyEvent = TRUE;
277  //Notify the TCP/IP stack of the event
278  osSetEvent(&interface->netContext->event);
279  }
280  }
281  }
282  }
283  else
284 #endif
285  {
286  //Initialize link state
287  linkState = FALSE;
288 
289  //Loop through the ports
291  {
292  //Retrieve current link state
293  if(ksz9563GetLinkState(interface, port))
294  {
295  linkState = TRUE;
296  }
297  }
298 
299  //Link up or link down event?
300  if(linkState != interface->linkState)
301  {
302  //Set event flag
303  interface->phyEvent = TRUE;
304  //Notify the TCP/IP stack of the event
305  osSetEvent(&interface->netContext->event);
306  }
307  }
308 }
309 
310 
311 /**
312  * @brief Enable interrupts
313  * @param[in] interface Underlying network interface
314  **/
315 
317 {
318 }
319 
320 
321 /**
322  * @brief Disable interrupts
323  * @param[in] interface Underlying network interface
324  **/
325 
327 {
328 }
329 
330 
331 /**
332  * @brief KSZ9563 event handler
333  * @param[in] interface Underlying network interface
334  **/
335 
336 __weak_func void ksz9563EventHandler(NetInterface *interface)
337 {
338  uint_t port;
339  bool_t linkState;
340 
341 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
342  //Port separation mode?
343  if(interface->port != 0)
344  {
345  uint_t i;
346  NetContext *context;
347  NetInterface *virtualInterface;
348 
349  //Point to the TCP/IP stack context
350  context = interface->netContext;
351 
352  //Loop through network interfaces
353  for(i = 0; i < context->numInterfaces; i++)
354  {
355  //Point to the current interface
356  virtualInterface = &context->interfaces[i];
357 
358  //Check whether the current virtual interface is attached to the
359  //physical interface
360  if(virtualInterface == interface ||
361  virtualInterface->parent == interface)
362  {
363  //Get the port number associated with the current interface
364  port = virtualInterface->port;
365 
366  //Valid port?
367  if(port >= KSZ9563_PORT1 && port <= KSZ9563_PORT2)
368  {
369  //Retrieve current link state
370  linkState = ksz9563GetLinkState(interface, port);
371 
372  //Link up event?
373  if(linkState && !virtualInterface->linkState)
374  {
375  //Retrieve host interface speed
376  interface->linkSpeed = ksz9563GetLinkSpeed(interface,
377  KSZ9563_PORT3);
378 
379  //Retrieve host interface duplex mode
380  interface->duplexMode = ksz9563GetDuplexMode(interface,
381  KSZ9563_PORT3);
382 
383  //Adjust MAC configuration parameters for proper operation
384  interface->nicDriver->updateMacConfig(interface);
385 
386  //Check current speed
387  virtualInterface->linkSpeed = ksz9563GetLinkSpeed(interface,
388  port);
389 
390  //Check current duplex mode
391  virtualInterface->duplexMode = ksz9563GetDuplexMode(interface,
392  port);
393 
394  //Update link state
395  virtualInterface->linkState = TRUE;
396 
397  //Process link state change event
398  nicNotifyLinkChange(virtualInterface);
399  }
400  //Link down event
401  else if(!linkState && virtualInterface->linkState)
402  {
403  //Update link state
404  virtualInterface->linkState = FALSE;
405 
406  //Process link state change event
407  nicNotifyLinkChange(virtualInterface);
408  }
409  }
410  }
411  }
412  }
413  else
414 #endif
415  {
416  //Initialize link state
417  linkState = FALSE;
418 
419  //Loop through the ports
421  {
422  //Retrieve current link state
423  if(ksz9563GetLinkState(interface, port))
424  {
425  linkState = TRUE;
426  }
427  }
428 
429  //Link up event?
430  if(linkState)
431  {
432  //Retrieve host interface speed
433  interface->linkSpeed = ksz9563GetLinkSpeed(interface, KSZ9563_PORT3);
434  //Retrieve host interface duplex mode
435  interface->duplexMode = ksz9563GetDuplexMode(interface, KSZ9563_PORT3);
436 
437  //Adjust MAC configuration parameters for proper operation
438  interface->nicDriver->updateMacConfig(interface);
439 
440  //Update link state
441  interface->linkState = TRUE;
442  }
443  else
444  {
445  //Update link state
446  interface->linkState = FALSE;
447  }
448 
449  //Process link state change event
450  nicNotifyLinkChange(interface);
451  }
452 }
453 
454 
455 /**
456  * @brief Add tail tag to Ethernet frame
457  * @param[in] interface Underlying network interface
458  * @param[in] buffer Multi-part buffer containing the payload
459  * @param[in,out] offset Offset to the first payload byte
460  * @param[in] ancillary Additional options passed to the stack along with
461  * the packet
462  * @return Error code
463  **/
464 
466  size_t *offset, NetTxAncillary *ancillary)
467 {
468  error_t error;
469 
470  //Initialize status code
471  error = NO_ERROR;
472 
473 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
474  //SPI slave mode?
475  if(interface->spiDriver != NULL)
476  {
477  //Valid port?
478  if(ancillary->port <= KSZ9563_PORT2)
479  {
480  size_t length;
481  const uint8_t *tailTag;
482 
483  //The one byte tail tagging is used to indicate the destination port
484  tailTag = &ksz9563IngressTailTag[ancillary->port];
485 
486  //Retrieve the length of the Ethernet frame
487  length = netBufferGetLength(buffer) - *offset;
488 
489  //The host controller should manually add padding to the packet before
490  //inserting the tail tag
491  error = ethPadFrame(buffer, &length);
492 
493  //Check status code
494  if(!error)
495  {
496  //The tail tag is inserted at the end of the packet, just before
497  //the CRC
498  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
499  }
500  }
501  else
502  {
503  //The port number is not valid
504  error = ERROR_INVALID_PORT;
505  }
506  }
507 #endif
508 
509  //Return status code
510  return error;
511 }
512 
513 
514 /**
515  * @brief Decode tail tag from incoming Ethernet frame
516  * @param[in] interface Underlying network interface
517  * @param[in,out] frame Pointer to the received Ethernet frame
518  * @param[in,out] length Length of the frame, in bytes
519  * @param[in,out] ancillary Additional options passed to the stack along with
520  * the packet
521  * @return Error code
522  **/
523 
524 error_t ksz9563UntagFrame(NetInterface *interface, uint8_t **frame,
525  size_t *length, NetRxAncillary *ancillary)
526 {
527  error_t error;
528 
529  //Initialize status code
530  error = NO_ERROR;
531 
532 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
533  //SPI slave mode?
534  if(interface->spiDriver != NULL)
535  {
536  //Valid Ethernet frame received?
537  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
538  {
539  uint8_t *tailTag;
540 
541  //The tail tag is inserted at the end of the packet, just before
542  //the CRC
543  tailTag = *frame + *length - sizeof(uint8_t);
544 
545  //The one byte tail tagging is used to indicate the source port
546  ancillary->port = (*tailTag & KSZ9563_TAIL_TAG_SRC_PORT) + 1;
547 
548  //Strip tail tag from Ethernet frame
549  *length -= sizeof(uint8_t);
550  }
551  else
552  {
553  //Drop the received frame
554  error = ERROR_INVALID_LENGTH;
555  }
556  }
557  else
558  {
559  //Tail tagging mode cannot be enabled through MDC/MDIO interface
560  ancillary->port = 0;
561  }
562 #endif
563 
564  //Return status code
565  return error;
566 }
567 
568 
569 /**
570  * @brief Get link state
571  * @param[in] interface Underlying network interface
572  * @param[in] port Port number
573  * @return Link state
574  **/
575 
577 {
578  uint16_t value;
579  bool_t linkState;
580 
581  //Check port number
582  if(port >= KSZ9563_PORT1 && port <= KSZ9563_PORT2)
583  {
584  //Any link failure condition is latched in the BMSR register. Reading
585  //the register twice will always return the actual link status
586  value = ksz9563ReadPhyReg(interface, port, KSZ9563_BMSR);
587  value = ksz9563ReadPhyReg(interface, port, KSZ9563_BMSR);
588 
589  //Retrieve current link state
590  linkState = (value & KSZ9563_BMSR_LINK_STATUS) ? TRUE : FALSE;
591  }
592  else
593  {
594  //The specified port number is not valid
595  linkState = FALSE;
596  }
597 
598  //Return link status
599  return linkState;
600 }
601 
602 
603 /**
604  * @brief Get link speed
605  * @param[in] interface Underlying network interface
606  * @param[in] port Port number
607  * @return Link speed
608  **/
609 
610 uint32_t ksz9563GetLinkSpeed(NetInterface *interface, uint8_t port)
611 {
612  uint8_t type;
613  uint16_t value;
614  uint32_t linkSpeed;
615 
616  //Check port number
617  if(port >= KSZ9563_PORT1 && port <= KSZ9563_PORT2)
618  {
619  //Read PHY control register
621 
622  //Retrieve current link speed
624  {
625  //1000BASE-T
626  linkSpeed = NIC_LINK_SPEED_1GBPS;
627  }
628  else if((value & KSZ9563_PHYCON_SPEED_100BTX) != 0)
629  {
630  //100BASE-TX
631  linkSpeed = NIC_LINK_SPEED_100MBPS;
632  }
633  else if((value & KSZ9563_PHYCON_SPEED_10BT) != 0)
634  {
635  //10BASE-T
636  linkSpeed = NIC_LINK_SPEED_10MBPS;
637  }
638  else
639  {
640  //The link speed is not valid
641  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
642  }
643  }
644  else if(port == KSZ9563_PORT3)
645  {
646  //SPI slave mode?
647  if(interface->spiDriver != NULL)
648  {
649  //Read port 3 XMII control 1 register
651 
652  //Retrieve host interface type
654 
655  //Gigabit interface?
658  {
659  //1000 Mb/s mode
660  linkSpeed = NIC_LINK_SPEED_1GBPS;
661  }
662  else
663  {
664  //Read port 3 XMII control 0 register
666 
667  //Retrieve host interface speed
669  {
670  //100 Mb/s mode
671  linkSpeed = NIC_LINK_SPEED_100MBPS;
672  }
673  else
674  {
675  //10 Mb/s mode
676  linkSpeed = NIC_LINK_SPEED_10MBPS;
677  }
678  }
679  }
680  else
681  {
682  //The MDC/MDIO interface does not have access to all the configuration
683  //registers. It can only access the standard MIIM registers
684  linkSpeed = NIC_LINK_SPEED_100MBPS;
685  }
686  }
687  else
688  {
689  //The specified port number is not valid
690  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
691  }
692 
693  //Return link speed
694  return linkSpeed;
695 }
696 
697 
698 /**
699  * @brief Get duplex mode
700  * @param[in] interface Underlying network interface
701  * @param[in] port Port number
702  * @return Duplex mode
703  **/
704 
706 {
707  uint16_t value;
708  NicDuplexMode duplexMode;
709 
710  //Check port number
711  if(port >= KSZ9563_PORT1 && port <= KSZ9563_PORT2)
712  {
713  //Read PHY control register
715 
716  //Retrieve current duplex mode
718  {
719  duplexMode = NIC_FULL_DUPLEX_MODE;
720  }
721  else
722  {
723  duplexMode = NIC_HALF_DUPLEX_MODE;
724  }
725  }
726  else if(port == KSZ9563_PORT3)
727  {
728  //SPI slave mode?
729  if(interface->spiDriver != NULL)
730  {
731  //Read port 3 XMII control 0 register
733 
734  //Retrieve host interface duplex mode
736  {
737  duplexMode = NIC_FULL_DUPLEX_MODE;
738  }
739  else
740  {
741  duplexMode = NIC_HALF_DUPLEX_MODE;
742  }
743  }
744  else
745  {
746  //The MDC/MDIO interface does not have access to all the configuration
747  //registers. It can only access the standard MIIM registers
748  duplexMode = NIC_FULL_DUPLEX_MODE;
749  }
750  }
751  else
752  {
753  //The specified port number is not valid
754  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
755  }
756 
757  //Return duplex mode
758  return duplexMode;
759 }
760 
761 
762 /**
763  * @brief Set port state
764  * @param[in] interface Underlying network interface
765  * @param[in] port Port number
766  * @param[in] state Port state
767  **/
768 
769 void ksz9563SetPortState(NetInterface *interface, uint8_t port,
770  SwitchPortState state)
771 {
772  uint8_t temp;
773 
774  //Check port number
775  if(port >= KSZ9563_PORT1 && port <= KSZ9563_PORT2)
776  {
777  //Read MSTP state register
779 
780  //Update port state
781  switch(state)
782  {
783  //Listening state
788  break;
789 
790  //Learning state
795  break;
796 
797  //Forwarding state
802  break;
803 
804  //Disabled state
805  default:
809  break;
810  }
811 
812  //Write the value back to MSTP state register
814  }
815 }
816 
817 
818 /**
819  * @brief Get port state
820  * @param[in] interface Underlying network interface
821  * @param[in] port Port number
822  * @return Port state
823  **/
824 
826 {
827  uint8_t temp;
828  SwitchPortState state;
829 
830  //Check port number
831  if(port >= KSZ9563_PORT1 && port <= KSZ9563_PORT2)
832  {
833  //Read MSTP state register
835 
836  //Check port state
837  if((temp & KSZ9563_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
838  (temp & KSZ9563_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
840  {
841  //Disabled state
843  }
844  else if((temp & KSZ9563_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
845  (temp & KSZ9563_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
847  {
848  //Listening state
850  }
851  else if((temp & KSZ9563_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
852  (temp & KSZ9563_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
854  {
855  //Learning state
857  }
858  else if((temp & KSZ9563_PORTn_MSTP_STATE_TRANSMIT_EN) != 0 &&
859  (temp & KSZ9563_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
861  {
862  //Forwarding state
864  }
865  else
866  {
867  //Unknown state
869  }
870  }
871  else
872  {
873  //The specified port number is not valid
875  }
876 
877  //Return port state
878  return state;
879 }
880 
881 
882 /**
883  * @brief Set aging time for dynamic filtering entries
884  * @param[in] interface Underlying network interface
885  * @param[in] agingTime Aging time, in seconds
886  **/
887 
888 void ksz9563SetAgingTime(NetInterface *interface, uint32_t agingTime)
889 {
890  //The Age Period in combination with the Age Count field determines the
891  //aging time of dynamic entries in the address lookup table
892  agingTime = (agingTime + 3) / 4;
893 
894  //Limit the range of the parameter
895  agingTime = MIN(agingTime, 255);
896 
897  //Write the value to Switch Lookup Engine Control 3 register
899  (uint8_t) agingTime);
900 }
901 
902 
903 /**
904  * @brief Enable IGMP snooping
905  * @param[in] interface Underlying network interface
906  * @param[in] enable Enable or disable IGMP snooping
907  **/
908 
910 {
911  uint8_t temp;
912 
913  //Read the Global Port Mirroring and Snooping Control register
914  temp = ksz9563ReadSwitchReg8(interface,
916 
917  //Enable or disable IGMP snooping
918  if(enable)
919  {
921  }
922  else
923  {
925  }
926 
927  //Write the value back to Global Port Mirroring and Snooping Control register
929  temp);
930 }
931 
932 
933 /**
934  * @brief Enable MLD snooping
935  * @param[in] interface Underlying network interface
936  * @param[in] enable Enable or disable MLD snooping
937  **/
938 
940 {
941  uint8_t temp;
942 
943  //Read the Global Port Mirroring and Snooping Control register
944  temp = ksz9563ReadSwitchReg8(interface,
946 
947  //Enable or disable MLD snooping
948  if(enable)
949  {
951  }
952  else
953  {
955  }
956 
957  //Write the value back to Global Port Mirroring and Snooping Control register
959  temp);
960 }
961 
962 
963 /**
964  * @brief Enable reserved multicast table
965  * @param[in] interface Underlying network interface
966  * @param[in] enable Enable or disable reserved group addresses
967  **/
968 
970 {
971  uint8_t temp;
972 
973  //Read the Switch Lookup Engine Control 0 register
975 
976  //Enable or disable the reserved multicast table
977  if(enable)
978  {
980  }
981  else
982  {
984  }
985 
986  //Write the value back to Switch Lookup Engine Control 0 register
988 }
989 
990 
991 /**
992  * @brief Add a new entry to the static MAC table
993  * @param[in] interface Underlying network interface
994  * @param[in] entry Pointer to the forwarding database entry
995  * @return Error code
996  **/
997 
999  const SwitchFdbEntry *entry)
1000 {
1001  error_t error;
1002  uint_t i;
1003  uint_t j;
1004  uint32_t value;
1005  SwitchFdbEntry currentEntry;
1006 
1007  //Keep track of the first free entry
1009 
1010  //Loop through the static MAC table
1011  for(i = 0; i < KSZ9563_STATIC_MAC_TABLE_SIZE; i++)
1012  {
1013  //Read current entry
1014  error = ksz9563GetStaticFdbEntry(interface, i, &currentEntry);
1015 
1016  //Valid entry?
1017  if(!error)
1018  {
1019  //Check whether the table already contains the specified MAC address
1020  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1021  {
1022  j = i;
1023  break;
1024  }
1025  }
1026  else
1027  {
1028  //Keep track of the first free entry
1030  {
1031  j = i;
1032  }
1033  }
1034  }
1035 
1036  //Any entry available?
1038  {
1039  //Write the Static Address Table Entry 1 register
1042 
1043  //Set the relevant forward ports
1044  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1045  {
1047  }
1048  else
1049  {
1050  value = entry->destPorts & KSZ9563_PORT_MASK;
1051  }
1052 
1053  //Enable overriding of port state
1054  if(entry->override)
1055  {
1057  }
1058 
1059  //Write the Static Address Table Entry 2 register
1061 
1062  //Copy MAC address (first 16 bits)
1063  value = (entry->macAddr.b[0] << 8) | entry->macAddr.b[1];
1064 
1065  //Write the Static Address Table Entry 3 register
1067 
1068  //Copy MAC address (last 32 bits)
1069  value = (entry->macAddr.b[2] << 24) | (entry->macAddr.b[3] << 16) |
1070  (entry->macAddr.b[4] << 8) | entry->macAddr.b[5];
1071 
1072  //Write the Static Address Table Entry 4 register
1074 
1075  //Write the TABLE_INDEX field with the 4-bit index value
1077  //Set the TABLE_SELECT bit to 0 to select the static address table
1079  //Set the ACTION bit to 0 to indicate a write operation
1081  //Set the START_FINISH bit to 1 to initiate the operation
1083 
1084  //Start the write operation
1086  value);
1087 
1088  //When the operation is complete, the START_FINISH bit will be cleared
1089  //automatically
1090  do
1091  {
1092  //Read the Static Address and Reserved Multicast Table Control register
1093  value = ksz9563ReadSwitchReg32(interface,
1095 
1096  //Poll the START_FINISH bit
1098 
1099  //Successful processing
1100  error = NO_ERROR;
1101  }
1102  else
1103  {
1104  //The static MAC table is full
1105  error = ERROR_TABLE_FULL;
1106  }
1107 
1108  //Return status code
1109  return error;
1110 }
1111 
1112 
1113 /**
1114  * @brief Remove an entry from the static MAC table
1115  * @param[in] interface Underlying network interface
1116  * @param[in] entry Forwarding database entry to remove from the table
1117  * @return Error code
1118  **/
1119 
1121  const SwitchFdbEntry *entry)
1122 {
1123  error_t error;
1124  uint_t j;
1125  uint32_t value;
1126  SwitchFdbEntry currentEntry;
1127 
1128  //Loop through the static MAC table
1129  for(j = 0; j < KSZ9563_STATIC_MAC_TABLE_SIZE; j++)
1130  {
1131  //Read current entry
1132  error = ksz9563GetStaticFdbEntry(interface, j, &currentEntry);
1133 
1134  //Valid entry?
1135  if(!error)
1136  {
1137  //Check whether the table contains the specified MAC address
1138  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1139  {
1140  break;
1141  }
1142  }
1143  }
1144 
1145  //Any matching entry?
1147  {
1148  //Clear Static Address Table Entry registers
1153 
1154  //Write the TABLE_INDEX field with the 4-bit index value
1156  //Set the TABLE_SELECT bit to 0 to select the static address table
1158  //Set the ACTION bit to 0 to indicate a write operation
1160  //Set the START_FINISH bit to 1 to initiate the operation
1162 
1163  //Start the write operation
1165  value);
1166 
1167  //When the operation is complete, the START_FINISH bit will be cleared
1168  //automatically
1169  do
1170  {
1171  //Read the Static Address and Reserved Multicast Table Control register
1172  value = ksz9563ReadSwitchReg32(interface,
1174 
1175  //Poll the START_FINISH bit
1177 
1178  //Successful processing
1179  error = NO_ERROR;
1180  }
1181  else
1182  {
1183  //The static MAC table does not contain the specified address
1184  error = ERROR_NOT_FOUND;
1185  }
1186 
1187  //Return status code
1188  return error;
1189 }
1190 
1191 
1192 /**
1193  * @brief Read an entry from the static MAC table
1194  * @param[in] interface Underlying network interface
1195  * @param[in] index Zero-based index of the entry to read
1196  * @param[out] entry Pointer to the forwarding database entry
1197  * @return Error code
1198  **/
1199 
1201  SwitchFdbEntry *entry)
1202 {
1203  error_t error;
1204  uint32_t value;
1205 
1206  //Check index parameter
1207  if(index < KSZ9563_STATIC_MAC_TABLE_SIZE)
1208  {
1209  //Write the TABLE_INDEX field with the 4-bit index value
1211  //Set the TABLE_SELECT bit to 0 to select the static address table
1213  //Set the ACTION bit to 1 to indicate a read operation
1215  //Set the START_FINISH bit to 1 to initiate the operation
1217 
1218  //Start the read operation
1220  value);
1221 
1222  //When the operation is complete, the START_FINISH bit will be cleared
1223  //automatically
1224  do
1225  {
1226  //Read the Static Address and Reserved Multicast Table Control register
1227  value = ksz9563ReadSwitchReg32(interface,
1229 
1230  //Poll the START_FINISH bit
1232 
1233  //Read the Static Address Table Entry 1 register
1235 
1236  //Valid entry?
1238  {
1239  //Read the Static Address Table Entry 2 register
1241 
1242  //Retrieve the ports associated with this MAC address
1243  entry->srcPort = 0;
1245 
1246  //Check the value of the OVERRIDE bit
1248  {
1249  entry->override = TRUE;
1250  }
1251  else
1252  {
1253  entry->override = FALSE;
1254  }
1255 
1256  //Read the Static Address Table Entry 3 register
1258 
1259  //Copy MAC address (first 16 bits)
1260  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1261  entry->macAddr.b[1] = value & 0xFF;
1262 
1263  //Read the Static Address Table Entry 4 register
1265 
1266  //Copy MAC address (last 32 bits)
1267  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1268  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1269  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1270  entry->macAddr.b[5] = value & 0xFF;
1271 
1272  //Successful processing
1273  error = NO_ERROR;
1274  }
1275  else
1276  {
1277  //The entry is not valid
1278  error = ERROR_INVALID_ENTRY;
1279  }
1280  }
1281  else
1282  {
1283  //The end of the table has been reached
1284  error = ERROR_END_OF_TABLE;
1285  }
1286 
1287  //Return status code
1288  return error;
1289 }
1290 
1291 
1292 /**
1293  * @brief Flush static MAC table
1294  * @param[in] interface Underlying network interface
1295  **/
1296 
1298 {
1299  uint_t i;
1300  uint32_t value;
1301 
1302  //Loop through the static MAC table
1303  for(i = 0; i < KSZ9563_STATIC_MAC_TABLE_SIZE; i++)
1304  {
1305  //Clear Static Address Table Entry registers
1310 
1311  //Write the TABLE_INDEX field with the 4-bit index value
1313  //Set the TABLE_SELECT bit to 0 to select the static address table
1315  //Set the ACTION bit to 0 to indicate a write operation
1317  //Set the START_FINISH bit to 1 to initiate the operation
1319 
1320  //Start the write operation
1322  value);
1323 
1324  //When the operation is complete, the START_FINISH bit will be cleared
1325  //automatically
1326  do
1327  {
1328  //Read the Static Address and Reserved Multicast Table Control register
1329  value = ksz9563ReadSwitchReg32(interface,
1331 
1332  //Poll the START_FINISH bit
1334  }
1335 }
1336 
1337 
1338 /**
1339  * @brief Read an entry from the dynamic MAC table
1340  * @param[in] interface Underlying network interface
1341  * @param[in] index Zero-based index of the entry to read
1342  * @param[out] entry Pointer to the forwarding database entry
1343  * @return Error code
1344  **/
1345 
1347  SwitchFdbEntry *entry)
1348 {
1349  error_t error;
1350  uint32_t value;
1351 
1352  //First entry?
1353  if(index == 0)
1354  {
1355  //Clear the ALU Table Access Control register to stop any operation
1357 
1358  //Start the search operation
1362  }
1363 
1364  //Poll the VALID_ENTRY_OR_SEARCH_END bit until it is set
1365  do
1366  {
1367  //Read the ALU Table Access Control register
1369 
1370  //This bit goes high to indicate either a new valid entry is returned or
1371  //the search is complete
1373 
1374  //Check whether the next valid entry is ready
1375  if((value & KSZ9563_ALU_TABLE_CTRL_VALID) != 0)
1376  {
1377  //Store the data from the ALU table entry
1378  entry->destPorts = 0;
1379  entry->override = FALSE;
1380 
1381  //Read the ALU Table Entry 1 and 2 registers
1384 
1385  //Retrieve the port associated with this MAC address
1387  {
1389  entry->srcPort = KSZ9563_PORT1;
1390  break;
1392  entry->srcPort = KSZ9563_PORT2;
1393  break;
1395  entry->srcPort = KSZ9563_PORT3;
1396  break;
1397  default:
1398  entry->srcPort = 0;
1399  break;
1400  }
1401 
1402  //Read the ALU Table Entry 3 register
1404 
1405  //Copy MAC address (first 16 bits)
1406  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1407  entry->macAddr.b[1] = value & 0xFF;
1408 
1409  //Read the ALU Table Entry 4 register
1411 
1412  //Copy MAC address (last 32 bits)
1413  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1414  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1415  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1416  entry->macAddr.b[5] = value & 0xFF;
1417 
1418  //Successful processing
1419  error = NO_ERROR;
1420  }
1421  else
1422  {
1423  //The search can be stopped any time by setting the START_FINISH bit to 0
1425 
1426  //The end of the table has been reached
1427  error = ERROR_END_OF_TABLE;
1428  }
1429 
1430  //Return status code
1431  return error;
1432 }
1433 
1434 
1435 /**
1436  * @brief Flush dynamic MAC table
1437  * @param[in] interface Underlying network interface
1438  * @param[in] port Port number
1439  **/
1440 
1442 {
1443  uint_t temp;
1444  uint8_t state;
1445 
1446  //Flush only dynamic table entries
1451 
1452  //Valid port number?
1453  if(port >= KSZ9563_PORT1 && port <= KSZ9563_PORT3)
1454  {
1455  //Save the current state of the port
1457 
1458  //Turn off learning capability
1461 
1462  //All the entries associated with a port that has its learning capability
1463  //being turned off will be flushed
1467 
1468  //Restore the original state of the port
1470  }
1471  else
1472  {
1473  //Trigger a flush of the entire address lookup table
1477  }
1478 }
1479 
1480 
1481 /**
1482  * @brief Set forward ports for unknown multicast packets
1483  * @param[in] interface Underlying network interface
1484  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1485  * @param[in] forwardPorts Port map
1486  **/
1487 
1489  bool_t enable, uint32_t forwardPorts)
1490 {
1491  uint32_t temp;
1492 
1493  //Read Unknown Multicast Control register
1495 
1496  //Clear port map
1498 
1499  //Enable or disable forwarding of unknown multicast packets
1500  if(enable)
1501  {
1502  //Enable forwarding
1504 
1505  //Check whether unknown multicast packets should be forwarded to the CPU port
1506  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1507  {
1509  }
1510 
1511  //Select the desired forward ports
1512  temp |= forwardPorts & KSZ9563_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL;
1513  }
1514  else
1515  {
1516  //Disable forwarding
1518  }
1519 
1520  //Write the value back to Unknown Multicast Control register
1522 }
1523 
1524 
1525 /**
1526  * @brief Write PHY register
1527  * @param[in] interface Underlying network interface
1528  * @param[in] port Port number
1529  * @param[in] address PHY register address
1530  * @param[in] data Register value
1531  **/
1532 
1533 void ksz9563WritePhyReg(NetInterface *interface, uint8_t port,
1534  uint8_t address, uint16_t data)
1535 {
1536  uint16_t n;
1537 
1538  //SPI slave mode?
1539  if(interface->spiDriver != NULL)
1540  {
1541  //The SPI interface provides access to all PHY registers
1543  //Write the 16-bit value
1544  ksz9563WriteSwitchReg16(interface, n, data);
1545  }
1546  else if(interface->smiDriver != NULL)
1547  {
1548  //Write the specified PHY register
1549  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1550  }
1551  else
1552  {
1553  //Write the specified PHY register
1554  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1555  }
1556 }
1557 
1558 
1559 /**
1560  * @brief Read PHY register
1561  * @param[in] interface Underlying network interface
1562  * @param[in] port Port number
1563  * @param[in] address PHY register address
1564  * @return Register value
1565  **/
1566 
1567 uint16_t ksz9563ReadPhyReg(NetInterface *interface, uint8_t port,
1568  uint8_t address)
1569 {
1570  uint16_t n;
1571  uint16_t data;
1572 
1573  //SPI slave mode?
1574  if(interface->spiDriver != NULL)
1575  {
1576  //The SPI interface provides access to all PHY registers
1578  //Read the 16-bit value
1579  data = ksz9563ReadSwitchReg16(interface, n);
1580  }
1581  else if(interface->smiDriver != NULL)
1582  {
1583  //Read the specified PHY register
1584  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1585  }
1586  else
1587  {
1588  //Read the specified PHY register
1589  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1590  }
1591 
1592  //Return register value
1593  return data;
1594 }
1595 
1596 
1597 /**
1598  * @brief Dump PHY registers for debugging purpose
1599  * @param[in] interface Underlying network interface
1600  * @param[in] port Port number
1601  **/
1602 
1603 void ksz9563DumpPhyReg(NetInterface *interface, uint8_t port)
1604 {
1605  uint8_t i;
1606 
1607  //Loop through PHY registers
1608  for(i = 0; i < 32; i++)
1609  {
1610  //Display current PHY register
1611  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1612  ksz9563ReadPhyReg(interface, port, i));
1613  }
1614 
1615  //Terminate with a line feed
1616  TRACE_DEBUG("\r\n");
1617 }
1618 
1619 
1620 /**
1621  * @brief Write MMD register
1622  * @param[in] interface Underlying network interface
1623  * @param[in] port Port number
1624  * @param[in] devAddr Device address
1625  * @param[in] regAddr Register address
1626  * @param[in] data Register value
1627  **/
1628 
1629 void ksz9563WriteMmdReg(NetInterface *interface, uint8_t port,
1630  uint8_t devAddr, uint16_t regAddr, uint16_t data)
1631 {
1632  //Select register operation
1635 
1636  //Write MMD register address
1638 
1639  //Select data operation
1642 
1643  //Write the content of the MMD register
1645 }
1646 
1647 
1648 /**
1649  * @brief Read MMD register
1650  * @param[in] interface Underlying network interface
1651  * @param[in] port Port number
1652  * @param[in] devAddr Device address
1653  * @param[in] regAddr Register address
1654  * @return Register value
1655  **/
1656 
1657 uint16_t ksz9563ReadMmdReg(NetInterface *interface, uint8_t port,
1658  uint8_t devAddr, uint16_t regAddr)
1659 {
1660  //Select register operation
1663 
1664  //Write MMD register address
1666 
1667  //Select data operation
1670 
1671  //Read the content of the MMD register
1672  return ksz9563ReadPhyReg(interface, port, KSZ9563_MMDAADR);
1673 }
1674 
1675 
1676 /**
1677  * @brief Write switch register (8 bits)
1678  * @param[in] interface Underlying network interface
1679  * @param[in] address Switch register address
1680  * @param[in] data Register value
1681  **/
1682 
1683 void ksz9563WriteSwitchReg8(NetInterface *interface, uint16_t address,
1684  uint8_t data)
1685 {
1686  uint32_t command;
1687 
1688  //SPI slave mode?
1689  if(interface->spiDriver != NULL)
1690  {
1691  //Set up a write operation
1692  command = KSZ9563_SPI_CMD_WRITE;
1693  //Set register address
1694  command |= (address << 5) & KSZ9563_SPI_CMD_ADDR;
1695 
1696  //Pull the CS pin low
1697  interface->spiDriver->assertCs();
1698 
1699  //Write 32-bit command
1700  interface->spiDriver->transfer((command >> 24) & 0xFF);
1701  interface->spiDriver->transfer((command >> 16) & 0xFF);
1702  interface->spiDriver->transfer((command >> 8) & 0xFF);
1703  interface->spiDriver->transfer(command & 0xFF);
1704 
1705  //Write 8-bit data
1706  interface->spiDriver->transfer(data);
1707 
1708  //Terminate the operation by raising the CS pin
1709  interface->spiDriver->deassertCs();
1710  }
1711  else
1712  {
1713  //The MDC/MDIO interface does not have access to all the configuration
1714  //registers. It can only access the standard MIIM registers
1715  }
1716 }
1717 
1718 
1719 /**
1720  * @brief Read switch register (8 bits)
1721  * @param[in] interface Underlying network interface
1722  * @param[in] address Switch register address
1723  * @return Register value
1724  **/
1725 
1726 uint8_t ksz9563ReadSwitchReg8(NetInterface *interface, uint16_t address)
1727 {
1728  uint8_t data;
1729  uint32_t command;
1730 
1731  //SPI slave mode?
1732  if(interface->spiDriver != NULL)
1733  {
1734  //Set up a read operation
1735  command = KSZ9563_SPI_CMD_READ;
1736  //Set register address
1737  command |= (address << 5) & KSZ9563_SPI_CMD_ADDR;
1738 
1739  //Pull the CS pin low
1740  interface->spiDriver->assertCs();
1741 
1742  //Write 32-bit command
1743  interface->spiDriver->transfer((command >> 24) & 0xFF);
1744  interface->spiDriver->transfer((command >> 16) & 0xFF);
1745  interface->spiDriver->transfer((command >> 8) & 0xFF);
1746  interface->spiDriver->transfer(command & 0xFF);
1747 
1748  //Read 8-bit data
1749  data = interface->spiDriver->transfer(0xFF);
1750 
1751  //Terminate the operation by raising the CS pin
1752  interface->spiDriver->deassertCs();
1753  }
1754  else
1755  {
1756  //The MDC/MDIO interface does not have access to all the configuration
1757  //registers. It can only access the standard MIIM registers
1758  data = 0;
1759  }
1760 
1761  //Return register value
1762  return data;
1763 }
1764 
1765 
1766 /**
1767  * @brief Write switch register (16 bits)
1768  * @param[in] interface Underlying network interface
1769  * @param[in] address Switch register address
1770  * @param[in] data Register value
1771  **/
1772 
1774  uint16_t data)
1775 {
1776  uint32_t command;
1777 
1778  //SPI slave mode?
1779  if(interface->spiDriver != NULL)
1780  {
1781  //Set up a write operation
1782  command = KSZ9563_SPI_CMD_WRITE;
1783  //Set register address
1784  command |= (address << 5) & KSZ9563_SPI_CMD_ADDR;
1785 
1786  //Pull the CS pin low
1787  interface->spiDriver->assertCs();
1788 
1789  //Write 32-bit command
1790  interface->spiDriver->transfer((command >> 24) & 0xFF);
1791  interface->spiDriver->transfer((command >> 16) & 0xFF);
1792  interface->spiDriver->transfer((command >> 8) & 0xFF);
1793  interface->spiDriver->transfer(command & 0xFF);
1794 
1795  //Write 16-bit data
1796  interface->spiDriver->transfer((data >> 8) & 0xFF);
1797  interface->spiDriver->transfer(data & 0xFF);
1798 
1799  //Terminate the operation by raising the CS pin
1800  interface->spiDriver->deassertCs();
1801  }
1802  else
1803  {
1804  //The MDC/MDIO interface does not have access to all the configuration
1805  //registers. It can only access the standard MIIM registers
1806  }
1807 }
1808 
1809 
1810 /**
1811  * @brief Read switch register (16 bits)
1812  * @param[in] interface Underlying network interface
1813  * @param[in] address Switch register address
1814  * @return Register value
1815  **/
1816 
1817 uint16_t ksz9563ReadSwitchReg16(NetInterface *interface, uint16_t address)
1818 {
1819  uint16_t data;
1820  uint32_t command;
1821 
1822  //SPI slave mode?
1823  if(interface->spiDriver != NULL)
1824  {
1825  //Set up a read operation
1826  command = KSZ9563_SPI_CMD_READ;
1827  //Set register address
1828  command |= (address << 5) & KSZ9563_SPI_CMD_ADDR;
1829 
1830  //Pull the CS pin low
1831  interface->spiDriver->assertCs();
1832 
1833  //Write 32-bit command
1834  interface->spiDriver->transfer((command >> 24) & 0xFF);
1835  interface->spiDriver->transfer((command >> 16) & 0xFF);
1836  interface->spiDriver->transfer((command >> 8) & 0xFF);
1837  interface->spiDriver->transfer(command & 0xFF);
1838 
1839  //Read 16-bit data
1840  data = interface->spiDriver->transfer(0xFF) << 8;
1841  data |= interface->spiDriver->transfer(0xFF);
1842 
1843  //Terminate the operation by raising the CS pin
1844  interface->spiDriver->deassertCs();
1845  }
1846  else
1847  {
1848  //The MDC/MDIO interface does not have access to all the configuration
1849  //registers. It can only access the standard MIIM registers
1850  data = 0;
1851  }
1852 
1853  //Return register value
1854  return data;
1855 }
1856 
1857 
1858 /**
1859  * @brief Write switch register (32 bits)
1860  * @param[in] interface Underlying network interface
1861  * @param[in] address Switch register address
1862  * @param[in] data Register value
1863  **/
1864 
1866  uint32_t data)
1867 {
1868  uint32_t command;
1869 
1870  //SPI slave mode?
1871  if(interface->spiDriver != NULL)
1872  {
1873  //Set up a write operation
1874  command = KSZ9563_SPI_CMD_WRITE;
1875  //Set register address
1876  command |= (address << 5) & KSZ9563_SPI_CMD_ADDR;
1877 
1878  //Pull the CS pin low
1879  interface->spiDriver->assertCs();
1880 
1881  //Write 32-bit command
1882  interface->spiDriver->transfer((command >> 24) & 0xFF);
1883  interface->spiDriver->transfer((command >> 16) & 0xFF);
1884  interface->spiDriver->transfer((command >> 8) & 0xFF);
1885  interface->spiDriver->transfer(command & 0xFF);
1886 
1887  //Write 32-bit data
1888  interface->spiDriver->transfer((data >> 24) & 0xFF);
1889  interface->spiDriver->transfer((data >> 16) & 0xFF);
1890  interface->spiDriver->transfer((data >> 8) & 0xFF);
1891  interface->spiDriver->transfer(data & 0xFF);
1892 
1893  //Terminate the operation by raising the CS pin
1894  interface->spiDriver->deassertCs();
1895  }
1896  else
1897  {
1898  //The MDC/MDIO interface does not have access to all the configuration
1899  //registers. It can only access the standard MIIM registers
1900  }
1901 }
1902 
1903 
1904 /**
1905  * @brief Read switch register (32 bits)
1906  * @param[in] interface Underlying network interface
1907  * @param[in] address Switch register address
1908  * @return Register value
1909  **/
1910 
1911 uint32_t ksz9563ReadSwitchReg32(NetInterface *interface, uint16_t address)
1912 {
1913  uint32_t data;
1914  uint32_t command;
1915 
1916  //SPI slave mode?
1917  if(interface->spiDriver != NULL)
1918  {
1919  //Set up a read operation
1920  command = KSZ9563_SPI_CMD_READ;
1921  //Set register address
1922  command |= (address << 5) & KSZ9563_SPI_CMD_ADDR;
1923 
1924  //Pull the CS pin low
1925  interface->spiDriver->assertCs();
1926 
1927  //Write 32-bit command
1928  interface->spiDriver->transfer((command >> 24) & 0xFF);
1929  interface->spiDriver->transfer((command >> 16) & 0xFF);
1930  interface->spiDriver->transfer((command >> 8) & 0xFF);
1931  interface->spiDriver->transfer(command & 0xFF);
1932 
1933  //Read 32-bit data
1934  data = interface->spiDriver->transfer(0xFF) << 24;
1935  data |= interface->spiDriver->transfer(0xFF) << 16;
1936  data |= interface->spiDriver->transfer(0xFF) << 8;
1937  data |= interface->spiDriver->transfer(0xFF);
1938 
1939  //Terminate the operation by raising the CS pin
1940  interface->spiDriver->deassertCs();
1941  }
1942  else
1943  {
1944  //The MDC/MDIO interface does not have access to all the configuration
1945  //registers. It can only access the standard MIIM registers
1946  data = 0;
1947  }
1948 
1949  //Return register value
1950  return data;
1951 }
#define KSZ9563_SWITCH_LUE_CTRL0_AGE_COUNT_DEFAULT
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:601
#define KSZ9563_MMD_LED_MODE
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define KSZ9563_SWITCH_OP_START_SWITCH
const uint8_t ksz9563IngressTailTag[3]
Tail tag rules (host to KSZ9563)
KSZ9563 3-port Gigabit Ethernet switch driver.
#define KSZ9563_SWITCH_LUE_CTRL1_FLUSH_ALU_TABLE
#define KSZ9563_PHYCON_SPEED_1000BT
#define KSZ9563_BMSR_LINK_STATUS
#define KSZ9563_PHYCON_DUPLEX_STATUS
#define NetContext
Definition: net.h:36
int bool_t
Definition: compiler_port.h:63
void ksz9563EnableIrq(NetInterface *interface)
Enable interrupts.
@ ERROR_NOT_FOUND
Definition: error.h:148
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
uint32_t destPorts
Definition: nic.h:152
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
void ksz9563DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
#define KSZ9563_PORTn_XMII_CTRL1_RGMII_ID_IG
#define KSZ9563_ALU_TABLE_ENTRY1
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
#define KSZ9563_STATIC_MCAST_TABLE_CTRL_TABLE_SELECT
void ksz9563WriteSwitchReg32(NetInterface *interface, uint16_t address, uint32_t data)
Write switch register (32 bits)
#define KSZ9563_ALU_TABLE_CTRL_VALID
void ksz9563FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
#define KSZ9563_ALU_TABLE_ENTRY4
@ ERROR_END_OF_TABLE
Definition: error.h:292
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define KSZ9563_SWITCH_LUE_CTRL2
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
#define KSZ9563_PORT3_XMII_CTRL0
uint16_t ksz9563ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
#define KSZ9563_GLOBAL_PORT_MIRROR_SNOOP_CTRL_MLD_SNOOP_EN
#define KSZ9563_SWITCH_OP
#define KSZ9563_PHYCON_SPEED_10BT
uint8_t type
Definition: coap_common.h:176
#define KSZ9563_TAIL_TAG_NORMAL_ADDR_LOOKUP
#define KSZ9563_STATIC_MCAST_TABLE_CTRL
#define KSZ9563_ALU_TABLE_ENTRY2_PORT3_FORWARD
#define KSZ9563_PORTn_XMII_CTRL1_SPEED_1000
@ ERROR_INVALID_PORT
Definition: error.h:104
uint16_t ksz9563ReadMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr)
Read MMD register.
error_t ksz9563Init(NetInterface *interface)
KSZ9563 Ethernet switch initialization.
#define KSZ9563_PORTn_XMII_CTRL1_RGMII_ID_EG
@ ERROR_TABLE_FULL
Definition: error.h:291
#define KSZ9563_STATIC_TABLE_ENTRY3
EthHeader
Definition: ethernet.h:225
__weak_func void ksz9563InitHook(NetInterface *interface)
KSZ9563 custom configuration.
void ksz9563WriteSwitchReg8(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register (8 bits)
#define KSZ9563_PHYCON
void ksz9563SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
#define KSZ9563_SPI_CMD_ADDR
uint16_t ksz9563ReadSwitchReg16(NetInterface *interface, uint16_t address)
Read switch register (16 bits)
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define KSZ9563_PORTn_XMII_CTRL0_SPEED_10_100
#define KSZ9563_ALU_TABLE_CTRL_START_FINISH
#define KSZ9563_PORT3
#define KSZ9563_STATIC_MCAST_TABLE_CTRL_START_FINISH
#define KSZ9563_MMD_1000BT_EEE_WAKE_TX_TIMER
#define KSZ9563_STATIC_TABLE_ENTRY4
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
#define KSZ9563_SWITCH_LUE_CTRL1
#define KSZ9563_CHIP_ID1
#define FALSE
Definition: os_port.h:46
void ksz9563FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
#define KSZ9563_PORT3_MASK
error_t
Error codes.
Definition: error.h:43
__weak_func void ksz9563EventHandler(NetInterface *interface)
KSZ9563 event handler.
#define KSZ9563_MMDAADR
#define KSZ9563_UNKONWN_MULTICAST_CTRL
#define KSZ9563_GLOBAL_PORT_MIRROR_SNOOP_CTRL
#define KSZ9563_MMDACR
#define KSZ9563_STATIC_TABLE_ENTRY1
#define KSZ9563_PORTn_XMII_CTRL0_DUPLEX
#define KSZ9563_PORTn_XMII_CTRL1_IF_TYPE_RGMII
#define KSZ9563_PORTn_MSTP_STATE_LEARNING_DIS
void ksz9563EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
void ksz9563WriteSwitchReg16(NetInterface *interface, uint16_t address, uint16_t data)
Write switch register (16 bits)
#define KSZ9563_PORTn_ETH_PHY_REG(port, addr)
#define KSZ9563_ALU_TABLE_ENTRY2_PORT1_FORWARD
#define KSZ9563_PORT2
#define KSZ9563_MMDACR_FUNC_ADDR
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:40
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define KSZ9563_UNKONWN_MULTICAST_CTRL_FWD
#define KSZ9563_UNKONWN_MULTICAST_CTRL_FWD_MAP_PORT3
error_t ksz9563GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
void ksz9563WriteMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr, uint16_t data)
Write MMD register.
#define KSZ9563_TAIL_TAG_DEST_PORT2
#define KSZ9563_TAIL_TAG_SRC_PORT
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
#define KSZ9563_UNKONWN_MULTICAST_CTRL_FWD_MAP
error_t ksz9563AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
void ksz9563SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
#define NetTxAncillary
Definition: net_misc.h:36
#define KSZ9563_PORT3_XMII_CTRL1
bool_t ksz9563GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
void ksz9563DisableIrq(NetInterface *interface)
Disable interrupts.
__weak_func void ksz9563Tick(NetInterface *interface)
KSZ9563 timer handler.
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
#define KSZ9563_SWITCH_LUE_CTRL2_FLUSH_OPTION_DYNAMIC
#define TRACE_INFO(...)
Definition: debug.h:105
#define KSZ9563_MMDACR_DEVAD
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define KSZ9563_SPI_CMD_READ
#define KSZ9563_PORTn_MSTP_STATE_RECEIVE_EN
#define KSZ9563_ALU_TABLE_ENTRY2_PORT2_FORWARD
#define MIN(a, b)
Definition: os_port.h:63
void ksz9563EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
error_t ksz9563TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
#define KSZ9563_STATIC_TABLE_ENTRY1_VALID
SwitchPortState ksz9563GetPortState(NetInterface *interface, uint8_t port)
Get port state.
#define KSZ9563_STATIC_TABLE_ENTRY2_OVERRIDE
#define KSZ9563_SWITCH_LUE_CTRL1_FLUSH_MSTP_ENTRIES
uint32_t ksz9563GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
NicDuplexMode ksz9563GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
#define KSZ9563_PORT3_OP_CTRL0
uint16_t port
Definition: dns_common.h:270
#define KSZ9563_PORTn_OP_CTRL0_TAIL_TAG_EN
#define KSZ9563_PORTn_XMII_CTRL1_IF_TYPE
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define KSZ9563_MMDACR_FUNC_DATA_NO_POST_INC
#define KSZ9563_SWITCH_LUE_CTRL0_HASH_OPTION_CRC
void ksz9563EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
#define KSZ9563_STATIC_TABLE_ENTRY2_PORT_FORWARD
uint16_t regAddr
error_t ksz9563UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
#define KSZ9563_ALU_TABLE_ENTRY3
#define KSZ9563_SWITCH_LUE_CTRL0_RESERVED_MCAST_LOOKUP_EN
Ethernet switch driver.
Definition: nic.h:325
#define KSZ9563_PORTn_MSTP_STATE_TRANSMIT_EN
#define KSZ9563_STATIC_MCAST_TABLE_CTRL_TABLE_INDEX
#define KSZ9563_ALU_TABLE_ENTRY2_PORT_FORWARD
uint8_t n
#define KSZ9563_GLOBAL_PORT_MIRROR_SNOOP_CTRL_IGMP_SNOOP_EN
@ 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 KSZ9563_SWITCH_MAC_CTRL0
Ipv6Addr address[]
Definition: ipv6.h:345
#define KSZ9563_PORT_MASK
#define KSZ9563_PHYCON_SPEED_100BTX
NicDuplexMode
Duplex mode.
Definition: nic.h:122
MacAddr macAddr
Definition: nic.h:150
#define KSZ9563_STATIC_TABLE_ENTRY2
uint8_t srcPort
Definition: nic.h:151
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
#define KSZ9563_ALU_TABLE_CTRL_VALID_ENTRY_OR_SEARCH_END
#define KSZ9563_SWITCH_OP_SOFT_HARD_RESET
const SwitchDriver ksz9563SwitchDriver
KSZ9563 Ethernet switch driver.
#define KSZ9563_SWITCH_LUE_CTRL3_AGE_PERIOD_DEFAULT
#define KSZ9563_TAIL_TAG_DEST_PORT1
uint8_t value[]
Definition: tcp.h:376
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
#define KSZ9563_STATIC_MAC_TABLE_SIZE
#define KSZ9563_CHIP_ID1_DEFAULT
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define KSZ9563_STATIC_MCAST_TABLE_CTRL_ACTION
void ksz9563SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
uint8_t ksz9563ReadSwitchReg8(NetInterface *interface, uint16_t address)
Read switch register (8 bits)
#define KSZ9563_MMD_LED_MODE_RESERVED_DEFAULT
#define KSZ9563_SWITCH_MAC_CTRL0_FRAME_LEN_CHECK_EN
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
#define KSZ9563_SWITCH_LUE_CTRL3
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
error_t ksz9563GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
#define KSZ9563_BMSR
#define KSZ9563_MMD_LED_MODE_LED_MODE_TRI_COLOR_DUAL
#define KSZ9563_SPI_CMD_WRITE
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
error_t ksz9563DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
#define KSZ9563_TAIL_TAG_PORT_BLOCKING_OVERRIDE
#define KSZ9563_PORTn_MSTP_STATE(port)
#define KSZ9563_ALU_TABLE_ENTRY2
#define KSZ9563_SWITCH_LUE_CTRL0
void ksz9563WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
#define KSZ9563_ALU_TABLE_CTRL_ACTION_SEARCH
Helper functions for Ethernet.
uint32_t ksz9563ReadSwitchReg32(NetInterface *interface, uint16_t address)
Read switch register (32 bits)
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
Debugging facilities.
Forwarding database entry.
Definition: nic.h:149
#define KSZ9563_SWITCH_LUE_CTRL2_FLUSH_OPTION
#define KSZ9563_PORT1
#define KSZ9563_ALU_TABLE_CTRL
#define KSZ9563_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL