ksz8463_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz8463_driver.c
3  * @brief KSZ8463 3-port Ethernet switch driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/ethernet_misc.h"
38 #include "debug.h"
39 
40 
41 /**
42  * @brief KSZ8463 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ8463)
75  **/
76 
77 const uint8_t ksz8463IngressTailTag[3] =
78 {
82 };
83 
84 
85 /**
86  * @brief KSZ8463 Ethernet switch initialization
87  * @param[in] interface Underlying network interface
88  * @return Error code
89  **/
90 
92 {
93  uint_t port;
94  uint16_t temp;
95 
96  //Debug message
97  TRACE_INFO("Initializing KSZ8463...\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 CIDER register
109  temp = ksz8463ReadSwitchReg(interface, KSZ8463_CIDER);
110 
111  //The returned data is invalid until the serial interface is ready
113 
114 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
115  //Enable tail tag feature
116  temp = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR8);
118  ksz8463WriteSwitchReg(interface, KSZ8463_SGCR8, temp);
119 #else
120  //Disable tail tag feature
121  temp = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR8);
122  temp &= ~KSZ8463_SGCR8_TAIL_TAG_EN;
123  ksz8463WriteSwitchReg(interface, KSZ8463_SGCR8, temp);
124 #endif
125 
126  //Loop through the ports
128  {
129 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
130  //Port separation mode?
131  if(interface->port != 0)
132  {
133  //Disable packet transmission and address learning
135  }
136  else
137 #endif
138  {
139  //Enable transmission, reception and address learning
141  }
142  }
143 
144  //Dump switch registers for debugging purpose
145  ksz8463DumpSwitchReg(interface);
146  }
147  else
148  {
149  //Initialize serial management interface
150  if(interface->smiDriver != NULL)
151  {
152  interface->smiDriver->init();
153  }
154 
155  //Loop through the ports
157  {
158  //Debug message
159  TRACE_DEBUG("Port %u:\r\n", port);
160  //Dump PHY registers for debugging purpose
161  ksz8463DumpPhyReg(interface, port);
162  }
163  }
164 
165  //Perform custom configuration
166  ksz8463InitHook(interface);
167 
168  //Force the TCP/IP stack to poll the link state at startup
169  interface->phyEvent = TRUE;
170  //Notify the TCP/IP stack of the event
171  osSetEvent(&interface->netContext->event);
172 
173  //Successful initialization
174  return NO_ERROR;
175 }
176 
177 
178 /**
179  * @brief KSZ8463 custom configuration
180  * @param[in] interface Underlying network interface
181  **/
182 
183 __weak_func void ksz8463InitHook(NetInterface *interface)
184 {
185 }
186 
187 
188 /**
189  * @brief KSZ8463 timer handler
190  * @param[in] interface Underlying network interface
191  **/
192 
193 __weak_func void ksz8463Tick(NetInterface *interface)
194 {
195  uint_t port;
196  bool_t linkState;
197 
198 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
199  //Port separation mode?
200  if(interface->port != 0)
201  {
202  uint_t i;
203  NetContext *context;
204  NetInterface *virtualInterface;
205 
206  //Point to the TCP/IP stack context
207  context = interface->netContext;
208 
209  //Loop through network interfaces
210  for(i = 0; i < context->numInterfaces; i++)
211  {
212  //Point to the current interface
213  virtualInterface = &context->interfaces[i];
214 
215  //Check whether the current virtual interface is attached to the
216  //physical interface
217  if(virtualInterface == interface ||
218  virtualInterface->parent == interface)
219  {
220  //Retrieve current link state
221  linkState = ksz8463GetLinkState(interface, virtualInterface->port);
222 
223  //Link up or link down event?
224  if(linkState != virtualInterface->linkState)
225  {
226  //Set event flag
227  interface->phyEvent = TRUE;
228  //Notify the TCP/IP stack of the event
229  osSetEvent(&interface->netContext->event);
230  }
231  }
232  }
233  }
234  else
235 #endif
236  {
237  //Initialize link state
238  linkState = FALSE;
239 
240  //Loop through the ports
242  {
243  //Retrieve current link state
244  if(ksz8463GetLinkState(interface, port))
245  {
246  linkState = TRUE;
247  }
248  }
249 
250  //Link up or link down event?
251  if(linkState != interface->linkState)
252  {
253  //Set event flag
254  interface->phyEvent = TRUE;
255  //Notify the TCP/IP stack of the event
256  osSetEvent(&interface->netContext->event);
257  }
258  }
259 }
260 
261 
262 /**
263  * @brief Enable interrupts
264  * @param[in] interface Underlying network interface
265  **/
266 
268 {
269 }
270 
271 
272 /**
273  * @brief Disable interrupts
274  * @param[in] interface Underlying network interface
275  **/
276 
278 {
279 }
280 
281 
282 /**
283  * @brief KSZ8463 event handler
284  * @param[in] interface Underlying network interface
285  **/
286 
287 __weak_func void ksz8463EventHandler(NetInterface *interface)
288 {
289  uint_t port;
290  bool_t linkState;
291 
292 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
293  //Port separation mode?
294  if(interface->port != 0)
295  {
296  uint_t i;
297  NetContext *context;
298  NetInterface *virtualInterface;
299 
300  //Point to the TCP/IP stack context
301  context = interface->netContext;
302 
303  //Loop through network interfaces
304  for(i = 0; i < context->numInterfaces; i++)
305  {
306  //Point to the current interface
307  virtualInterface = &context->interfaces[i];
308 
309  //Check whether the current virtual interface is attached to the
310  //physical interface
311  if(virtualInterface == interface ||
312  virtualInterface->parent == interface)
313  {
314  //Get the port number associated with the current interface
315  port = virtualInterface->port;
316 
317  //Valid port?
318  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
319  {
320  //Read port status register
321  linkState = ksz8463GetLinkState(interface, port);
322 
323  //Link up event?
324  if(linkState && !virtualInterface->linkState)
325  {
326  //Retrieve host interface speed
327  interface->linkSpeed = ksz8463GetLinkSpeed(interface,
328  KSZ8463_PORT3);
329 
330  //Retrieve host interface duplex mode
331  interface->duplexMode = ksz8463GetDuplexMode(interface,
332  KSZ8463_PORT3);
333 
334  //Adjust MAC configuration parameters for proper operation
335  interface->nicDriver->updateMacConfig(interface);
336 
337  //Check current speed
338  virtualInterface->linkSpeed = ksz8463GetLinkSpeed(interface,
339  port);
340 
341  //Check current duplex mode
342  virtualInterface->duplexMode = ksz8463GetDuplexMode(interface,
343  port);
344 
345  //Update link state
346  virtualInterface->linkState = TRUE;
347 
348  //Process link state change event
349  nicNotifyLinkChange(virtualInterface);
350  }
351  //Link down event
352  else if(!linkState && virtualInterface->linkState)
353  {
354  //Update link state
355  virtualInterface->linkState = FALSE;
356 
357  //Process link state change event
358  nicNotifyLinkChange(virtualInterface);
359  }
360  }
361  }
362  }
363  }
364  else
365 #endif
366  {
367  //Initialize link state
368  linkState = FALSE;
369 
370  //Loop through the ports
372  {
373  //Retrieve current link state
374  if(ksz8463GetLinkState(interface, port))
375  {
376  linkState = TRUE;
377  }
378  }
379 
380  //Link up event?
381  if(linkState)
382  {
383  //Retrieve host interface speed
384  interface->linkSpeed = ksz8463GetLinkSpeed(interface, KSZ8463_PORT3);
385  //Retrieve host interface duplex mode
386  interface->duplexMode = ksz8463GetDuplexMode(interface, KSZ8463_PORT3);
387 
388  //Adjust MAC configuration parameters for proper operation
389  interface->nicDriver->updateMacConfig(interface);
390 
391  //Update link state
392  interface->linkState = TRUE;
393  }
394  else
395  {
396  //Update link state
397  interface->linkState = FALSE;
398  }
399 
400  //Process link state change event
401  nicNotifyLinkChange(interface);
402  }
403 }
404 
405 
406 /**
407  * @brief Add tail tag to Ethernet frame
408  * @param[in] interface Underlying network interface
409  * @param[in] buffer Multi-part buffer containing the payload
410  * @param[in,out] offset Offset to the first payload byte
411  * @param[in] ancillary Additional options passed to the stack along with
412  * the packet
413  * @return Error code
414  **/
415 
417  size_t *offset, NetTxAncillary *ancillary)
418 {
419  error_t error;
420 
421  //Initialize status code
422  error = NO_ERROR;
423 
424 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
425  //SPI slave mode?
426  if(interface->spiDriver != NULL)
427  {
428  //Valid port?
429  if(ancillary->port <= KSZ8463_PORT2)
430  {
431  size_t length;
432  const uint8_t *tailTag;
433 
434  //The one byte tail tagging is used to indicate the destination port
435  tailTag = &ksz8463IngressTailTag[ancillary->port];
436 
437  //Retrieve the length of the Ethernet frame
438  length = netBufferGetLength(buffer) - *offset;
439 
440  //The host controller should manually add padding to the packet before
441  //inserting the tail tag
442  error = ethPadFrame(buffer, &length);
443 
444  //Check status code
445  if(!error)
446  {
447  //The tail tag is inserted at the end of the packet, just before
448  //the CRC
449  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
450  }
451  }
452  else
453  {
454  //The port number is not valid
455  error = ERROR_INVALID_PORT;
456  }
457  }
458 #endif
459 
460  //Return status code
461  return error;
462 }
463 
464 
465 /**
466  * @brief Decode tail tag from incoming Ethernet frame
467  * @param[in] interface Underlying network interface
468  * @param[in,out] frame Pointer to the received Ethernet frame
469  * @param[in,out] length Length of the frame, in bytes
470  * @param[in,out] ancillary Additional options passed to the stack along with
471  * the packet
472  * @return Error code
473  **/
474 
475 error_t ksz8463UntagFrame(NetInterface *interface, uint8_t **frame,
476  size_t *length, NetRxAncillary *ancillary)
477 {
478  error_t error;
479 
480  //Initialize status code
481  error = NO_ERROR;
482 
483 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
484  //SPI slave mode?
485  if(interface->spiDriver != NULL)
486  {
487  //Valid Ethernet frame received?
488  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
489  {
490  uint8_t *tailTag;
491 
492  //The tail tag is inserted at the end of the packet, just before
493  //the CRC
494  tailTag = *frame + *length - sizeof(uint8_t);
495 
496  //The one byte tail tagging is used to indicate the source port
497  ancillary->port = (*tailTag & KSZ8463_TAIL_TAG_SRC_PORT) + 1;
498 
499  //Strip tail tag from Ethernet frame
500  *length -= sizeof(uint8_t);
501  }
502  else
503  {
504  //Drop the received frame
505  error = ERROR_INVALID_LENGTH;
506  }
507  }
508  else
509  {
510  //Tail tagging mode cannot be enabled through MDC/MDIO interface
511  ancillary->port = 0;
512  }
513 #endif
514 
515  //Return status code
516  return error;
517 }
518 
519 
520 /**
521  * @brief Get link state
522  * @param[in] interface Underlying network interface
523  * @param[in] port Port number
524  * @return Link state
525  **/
526 
528 {
529  uint16_t status;
530  bool_t linkState;
531 
532  //Check port number
533  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
534  {
535  //SPI slave mode?
536  if(interface->spiDriver != NULL)
537  {
538  //Read port status register
539  status = ksz8463ReadSwitchReg(interface, KSZ8463_PnSR(port));
540 
541  //Retrieve current link state
542  linkState = (status & KSZ8463_PnSR_LINK_STATUS) ? TRUE : FALSE;
543  }
544  else
545  {
546  //Read status register
547  status = ksz8463ReadPhyReg(interface, port, KSZ8463_BMSR);
548 
549  //Retrieve current link state
550  linkState = (status & KSZ8463_BMSR_LINK_STATUS) ? TRUE : FALSE;
551  }
552  }
553  else
554  {
555  //The specified port number is not valid
556  linkState = FALSE;
557  }
558 
559  //Return link status
560  return linkState;
561 }
562 
563 
564 /**
565  * @brief Get link speed
566  * @param[in] interface Underlying network interface
567  * @param[in] port Port number
568  * @return Link speed
569  **/
570 
571 uint32_t ksz8463GetLinkSpeed(NetInterface *interface, uint8_t port)
572 {
573  uint16_t status;
574  uint32_t linkSpeed;
575 
576  //Check port number
577  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
578  {
579  //Read port status register
580  status = ksz8463ReadSwitchReg(interface, KSZ8463_PnSR(port));
581 
582  //Retrieve current link speed
583  if((status & KSZ8463_PnSR_OP_SPEED) != 0)
584  {
585  linkSpeed = NIC_LINK_SPEED_100MBPS;
586  }
587  else
588  {
589  linkSpeed = NIC_LINK_SPEED_10MBPS;
590  }
591  }
592  else if(port == KSZ8463_PORT3)
593  {
594  //Read switch global control 3 register
595  status = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR3);
596 
597  //Retrieve host interface speed
598  if((status & KSZ8463_SGCR3_SW_MII_10BT) != 0)
599  {
600  linkSpeed = NIC_LINK_SPEED_10MBPS;
601  }
602  else
603  {
604  linkSpeed = NIC_LINK_SPEED_100MBPS;
605  }
606  }
607  else
608  {
609  //The specified port number is not valid
610  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
611  }
612 
613  //Return link speed
614  return linkSpeed;
615 }
616 
617 
618 /**
619  * @brief Get duplex mode
620  * @param[in] interface Underlying network interface
621  * @param[in] port Port number
622  * @return Duplex mode
623  **/
624 
626 {
627  uint16_t status;
628  NicDuplexMode duplexMode;
629 
630  //Check port number
631  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
632  {
633  //Read port status register
634  status = ksz8463ReadSwitchReg(interface, KSZ8463_PnSR(port));
635 
636  //Retrieve current duplex mode
637  if((status & KSZ8463_PnSR_OP_DUPLEX) != 0)
638  {
639  duplexMode = NIC_FULL_DUPLEX_MODE;
640  }
641  else
642  {
643  duplexMode = NIC_HALF_DUPLEX_MODE;
644  }
645  }
646  else if(port == KSZ8463_PORT3)
647  {
648  //Read switch global control 3 register
649  status = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR3);
650 
651  //Retrieve host interface duplex mode
653  {
654  duplexMode = NIC_HALF_DUPLEX_MODE;
655  }
656  else
657  {
658  duplexMode = NIC_FULL_DUPLEX_MODE;
659  }
660  }
661  else
662  {
663  //The specified port number is not valid
664  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
665  }
666 
667  //Return duplex mode
668  return duplexMode;
669 }
670 
671 
672 /**
673  * @brief Set port state
674  * @param[in] interface Underlying network interface
675  * @param[in] port Port number
676  * @param[in] state Port state
677  **/
678 
679 void ksz8463SetPortState(NetInterface *interface, uint8_t port,
680  SwitchPortState state)
681 {
682  uint16_t temp;
683 
684  //Check port number
685  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
686  {
687  //Read port control 2 register
688  temp = ksz8463ReadSwitchReg(interface, KSZ8463_PnCR2(port));
689 
690  //Update port state
691  switch(state)
692  {
693  //Listening state
695  temp &= ~KSZ8463_PnCR2_TRANSMIT_EN;
696  temp |= KSZ8463_PnCR2_RECEIVE_EN;
698  break;
699 
700  //Learning state
702  temp &= ~KSZ8463_PnCR2_TRANSMIT_EN;
703  temp &= ~KSZ8463_PnCR2_RECEIVE_EN;
705  break;
706 
707  //Forwarding state
710  temp |= KSZ8463_PnCR2_RECEIVE_EN;
712  break;
713 
714  //Disabled state
715  default:
716  temp &= ~KSZ8463_PnCR2_TRANSMIT_EN;
717  temp &= ~KSZ8463_PnCR2_RECEIVE_EN;
719  break;
720  }
721 
722  //Write the value back to port control 2 register
723  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(port), temp);
724  }
725 }
726 
727 
728 /**
729  * @brief Get port state
730  * @param[in] interface Underlying network interface
731  * @param[in] port Port number
732  * @return Port state
733  **/
734 
736 {
737  uint16_t temp;
738  SwitchPortState state;
739 
740  //Check port number
741  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
742  {
743  //Read port control 2 register
744  temp = ksz8463ReadSwitchReg(interface, KSZ8463_PnCR2(port));
745 
746  //Check port state
747  if((temp & KSZ8463_PnCR2_TRANSMIT_EN) == 0 &&
748  (temp & KSZ8463_PnCR2_RECEIVE_EN) == 0 &&
749  (temp & KSZ8463_PnCR2_LEARNING_DIS) != 0)
750  {
751  //Disabled state
753  }
754  else if((temp & KSZ8463_PnCR2_TRANSMIT_EN) == 0 &&
755  (temp & KSZ8463_PnCR2_RECEIVE_EN) != 0 &&
756  (temp & KSZ8463_PnCR2_LEARNING_DIS) != 0)
757  {
758  //Listening state
760  }
761  else if((temp & KSZ8463_PnCR2_TRANSMIT_EN) == 0 &&
762  (temp & KSZ8463_PnCR2_RECEIVE_EN) == 0 &&
763  (temp & KSZ8463_PnCR2_LEARNING_DIS) == 0)
764  {
765  //Learning state
767  }
768  else if((temp & KSZ8463_PnCR2_TRANSMIT_EN) != 0 &&
769  (temp & KSZ8463_PnCR2_RECEIVE_EN) != 0 &&
770  (temp & KSZ8463_PnCR2_LEARNING_DIS) == 0)
771  {
772  //Forwarding state
774  }
775  else
776  {
777  //Unknown state
779  }
780  }
781  else
782  {
783  //The specified port number is not valid
785  }
786 
787  //Return port state
788  return state;
789 }
790 
791 
792 /**
793  * @brief Set aging time for dynamic filtering entries
794  * @param[in] interface Underlying network interface
795  * @param[in] agingTime Aging time, in seconds
796  **/
797 
798 void ksz8463SetAgingTime(NetInterface *interface, uint32_t agingTime)
799 {
800  //The aging period is fixed to 300 seconds
801 }
802 
803 
804 /**
805  * @brief Enable IGMP snooping
806  * @param[in] interface Underlying network interface
807  * @param[in] enable Enable or disable IGMP snooping
808  **/
809 
811 {
812  uint16_t temp;
813 
814  //Read switch global control 2 register
815  temp = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR2);
816 
817  //Enable or disable IGMP snooping
818  if(enable)
819  {
821  }
822  else
823  {
825  }
826 
827  //Write the value back to switch global control 2 register
828  ksz8463WriteSwitchReg(interface, KSZ8463_SGCR2, temp);
829 }
830 
831 
832 /**
833  * @brief Enable MLD snooping
834  * @param[in] interface Underlying network interface
835  * @param[in] enable Enable or disable MLD snooping
836  **/
837 
839 {
840  //Not implemented
841 }
842 
843 
844 /**
845  * @brief Enable reserved multicast table
846  * @param[in] interface Underlying network interface
847  * @param[in] enable Enable or disable reserved group addresses
848  **/
849 
851 {
852  //Not implemented
853 }
854 
855 
856 /**
857  * @brief Add a new entry to the static MAC table
858  * @param[in] interface Underlying network interface
859  * @param[in] entry Pointer to the forwarding database entry
860  * @return Error code
861  **/
862 
864  const SwitchFdbEntry *entry)
865 {
866  error_t error;
867  uint_t i;
868  uint_t j;
869  uint8_t *p;
870  SwitchFdbEntry currentEntry;
871  Ksz8463StaticMacEntry newEntry;
872 
873  //Keep track of the first free entry
875 
876  //Loop through the static MAC table
877  for(i = 0; i < KSZ8463_STATIC_MAC_TABLE_SIZE; i++)
878  {
879  //Read current entry
880  error = ksz8463GetStaticFdbEntry(interface, i, &currentEntry);
881 
882  //Valid entry?
883  if(!error)
884  {
885  //Check whether the table already contains the specified MAC address
886  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
887  {
888  j = i;
889  break;
890  }
891  }
892  else
893  {
894  //Keep track of the first free entry
896  {
897  j = i;
898  }
899  }
900  }
901 
902  //Any entry available?
904  {
905  //Format MAC entry
906  newEntry.reserved = 0;
907  newEntry.fidH = 0;
908  newEntry.fidL = 0;
909  newEntry.useFid = 0;
910  newEntry.override = entry->override;
911  newEntry.valid = TRUE;
912  newEntry.macAddr = entry->macAddr;
913 
914  //Set the relevant forward ports
915  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
916  {
917  newEntry.forwardPorts = KSZ8463_PORT3_MASK;
918  }
919  else
920  {
921  newEntry.forwardPorts = entry->destPorts & KSZ8463_PORT_MASK;
922  }
923 
924  //Point to the MAC entry
925  p = (uint8_t *) &newEntry;
926 
927  //Write indirect data registers
928  ksz8463WriteSwitchReg(interface, KSZ8463_IADR3, p[0] << 8 | p[1]);
929  ksz8463WriteSwitchReg(interface, KSZ8463_IADR2, p[2] << 8 | p[3]);
930  ksz8463WriteSwitchReg(interface, KSZ8463_IADR5, p[4] << 8 | p[5]);
931  ksz8463WriteSwitchReg(interface, KSZ8463_IADR4, p[6] << 8 | p[7]);
932 
933  //Trigger a write static MAC table operation
936 
937  //Successful processing
938  error = NO_ERROR;
939  }
940  else
941  {
942  //The static MAC table is full
943  error = ERROR_TABLE_FULL;
944  }
945 
946  //Return status code
947  return error;
948 }
949 
950 
951 /**
952  * @brief Remove an entry from the static MAC table
953  * @param[in] interface Underlying network interface
954  * @param[in] entry Forwarding database entry to remove from the table
955  * @return Error code
956  **/
957 
959  const SwitchFdbEntry *entry)
960 {
961  error_t error;
962  uint_t j;
963  SwitchFdbEntry currentEntry;
964 
965  //Loop through the static MAC table
966  for(j = 0; j < KSZ8463_STATIC_MAC_TABLE_SIZE; j++)
967  {
968  //Read current entry
969  error = ksz8463GetStaticFdbEntry(interface, j, &currentEntry);
970 
971  //Valid entry?
972  if(!error)
973  {
974  //Check whether the table contains the specified MAC address
975  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
976  {
977  break;
978  }
979  }
980  }
981 
982  //Any matching entry?
984  {
985  //Clear indirect data registers
986  ksz8463WriteSwitchReg(interface, KSZ8463_IADR3, 0);
987  ksz8463WriteSwitchReg(interface, KSZ8463_IADR2, 0);
988  ksz8463WriteSwitchReg(interface, KSZ8463_IADR5, 0);
989  ksz8463WriteSwitchReg(interface, KSZ8463_IADR4, 0);
990 
991  //Trigger a write static MAC table operation
994 
995  //Successful processing
996  error = NO_ERROR;
997  }
998  else
999  {
1000  //The static MAC table does not contain the specified address
1001  error = ERROR_NOT_FOUND;
1002  }
1003 
1004  //Return status code
1005  return error;
1006 }
1007 
1008 
1009 /**
1010  * @brief Read an entry from the static MAC table
1011  * @param[in] interface Underlying network interface
1012  * @param[in] index Zero-based index of the entry to read
1013  * @param[out] entry Pointer to the forwarding database entry
1014  * @return Error code
1015  **/
1016 
1018  SwitchFdbEntry *entry)
1019 {
1020  error_t error;
1021  uint16_t temp;
1022  uint8_t *p;
1023  Ksz8463StaticMacEntry currentEntry;
1024 
1025  //Check index parameter
1026  if(index < KSZ8463_STATIC_MAC_TABLE_SIZE)
1027  {
1028  //Trigger a read static MAC table operation
1031 
1032  //Point to the MAC entry
1033  p = (uint8_t *) &currentEntry;
1034 
1035  //Read indirect data registers
1036  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR3);
1037  p[0] = (temp >> 8) & 0xFF;
1038  p[1] = temp & 0xFF;
1039  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR2);
1040  p[2] = (temp >> 8) & 0xFF;
1041  p[3] = temp & 0xFF;
1042  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR5);
1043  p[4] = (temp >> 8) & 0xFF;
1044  p[5] = temp & 0xFF;
1045  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR4);
1046  p[6] = (temp >> 8) & 0xFF;
1047  p[7] = temp & 0xFF;
1048 
1049  //Valid entry?
1050  if(currentEntry.valid)
1051  {
1052  //Copy MAC entry
1053  entry->macAddr = currentEntry.macAddr;
1054  entry->srcPort = 0;
1055  entry->destPorts = currentEntry.forwardPorts & KSZ8463_PORT_MASK;
1056  entry->override = currentEntry.override;
1057 
1058  //Successful processing
1059  error = NO_ERROR;
1060  }
1061  else
1062  {
1063  //The entry is not valid
1064  error = ERROR_INVALID_ENTRY;
1065  }
1066  }
1067  else
1068  {
1069  //The end of the table has been reached
1070  error = ERROR_END_OF_TABLE;
1071  }
1072 
1073  //Return status code
1074  return error;
1075 }
1076 
1077 
1078 /**
1079  * @brief Flush static MAC table
1080  * @param[in] interface Underlying network interface
1081  **/
1082 
1084 {
1085  uint_t i;
1086  uint_t temp;
1087  uint16_t state[3];
1088 
1089  //Loop through the ports
1090  for(i = KSZ8463_PORT1; i <= KSZ8463_PORT3; i++)
1091  {
1092  //Save the current state of the port
1093  state[i - 1] = ksz8463ReadSwitchReg(interface, KSZ8463_PnCR2(i));
1094 
1095  //Turn off learning capability
1096  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(i),
1097  state[i - 1] | KSZ8463_PnCR2_LEARNING_DIS);
1098  }
1099 
1100  //All the entries associated with a port that has its learning capability
1101  //being turned off will be flushed
1102  temp = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR8);
1104  ksz8463WriteSwitchReg(interface, KSZ8463_SGCR8, temp);
1105 
1106  //Loop through the ports
1107  for(i = KSZ8463_PORT1; i <= KSZ8463_PORT3; i++)
1108  {
1109  //Restore the original state of the port
1110  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(i), state[i - 1]);
1111  }
1112 }
1113 
1114 
1115 /**
1116  * @brief Read an entry from the dynamic MAC table
1117  * @param[in] interface Underlying network interface
1118  * @param[in] index Zero-based index of the entry to read
1119  * @param[out] entry Pointer to the forwarding database entry
1120  * @return Error code
1121  **/
1122 
1124  SwitchFdbEntry *entry)
1125 {
1126  error_t error;
1127  uint16_t temp;
1128  uint_t n;
1129  uint8_t *p;
1130  Ksz8463DynamicMacEntry currentEntry;
1131 
1132  //Check index parameter
1133  if(index < KSZ8463_DYNAMIC_MAC_TABLE_SIZE)
1134  {
1135  //Read the MAC entry at the specified index
1136  do
1137  {
1138  //Trigger a read dynamic MAC table operation
1141 
1142  //Point to the MAC entry
1143  p = (uint8_t *) &currentEntry;
1144 
1145  //Read indirect data registers
1146  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR1);
1147  p[0] = temp & 0xFF;
1148  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR3);
1149  p[1] = (temp >> 8) & 0xFF;
1150  p[2] = temp & 0xFF;
1151  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR2);
1152  p[3] = (temp >> 8) & 0xFF;
1153  p[4] = temp & 0xFF;
1154  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR5);
1155  p[5] = (temp >> 8) & 0xFF;
1156  p[6] = temp & 0xFF;
1157  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR4);
1158  p[7] = (temp >> 8) & 0xFF;
1159  p[8] = temp & 0xFF;
1160 
1161  //Retry until the entry is ready
1162  } while(currentEntry.dataNotReady);
1163 
1164  //Check whether there are valid entries in the table
1165  if(!currentEntry.macEmpty)
1166  {
1167  //Retrieve the number of valid entries
1168  n = ((currentEntry.numValidEntriesH << 8) |
1169  currentEntry.numValidEntriesL) + 1;
1170  }
1171  else
1172  {
1173  //The table is empty
1174  n = 0;
1175  }
1176 
1177  //Valid entry?
1178  if(index < n)
1179  {
1180  //Copy MAC entry
1181  entry->macAddr = currentEntry.macAddr;
1182  entry->srcPort = currentEntry.sourcePort + 1;
1183  entry->destPorts = 0;
1184  entry->override = FALSE;
1185 
1186  //Successful processing
1187  error = NO_ERROR;
1188  }
1189  else
1190  {
1191  //The end of the table has been reached
1192  error = ERROR_END_OF_TABLE;
1193  }
1194  }
1195  else
1196  {
1197  //The end of the table has been reached
1198  error = ERROR_END_OF_TABLE;
1199  }
1200 
1201  //Return status code
1202  return error;
1203 }
1204 
1205 
1206 /**
1207  * @brief Flush dynamic MAC table
1208  * @param[in] interface Underlying network interface
1209  * @param[in] port Port number
1210  **/
1211 
1213 {
1214  uint_t i;
1215  uint_t temp;
1216  uint16_t state[3];
1217 
1218  //Loop through the ports
1219  for(i = KSZ8463_PORT1; i <= KSZ8463_PORT3; i++)
1220  {
1221  //Matching port number?
1222  if(i == port || port == 0)
1223  {
1224  //Save the current state of the port
1225  state[i - 1] = ksz8463ReadSwitchReg(interface, KSZ8463_PnCR2(i));
1226 
1227  //Turn off learning capability
1228  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(i),
1229  state[i - 1] | KSZ8463_PnCR2_LEARNING_DIS);
1230  }
1231  }
1232 
1233  //All the entries associated with a port that has its learning capability
1234  //being turned off will be flushed
1235  temp = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR8);
1237  ksz8463WriteSwitchReg(interface, KSZ8463_SGCR8, temp);
1238 
1239  //Loop through the ports
1240  for(i = KSZ8463_PORT1; i <= KSZ8463_PORT3; i++)
1241  {
1242  //Matching port number?
1243  if(i == port || port == 0)
1244  {
1245  //Restore the original state of the port
1246  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(i), state[i - 1]);
1247  }
1248  }
1249 }
1250 
1251 
1252 /**
1253  * @brief Set forward ports for unknown multicast packets
1254  * @param[in] interface Underlying network interface
1255  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1256  * @param[in] forwardPorts Port map
1257  **/
1258 
1260  bool_t enable, uint32_t forwardPorts)
1261 {
1262  //Not implemented
1263 }
1264 
1265 
1266 /**
1267  * @brief Write PHY register
1268  * @param[in] interface Underlying network interface
1269  * @param[in] port Port number
1270  * @param[in] address PHY register address
1271  * @param[in] data Register value
1272  **/
1273 
1274 void ksz8463WritePhyReg(NetInterface *interface, uint8_t port,
1275  uint8_t address, uint16_t data)
1276 {
1277  //Write the specified PHY register
1278  if(interface->smiDriver != NULL)
1279  {
1280  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1281  }
1282  else
1283  {
1284  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1285  }
1286 }
1287 
1288 
1289 /**
1290  * @brief Read PHY register
1291  * @param[in] interface Underlying network interface
1292  * @param[in] port Port number
1293  * @param[in] address PHY register address
1294  * @return Register value
1295  **/
1296 
1297 uint16_t ksz8463ReadPhyReg(NetInterface *interface, uint8_t port,
1298  uint8_t address)
1299 {
1300  uint16_t data;
1301 
1302  //Read the specified PHY register
1303  if(interface->smiDriver != NULL)
1304  {
1305  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1306  }
1307  else
1308  {
1309  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1310  }
1311 
1312  //Return the value of the PHY register
1313  return data;
1314 }
1315 
1316 
1317 /**
1318  * @brief Dump PHY registers for debugging purpose
1319  * @param[in] interface Underlying network interface
1320  * @param[in] port Port number
1321  **/
1322 
1323 void ksz8463DumpPhyReg(NetInterface *interface, uint8_t port)
1324 {
1325  uint8_t i;
1326 
1327  //Loop through PHY registers
1328  for(i = 0; i < 32; i++)
1329  {
1330  //Display current PHY register
1331  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1332  ksz8463ReadPhyReg(interface, port, i));
1333  }
1334 
1335  //Terminate with a line feed
1336  TRACE_DEBUG("\r\n");
1337 }
1338 
1339 
1340 /**
1341  * @brief Write switch register
1342  * @param[in] interface Underlying network interface
1343  * @param[in] address Switch register address
1344  * @param[in] data Register value
1345  **/
1346 
1347 void ksz8463WriteSwitchReg(NetInterface *interface, uint16_t address,
1348  uint16_t data)
1349 {
1350  uint16_t command;
1351 
1352  //SPI slave mode?
1353  if(interface->spiDriver != NULL)
1354  {
1355  //Set up a write operation
1356  command = KSZ8463_SPI_CMD_WRITE;
1357 
1358  //The byte enable bits are set to indicate which bytes will be
1359  //transferred in the data phase
1360  if((address & 0x02) != 0)
1361  {
1363  }
1364  else
1365  {
1367  }
1368 
1369  //Set register address
1370  command |= (address << 4) & KSZ8463_SPI_CMD_ADDR;
1371 
1372  //Pull the CS pin low
1373  interface->spiDriver->assertCs();
1374 
1375  //Write 16-bit command
1376  interface->spiDriver->transfer(MSB(command));
1377  interface->spiDriver->transfer(LSB(command));
1378 
1379  //Write 16-bit data
1380  interface->spiDriver->transfer(LSB(data));
1381  interface->spiDriver->transfer(MSB(data));
1382 
1383  //Terminate the operation by raising the CS pin
1384  interface->spiDriver->deassertCs();
1385  }
1386  else
1387  {
1388  //The MDC/MDIO interface does not have access to all the configuration
1389  //registers. It can only access the standard MIIM registers
1390  }
1391 }
1392 
1393 
1394 /**
1395  * @brief Read switch register
1396  * @param[in] interface Underlying network interface
1397  * @param[in] address Switch register address
1398  * @return Register value
1399  **/
1400 
1401 uint16_t ksz8463ReadSwitchReg(NetInterface *interface, uint16_t address)
1402 {
1403  uint16_t data;
1404  uint16_t command;
1405 
1406  //SPI slave mode?
1407  if(interface->spiDriver != NULL)
1408  {
1409  //Set up a read operation
1410  command = KSZ8463_SPI_CMD_READ;
1411 
1412  //The byte enable bits are set to indicate which bytes will be
1413  //transferred in the data phase
1414  if((address & 0x02) != 0)
1415  {
1417  }
1418  else
1419  {
1421  }
1422 
1423  //Set register address
1424  command |= (address << 4) & KSZ8463_SPI_CMD_ADDR;
1425 
1426  //Pull the CS pin low
1427  interface->spiDriver->assertCs();
1428 
1429  //Write 16-bit command
1430  interface->spiDriver->transfer(MSB(command));
1431  interface->spiDriver->transfer(LSB(command));
1432 
1433  //Read 16-bit data
1434  data = interface->spiDriver->transfer(0xFF);
1435  data |= interface->spiDriver->transfer(0xFF) << 8;
1436 
1437  //Terminate the operation by raising the CS pin
1438  interface->spiDriver->deassertCs();
1439  }
1440  else
1441  {
1442  //The MDC/MDIO interface does not have access to all the configuration
1443  //registers. It can only access the standard MIIM registers
1444  data = 0;
1445  }
1446 
1447  //Return register value
1448  return data;
1449 }
1450 
1451 
1452 /**
1453  * @brief Dump switch registers for debugging purpose
1454  * @param[in] interface Underlying network interface
1455  **/
1456 
1458 {
1459  uint16_t i;
1460 
1461  //Loop through switch registers
1462  for(i = 0; i < 256; i += 2)
1463  {
1464  //Display current switch register
1465  TRACE_DEBUG("0x%02" PRIX16 " (%02" PRIu16 ") : 0x%04" PRIX16 "\r\n",
1466  i, i, ksz8463ReadSwitchReg(interface, i));
1467  }
1468 
1469  //Terminate with a line feed
1470  TRACE_DEBUG("\r\n");
1471 }
#define KSZ8463_PnCR2(port)
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:601
#define NetContext
Definition: net.h:36
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
#define KSZ8463_SGCR8
MacAddr macAddr
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
#define KSZ8463_IADR4
uint32_t ksz8463GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
uint32_t destPorts
Definition: nic.h:152
void ksz8463FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
#define KSZ8463_IACR_READ
#define KSZ8463_CIDER
error_t ksz8463GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
#define KSZ8463_IADR3
#define KSZ8463_TAIL_TAG_DEST_PORT2
@ ERROR_END_OF_TABLE
Definition: error.h:292
uint8_t p
Definition: ndp.h:300
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define KSZ8463_IACR
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
void ksz8463EnableIrq(NetInterface *interface)
Enable interrupts.
#define KSZ8463_TAIL_TAG_DEST_PORT1
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
#define KSZ8463_CIDER_FAMILY_ID
#define KSZ8463_IACR_TABLE_SEL_DYNAMIC_MAC
error_t ksz8463Init(NetInterface *interface)
KSZ8463 Ethernet switch initialization.
error_t ksz8463AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
#define KSZ8463_PnCR2_RECEIVE_EN
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_TABLE_FULL
Definition: error.h:291
uint8_t useFid
void ksz8463SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
#define KSZ8463_IADR2
#define KSZ8463_PORT2
uint8_t numValidEntriesH
#define KSZ8463_IACR_WRITE
EthHeader
Definition: ethernet.h:225
uint8_t fidL
KSZ8463 3-port Ethernet switch driver.
#define KSZ8463_PORT_MASK
#define SMI_OPCODE_WRITE
Definition: nic.h:66
__weak_func void ksz8463InitHook(NetInterface *interface)
KSZ8463 custom configuration.
uint8_t sourcePort
#define KSZ8463_DYNAMIC_MAC_TABLE_SIZE
const uint8_t ksz8463IngressTailTag[3]
Tail tag rules (host to KSZ8463)
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
#define FALSE
Definition: os_port.h:46
#define KSZ8463_PnSR_LINK_STATUS
uint16_t ksz8463ReadSwitchReg(NetInterface *interface, uint16_t address)
Read switch register.
void ksz8463FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
error_t
Error codes.
Definition: error.h:43
void ksz8463EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
#define KSZ8463_SPI_CMD_ADDR
#define KSZ8463_STATIC_MAC_TABLE_SIZE
#define KSZ8463_SPI_CMD_B1
#define KSZ8463_SPI_CMD_B0
const SwitchDriver ksz8463SwitchDriver
KSZ8463 Ethernet switch driver.
uint8_t dataNotReady
#define KSZ8463_PORT3
Static MAC table entry.
__weak_func void ksz8463EventHandler(NetInterface *interface)
KSZ8463 event handler.
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:40
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
void ksz8463DisableIrq(NetInterface *interface)
Disable interrupts.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define KSZ8463_SGCR3_SW_MII_10BT
#define KSZ8463_SGCR2
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
#define KSZ8463_SGCR2_IGMP_SNOOP_EN
#define KSZ8463_SPI_CMD_B2
#define NetTxAncillary
Definition: net_misc.h:36
error_t ksz8463TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
void ksz8463EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
#define MSB(x)
Definition: os_port.h:59
#define KSZ8463_BMSR
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
#define KSZ8463_IADR1
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
uint16_t ksz8463ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define LSB(x)
Definition: os_port.h:55
#define KSZ8463_SPI_CMD_WRITE
#define KSZ8463_BMSR_LINK_STATUS
#define KSZ8463_PnSR_OP_SPEED
#define KSZ8463_SPI_CMD_B3
#define KSZ8463_SGCR8_TAIL_TAG_EN
#define KSZ8463_TAIL_TAG_SRC_PORT
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
uint16_t port
Definition: dns_common.h:270
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define KSZ8463_SGCR8_FLUSH_DYNAMIC_MAC_TABLE
#define KSZ8463_PnSR(port)
void ksz8463DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
Ethernet switch driver.
Definition: nic.h:325
uint8_t n
bool_t ksz8463GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
#define KSZ8463_PORT1
#define KSZ8463_SGCR3_SW_HOST_PORT_HALF_DUPLEX_MODE
__weak_func void ksz8463Tick(NetInterface *interface)
KSZ8463 timer handler.
@ 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 KSZ8463_PnSR_OP_DUPLEX
Ipv6Addr address[]
Definition: ipv6.h:345
MacAddr macAddr
#define KSZ8463_CIDER_FAMILY_ID_DEFAULT
NicDuplexMode
Duplex mode.
Definition: nic.h:122
void ksz8463WriteSwitchReg(NetInterface *interface, uint16_t address, uint16_t data)
Write switch register.
MacAddr macAddr
Definition: nic.h:150
SwitchPortState ksz8463GetPortState(NetInterface *interface, uint8_t port)
Get port state.
uint8_t srcPort
Definition: nic.h:151
error_t ksz8463DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
uint8_t valid
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
uint8_t macEmpty
void ksz8463DumpSwitchReg(NetInterface *interface)
Dump switch registers for debugging purpose.
void ksz8463SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
error_t ksz8463GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define KSZ8463_PnCR2_LEARNING_DIS
#define KSZ8463_PnCR2_TRANSMIT_EN
void ksz8463EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
NicDuplexMode ksz8463GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
uint8_t reserved
void ksz8463SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define KSZ8463_SPI_CMD_READ
error_t ksz8463UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
unsigned int uint_t
Definition: compiler_port.h:57
#define KSZ8463_IADR5
TCP/IP stack core.
Dynamic MAC table entry.
uint8_t forwardPorts
#define KSZ8463_SGCR8_FLUSH_STATIC_MAC_TABLE
#define KSZ8463_IACR_TABLE_SEL_STATIC_MAC
uint8_t numValidEntriesL
#define KSZ8463_SGCR3
Helper functions for Ethernet.
void ksz8463WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
uint8_t fidH
Debugging facilities.
uint8_t override
Forwarding database entry.
Definition: nic.h:149
#define KSZ8463_PORT3_MASK
#define KSZ8463_TAIL_TAG_NORMAL_ADDR_LOOKUP