ksz8864_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz8864_driver.c
3  * @brief KSZ8864 4-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 KSZ8864 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ8864)
75  **/
76 
77 const uint8_t ksz8864IngressTailTag[4] =
78 {
83 };
84 
85 
86 /**
87  * @brief KSZ8864 Ethernet switch initialization
88  * @param[in] interface Underlying network interface
89  * @return Error code
90  **/
91 
93 {
94  uint_t port;
95  uint8_t temp;
96 
97  //Debug message
98  TRACE_INFO("Initializing KSZ8864...\r\n");
99 
100  //SPI slave mode?
101  if(interface->spiDriver != NULL)
102  {
103  //Initialize SPI interface
104  interface->spiDriver->init();
105  }
106  else if(interface->smiDriver != NULL)
107  {
108  //Initialize serial management interface
109  interface->smiDriver->init();
110  }
111  else
112  {
113  //Just for sanity
114  }
115 
116  //Wait for the serial interface to be ready
117  do
118  {
119  //Read CHIP_ID0 register
120  temp = ksz8864ReadSwitchReg(interface, KSZ8864_CHIP_ID0);
121 
122  //The returned data is invalid until the serial interface is ready
123  } while(temp != KSZ8864_CHIP_ID0_FAMILY_ID_DEFAULT);
124 
125 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
126  //Enable tail tag feature
127  temp = ksz8864ReadSwitchReg(interface, KSZ8864_GLOBAL_CTRL10);
130 #else
131  //Disable tail tag feature
132  temp = ksz8864ReadSwitchReg(interface, KSZ8864_GLOBAL_CTRL10);
135 #endif
136 
137  //Loop through the ports
139  {
140 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
141  //Port separation mode?
142  if(interface->port != 0)
143  {
144  //Disable packet transmission and address learning
146  }
147  else
148 #endif
149  {
150  //Enable transmission, reception and address learning
152  }
153  }
154 
155  //Start switch operation
158 
159  //Dump switch registers for debugging purpose
160  ksz8864DumpSwitchReg(interface);
161 
162  //SMI interface mode?
163  if(interface->spiDriver == NULL)
164  {
165  //Loop through the ports
167  {
168  //Debug message
169  TRACE_DEBUG("Port %u:\r\n", port);
170  //Dump PHY registers for debugging purpose
171  ksz8864DumpPhyReg(interface, port);
172  }
173  }
174 
175  //Perform custom configuration
176  ksz8864InitHook(interface);
177 
178  //Force the TCP/IP stack to poll the link state at startup
179  interface->phyEvent = TRUE;
180  //Notify the TCP/IP stack of the event
181  osSetEvent(&interface->netContext->event);
182 
183  //Successful initialization
184  return NO_ERROR;
185 }
186 
187 
188 /**
189  * @brief KSZ8864 custom configuration
190  * @param[in] interface Underlying network interface
191  **/
192 
193 __weak_func void ksz8864InitHook(NetInterface *interface)
194 {
195 }
196 
197 
198 /**
199  * @brief KSZ8864 timer handler
200  * @param[in] interface Underlying network interface
201  **/
202 
203 __weak_func void ksz8864Tick(NetInterface *interface)
204 {
205  uint_t port;
206  bool_t linkState;
207 
208 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
209  //Port separation mode?
210  if(interface->port != 0)
211  {
212  uint_t i;
213  NetContext *context;
214  NetInterface *virtualInterface;
215 
216  //Point to the TCP/IP stack context
217  context = interface->netContext;
218 
219  //Loop through network interfaces
220  for(i = 0; i < context->numInterfaces; i++)
221  {
222  //Point to the current interface
223  virtualInterface = &context->interfaces[i];
224 
225  //Check whether the current virtual interface is attached to the
226  //physical interface
227  if(virtualInterface == interface ||
228  virtualInterface->parent == interface)
229  {
230  //Retrieve current link state
231  linkState = ksz8864GetLinkState(interface, virtualInterface->port);
232 
233  //Link up or link down event?
234  if(linkState != virtualInterface->linkState)
235  {
236  //Set event flag
237  interface->phyEvent = TRUE;
238  //Notify the TCP/IP stack of the event
239  osSetEvent(&interface->netContext->event);
240  }
241  }
242  }
243  }
244  else
245 #endif
246  {
247  //Initialize link state
248  linkState = FALSE;
249 
250  //Loop through the ports
252  {
253  //Retrieve current link state
254  if(ksz8864GetLinkState(interface, port))
255  {
256  linkState = TRUE;
257  }
258  }
259 
260  //Link up or link down event?
261  if(linkState != interface->linkState)
262  {
263  //Set event flag
264  interface->phyEvent = TRUE;
265  //Notify the TCP/IP stack of the event
266  osSetEvent(&interface->netContext->event);
267  }
268  }
269 }
270 
271 
272 /**
273  * @brief Enable interrupts
274  * @param[in] interface Underlying network interface
275  **/
276 
278 {
279 }
280 
281 
282 /**
283  * @brief Disable interrupts
284  * @param[in] interface Underlying network interface
285  **/
286 
288 {
289 }
290 
291 
292 /**
293  * @brief KSZ8864 event handler
294  * @param[in] interface Underlying network interface
295  **/
296 
297 __weak_func void ksz8864EventHandler(NetInterface *interface)
298 {
299  uint_t port;
300  bool_t linkState;
301 
302 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
303  //Port separation mode?
304  if(interface->port != 0)
305  {
306  uint_t i;
307  NetContext *context;
308  NetInterface *virtualInterface;
309 
310  //Point to the TCP/IP stack context
311  context = interface->netContext;
312 
313  //Loop through network interfaces
314  for(i = 0; i < context->numInterfaces; i++)
315  {
316  //Point to the current interface
317  virtualInterface = &context->interfaces[i];
318 
319  //Check whether the current virtual interface is attached to the
320  //physical interface
321  if(virtualInterface == interface ||
322  virtualInterface->parent == interface)
323  {
324  //Get the port number associated with the current interface
325  port = virtualInterface->port;
326 
327  //Check port number
328  if(port >= KSZ8864_PORT1 && port <= KSZ8864_PORT3)
329  {
330  //Retrieve current link state
331  linkState = ksz8864GetLinkState(interface, port);
332 
333  //Link up event?
334  if(linkState && !virtualInterface->linkState)
335  {
336  //Retrieve host interface speed
337  interface->linkSpeed = ksz8864GetLinkSpeed(interface,
338  KSZ8864_PORT4);
339 
340  //Retrieve host interface duplex mode
341  interface->duplexMode = ksz8864GetDuplexMode(interface,
342  KSZ8864_PORT4);
343 
344  //Adjust MAC configuration parameters for proper operation
345  interface->nicDriver->updateMacConfig(interface);
346 
347  //Check current speed
348  virtualInterface->linkSpeed = ksz8864GetLinkSpeed(interface,
349  port);
350 
351  //Check current duplex mode
352  virtualInterface->duplexMode = ksz8864GetDuplexMode(interface,
353  port);
354 
355  //Update link state
356  virtualInterface->linkState = TRUE;
357 
358  //Process link state change event
359  nicNotifyLinkChange(virtualInterface);
360  }
361  //Link down event
362  else if(!linkState && virtualInterface->linkState)
363  {
364  //Update link state
365  virtualInterface->linkState = FALSE;
366 
367  //Process link state change event
368  nicNotifyLinkChange(virtualInterface);
369  }
370  }
371  else
372  {
373  //The specified port number is not valid
374  }
375  }
376  }
377  }
378  else
379 #endif
380  {
381  //Initialize link state
382  linkState = FALSE;
383 
384  //Loop through the ports
386  {
387  //Retrieve current link state
388  if(ksz8864GetLinkState(interface, port))
389  {
390  linkState = TRUE;
391  }
392  }
393 
394  //Link up event?
395  if(linkState)
396  {
397  //Retrieve host interface speed
398  interface->linkSpeed = ksz8864GetLinkSpeed(interface, KSZ8864_PORT4);
399  //Retrieve host interface duplex mode
400  interface->duplexMode = ksz8864GetDuplexMode(interface, KSZ8864_PORT4);
401 
402  //Adjust MAC configuration parameters for proper operation
403  interface->nicDriver->updateMacConfig(interface);
404 
405  //Update link state
406  interface->linkState = TRUE;
407  }
408  else
409  {
410  //Update link state
411  interface->linkState = FALSE;
412  }
413 
414  //Process link state change event
415  nicNotifyLinkChange(interface);
416  }
417 }
418 
419 
420 /**
421  * @brief Add tail tag to Ethernet frame
422  * @param[in] interface Underlying network interface
423  * @param[in] buffer Multi-part buffer containing the payload
424  * @param[in,out] offset Offset to the first payload byte
425  * @param[in] ancillary Additional options passed to the stack along with
426  * the packet
427  * @return Error code
428  **/
429 
431  size_t *offset, NetTxAncillary *ancillary)
432 {
433  error_t error;
434 
435  //Initialize status code
436  error = NO_ERROR;
437 
438 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
439  //Valid port?
440  if(ancillary->port <= KSZ8864_PORT3)
441  {
442  size_t length;
443  const uint8_t *tailTag;
444 
445  //The one byte tail tagging is used to indicate the destination port
446  tailTag = &ksz8864IngressTailTag[ancillary->port];
447 
448  //Retrieve the length of the Ethernet frame
449  length = netBufferGetLength(buffer) - *offset;
450 
451  //The host controller should manually add padding to the packet before
452  //inserting the tail tag
453  error = ethPadFrame(buffer, &length);
454 
455  //Check status code
456  if(!error)
457  {
458  //The tail tag is inserted at the end of the packet, just before
459  //the CRC
460  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
461  }
462  }
463  else
464  {
465  //The port number is not valid
466  error = ERROR_INVALID_PORT;
467  }
468 #endif
469 
470  //Return status code
471  return error;
472 }
473 
474 
475 /**
476  * @brief Decode tail tag from incoming Ethernet frame
477  * @param[in] interface Underlying network interface
478  * @param[in,out] frame Pointer to the received Ethernet frame
479  * @param[in,out] length Length of the frame, in bytes
480  * @param[in,out] ancillary Additional options passed to the stack along with
481  * the packet
482  * @return Error code
483  **/
484 
485 error_t ksz8864UntagFrame(NetInterface *interface, uint8_t **frame,
486  size_t *length, NetRxAncillary *ancillary)
487 {
488  error_t error;
489 
490  //Initialize status code
491  error = NO_ERROR;
492 
493 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
494  //Valid Ethernet frame received?
495  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
496  {
497  uint8_t *tailTag;
498 
499  //The tail tag is inserted at the end of the packet, just before
500  //the CRC
501  tailTag = *frame + *length - sizeof(uint8_t);
502 
503  //The one byte tail tagging is used to indicate the source port
504  ancillary->port = *tailTag & KSZ8864_TAIL_TAG_SRC_PORT;
505 
506  //Strip tail tag from Ethernet frame
507  *length -= sizeof(uint8_t);
508  }
509  else
510  {
511  //Drop the received frame
512  error = ERROR_INVALID_LENGTH;
513  }
514 #endif
515 
516  //Return status code
517  return error;
518 }
519 
520 
521 /**
522  * @brief Get link state
523  * @param[in] interface Underlying network interface
524  * @param[in] port Port number
525  * @return Link state
526  **/
527 
529 {
530  uint16_t status;
531  bool_t linkState;
532 
533  //Check port number
534  if(port == KSZ8864_PORT1 || port == KSZ8864_PORT2)
535  {
536  //Read port status 1 register
537  status = ksz8864ReadSwitchReg(interface, KSZ8864_PORTn_STAT1(port));
538 
539  //Retrieve current link state
540  linkState = (status & KSZ8864_PORTn_STAT1_LINK_GOOD) ? TRUE : FALSE;
541  }
542  else if(port == KSZ8864_PORT3)
543  {
544  //Port 3 is always up
545  linkState = TRUE;
546  }
547  else
548  {
549  //The specified port number is not valid
550  linkState = FALSE;
551  }
552 
553  //Return link status
554  return linkState;
555 }
556 
557 
558 /**
559  * @brief Get link speed
560  * @param[in] interface Underlying network interface
561  * @param[in] port Port number
562  * @return Link speed
563  **/
564 
565 uint32_t ksz8864GetLinkSpeed(NetInterface *interface, uint8_t port)
566 {
567  uint16_t status;
568  uint32_t linkSpeed;
569 
570  //Check port number
571  if(port == KSZ8864_PORT1 || port == KSZ8864_PORT2)
572  {
573  //Read port status 0 register
574  status = ksz8864ReadSwitchReg(interface, KSZ8864_PORTn_STAT0(port));
575 
576  //Retrieve current link speed
577  if((status & KSZ8864_PORTn_STAT0_OP_SPEED) != 0)
578  {
579  linkSpeed = NIC_LINK_SPEED_100MBPS;
580  }
581  else
582  {
583  linkSpeed = NIC_LINK_SPEED_10MBPS;
584  }
585  }
586  else if(port == KSZ8864_PORT3)
587  {
588  //Port 3 link speed
589  linkSpeed = NIC_LINK_SPEED_100MBPS;
590  }
591  else if(port == KSZ8864_PORT4)
592  {
593  //Read global control 4 register
594  status = ksz8864ReadSwitchReg(interface, KSZ8864_GLOBAL_CTRL4);
595 
596  //Retrieve host interface speed
597  if((status & KSZ8864_GLOBAL_CTRL4_SW4_SPEED) != 0)
598  {
599  linkSpeed = NIC_LINK_SPEED_10MBPS;
600  }
601  else
602  {
603  linkSpeed = NIC_LINK_SPEED_100MBPS;
604  }
605  }
606  else
607  {
608  //The specified port number is not valid
609  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
610  }
611 
612  //Return link speed
613  return linkSpeed;
614 }
615 
616 
617 /**
618  * @brief Get duplex mode
619  * @param[in] interface Underlying network interface
620  * @param[in] port Port number
621  * @return Duplex mode
622  **/
623 
625 {
626  uint16_t status;
627  NicDuplexMode duplexMode;
628 
629  //Check port number
630  if(port == KSZ8864_PORT1 || port == KSZ8864_PORT2)
631  {
632  //Read port status 0 register
633  status = ksz8864ReadSwitchReg(interface, KSZ8864_PORTn_STAT0(port));
634 
635  //Retrieve current duplex mode
636  if((status & KSZ8864_PORTn_STAT0_OP_DUPLEX) != 0)
637  {
638  duplexMode = NIC_FULL_DUPLEX_MODE;
639  }
640  else
641  {
642  duplexMode = NIC_HALF_DUPLEX_MODE;
643  }
644  }
645  else if(port == KSZ8864_PORT3)
646  {
647  //Port 3 duplex mode
648  duplexMode = NIC_FULL_DUPLEX_MODE;
649  }
650  else if(port == KSZ8864_PORT4)
651  {
652  //Read global control 4 register
653  status = ksz8864ReadSwitchReg(interface, KSZ8864_GLOBAL_CTRL4);
654 
655  //Retrieve host interface duplex mode
657  {
658  duplexMode = NIC_HALF_DUPLEX_MODE;
659  }
660  else
661  {
662  duplexMode = NIC_FULL_DUPLEX_MODE;
663  }
664  }
665  else
666  {
667  //The specified port number is not valid
668  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
669  }
670 
671  //Return duplex mode
672  return duplexMode;
673 }
674 
675 
676 /**
677  * @brief Set port state
678  * @param[in] interface Underlying network interface
679  * @param[in] port Port number
680  * @param[in] state Port state
681  **/
682 
683 void ksz8864SetPortState(NetInterface *interface, uint8_t port,
684  SwitchPortState state)
685 {
686  uint8_t temp;
687 
688  //Check port number
689  if(port >= KSZ8864_PORT1 && port <= KSZ8864_PORT3)
690  {
691  //Read port control 2 register
692  temp = ksz8864ReadSwitchReg(interface, KSZ8864_PORTn_CTRL2(port));
693 
694  //Update port state
695  switch(state)
696  {
697  //Listening state
702  break;
703 
704  //Learning state
709  break;
710 
711  //Forwarding state
716  break;
717 
718  //Disabled state
719  default:
723  break;
724  }
725 
726  //Write the value back to port control 2 register
728  }
729 }
730 
731 
732 /**
733  * @brief Get port state
734  * @param[in] interface Underlying network interface
735  * @param[in] port Port number
736  * @return Port state
737  **/
738 
740 {
741  uint8_t temp;
742  SwitchPortState state;
743 
744  //Check port number
745  if(port >= KSZ8864_PORT1 && port <= KSZ8864_PORT3)
746  {
747  //Read port control 2 register
748  temp = ksz8864ReadSwitchReg(interface, KSZ8864_PORTn_CTRL2(port));
749 
750  //Check port state
751  if((temp & KSZ8864_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
752  (temp & KSZ8864_PORTn_CTRL2_RECEIVE_EN) == 0 &&
753  (temp & KSZ8864_PORTn_CTRL2_LEARNING_DIS) != 0)
754  {
755  //Disabled state
757  }
758  else if((temp & KSZ8864_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
759  (temp & KSZ8864_PORTn_CTRL2_RECEIVE_EN) != 0 &&
760  (temp & KSZ8864_PORTn_CTRL2_LEARNING_DIS) != 0)
761  {
762  //Listening state
764  }
765  else if((temp & KSZ8864_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
766  (temp & KSZ8864_PORTn_CTRL2_RECEIVE_EN) == 0 &&
767  (temp & KSZ8864_PORTn_CTRL2_LEARNING_DIS) == 0)
768  {
769  //Learning state
771  }
772  else if((temp & KSZ8864_PORTn_CTRL2_TRANSMIT_EN) != 0 &&
773  (temp & KSZ8864_PORTn_CTRL2_RECEIVE_EN) != 0 &&
774  (temp & KSZ8864_PORTn_CTRL2_LEARNING_DIS) == 0)
775  {
776  //Forwarding state
778  }
779  else
780  {
781  //Unknown state
783  }
784  }
785  else
786  {
787  //The specified port number is not valid
789  }
790 
791  //Return port state
792  return state;
793 }
794 
795 
796 /**
797  * @brief Set aging time for dynamic filtering entries
798  * @param[in] interface Underlying network interface
799  * @param[in] agingTime Aging time, in seconds
800  **/
801 
802 void ksz8864SetAgingTime(NetInterface *interface, uint32_t agingTime)
803 {
804  //The aging period is fixed to 300 seconds
805 }
806 
807 
808 /**
809  * @brief Enable IGMP snooping
810  * @param[in] interface Underlying network interface
811  * @param[in] enable Enable or disable IGMP snooping
812  **/
813 
815 {
816  uint8_t temp;
817 
818  //Read global control 3 register
819  temp = ksz8864ReadSwitchReg(interface, KSZ8864_GLOBAL_CTRL3);
820 
821  //Enable or disable IGMP snooping
822  if(enable)
823  {
825  }
826  else
827  {
829  }
830 
831  //Write the value back to global control 3 register
833 }
834 
835 
836 /**
837  * @brief Enable MLD snooping
838  * @param[in] interface Underlying network interface
839  * @param[in] enable Enable or disable MLD snooping
840  **/
841 
843 {
844  //Not implemented
845 }
846 
847 
848 /**
849  * @brief Enable reserved multicast table
850  * @param[in] interface Underlying network interface
851  * @param[in] enable Enable or disable reserved group addresses
852  **/
853 
855 {
856  uint_t i;
857  SwitchFdbEntry entry;
858 
859  //The reserved group addresses are in the range of 01-80-C2-00-00-00 to
860  //01-80-C2-00-00-0F
861  for(i = 0; i <= 15; i++)
862  {
863  //Specify the reserved group address to be added or removed
864  entry.macAddr.b[0] = 0x01;
865  entry.macAddr.b[1] = 0x80;
866  entry.macAddr.b[2] = 0xC2;
867  entry.macAddr.b[3] = 0x00;
868  entry.macAddr.b[4] = 0x00;
869  entry.macAddr.b[5] = i;
870 
871  //Format forwarding database entry
872  entry.srcPort = 0;
874  entry.override = TRUE;
875 
876  //Update the static MAC table
877  if(enable)
878  {
879  ksz8864AddStaticFdbEntry(interface, &entry);
880  }
881  else
882  {
883  ksz8864DeleteStaticFdbEntry(interface, &entry);
884  }
885  }
886 }
887 
888 
889 /**
890  * @brief Add a new entry to the static MAC table
891  * @param[in] interface Underlying network interface
892  * @param[in] entry Pointer to the forwarding database entry
893  * @return Error code
894  **/
895 
897  const SwitchFdbEntry *entry)
898 {
899  error_t error;
900  uint_t i;
901  uint_t j;
902  uint8_t *p;
903  SwitchFdbEntry currentEntry;
904  Ksz8864StaticMacEntryW newEntry;
905 
906  //Keep track of the first free entry
908 
909  //Loop through the static MAC table
910  for(i = 0; i < KSZ8864_STATIC_MAC_TABLE_SIZE; i++)
911  {
912  //Read current entry
913  error = ksz8864GetStaticFdbEntry(interface, i, &currentEntry);
914 
915  //Valid entry?
916  if(!error)
917  {
918  //Check whether the table already contains the specified MAC address
919  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
920  {
921  j = i;
922  break;
923  }
924  }
925  else
926  {
927  //Keep track of the first free entry
929  {
930  j = i;
931  }
932  }
933  }
934 
935  //Any entry available?
937  {
938  //Format MAC entry
939  newEntry.fid = 0;
940  newEntry.useFid = 0;
941  newEntry.override = entry->override;
942  newEntry.valid = TRUE;
943  newEntry.reserved = 0;
944  newEntry.macAddr = entry->macAddr;
945 
946  //Set the relevant forward ports
947  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
948  {
949  newEntry.forwardPorts = KSZ8864_PORT4_MASK;
950  }
951  else
952  {
953  newEntry.forwardPorts = entry->destPorts & KSZ8864_PORT_MASK;
954  }
955 
956  //Select the static MAC address table
960 
961  //Point to the MAC entry
962  p = (uint8_t *) &newEntry;
963 
964  //Write indirect data registers
965  for(i = 0; i < sizeof(Ksz8864StaticMacEntryW); i++)
966  {
967  ksz8864WriteSwitchReg(interface, KSZ8864_INDIRECT_DATA7 + i, p[i]);
968  }
969 
970  //Setup a write operation
974 
975  //Trigger the write operation
977 
978  //Successful processing
979  error = NO_ERROR;
980  }
981  else
982  {
983  //The static MAC table is full
984  error = ERROR_TABLE_FULL;
985  }
986 
987  //Return status code
988  return error;
989 }
990 
991 
992 /**
993  * @brief Remove an entry from the static MAC table
994  * @param[in] interface Underlying network interface
995  * @param[in] entry Forwarding database entry to remove from the table
996  * @return Error code
997  **/
998 
1000  const SwitchFdbEntry *entry)
1001 {
1002  error_t error;
1003  uint_t i;
1004  uint_t j;
1005  SwitchFdbEntry currentEntry;
1006 
1007  //Loop through the static MAC table
1008  for(j = 0; j < KSZ8864_STATIC_MAC_TABLE_SIZE; j++)
1009  {
1010  //Read current entry
1011  error = ksz8864GetStaticFdbEntry(interface, j, &currentEntry);
1012 
1013  //Valid entry?
1014  if(!error)
1015  {
1016  //Check whether the table contains the specified MAC address
1017  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1018  {
1019  break;
1020  }
1021  }
1022  }
1023 
1024  //Any matching entry?
1026  {
1027  //Select the static MAC address table
1031 
1032  //Clear indirect data registers
1033  for(i = 0; i < sizeof(Ksz8864StaticMacEntryW); i++)
1034  {
1035  ksz8864WriteSwitchReg(interface, KSZ8864_INDIRECT_DATA7 + i, 0);
1036  }
1037 
1038  //Setup a write operation
1042 
1043  //Trigger the write operation
1045 
1046  //Successful processing
1047  error = NO_ERROR;
1048  }
1049  else
1050  {
1051  //The static MAC table does not contain the specified address
1052  error = ERROR_NOT_FOUND;
1053  }
1054 
1055  //Return status code
1056  return error;
1057 }
1058 
1059 
1060 /**
1061  * @brief Read an entry from the static MAC table
1062  * @param[in] interface Underlying network interface
1063  * @param[in] index Zero-based index of the entry to read
1064  * @param[out] entry Pointer to the forwarding database entry
1065  * @return Error code
1066  **/
1067 
1069  SwitchFdbEntry *entry)
1070 {
1071  error_t error;
1072  uint_t i;
1073  uint8_t *p;
1074  Ksz8864StaticMacEntryR currentEntry;
1075 
1076  //Check index parameter
1077  if(index < KSZ8864_STATIC_MAC_TABLE_SIZE)
1078  {
1079  //Select the static MAC address table
1083 
1084  //Trigger the read operation
1085  ksz8864WriteSwitchReg(interface, KSZ8864_INDIRECT_CTRL1, index);
1086 
1087  //Point to the MAC entry
1088  p = (uint8_t *) &currentEntry;
1089 
1090  //Read indirect data registers
1091  for(i = 0; i < sizeof(Ksz8864StaticMacEntryR); i++)
1092  {
1093  p[i] = ksz8864ReadSwitchReg(interface, KSZ8864_INDIRECT_DATA7 + i);
1094  }
1095 
1096  //Valid entry?
1097  if(currentEntry.valid)
1098  {
1099  //Copy MAC entry
1100  entry->macAddr = currentEntry.macAddr;
1101  entry->srcPort = 0;
1102  entry->destPorts = currentEntry.forwardPorts & KSZ8864_PORT_MASK;
1103  entry->override = currentEntry.override;
1104 
1105  //Successful processing
1106  error = NO_ERROR;
1107  }
1108  else
1109  {
1110  //The entry is not valid
1111  error = ERROR_INVALID_ENTRY;
1112  }
1113  }
1114  else
1115  {
1116  //The end of the table has been reached
1117  error = ERROR_END_OF_TABLE;
1118  }
1119 
1120  //Return status code
1121  return error;
1122 }
1123 
1124 
1125 /**
1126  * @brief Flush static MAC table
1127  * @param[in] interface Underlying network interface
1128  **/
1129 
1131 {
1132  uint_t i;
1133  uint_t temp;
1134  uint8_t state[4];
1135 
1136  //Loop through the ports
1137  for(i = KSZ8864_PORT1; i <= KSZ8864_PORT4; i++)
1138  {
1139  //Save the current state of the port
1140  state[i - 1] = ksz8864ReadSwitchReg(interface, KSZ8864_PORTn_CTRL2(i));
1141 
1142  //Turn off learning capability
1144  state[i - 1] | KSZ8864_PORTn_CTRL2_LEARNING_DIS);
1145  }
1146 
1147  //All the entries associated with a port that has its learning capability
1148  //being turned off will be flushed
1149  temp = ksz8864ReadSwitchReg(interface, KSZ8864_GLOBAL_CTRL0);
1151  ksz8864WriteSwitchReg(interface, KSZ8864_GLOBAL_CTRL0, temp);
1152 
1153  //Loop through the ports
1154  for(i = KSZ8864_PORT1; i <= KSZ8864_PORT4; i++)
1155  {
1156  //Restore the original state of the port
1157  ksz8864WriteSwitchReg(interface, KSZ8864_PORTn_CTRL2(i), state[i - 1]);
1158  }
1159 }
1160 
1161 
1162 /**
1163  * @brief Read an entry from the dynamic MAC table
1164  * @param[in] interface Underlying network interface
1165  * @param[in] index Zero-based index of the entry to read
1166  * @param[out] entry Pointer to the forwarding database entry
1167  * @return Error code
1168  **/
1169 
1171  SwitchFdbEntry *entry)
1172 {
1173  error_t error;
1174  uint_t i;
1175  uint_t n;
1176  uint8_t *p;
1177  Ksz8864DynamicMacEntry currentEntry;
1178 
1179  //Check index parameter
1180  if(index < KSZ8864_DYNAMIC_MAC_TABLE_SIZE)
1181  {
1182  //Read the MAC entry at the specified index
1183  do
1184  {
1185  //Select the dynamic MAC address table
1189  (MSB(index) & KSZ8864_INDIRECT_CTRL0_ADDR_H));
1190 
1191  //Trigger the read operation
1192  ksz8864WriteSwitchReg(interface, KSZ8864_INDIRECT_CTRL1, LSB(index));
1193 
1194  //Point to the MAC entry
1195  p = (uint8_t *) &currentEntry;
1196 
1197  //Read indirect data registers
1198  for(i = 0; i < sizeof(Ksz8864DynamicMacEntry); i++)
1199  {
1200  p[i] = ksz8864ReadSwitchReg(interface, KSZ8864_INDIRECT_DATA8 + i);
1201  }
1202 
1203  //Retry until the entry is ready
1204  } while(currentEntry.dataNotReady);
1205 
1206  //Check whether there are valid entries in the table
1207  if(!currentEntry.macEmpty)
1208  {
1209  //Retrieve the number of valid entries
1210  n = ((currentEntry.numValidEntriesH << 3) |
1211  currentEntry.numValidEntriesL) + 1;
1212  }
1213  else
1214  {
1215  //The table is empty
1216  n = 0;
1217  }
1218 
1219  //Valid entry?
1220  if(index < n)
1221  {
1222  //Copy MAC entry
1223  entry->macAddr = currentEntry.macAddr;
1224  entry->srcPort = currentEntry.sourcePort;
1225  entry->destPorts = 0;
1226  entry->override = FALSE;
1227 
1228  //Successful processing
1229  error = NO_ERROR;
1230  }
1231  else
1232  {
1233  //The end of the table has been reached
1234  error = ERROR_END_OF_TABLE;
1235  }
1236  }
1237  else
1238  {
1239  //The end of the table has been reached
1240  error = ERROR_END_OF_TABLE;
1241  }
1242 
1243  //Return status code
1244  return error;
1245 }
1246 
1247 
1248 /**
1249  * @brief Flush dynamic MAC table
1250  * @param[in] interface Underlying network interface
1251  * @param[in] port Port number
1252  **/
1253 
1255 {
1256  uint_t i;
1257  uint_t temp;
1258  uint8_t state[4];
1259 
1260  //Loop through the ports
1261  for(i = KSZ8864_PORT1; i <= KSZ8864_PORT4; i++)
1262  {
1263  //Matching port number?
1264  if(i == port || port == 0)
1265  {
1266  //Save the current state of the port
1267  state[i - 1] = ksz8864ReadSwitchReg(interface, KSZ8864_PORTn_CTRL2(i));
1268 
1269  //Turn off learning capability
1271  state[i - 1] | KSZ8864_PORTn_CTRL2_LEARNING_DIS);
1272  }
1273  }
1274 
1275  //All the entries associated with a port that has its learning capability
1276  //being turned off will be flushed
1277  temp = ksz8864ReadSwitchReg(interface, KSZ8864_GLOBAL_CTRL0);
1279  ksz8864WriteSwitchReg(interface, KSZ8864_GLOBAL_CTRL0, temp);
1280 
1281  //Loop through the ports
1282  for(i = KSZ8864_PORT1; i <= KSZ8864_PORT4; i++)
1283  {
1284  //Matching port number?
1285  if(i == port || port == 0)
1286  {
1287  //Restore the original state of the port
1288  ksz8864WriteSwitchReg(interface, KSZ8864_PORTn_CTRL2(i), state[i - 1]);
1289  }
1290  }
1291 }
1292 
1293 
1294 /**
1295  * @brief Set forward ports for unknown multicast packets
1296  * @param[in] interface Underlying network interface
1297  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1298  * @param[in] forwardPorts Port map
1299  **/
1300 
1302  bool_t enable, uint32_t forwardPorts)
1303 {
1304  uint8_t temp;
1305 
1306  //Read global control 16 register
1307  temp = ksz8864ReadSwitchReg(interface, KSZ8864_GLOBAL_CTRL16);
1308 
1309  //Clear port map
1311 
1312  //Enable or disable forwarding of unknown multicast packets
1313  if(enable)
1314  {
1315  //Enable forwarding
1317 
1318  //Check whether unknown multicast packets should be forwarded to the CPU port
1319  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1320  {
1322  }
1323 
1324  //Select the desired forward ports
1325  temp |= forwardPorts & KSZ8864_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL;
1326  }
1327  else
1328  {
1329  //Disable forwarding
1331  }
1332 
1333  //Write the value back to global control 16 register
1334  ksz8864WriteSwitchReg(interface, KSZ8864_GLOBAL_CTRL16, temp);
1335 }
1336 
1337 
1338 /**
1339  * @brief Write PHY register
1340  * @param[in] interface Underlying network interface
1341  * @param[in] port Port number
1342  * @param[in] address PHY register address
1343  * @param[in] data Register value
1344  **/
1345 
1346 void ksz8864WritePhyReg(NetInterface *interface, uint8_t port,
1347  uint8_t address, uint16_t data)
1348 {
1349  //Write the specified PHY register
1350  if(interface->smiDriver != NULL)
1351  {
1352  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1353  }
1354  else
1355  {
1356  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1357  }
1358 }
1359 
1360 
1361 /**
1362  * @brief Read PHY register
1363  * @param[in] interface Underlying network interface
1364  * @param[in] port Port number
1365  * @param[in] address PHY register address
1366  * @return Register value
1367  **/
1368 
1369 uint16_t ksz8864ReadPhyReg(NetInterface *interface, uint8_t port,
1370  uint8_t address)
1371 {
1372  uint16_t data;
1373 
1374  //Read the specified PHY register
1375  if(interface->smiDriver != NULL)
1376  {
1377  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1378  }
1379  else
1380  {
1381  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1382  }
1383 
1384  //Return the value of the PHY register
1385  return data;
1386 }
1387 
1388 
1389 /**
1390  * @brief Dump PHY registers for debugging purpose
1391  * @param[in] interface Underlying network interface
1392  * @param[in] port Port number
1393  **/
1394 
1395 void ksz8864DumpPhyReg(NetInterface *interface, uint8_t port)
1396 {
1397  uint8_t i;
1398 
1399  //Loop through PHY registers
1400  for(i = 0; i < 32; i++)
1401  {
1402  //Display current PHY register
1403  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1404  ksz8864ReadPhyReg(interface, port, i));
1405  }
1406 
1407  //Terminate with a line feed
1408  TRACE_DEBUG("\r\n");
1409 }
1410 
1411 
1412 /**
1413  * @brief Write switch register
1414  * @param[in] interface Underlying network interface
1415  * @param[in] address Switch register address
1416  * @param[in] data Register value
1417  **/
1418 
1419 void ksz8864WriteSwitchReg(NetInterface *interface, uint8_t address,
1420  uint8_t data)
1421 {
1422  uint8_t phyAddr;
1423  uint8_t regAddr;
1424 
1425  //SPI slave mode?
1426  if(interface->spiDriver != NULL)
1427  {
1428  //Pull the CS pin low
1429  interface->spiDriver->assertCs();
1430 
1431  //Set up a write operation
1432  interface->spiDriver->transfer(KSZ8864_SPI_CMD_WRITE);
1433  //Write register address
1434  interface->spiDriver->transfer(address);
1435 
1436  //Write data
1437  interface->spiDriver->transfer(data);
1438 
1439  //Terminate the operation by raising the CS pin
1440  interface->spiDriver->deassertCs();
1441  }
1442  else
1443  {
1444  //SMI register write access is selected when opcode is set to 10 and
1445  //bits 2:1 of the PHY address are set to 11
1446  phyAddr = 0x06 | ((address >> 3) & 0x18) | ((address >> 5) & 0x01);
1447 
1448  //Register address field forms register address bits 4:0
1449  regAddr = address & 0x1F;
1450 
1451  //Registers are 8 data bits wide. For write operation, data bits 15:8
1452  //are not defined, and hence can be set to either zeroes or ones
1453  if(interface->smiDriver != NULL)
1454  {
1455  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr,
1456  data);
1457  }
1458  else
1459  {
1460  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr,
1461  data);
1462  }
1463  }
1464 }
1465 
1466 
1467 /**
1468  * @brief Read switch register
1469  * @param[in] interface Underlying network interface
1470  * @param[in] address Switch register address
1471  * @return Register value
1472  **/
1473 
1474 uint8_t ksz8864ReadSwitchReg(NetInterface *interface, uint8_t address)
1475 {
1476  uint8_t phyAddr;
1477  uint8_t regAddr;
1478  uint8_t data;
1479 
1480  //SPI slave mode?
1481  if(interface->spiDriver != NULL)
1482  {
1483  //Pull the CS pin low
1484  interface->spiDriver->assertCs();
1485 
1486  //Set up a read operation
1487  interface->spiDriver->transfer(KSZ8864_SPI_CMD_READ);
1488  //Write register address
1489  interface->spiDriver->transfer(address);
1490 
1491  //Read data
1492  data = interface->spiDriver->transfer(0xFF);
1493 
1494  //Terminate the operation by raising the CS pin
1495  interface->spiDriver->deassertCs();
1496  }
1497  else
1498  {
1499  //SMI register read access is selected when opcode is set to 10 and
1500  //bits 2:1 of the PHY address are set to 11
1501  phyAddr = 0x06 | ((address >> 3) & 0x18) | ((address >> 5) & 0x01);
1502 
1503  //Register address field forms register address bits 4:0
1504  regAddr = address & 0x1F;
1505 
1506  //Registers are 8 data bits wide. For read operation, data bits 15:8
1507  //are read back as zeroes
1508  if(interface->smiDriver != NULL)
1509  {
1510  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1511  regAddr) & 0xFF;
1512  }
1513  else
1514  {
1515  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
1516  regAddr) & 0xFF;
1517  }
1518  }
1519 
1520  //Return register value
1521  return data;
1522 }
1523 
1524 
1525 /**
1526  * @brief Dump switch registers for debugging purpose
1527  * @param[in] interface Underlying network interface
1528  **/
1529 
1531 {
1532  uint16_t i;
1533 
1534  //Loop through switch registers
1535  for(i = 0; i < 256; i++)
1536  {
1537  //Display current switch register
1538  TRACE_DEBUG("0x%02" PRIX16 " (%02" PRIu16 ") : 0x%02" PRIX8 "\r\n",
1539  i, i, ksz8864ReadSwitchReg(interface, i));
1540  }
1541 
1542  //Terminate with a line feed
1543  TRACE_DEBUG("\r\n");
1544 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:601
#define KSZ8864_TAIL_TAG_SRC_PORT
void ksz8864EnableIrq(NetInterface *interface)
Enable interrupts.
#define NetContext
Definition: net.h:36
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
uint32_t destPorts
Definition: nic.h:152
void ksz8864SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
error_t ksz8864Init(NetInterface *interface)
KSZ8864 Ethernet switch initialization.
#define KSZ8864_SPI_CMD_WRITE
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
uint32_t ksz8864GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
#define KSZ8864_INDIRECT_CTRL0
#define KSZ8864_INDIRECT_DATA7
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
void ksz8864DumpSwitchReg(NetInterface *interface)
Dump switch registers for debugging purpose.
KSZ8864 4-port Ethernet switch driver.
void ksz8864SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
@ ERROR_END_OF_TABLE
Definition: error.h:292
#define KSZ8864_TAIL_TAG_DEST_PORT1
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 KSZ8864_INDIRECT_CTRL0_TABLE_SEL_DYNAMIC_MAC
uint8_t macEmpty
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
#define KSZ8864_INDIRECT_DATA8
uint8_t dataNotReady
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
#define KSZ8864_GLOBAL_CTRL10_TAIL_TAG_EN
void ksz8864EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
uint8_t useFid
error_t ksz8864AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
@ ERROR_INVALID_PORT
Definition: error.h:104
#define KSZ8864_STATIC_MAC_TABLE_SIZE
#define KSZ8864_GLOBAL_CTRL3
@ ERROR_TABLE_FULL
Definition: error.h:291
uint8_t forwardPorts
#define KSZ8864_PORT2
EthHeader
Definition: ethernet.h:225
error_t ksz8864GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
#define KSZ8864_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define KSZ8864_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP
#define KSZ8864_PORTn_CTRL2_RECEIVE_EN
#define KSZ8864_CHIP_ID1
uint8_t override
#define KSZ8864_PORTn_STAT1(port)
bool_t ksz8864GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
#define FALSE
Definition: os_port.h:46
#define KSZ8864_GLOBAL_CTRL3_SW4_IGMP_SNOOP_EN
error_t
Error codes.
Definition: error.h:43
void ksz8864WriteSwitchReg(NetInterface *interface, uint8_t address, uint8_t data)
Write switch register.
Static MAC table entry (read operation)
#define KSZ8864_GLOBAL_CTRL4
void ksz8864EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
uint8_t sourcePort
MacAddr macAddr
#define KSZ8864_PORTn_STAT0_OP_DUPLEX
#define KSZ8864_PORTn_CTRL2_LEARNING_DIS
#define KSZ8864_PORTn_STAT0(port)
const SwitchDriver ksz8864SwitchDriver
KSZ8864 Ethernet switch driver.
#define NetRxAncillary
Definition: net_misc.h:40
#define KSZ8864_INDIRECT_CTRL0_TABLE_SEL_STATIC_MAC
Static MAC table entry (write operation)
#define NetInterface
Definition: net.h:40
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
uint8_t ksz8864ReadSwitchReg(NetInterface *interface, uint8_t address)
Read switch register.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
__weak_func void ksz8864Tick(NetInterface *interface)
KSZ8864 timer handler.
#define KSZ8864_PORT4_MASK
#define KSZ8864_INDIRECT_CTRL0_ADDR_H
#define KSZ8864_TAIL_TAG_PORT_SEL
__weak_func void ksz8864InitHook(NetInterface *interface)
KSZ8864 custom configuration.
#define KSZ8864_INDIRECT_CTRL1
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
error_t ksz8864UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
#define KSZ8864_PORT3
#define NetTxAncillary
Definition: net_misc.h:36
error_t ksz8864DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
void ksz8864DisableIrq(NetInterface *interface)
Disable interrupts.
#define KSZ8864_PORTn_CTRL2(port)
#define MSB(x)
Definition: os_port.h:59
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
#define TRACE_INFO(...)
Definition: debug.h:105
#define KSZ8864_TAIL_TAG_NORMAL_ADDR_LOOKUP
uint8_t length
Definition: tcp.h:375
#define KSZ8864_PORT4
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
uint8_t forwardPorts
#define KSZ8864_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL
#define KSZ8864_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_PORT4
MacAddr macAddr
NicDuplexMode ksz8864GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
uint8_t fid
#define KSZ8864_GLOBAL_CTRL0
#define KSZ8864_PORT1
const uint8_t ksz8864IngressTailTag[4]
Tail tag rules (host to KSZ8864)
#define KSZ8864_CHIP_ID0
uint8_t valid
#define KSZ8864_GLOBAL_CTRL0_FLUSH_STATIC_MAC_TABLE
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
#define KSZ8864_CHIP_ID1_START_SWITCH
uint16_t port
Definition: dns_common.h:270
MacAddr macAddr
#define TRACE_DEBUG(...)
Definition: debug.h:119
void ksz8864SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
uint8_t numValidEntriesL
uint16_t regAddr
__weak_func void ksz8864EventHandler(NetInterface *interface)
KSZ8864 event handler.
void ksz8864WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
#define KSZ8864_TAIL_TAG_DEST_PORT2
Ethernet switch driver.
Definition: nic.h:325
Dynamic MAC table entry.
uint8_t n
#define KSZ8864_PORT_MASK
@ 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
Ipv6Addr address[]
Definition: ipv6.h:345
NicDuplexMode
Duplex mode.
Definition: nic.h:122
MacAddr macAddr
Definition: nic.h:150
uint8_t srcPort
Definition: nic.h:151
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
#define KSZ8864_TAIL_TAG_DEST_PORT3
void ksz8864FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
#define KSZ8864_PORTn_CTRL2_TRANSMIT_EN
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
SwitchPortState ksz8864GetPortState(NetInterface *interface, uint8_t port)
Get port state.
void ksz8864EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
uint16_t ksz8864ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t ksz8864TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
error_t ksz8864GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
#define KSZ8864_GLOBAL_CTRL4_SW4_HALF_DUPLEX_MODE
#define KSZ8864_GLOBAL_CTRL10
#define KSZ8864_CHIP_ID0_FAMILY_ID_DEFAULT
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define KSZ8864_PORTn_STAT0_OP_SPEED
void ksz8864DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
void ksz8864FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
uint8_t numValidEntriesH
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
#define KSZ8864_SPI_CMD_READ
uint8_t valid
#define KSZ8864_DYNAMIC_MAC_TABLE_SIZE
#define KSZ8864_GLOBAL_CTRL4_SW4_SPEED
#define KSZ8864_GLOBAL_CTRL16
#define KSZ8864_GLOBAL_CTRL0_FLUSH_DYNAMIC_MAC_TABLE
Helper functions for Ethernet.
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
Debugging facilities.
#define KSZ8864_PORTn_STAT1_LINK_GOOD
Forwarding database entry.
Definition: nic.h:149
uint8_t reserved
#define KSZ8864_INDIRECT_CTRL0_READ
uint8_t override
#define KSZ8864_INDIRECT_CTRL0_WRITE