ksz9893_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz9893_driver.c
3  * @brief KSZ9893 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-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/ethernet_misc.h"
38 #include "debug.h"
39 
40 
41 /**
42  * @brief KSZ9893 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ9893)
75  **/
76 
77 const uint8_t ksz9893IngressTailTag[3] =
78 {
82 };
83 
84 
85 /**
86  * @brief KSZ9893 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 KSZ9893...\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 = ksz9893ReadSwitchReg8(interface, KSZ9893_CHIP_ID1);
110 
111  //The returned data is invalid until the serial interface is ready
112  } while(temp != KSZ9893_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 = ksz9893ReadSwitchReg8(interface, KSZ9893_SWITCH_OP);
123 
124  //The reset bit is self-clearing
125  } while((temp & KSZ9893_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 2)
201  0x0021);
202 
203  //Select tri-color dual-LED mode (silicon errata workaround 7)
207 
208  //Debug message
209  TRACE_DEBUG("Port %u:\r\n", port);
210  //Dump PHY registers for debugging purpose
211  ksz9893DumpPhyReg(interface, port);
212  }
213 
214  //Perform custom configuration
215  ksz9893InitHook(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
221 
222  //Successful initialization
223  return NO_ERROR;
224 }
225 
226 
227 /**
228  * @brief KSZ9893 custom configuration
229  * @param[in] interface Underlying network interface
230  **/
231 
232 __weak_func void ksz9893InitHook(NetInterface *interface)
233 {
234 }
235 
236 
237 /**
238  * @brief KSZ9893 timer handler
239  * @param[in] interface Underlying network interface
240  **/
241 
242 void ksz9893Tick(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  NetInterface *virtualInterface;
253 
254  //Loop through network interfaces
255  for(i = 0; i < NET_INTERFACE_COUNT; i++)
256  {
257  //Point to the current interface
258  virtualInterface = &netInterface[i];
259 
260  //Check whether the current virtual interface is attached to the
261  //physical interface
262  if(virtualInterface == interface ||
263  virtualInterface->parent == interface)
264  {
265  //Retrieve current link state
266  linkState = ksz9893GetLinkState(interface, virtualInterface->port);
267 
268  //Link up or link down event?
269  if(linkState != virtualInterface->linkState)
270  {
271  //Set event flag
272  interface->phyEvent = TRUE;
273  //Notify the TCP/IP stack of the event
275  }
276  }
277  }
278  }
279  else
280 #endif
281  {
282  //Initialize link state
283  linkState = FALSE;
284 
285  //Loop through the ports
287  {
288  //Retrieve current link state
289  if(ksz9893GetLinkState(interface, port))
290  {
291  linkState = TRUE;
292  }
293  }
294 
295  //Link up or link down event?
296  if(linkState != interface->linkState)
297  {
298  //Set event flag
299  interface->phyEvent = TRUE;
300  //Notify the TCP/IP stack of the event
302  }
303  }
304 }
305 
306 
307 /**
308  * @brief Enable interrupts
309  * @param[in] interface Underlying network interface
310  **/
311 
313 {
314 }
315 
316 
317 /**
318  * @brief Disable interrupts
319  * @param[in] interface Underlying network interface
320  **/
321 
323 {
324 }
325 
326 
327 /**
328  * @brief KSZ9893 event handler
329  * @param[in] interface Underlying network interface
330  **/
331 
333 {
334  uint_t port;
335  bool_t linkState;
336 
337 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
338  //Port separation mode?
339  if(interface->port != 0)
340  {
341  uint_t i;
342  NetInterface *virtualInterface;
343 
344  //Loop through network interfaces
345  for(i = 0; i < NET_INTERFACE_COUNT; i++)
346  {
347  //Point to the current interface
348  virtualInterface = &netInterface[i];
349 
350  //Check whether the current virtual interface is attached to the
351  //physical interface
352  if(virtualInterface == interface ||
353  virtualInterface->parent == interface)
354  {
355  //Get the port number associated with the current interface
356  port = virtualInterface->port;
357 
358  //Valid port?
359  if(port >= KSZ9893_PORT1 && port <= KSZ9893_PORT2)
360  {
361  //Retrieve current link state
362  linkState = ksz9893GetLinkState(interface, port);
363 
364  //Link up event?
365  if(linkState && !virtualInterface->linkState)
366  {
367  //Retrieve host interface speed
368  interface->linkSpeed = ksz9893GetLinkSpeed(interface,
369  KSZ9893_PORT3);
370 
371  //Retrieve host interface duplex mode
372  interface->duplexMode = ksz9893GetDuplexMode(interface,
373  KSZ9893_PORT3);
374 
375  //Adjust MAC configuration parameters for proper operation
376  interface->nicDriver->updateMacConfig(interface);
377 
378  //Check current speed
379  virtualInterface->linkSpeed = ksz9893GetLinkSpeed(interface,
380  port);
381 
382  //Check current duplex mode
383  virtualInterface->duplexMode = ksz9893GetDuplexMode(interface,
384  port);
385 
386  //Update link state
387  virtualInterface->linkState = TRUE;
388 
389  //Process link state change event
390  nicNotifyLinkChange(virtualInterface);
391  }
392  //Link down event
393  else if(!linkState && virtualInterface->linkState)
394  {
395  //Update link state
396  virtualInterface->linkState = FALSE;
397 
398  //Process link state change event
399  nicNotifyLinkChange(virtualInterface);
400  }
401  }
402  }
403  }
404  }
405  else
406 #endif
407  {
408  //Initialize link state
409  linkState = FALSE;
410 
411  //Loop through the ports
413  {
414  //Retrieve current link state
415  if(ksz9893GetLinkState(interface, port))
416  {
417  linkState = TRUE;
418  }
419  }
420 
421  //Link up event?
422  if(linkState)
423  {
424  //Retrieve host interface speed
425  interface->linkSpeed = ksz9893GetLinkSpeed(interface, KSZ9893_PORT3);
426  //Retrieve host interface duplex mode
427  interface->duplexMode = ksz9893GetDuplexMode(interface, KSZ9893_PORT3);
428 
429  //Adjust MAC configuration parameters for proper operation
430  interface->nicDriver->updateMacConfig(interface);
431 
432  //Update link state
433  interface->linkState = TRUE;
434  }
435  else
436  {
437  //Update link state
438  interface->linkState = FALSE;
439  }
440 
441  //Process link state change event
442  nicNotifyLinkChange(interface);
443  }
444 }
445 
446 
447 /**
448  * @brief Add tail tag to Ethernet frame
449  * @param[in] interface Underlying network interface
450  * @param[in] buffer Multi-part buffer containing the payload
451  * @param[in,out] offset Offset to the first payload byte
452  * @param[in] ancillary Additional options passed to the stack along with
453  * the packet
454  * @return Error code
455  **/
456 
458  size_t *offset, NetTxAncillary *ancillary)
459 {
460  error_t error;
461 
462  //Initialize status code
463  error = NO_ERROR;
464 
465 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
466  //SPI slave mode?
467  if(interface->spiDriver != NULL)
468  {
469  //Valid port?
470  if(ancillary->port <= KSZ9893_PORT2)
471  {
472  size_t length;
473  const uint8_t *tailTag;
474 
475  //The one byte tail tagging is used to indicate the destination port
476  tailTag = &ksz9893IngressTailTag[ancillary->port];
477 
478  //Retrieve the length of the Ethernet frame
479  length = netBufferGetLength(buffer) - *offset;
480 
481  //The host controller should manually add padding to the packet before
482  //inserting the tail tag
483  error = ethPadFrame(buffer, &length);
484 
485  //Check status code
486  if(!error)
487  {
488  //The tail tag is inserted at the end of the packet, just before
489  //the CRC
490  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
491  }
492  }
493  else
494  {
495  //The port number is not valid
496  error = ERROR_INVALID_PORT;
497  }
498  }
499 #endif
500 
501  //Return status code
502  return error;
503 }
504 
505 
506 /**
507  * @brief Decode tail tag from incoming Ethernet frame
508  * @param[in] interface Underlying network interface
509  * @param[in,out] frame Pointer to the received Ethernet frame
510  * @param[in,out] length Length of the frame, in bytes
511  * @param[in,out] ancillary Additional options passed to the stack along with
512  * the packet
513  * @return Error code
514  **/
515 
516 error_t ksz9893UntagFrame(NetInterface *interface, uint8_t **frame,
517  size_t *length, NetRxAncillary *ancillary)
518 {
519  error_t error;
520 
521  //Initialize status code
522  error = NO_ERROR;
523 
524 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
525  //SPI slave mode?
526  if(interface->spiDriver != NULL)
527  {
528  //Valid Ethernet frame received?
529  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
530  {
531  uint8_t *tailTag;
532 
533  //The tail tag is inserted at the end of the packet, just before
534  //the CRC
535  tailTag = *frame + *length - sizeof(uint8_t);
536 
537  //The one byte tail tagging is used to indicate the source port
538  ancillary->port = (*tailTag & KSZ9893_TAIL_TAG_SRC_PORT) + 1;
539 
540  //Strip tail tag from Ethernet frame
541  *length -= sizeof(uint8_t);
542  }
543  else
544  {
545  //Drop the received frame
546  error = ERROR_INVALID_LENGTH;
547  }
548  }
549  else
550  {
551  //Tail tagging mode cannot be enabled through MDC/MDIO interface
552  ancillary->port = 0;
553  }
554 #endif
555 
556  //Return status code
557  return error;
558 }
559 
560 
561 /**
562  * @brief Get link state
563  * @param[in] interface Underlying network interface
564  * @param[in] port Port number
565  * @return Link state
566  **/
567 
569 {
570  uint16_t value;
571  bool_t linkState;
572 
573  //Check port number
574  if(port >= KSZ9893_PORT1 && port <= KSZ9893_PORT2)
575  {
576  //Any link failure condition is latched in the BMSR register. Reading
577  //the register twice will always return the actual link status
578  value = ksz9893ReadPhyReg(interface, port, KSZ9893_BMSR);
579  value = ksz9893ReadPhyReg(interface, port, KSZ9893_BMSR);
580 
581  //Retrieve current link state
582  linkState = (value & KSZ9893_BMSR_LINK_STATUS) ? TRUE : FALSE;
583  }
584  else
585  {
586  //The specified port number is not valid
587  linkState = FALSE;
588  }
589 
590  //Return link status
591  return linkState;
592 }
593 
594 
595 /**
596  * @brief Get link speed
597  * @param[in] interface Underlying network interface
598  * @param[in] port Port number
599  * @return Link speed
600  **/
601 
602 uint32_t ksz9893GetLinkSpeed(NetInterface *interface, uint8_t port)
603 {
604  uint8_t type;
605  uint16_t value;
606  uint32_t linkSpeed;
607 
608  //Check port number
609  if(port >= KSZ9893_PORT1 && port <= KSZ9893_PORT2)
610  {
611  //Read PHY control register
613 
614  //Retrieve current link speed
616  {
617  //1000BASE-T
618  linkSpeed = NIC_LINK_SPEED_1GBPS;
619  }
620  else if((value & KSZ9893_PHYCON_SPEED_100BTX) != 0)
621  {
622  //100BASE-TX
623  linkSpeed = NIC_LINK_SPEED_100MBPS;
624  }
625  else if((value & KSZ9893_PHYCON_SPEED_10BT) != 0)
626  {
627  //10BASE-T
628  linkSpeed = NIC_LINK_SPEED_10MBPS;
629  }
630  else
631  {
632  //The link speed is not valid
633  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
634  }
635  }
636  else if(port == KSZ9893_PORT3)
637  {
638  //SPI slave mode?
639  if(interface->spiDriver != NULL)
640  {
641  //Read port 3 XMII control 1 register
643 
644  //Retrieve host interface type
646 
647  //Gigabit interface?
650  {
651  //1000 Mb/s mode
652  linkSpeed = NIC_LINK_SPEED_1GBPS;
653  }
654  else
655  {
656  //Read port 3 XMII control 0 register
658 
659  //Retrieve host interface speed
661  {
662  //100 Mb/s mode
663  linkSpeed = NIC_LINK_SPEED_100MBPS;
664  }
665  else
666  {
667  //10 Mb/s mode
668  linkSpeed = NIC_LINK_SPEED_10MBPS;
669  }
670  }
671  }
672  else
673  {
674  //The MDC/MDIO interface does not have access to all the configuration
675  //registers. It can only access the standard MIIM registers
676  linkSpeed = NIC_LINK_SPEED_100MBPS;
677  }
678  }
679  else
680  {
681  //The specified port number is not valid
682  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
683  }
684 
685  //Return link status
686  return linkSpeed;
687 }
688 
689 
690 /**
691  * @brief Get duplex mode
692  * @param[in] interface Underlying network interface
693  * @param[in] port Port number
694  * @return Duplex mode
695  **/
696 
698 {
699  uint16_t value;
700  NicDuplexMode duplexMode;
701 
702  //Check port number
703  if(port >= KSZ9893_PORT1 && port <= KSZ9893_PORT2)
704  {
705  //Read PHY control register
707 
708  //Retrieve current duplex mode
710  {
711  duplexMode = NIC_FULL_DUPLEX_MODE;
712  }
713  else
714  {
715  duplexMode = NIC_HALF_DUPLEX_MODE;
716  }
717  }
718  else if(port == KSZ9893_PORT3)
719  {
720  //SPI slave mode?
721  if(interface->spiDriver != NULL)
722  {
723  //Read port 3 XMII control 0 register
725 
726  //Retrieve host interface duplex mode
728  {
729  duplexMode = NIC_FULL_DUPLEX_MODE;
730  }
731  else
732  {
733  duplexMode = NIC_HALF_DUPLEX_MODE;
734  }
735  }
736  else
737  {
738  //The MDC/MDIO interface does not have access to all the configuration
739  //registers. It can only access the standard MIIM registers
740  duplexMode = NIC_FULL_DUPLEX_MODE;
741  }
742  }
743  else
744  {
745  //The specified port number is not valid
746  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
747  }
748 
749  //Return duplex mode
750  return duplexMode;
751 }
752 
753 
754 /**
755  * @brief Set port state
756  * @param[in] interface Underlying network interface
757  * @param[in] port Port number
758  * @param[in] state Port state
759  **/
760 
761 void ksz9893SetPortState(NetInterface *interface, uint8_t port,
762  SwitchPortState state)
763 {
764  uint8_t temp;
765 
766  //Check port number
767  if(port >= KSZ9893_PORT1 && port <= KSZ9893_PORT2)
768  {
769  //Read MSTP state register
771 
772  //Update port state
773  switch(state)
774  {
775  //Listening state
780  break;
781 
782  //Learning state
787  break;
788 
789  //Forwarding state
794  break;
795 
796  //Disabled state
797  default:
801  break;
802  }
803 
804  //Write the value back to MSTP state register
806  }
807 }
808 
809 
810 /**
811  * @brief Get port state
812  * @param[in] interface Underlying network interface
813  * @param[in] port Port number
814  * @return Port state
815  **/
816 
818 {
819  uint8_t temp;
820  SwitchPortState state;
821 
822  //Check port number
823  if(port >= KSZ9893_PORT1 && port <= KSZ9893_PORT2)
824  {
825  //Read MSTP state register
827 
828  //Check port state
829  if((temp & KSZ9893_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
830  (temp & KSZ9893_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
832  {
833  //Disabled state
835  }
836  else if((temp & KSZ9893_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
837  (temp & KSZ9893_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
839  {
840  //Listening state
842  }
843  else if((temp & KSZ9893_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
844  (temp & KSZ9893_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
846  {
847  //Learning state
849  }
850  else if((temp & KSZ9893_PORTn_MSTP_STATE_TRANSMIT_EN) != 0 &&
851  (temp & KSZ9893_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
853  {
854  //Forwarding state
856  }
857  else
858  {
859  //Unknown state
861  }
862  }
863  else
864  {
865  //The specified port number is not valid
867  }
868 
869  //Return port state
870  return state;
871 }
872 
873 
874 /**
875  * @brief Set aging time for dynamic filtering entries
876  * @param[in] interface Underlying network interface
877  * @param[in] agingTime Aging time, in seconds
878  **/
879 
880 void ksz9893SetAgingTime(NetInterface *interface, uint32_t agingTime)
881 {
882  //The Age Period in combination with the Age Count field determines the
883  //aging time of dynamic entries in the address lookup table
884  agingTime = (agingTime + 3) / 4;
885 
886  //Limit the range of the parameter
887  agingTime = MIN(agingTime, 255);
888 
889  //Write the value to Switch Lookup Engine Control 3 register
891  (uint8_t) agingTime);
892 }
893 
894 
895 /**
896  * @brief Enable IGMP snooping
897  * @param[in] interface Underlying network interface
898  * @param[in] enable Enable or disable IGMP snooping
899  **/
900 
902 {
903  uint8_t temp;
904 
905  //Read the Global Port Mirroring and Snooping Control register
906  temp = ksz9893ReadSwitchReg8(interface,
908 
909  //Enable or disable IGMP snooping
910  if(enable)
911  {
913  }
914  else
915  {
917  }
918 
919  //Write the value back to Global Port Mirroring and Snooping Control register
921  temp);
922 }
923 
924 
925 /**
926  * @brief Enable MLD snooping
927  * @param[in] interface Underlying network interface
928  * @param[in] enable Enable or disable MLD snooping
929  **/
930 
932 {
933  uint8_t temp;
934 
935  //Read the Global Port Mirroring and Snooping Control register
936  temp = ksz9893ReadSwitchReg8(interface,
938 
939  //Enable or disable MLD snooping
940  if(enable)
941  {
943  }
944  else
945  {
947  }
948 
949  //Write the value back to Global Port Mirroring and Snooping Control register
951  temp);
952 }
953 
954 
955 /**
956  * @brief Enable reserved multicast table
957  * @param[in] interface Underlying network interface
958  * @param[in] enable Enable or disable reserved group addresses
959  **/
960 
962 {
963  uint8_t temp;
964 
965  //Read the Switch Lookup Engine Control 0 register
967 
968  //Enable or disable the reserved multicast table
969  if(enable)
970  {
972  }
973  else
974  {
976  }
977 
978  //Write the value back to Switch Lookup Engine Control 0 register
980 }
981 
982 
983 /**
984  * @brief Add a new entry to the static MAC table
985  * @param[in] interface Underlying network interface
986  * @param[in] entry Pointer to the forwarding database entry
987  * @return Error code
988  **/
989 
991  const SwitchFdbEntry *entry)
992 {
993  error_t error;
994  uint_t i;
995  uint_t j;
996  uint32_t value;
997  SwitchFdbEntry currentEntry;
998 
999  //Keep track of the first free entry
1001 
1002  //Loop through the static MAC table
1003  for(i = 0; i < KSZ9893_STATIC_MAC_TABLE_SIZE; i++)
1004  {
1005  //Read current entry
1006  error = ksz9893GetStaticFdbEntry(interface, i, &currentEntry);
1007 
1008  //Valid entry?
1009  if(!error)
1010  {
1011  //Check whether the table already contains the specified MAC address
1012  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1013  {
1014  j = i;
1015  break;
1016  }
1017  }
1018  else
1019  {
1020  //Keep track of the first free entry
1022  {
1023  j = i;
1024  }
1025  }
1026  }
1027 
1028  //Any entry available?
1030  {
1031  //Write the Static Address Table Entry 1 register
1034 
1035  //Set the relevant forward ports
1036  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1037  {
1039  }
1040  else
1041  {
1042  value = entry->destPorts & KSZ9893_PORT_MASK;
1043  }
1044 
1045  //Enable overriding of port state
1046  if(entry->override)
1047  {
1049  }
1050 
1051  //Write the Static Address Table Entry 2 register
1053 
1054  //Copy MAC address (first 16 bits)
1055  value = (entry->macAddr.b[0] << 8) | entry->macAddr.b[1];
1056 
1057  //Write the Static Address Table Entry 3 register
1059 
1060  //Copy MAC address (last 32 bits)
1061  value = (entry->macAddr.b[2] << 24) | (entry->macAddr.b[3] << 16) |
1062  (entry->macAddr.b[4] << 8) | entry->macAddr.b[5];
1063 
1064  //Write the Static Address Table Entry 4 register
1066 
1067  //Write the TABLE_INDEX field with the 4-bit index value
1069  //Set the TABLE_SELECT bit to 0 to select the static address table
1071  //Set the ACTION bit to 0 to indicate a write operation
1073  //Set the START_FINISH bit to 1 to initiate the operation
1075 
1076  //Start the write operation
1078  value);
1079 
1080  //When the operation is complete, the START_FINISH bit will be cleared
1081  //automatically
1082  do
1083  {
1084  //Read the Static Address and Reserved Multicast Table Control register
1085  value = ksz9893ReadSwitchReg32(interface,
1087 
1088  //Poll the START_FINISH bit
1090 
1091  //Successful processing
1092  error = NO_ERROR;
1093  }
1094  else
1095  {
1096  //The static MAC table is full
1097  error = ERROR_TABLE_FULL;
1098  }
1099 
1100  //Return status code
1101  return error;
1102 }
1103 
1104 
1105 /**
1106  * @brief Remove an entry from the static MAC table
1107  * @param[in] interface Underlying network interface
1108  * @param[in] entry Forwarding database entry to remove from the table
1109  * @return Error code
1110  **/
1111 
1113  const SwitchFdbEntry *entry)
1114 {
1115  error_t error;
1116  uint_t j;
1117  uint32_t value;
1118  SwitchFdbEntry currentEntry;
1119 
1120  //Loop through the static MAC table
1121  for(j = 0; j < KSZ9893_STATIC_MAC_TABLE_SIZE; j++)
1122  {
1123  //Read current entry
1124  error = ksz9893GetStaticFdbEntry(interface, j, &currentEntry);
1125 
1126  //Valid entry?
1127  if(!error)
1128  {
1129  //Check whether the table contains the specified MAC address
1130  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1131  {
1132  break;
1133  }
1134  }
1135  }
1136 
1137  //Any matching entry?
1139  {
1140  //Clear Static Address Table Entry registers
1145 
1146  //Write the TABLE_INDEX field with the 4-bit index value
1148  //Set the TABLE_SELECT bit to 0 to select the static address table
1150  //Set the ACTION bit to 0 to indicate a write operation
1152  //Set the START_FINISH bit to 1 to initiate the operation
1154 
1155  //Start the write operation
1157  value);
1158 
1159  //When the operation is complete, the START_FINISH bit will be cleared
1160  //automatically
1161  do
1162  {
1163  //Read the Static Address and Reserved Multicast Table Control register
1164  value = ksz9893ReadSwitchReg32(interface,
1166 
1167  //Poll the START_FINISH bit
1169 
1170  //Successful processing
1171  error = NO_ERROR;
1172  }
1173  else
1174  {
1175  //The static MAC table does not contain the specified address
1176  error = ERROR_NOT_FOUND;
1177  }
1178 
1179  //Return status code
1180  return error;
1181 }
1182 
1183 
1184 /**
1185  * @brief Read an entry from the static MAC table
1186  * @param[in] interface Underlying network interface
1187  * @param[in] index Zero-based index of the entry to read
1188  * @param[out] entry Pointer to the forwarding database entry
1189  * @return Error code
1190  **/
1191 
1193  SwitchFdbEntry *entry)
1194 {
1195  error_t error;
1196  uint32_t value;
1197 
1198  //Check index parameter
1199  if(index < KSZ9893_STATIC_MAC_TABLE_SIZE)
1200  {
1201  //Write the TABLE_INDEX field with the 4-bit index value
1203  //Set the TABLE_SELECT bit to 0 to select the static address table
1205  //Set the ACTION bit to 1 to indicate a read operation
1207  //Set the START_FINISH bit to 1 to initiate the operation
1209 
1210  //Start the read operation
1212  value);
1213 
1214  //When the operation is complete, the START_FINISH bit will be cleared
1215  //automatically
1216  do
1217  {
1218  //Read the Static Address and Reserved Multicast Table Control register
1219  value = ksz9893ReadSwitchReg32(interface,
1221 
1222  //Poll the START_FINISH bit
1224 
1225  //Read the Static Address Table Entry 1 register
1227 
1228  //Valid entry?
1230  {
1231  //Read the Static Address Table Entry 2 register
1233 
1234  //Retrieve the ports associated with this MAC address
1235  entry->srcPort = 0;
1237 
1238  //Check the value of the OVERRIDE bit
1240  {
1241  entry->override = TRUE;
1242  }
1243  else
1244  {
1245  entry->override = FALSE;
1246  }
1247 
1248  //Read the Static Address Table Entry 3 register
1250 
1251  //Copy MAC address (first 16 bits)
1252  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1253  entry->macAddr.b[1] = value & 0xFF;
1254 
1255  //Read the Static Address Table Entry 4 register
1257 
1258  //Copy MAC address (last 32 bits)
1259  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1260  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1261  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1262  entry->macAddr.b[5] = value & 0xFF;
1263 
1264  //Successful processing
1265  error = NO_ERROR;
1266  }
1267  else
1268  {
1269  //The entry is not valid
1270  error = ERROR_INVALID_ENTRY;
1271  }
1272  }
1273  else
1274  {
1275  //The end of the table has been reached
1276  error = ERROR_END_OF_TABLE;
1277  }
1278 
1279  //Return status code
1280  return error;
1281 }
1282 
1283 
1284 /**
1285  * @brief Flush static MAC table
1286  * @param[in] interface Underlying network interface
1287  **/
1288 
1290 {
1291  uint_t i;
1292  uint32_t value;
1293 
1294  //Loop through the static MAC table
1295  for(i = 0; i < KSZ9893_STATIC_MAC_TABLE_SIZE; i++)
1296  {
1297  //Clear Static Address Table Entry registers
1302 
1303  //Write the TABLE_INDEX field with the 4-bit index value
1305  //Set the TABLE_SELECT bit to 0 to select the static address table
1307  //Set the ACTION bit to 0 to indicate a write operation
1309  //Set the START_FINISH bit to 1 to initiate the operation
1311 
1312  //Start the write operation
1314  value);
1315 
1316  //When the operation is complete, the START_FINISH bit will be cleared
1317  //automatically
1318  do
1319  {
1320  //Read the Static Address and Reserved Multicast Table Control register
1321  value = ksz9893ReadSwitchReg32(interface,
1323 
1324  //Poll the START_FINISH bit
1326  }
1327 }
1328 
1329 
1330 /**
1331  * @brief Read an entry from the dynamic MAC table
1332  * @param[in] interface Underlying network interface
1333  * @param[in] index Zero-based index of the entry to read
1334  * @param[out] entry Pointer to the forwarding database entry
1335  * @return Error code
1336  **/
1337 
1339  SwitchFdbEntry *entry)
1340 {
1341  error_t error;
1342  uint32_t value;
1343 
1344  //First entry?
1345  if(index == 0)
1346  {
1347  //Clear the ALU Table Access Control register to stop any operation
1349 
1350  //Start the search operation
1354  }
1355 
1356  //Poll the VALID_ENTRY_OR_SEARCH_END bit until it is set
1357  do
1358  {
1359  //Read the ALU Table Access Control register
1361 
1362  //This bit goes high to indicate either a new valid entry is returned or
1363  //the search is complete
1365 
1366  //Check whether the next valid entry is ready
1367  if((value & KSZ9893_ALU_TABLE_CTRL_VALID) != 0)
1368  {
1369  //Store the data from the ALU table entry
1370  entry->destPorts = 0;
1371  entry->override = FALSE;
1372 
1373  //Read the ALU Table Entry 1 and 2 registers
1376 
1377  //Retrieve the port associated with this MAC address
1379  {
1381  entry->srcPort = KSZ9893_PORT1;
1382  break;
1384  entry->srcPort = KSZ9893_PORT2;
1385  break;
1387  entry->srcPort = KSZ9893_PORT3;
1388  break;
1389  default:
1390  entry->srcPort = 0;
1391  break;
1392  }
1393 
1394  //Read the ALU Table Entry 3 register
1396 
1397  //Copy MAC address (first 16 bits)
1398  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1399  entry->macAddr.b[1] = value & 0xFF;
1400 
1401  //Read the ALU Table Entry 4 register
1403 
1404  //Copy MAC address (last 32 bits)
1405  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1406  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1407  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1408  entry->macAddr.b[5] = value & 0xFF;
1409 
1410  //Successful processing
1411  error = NO_ERROR;
1412  }
1413  else
1414  {
1415  //The search can be stopped any time by setting the START_FINISH bit to 0
1417 
1418  //The end of the table has been reached
1419  error = ERROR_END_OF_TABLE;
1420  }
1421 
1422  //Return status code
1423  return error;
1424 }
1425 
1426 
1427 /**
1428  * @brief Flush dynamic MAC table
1429  * @param[in] interface Underlying network interface
1430  * @param[in] port Port number
1431  **/
1432 
1434 {
1435  uint_t temp;
1436  uint8_t state;
1437 
1438  //Flush only dynamic table entries
1443 
1444  //Valid port number?
1445  if(port >= KSZ9893_PORT1 && port <= KSZ9893_PORT3)
1446  {
1447  //Save the current state of the port
1449 
1450  //Turn off learning capability
1453 
1454  //All the entries associated with a port that has its learning capability
1455  //being turned off will be flushed
1459 
1460  //Restore the original state of the port
1462  }
1463  else
1464  {
1465  //Trigger a flush of the entire address lookup table
1469  }
1470 }
1471 
1472 
1473 /**
1474  * @brief Set forward ports for unknown multicast packets
1475  * @param[in] interface Underlying network interface
1476  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1477  * @param[in] forwardPorts Port map
1478  **/
1479 
1481  bool_t enable, uint32_t forwardPorts)
1482 {
1483  uint32_t temp;
1484 
1485  //Read Unknown Multicast Control register
1487 
1488  //Clear port map
1490 
1491  //Enable or disable forwarding of unknown multicast packets
1492  if(enable)
1493  {
1494  //Enable forwarding
1496 
1497  //Check whether unknown multicast packets should be forwarded to the CPU port
1498  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1499  {
1501  }
1502 
1503  //Select the desired forward ports
1504  temp |= forwardPorts & KSZ9893_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL;
1505  }
1506  else
1507  {
1508  //Disable forwarding
1510  }
1511 
1512  //Write the value back to Unknown Multicast Control register
1514 }
1515 
1516 
1517 /**
1518  * @brief Write PHY register
1519  * @param[in] interface Underlying network interface
1520  * @param[in] port Port number
1521  * @param[in] address PHY register address
1522  * @param[in] data Register value
1523  **/
1524 
1525 void ksz9893WritePhyReg(NetInterface *interface, uint8_t port,
1526  uint8_t address, uint16_t data)
1527 {
1528  uint16_t n;
1529 
1530  //SPI slave mode?
1531  if(interface->spiDriver != NULL)
1532  {
1533  //The SPI interface provides access to all PHY registers
1535  //Write the 16-bit value
1536  ksz9893WriteSwitchReg16(interface, n, data);
1537  }
1538  else if(interface->smiDriver != NULL)
1539  {
1540  //Write the specified PHY register
1541  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1542  }
1543  else
1544  {
1545  //Write the specified PHY register
1546  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1547  }
1548 }
1549 
1550 
1551 /**
1552  * @brief Read PHY register
1553  * @param[in] interface Underlying network interface
1554  * @param[in] port Port number
1555  * @param[in] address PHY register address
1556  * @return Register value
1557  **/
1558 
1559 uint16_t ksz9893ReadPhyReg(NetInterface *interface, uint8_t port,
1560  uint8_t address)
1561 {
1562  uint16_t n;
1563  uint16_t data;
1564 
1565  //SPI slave mode?
1566  if(interface->spiDriver != NULL)
1567  {
1568  //The SPI interface provides access to all PHY registers
1570  //Read the 16-bit value
1571  data = ksz9893ReadSwitchReg16(interface, n);
1572  }
1573  else if(interface->smiDriver != NULL)
1574  {
1575  //Read the specified PHY register
1576  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1577  }
1578  else
1579  {
1580  //Read the specified PHY register
1581  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1582  }
1583 
1584  //Return register value
1585  return data;
1586 }
1587 
1588 
1589 /**
1590  * @brief Dump PHY registers for debugging purpose
1591  * @param[in] interface Underlying network interface
1592  * @param[in] port Port number
1593  **/
1594 
1595 void ksz9893DumpPhyReg(NetInterface *interface, uint8_t port)
1596 {
1597  uint8_t i;
1598 
1599  //Loop through PHY registers
1600  for(i = 0; i < 32; i++)
1601  {
1602  //Display current PHY register
1603  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1604  ksz9893ReadPhyReg(interface, port, i));
1605  }
1606 
1607  //Terminate with a line feed
1608  TRACE_DEBUG("\r\n");
1609 }
1610 
1611 
1612 /**
1613  * @brief Write MMD register
1614  * @param[in] interface Underlying network interface
1615  * @param[in] port Port number
1616  * @param[in] devAddr Device address
1617  * @param[in] regAddr Register address
1618  * @param[in] data Register value
1619  **/
1620 
1621 void ksz9893WriteMmdReg(NetInterface *interface, uint8_t port,
1622  uint8_t devAddr, uint16_t regAddr, uint16_t data)
1623 {
1624  //Select register operation
1627 
1628  //Write MMD register address
1630 
1631  //Select data operation
1634 
1635  //Write the content of the MMD register
1637 }
1638 
1639 
1640 /**
1641  * @brief Read MMD register
1642  * @param[in] interface Underlying network interface
1643  * @param[in] port Port number
1644  * @param[in] devAddr Device address
1645  * @param[in] regAddr Register address
1646  * @return Register value
1647  **/
1648 
1649 uint16_t ksz9893ReadMmdReg(NetInterface *interface, uint8_t port,
1650  uint8_t devAddr, uint16_t regAddr)
1651 {
1652  //Select register operation
1655 
1656  //Write MMD register address
1658 
1659  //Select data operation
1662 
1663  //Read the content of the MMD register
1664  return ksz9893ReadPhyReg(interface, port, KSZ9893_MMDAADR);
1665 }
1666 
1667 
1668 /**
1669  * @brief Write switch register (8 bits)
1670  * @param[in] interface Underlying network interface
1671  * @param[in] address Switch register address
1672  * @param[in] data Register value
1673  **/
1674 
1675 void ksz9893WriteSwitchReg8(NetInterface *interface, uint16_t address,
1676  uint8_t data)
1677 {
1678  uint32_t command;
1679 
1680  //SPI slave mode?
1681  if(interface->spiDriver != NULL)
1682  {
1683  //Set up a write operation
1684  command = KSZ9893_SPI_CMD_WRITE;
1685  //Set register address
1686  command |= (address << 5) & KSZ9893_SPI_CMD_ADDR;
1687 
1688  //Pull the CS pin low
1689  interface->spiDriver->assertCs();
1690 
1691  //Write 32-bit command
1692  interface->spiDriver->transfer((command >> 24) & 0xFF);
1693  interface->spiDriver->transfer((command >> 16) & 0xFF);
1694  interface->spiDriver->transfer((command >> 8) & 0xFF);
1695  interface->spiDriver->transfer(command & 0xFF);
1696 
1697  //Write 8-bit data
1698  interface->spiDriver->transfer(data);
1699 
1700  //Terminate the operation by raising the CS pin
1701  interface->spiDriver->deassertCs();
1702  }
1703  else
1704  {
1705  //The MDC/MDIO interface does not have access to all the configuration
1706  //registers. It can only access the standard MIIM registers
1707  }
1708 }
1709 
1710 
1711 /**
1712  * @brief Read switch register (8 bits)
1713  * @param[in] interface Underlying network interface
1714  * @param[in] address Switch register address
1715  * @return Register value
1716  **/
1717 
1718 uint8_t ksz9893ReadSwitchReg8(NetInterface *interface, uint16_t address)
1719 {
1720  uint8_t data;
1721  uint32_t command;
1722 
1723  //SPI slave mode?
1724  if(interface->spiDriver != NULL)
1725  {
1726  //Set up a read operation
1727  command = KSZ9893_SPI_CMD_READ;
1728  //Set register address
1729  command |= (address << 5) & KSZ9893_SPI_CMD_ADDR;
1730 
1731  //Pull the CS pin low
1732  interface->spiDriver->assertCs();
1733 
1734  //Write 32-bit command
1735  interface->spiDriver->transfer((command >> 24) & 0xFF);
1736  interface->spiDriver->transfer((command >> 16) & 0xFF);
1737  interface->spiDriver->transfer((command >> 8) & 0xFF);
1738  interface->spiDriver->transfer(command & 0xFF);
1739 
1740  //Read 8-bit data
1741  data = interface->spiDriver->transfer(0xFF);
1742 
1743  //Terminate the operation by raising the CS pin
1744  interface->spiDriver->deassertCs();
1745  }
1746  else
1747  {
1748  //The MDC/MDIO interface does not have access to all the configuration
1749  //registers. It can only access the standard MIIM registers
1750  data = 0;
1751  }
1752 
1753  //Return register value
1754  return data;
1755 }
1756 
1757 
1758 /**
1759  * @brief Write switch register (16 bits)
1760  * @param[in] interface Underlying network interface
1761  * @param[in] address Switch register address
1762  * @param[in] data Register value
1763  **/
1764 
1766  uint16_t data)
1767 {
1768  uint32_t command;
1769 
1770  //SPI slave mode?
1771  if(interface->spiDriver != NULL)
1772  {
1773  //Set up a write operation
1774  command = KSZ9893_SPI_CMD_WRITE;
1775  //Set register address
1776  command |= (address << 5) & KSZ9893_SPI_CMD_ADDR;
1777 
1778  //Pull the CS pin low
1779  interface->spiDriver->assertCs();
1780 
1781  //Write 32-bit command
1782  interface->spiDriver->transfer((command >> 24) & 0xFF);
1783  interface->spiDriver->transfer((command >> 16) & 0xFF);
1784  interface->spiDriver->transfer((command >> 8) & 0xFF);
1785  interface->spiDriver->transfer(command & 0xFF);
1786 
1787  //Write 16-bit data
1788  interface->spiDriver->transfer((data >> 8) & 0xFF);
1789  interface->spiDriver->transfer(data & 0xFF);
1790 
1791  //Terminate the operation by raising the CS pin
1792  interface->spiDriver->deassertCs();
1793  }
1794  else
1795  {
1796  //The MDC/MDIO interface does not have access to all the configuration
1797  //registers. It can only access the standard MIIM registers
1798  }
1799 }
1800 
1801 
1802 /**
1803  * @brief Read switch register (16 bits)
1804  * @param[in] interface Underlying network interface
1805  * @param[in] address Switch register address
1806  * @return Register value
1807  **/
1808 
1809 uint16_t ksz9893ReadSwitchReg16(NetInterface *interface, uint16_t address)
1810 {
1811  uint16_t data;
1812  uint32_t command;
1813 
1814  //SPI slave mode?
1815  if(interface->spiDriver != NULL)
1816  {
1817  //Set up a read operation
1818  command = KSZ9893_SPI_CMD_READ;
1819  //Set register address
1820  command |= (address << 5) & KSZ9893_SPI_CMD_ADDR;
1821 
1822  //Pull the CS pin low
1823  interface->spiDriver->assertCs();
1824 
1825  //Write 32-bit command
1826  interface->spiDriver->transfer((command >> 24) & 0xFF);
1827  interface->spiDriver->transfer((command >> 16) & 0xFF);
1828  interface->spiDriver->transfer((command >> 8) & 0xFF);
1829  interface->spiDriver->transfer(command & 0xFF);
1830 
1831  //Read 16-bit data
1832  data = interface->spiDriver->transfer(0xFF) << 8;
1833  data |= interface->spiDriver->transfer(0xFF);
1834 
1835  //Terminate the operation by raising the CS pin
1836  interface->spiDriver->deassertCs();
1837  }
1838  else
1839  {
1840  //The MDC/MDIO interface does not have access to all the configuration
1841  //registers. It can only access the standard MIIM registers
1842  data = 0;
1843  }
1844 
1845  //Return register value
1846  return data;
1847 }
1848 
1849 
1850 /**
1851  * @brief Write switch register (32 bits)
1852  * @param[in] interface Underlying network interface
1853  * @param[in] address Switch register address
1854  * @param[in] data Register value
1855  **/
1856 
1858  uint32_t data)
1859 {
1860  uint32_t command;
1861 
1862  //SPI slave mode?
1863  if(interface->spiDriver != NULL)
1864  {
1865  //Set up a write operation
1866  command = KSZ9893_SPI_CMD_WRITE;
1867  //Set register address
1868  command |= (address << 5) & KSZ9893_SPI_CMD_ADDR;
1869 
1870  //Pull the CS pin low
1871  interface->spiDriver->assertCs();
1872 
1873  //Write 32-bit command
1874  interface->spiDriver->transfer((command >> 24) & 0xFF);
1875  interface->spiDriver->transfer((command >> 16) & 0xFF);
1876  interface->spiDriver->transfer((command >> 8) & 0xFF);
1877  interface->spiDriver->transfer(command & 0xFF);
1878 
1879  //Write 32-bit data
1880  interface->spiDriver->transfer((data >> 24) & 0xFF);
1881  interface->spiDriver->transfer((data >> 16) & 0xFF);
1882  interface->spiDriver->transfer((data >> 8) & 0xFF);
1883  interface->spiDriver->transfer(data & 0xFF);
1884 
1885  //Terminate the operation by raising the CS pin
1886  interface->spiDriver->deassertCs();
1887  }
1888  else
1889  {
1890  //The MDC/MDIO interface does not have access to all the configuration
1891  //registers. It can only access the standard MIIM registers
1892  }
1893 }
1894 
1895 
1896 /**
1897  * @brief Read switch register (32 bits)
1898  * @param[in] interface Underlying network interface
1899  * @param[in] address Switch register address
1900  * @return Register value
1901  **/
1902 
1903 uint32_t ksz9893ReadSwitchReg32(NetInterface *interface, uint16_t address)
1904 {
1905  uint32_t data;
1906  uint32_t command;
1907 
1908  //SPI slave mode?
1909  if(interface->spiDriver != NULL)
1910  {
1911  //Set up a read operation
1912  command = KSZ9893_SPI_CMD_READ;
1913  //Set register address
1914  command |= (address << 5) & KSZ9893_SPI_CMD_ADDR;
1915 
1916  //Pull the CS pin low
1917  interface->spiDriver->assertCs();
1918 
1919  //Write 32-bit command
1920  interface->spiDriver->transfer((command >> 24) & 0xFF);
1921  interface->spiDriver->transfer((command >> 16) & 0xFF);
1922  interface->spiDriver->transfer((command >> 8) & 0xFF);
1923  interface->spiDriver->transfer(command & 0xFF);
1924 
1925  //Read 32-bit data
1926  data = interface->spiDriver->transfer(0xFF) << 24;
1927  data |= interface->spiDriver->transfer(0xFF) << 16;
1928  data |= interface->spiDriver->transfer(0xFF) << 8;
1929  data |= interface->spiDriver->transfer(0xFF);
1930 
1931  //Terminate the operation by raising the CS pin
1932  interface->spiDriver->deassertCs();
1933  }
1934  else
1935  {
1936  //The MDC/MDIO interface does not have access to all the configuration
1937  //registers. It can only access the standard MIIM registers
1938  data = 0;
1939  }
1940 
1941  //Return register value
1942  return data;
1943 }
uint8_t type
Definition: coap_common.h:176
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint16_t port
Definition: dns_common.h:267
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_NOT_FOUND
Definition: error.h:147
@ ERROR_END_OF_TABLE
Definition: error.h:290
@ ERROR_INVALID_ENTRY
Definition: error.h:288
@ ERROR_TABLE_FULL
Definition: error.h:289
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint8_t data[]
Definition: ethernet.h:222
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
EthHeader
Definition: ethernet.h:223
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
Helper functions for Ethernet.
Ipv6Addr address[]
Definition: ipv6.h:316
void ksz9893EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
void ksz9893EnableIrq(NetInterface *interface)
Enable interrupts.
NicDuplexMode ksz9893GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
void ksz9893FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
__weak_func void ksz9893InitHook(NetInterface *interface)
KSZ9893 custom configuration.
void ksz9893SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
void ksz9893Tick(NetInterface *interface)
KSZ9893 timer handler.
void ksz9893WriteSwitchReg16(NetInterface *interface, uint16_t address, uint16_t data)
Write switch register (16 bits)
void ksz9893WriteMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr, uint16_t data)
Write MMD register.
uint16_t ksz9893ReadMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr)
Read MMD register.
error_t ksz9893AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
bool_t ksz9893GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
void ksz9893SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
SwitchPortState ksz9893GetPortState(NetInterface *interface, uint8_t port)
Get port state.
void ksz9893WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
error_t ksz9893Init(NetInterface *interface)
KSZ9893 Ethernet switch initialization.
void ksz9893WriteSwitchReg8(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register (8 bits)
void ksz9893DisableIrq(NetInterface *interface)
Disable interrupts.
void ksz9893EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
uint16_t ksz9893ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
uint32_t ksz9893ReadSwitchReg32(NetInterface *interface, uint16_t address)
Read switch register (32 bits)
const SwitchDriver ksz9893SwitchDriver
KSZ9893 Ethernet switch driver.
void ksz9893WriteSwitchReg32(NetInterface *interface, uint16_t address, uint32_t data)
Write switch register (32 bits)
uint16_t ksz9893ReadSwitchReg16(NetInterface *interface, uint16_t address)
Read switch register (16 bits)
void ksz9893FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
error_t ksz9893GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
error_t ksz9893TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
uint8_t ksz9893ReadSwitchReg8(NetInterface *interface, uint16_t address)
Read switch register (8 bits)
void ksz9893EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
const uint8_t ksz9893IngressTailTag[3]
Tail tag rules (host to KSZ9893)
void ksz9893SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
void ksz9893DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
error_t ksz9893DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
uint32_t ksz9893GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
error_t ksz9893GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
void ksz9893EventHandler(NetInterface *interface)
KSZ9893 event handler.
error_t ksz9893UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
KSZ9893 3-port Gigabit Ethernet switch driver.
#define KSZ9893_ALU_TABLE_CTRL_ACTION_SEARCH
#define KSZ9893_PHYCON_SPEED_1000BT
#define KSZ9893_PORT3_XMII_CTRL1
#define KSZ9893_BMSR_LINK_STATUS
#define KSZ9893_BMSR
#define KSZ9893_PORT3_MASK
#define KSZ9893_SWITCH_OP_START_SWITCH
#define KSZ9893_UNKONWN_MULTICAST_CTRL
#define KSZ9893_SWITCH_OP_SOFT_HARD_RESET
#define KSZ9893_UNKONWN_MULTICAST_CTRL_FWD_MAP
#define KSZ9893_GLOBAL_PORT_MIRROR_SNOOP_CTRL_IGMP_SNOOP_EN
#define KSZ9893_MMD_LED_MODE_LED_MODE_TRI_COLOR_DUAL
#define KSZ9893_STATIC_MCAST_TABLE_CTRL_TABLE_INDEX
#define KSZ9893_PORT2
#define KSZ9893_GLOBAL_PORT_MIRROR_SNOOP_CTRL_MLD_SNOOP_EN
#define KSZ9893_UNKONWN_MULTICAST_CTRL_FWD_MAP_PORT3
#define KSZ9893_PORT3_OP_CTRL0
#define KSZ9893_STATIC_TABLE_ENTRY3
#define KSZ9893_MMDAADR
#define KSZ9893_PHYCON_SPEED_10BT
#define KSZ9893_SWITCH_LUE_CTRL3
#define KSZ9893_STATIC_TABLE_ENTRY2_OVERRIDE
#define KSZ9893_TAIL_TAG_NORMAL_ADDR_LOOKUP
#define KSZ9893_SWITCH_LUE_CTRL1
#define KSZ9893_MMD_LED_MODE
#define KSZ9893_SWITCH_LUE_CTRL0_AGE_COUNT_DEFAULT
#define KSZ9893_TAIL_TAG_DEST_PORT1
#define KSZ9893_PORTn_XMII_CTRL1_SPEED_1000
#define KSZ9893_PORT1
#define KSZ9893_SWITCH_MAC_CTRL0
#define KSZ9893_TAIL_TAG_DEST_PORT2
#define KSZ9893_PORT3_XMII_CTRL0
#define KSZ9893_SWITCH_LUE_CTRL1_FLUSH_ALU_TABLE
#define KSZ9893_ALU_TABLE_ENTRY2
#define KSZ9893_SWITCH_LUE_CTRL2_FLUSH_OPTION
#define KSZ9893_MMD_1000BT_EEE_WAKE_TX_TIMER
#define KSZ9893_MMDACR_DEVAD
#define KSZ9893_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL
#define KSZ9893_SPI_CMD_WRITE
#define KSZ9893_MMDACR_FUNC_DATA_NO_POST_INC
#define KSZ9893_PHYCON
#define KSZ9893_STATIC_TABLE_ENTRY2
#define KSZ9893_ALU_TABLE_CTRL_VALID_ENTRY_OR_SEARCH_END
#define KSZ9893_PORTn_MSTP_STATE(port)
#define KSZ9893_STATIC_TABLE_ENTRY1_VALID
#define KSZ9893_STATIC_TABLE_ENTRY2_PORT_FORWARD
#define KSZ9893_STATIC_TABLE_ENTRY4
#define KSZ9893_PORTn_MSTP_STATE_LEARNING_DIS
#define KSZ9893_MMDACR
#define KSZ9893_STATIC_MCAST_TABLE_CTRL
#define KSZ9893_ALU_TABLE_ENTRY2_PORT1_FORWARD
#define KSZ9893_UNKONWN_MULTICAST_CTRL_FWD
#define KSZ9893_PORT3
#define KSZ9893_TAIL_TAG_SRC_PORT
#define KSZ9893_SWITCH_LUE_CTRL3_AGE_PERIOD_DEFAULT
#define KSZ9893_PORTn_MSTP_STATE_TRANSMIT_EN
#define KSZ9893_PORTn_XMII_CTRL1_RGMII_ID_EG
#define KSZ9893_PHYCON_DUPLEX_STATUS
#define KSZ9893_SPI_CMD_READ
#define KSZ9893_STATIC_MCAST_TABLE_CTRL_TABLE_SELECT
#define KSZ9893_PORTn_XMII_CTRL1_RGMII_ID_IG
#define KSZ9893_SWITCH_MAC_CTRL0_FRAME_LEN_CHECK_EN
#define KSZ9893_STATIC_MCAST_TABLE_CTRL_ACTION
#define KSZ9893_TAIL_TAG_PORT_BLOCKING_OVERRIDE
#define KSZ9893_STATIC_MCAST_TABLE_CTRL_START_FINISH
#define KSZ9893_PORTn_XMII_CTRL0_DUPLEX
#define KSZ9893_MMDACR_FUNC_ADDR
#define KSZ9893_ALU_TABLE_ENTRY2_PORT3_FORWARD
#define KSZ9893_SWITCH_OP
#define KSZ9893_SWITCH_LUE_CTRL2
#define KSZ9893_ALU_TABLE_ENTRY4
#define KSZ9893_PORTn_XMII_CTRL1_IF_TYPE_RGMII
#define KSZ9893_PORTn_XMII_CTRL0_SPEED_10_100
#define KSZ9893_GLOBAL_PORT_MIRROR_SNOOP_CTRL
#define KSZ9893_ALU_TABLE_CTRL
#define KSZ9893_CHIP_ID1_DEFAULT
#define KSZ9893_PORTn_XMII_CTRL1_IF_TYPE
#define KSZ9893_SWITCH_LUE_CTRL0_RESERVED_MCAST_LOOKUP_EN
#define KSZ9893_ALU_TABLE_ENTRY3
#define KSZ9893_ALU_TABLE_CTRL_VALID
#define KSZ9893_PORTn_MSTP_STATE_RECEIVE_EN
#define KSZ9893_PHYCON_SPEED_100BTX
#define KSZ9893_ALU_TABLE_ENTRY2_PORT_FORWARD
#define KSZ9893_PORTn_OP_CTRL0_TAIL_TAG_EN
#define KSZ9893_SWITCH_LUE_CTRL0_HASH_OPTION_CRC
#define KSZ9893_MMD_LED_MODE_RESERVED_DEFAULT
#define KSZ9893_STATIC_MAC_TABLE_SIZE
#define KSZ9893_ALU_TABLE_ENTRY2_PORT2_FORWARD
#define KSZ9893_SWITCH_LUE_CTRL2_FLUSH_OPTION_DYNAMIC
#define KSZ9893_SPI_CMD_ADDR
#define KSZ9893_SWITCH_LUE_CTRL1_FLUSH_MSTP_ENTRIES
#define KSZ9893_STATIC_TABLE_ENTRY1
#define KSZ9893_PORT_MASK
#define KSZ9893_ALU_TABLE_ENTRY1
#define KSZ9893_ALU_TABLE_CTRL_START_FINISH
#define KSZ9893_CHIP_ID1
#define KSZ9893_SWITCH_LUE_CTRL0
#define KSZ9893_PORTn_ETH_PHY_REG(port, addr)
uint16_t regAddr
TCP/IP stack core.
#define NET_INTERFACE_COUNT
Definition: net.h:113
#define NetInterface
Definition: net.h:36
#define netInterface
Definition: net_legacy.h:199
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:588
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:548
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define SMI_OPCODE_READ
Definition: nic.h:67
NicDuplexMode
Duplex mode.
Definition: nic.h:122
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
SwitchPortState
Switch port state.
Definition: nic.h:134
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
Ethernet switch driver.
Definition: nic.h:322
Forwarding database entry.
Definition: nic.h:149
MacAddr macAddr
Definition: nic.h:150
uint32_t destPorts
Definition: nic.h:152
bool_t override
Definition: nic.h:153
uint8_t srcPort
Definition: nic.h:151
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369