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-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.4
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
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 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  NetInterface *virtualInterface;
204 
205  //Loop through network interfaces
206  for(i = 0; i < NET_INTERFACE_COUNT; i++)
207  {
208  //Point to the current interface
209  virtualInterface = &netInterface[i];
210 
211  //Check whether the current virtual interface is attached to the
212  //physical interface
213  if(virtualInterface == interface ||
214  virtualInterface->parent == interface)
215  {
216  //Retrieve current link state
217  linkState = ksz8463GetLinkState(interface, virtualInterface->port);
218 
219  //Link up or link down event?
220  if(linkState != virtualInterface->linkState)
221  {
222  //Set event flag
223  interface->phyEvent = TRUE;
224  //Notify the TCP/IP stack of the event
226  }
227  }
228  }
229  }
230  else
231 #endif
232  {
233  //Initialize link state
234  linkState = FALSE;
235 
236  //Loop through the ports
238  {
239  //Retrieve current link state
240  if(ksz8463GetLinkState(interface, port))
241  {
242  linkState = TRUE;
243  }
244  }
245 
246  //Link up or link down event?
247  if(linkState != interface->linkState)
248  {
249  //Set event flag
250  interface->phyEvent = TRUE;
251  //Notify the TCP/IP stack of the event
253  }
254  }
255 }
256 
257 
258 /**
259  * @brief Enable interrupts
260  * @param[in] interface Underlying network interface
261  **/
262 
264 {
265 }
266 
267 
268 /**
269  * @brief Disable interrupts
270  * @param[in] interface Underlying network interface
271  **/
272 
274 {
275 }
276 
277 
278 /**
279  * @brief KSZ8463 event handler
280  * @param[in] interface Underlying network interface
281  **/
282 
284 {
285  uint_t port;
286  bool_t linkState;
287 
288 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
289  //Port separation mode?
290  if(interface->port != 0)
291  {
292  uint_t i;
293  NetInterface *virtualInterface;
294 
295  //Loop through network interfaces
296  for(i = 0; i < NET_INTERFACE_COUNT; i++)
297  {
298  //Point to the current interface
299  virtualInterface = &netInterface[i];
300 
301  //Check whether the current virtual interface is attached to the
302  //physical interface
303  if(virtualInterface == interface ||
304  virtualInterface->parent == interface)
305  {
306  //Get the port number associated with the current interface
307  port = virtualInterface->port;
308 
309  //Valid port?
310  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
311  {
312  //Read port status register
313  linkState = ksz8463GetLinkState(interface, port);
314 
315  //Link up event?
316  if(linkState && !virtualInterface->linkState)
317  {
318  //Retrieve host interface speed
319  interface->linkSpeed = ksz8463GetLinkSpeed(interface,
320  KSZ8463_PORT3);
321 
322  //Retrieve host interface duplex mode
323  interface->duplexMode = ksz8463GetDuplexMode(interface,
324  KSZ8463_PORT3);
325 
326  //Adjust MAC configuration parameters for proper operation
327  interface->nicDriver->updateMacConfig(interface);
328 
329  //Check current speed
330  virtualInterface->linkSpeed = ksz8463GetLinkSpeed(interface,
331  port);
332 
333  //Check current duplex mode
334  virtualInterface->duplexMode = ksz8463GetDuplexMode(interface,
335  port);
336 
337  //Update link state
338  virtualInterface->linkState = TRUE;
339 
340  //Process link state change event
341  nicNotifyLinkChange(virtualInterface);
342  }
343  //Link down event
344  else if(!linkState && virtualInterface->linkState)
345  {
346  //Update link state
347  virtualInterface->linkState = FALSE;
348 
349  //Process link state change event
350  nicNotifyLinkChange(virtualInterface);
351  }
352  }
353  }
354  }
355  }
356  else
357 #endif
358  {
359  //Initialize link state
360  linkState = FALSE;
361 
362  //Loop through the ports
364  {
365  //Retrieve current link state
366  if(ksz8463GetLinkState(interface, port))
367  {
368  linkState = TRUE;
369  }
370  }
371 
372  //Link up event?
373  if(linkState)
374  {
375  //Retrieve host interface speed
376  interface->linkSpeed = ksz8463GetLinkSpeed(interface, KSZ8463_PORT3);
377  //Retrieve host interface duplex mode
378  interface->duplexMode = ksz8463GetDuplexMode(interface, KSZ8463_PORT3);
379 
380  //Adjust MAC configuration parameters for proper operation
381  interface->nicDriver->updateMacConfig(interface);
382 
383  //Update link state
384  interface->linkState = TRUE;
385  }
386  else
387  {
388  //Update link state
389  interface->linkState = FALSE;
390  }
391 
392  //Process link state change event
393  nicNotifyLinkChange(interface);
394  }
395 }
396 
397 
398 /**
399  * @brief Add tail tag to Ethernet frame
400  * @param[in] interface Underlying network interface
401  * @param[in] buffer Multi-part buffer containing the payload
402  * @param[in,out] offset Offset to the first payload byte
403  * @param[in] ancillary Additional options passed to the stack along with
404  * the packet
405  * @return Error code
406  **/
407 
409  size_t *offset, NetTxAncillary *ancillary)
410 {
411  error_t error;
412 
413  //Initialize status code
414  error = NO_ERROR;
415 
416 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
417  //SPI slave mode?
418  if(interface->spiDriver != NULL)
419  {
420  //Valid port?
421  if(ancillary->port <= KSZ8463_PORT2)
422  {
423  size_t length;
424  const uint8_t *tailTag;
425 
426  //The one byte tail tagging is used to indicate the destination port
427  tailTag = &ksz8463IngressTailTag[ancillary->port];
428 
429  //Retrieve the length of the Ethernet frame
430  length = netBufferGetLength(buffer) - *offset;
431 
432  //The host controller should manually add padding to the packet before
433  //inserting the tail tag
434  error = ethPadFrame(buffer, &length);
435 
436  //Check status code
437  if(!error)
438  {
439  //The tail tag is inserted at the end of the packet, just before
440  //the CRC
441  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
442  }
443  }
444  else
445  {
446  //The port number is not valid
447  error = ERROR_INVALID_PORT;
448  }
449  }
450 #endif
451 
452  //Return status code
453  return error;
454 }
455 
456 
457 /**
458  * @brief Decode tail tag from incoming Ethernet frame
459  * @param[in] interface Underlying network interface
460  * @param[in,out] frame Pointer to the received Ethernet frame
461  * @param[in,out] length Length of the frame, in bytes
462  * @param[in,out] ancillary Additional options passed to the stack along with
463  * the packet
464  * @return Error code
465  **/
466 
467 error_t ksz8463UntagFrame(NetInterface *interface, uint8_t **frame,
468  size_t *length, NetRxAncillary *ancillary)
469 {
470  error_t error;
471 
472  //Initialize status code
473  error = NO_ERROR;
474 
475 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
476  //SPI slave mode?
477  if(interface->spiDriver != NULL)
478  {
479  //Valid Ethernet frame received?
480  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
481  {
482  uint8_t *tailTag;
483 
484  //The tail tag is inserted at the end of the packet, just before
485  //the CRC
486  tailTag = *frame + *length - sizeof(uint8_t);
487 
488  //The one byte tail tagging is used to indicate the source port
489  ancillary->port = (*tailTag & KSZ8463_TAIL_TAG_SRC_PORT) + 1;
490 
491  //Strip tail tag from Ethernet frame
492  *length -= sizeof(uint8_t);
493  }
494  else
495  {
496  //Drop the received frame
497  error = ERROR_INVALID_LENGTH;
498  }
499  }
500  else
501  {
502  //Tail tagging mode cannot be enabled through MDC/MDIO interface
503  ancillary->port = 0;
504  }
505 #endif
506 
507  //Return status code
508  return error;
509 }
510 
511 
512 /**
513  * @brief Get link state
514  * @param[in] interface Underlying network interface
515  * @param[in] port Port number
516  * @return Link state
517  **/
518 
520 {
521  uint16_t status;
522  bool_t linkState;
523 
524  //Check port number
525  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
526  {
527  //SPI slave mode?
528  if(interface->spiDriver != NULL)
529  {
530  //Read port status register
531  status = ksz8463ReadSwitchReg(interface, KSZ8463_PnSR(port));
532 
533  //Retrieve current link state
534  linkState = (status & KSZ8463_PnSR_LINK_STATUS) ? TRUE : FALSE;
535  }
536  else
537  {
538  //Read status register
539  status = ksz8463ReadPhyReg(interface, port, KSZ8463_BMSR);
540 
541  //Retrieve current link state
542  linkState = (status & KSZ8463_BMSR_LINK_STATUS) ? TRUE : FALSE;
543  }
544  }
545  else
546  {
547  //The specified port number is not valid
548  linkState = FALSE;
549  }
550 
551  //Return link status
552  return linkState;
553 }
554 
555 
556 /**
557  * @brief Get link speed
558  * @param[in] interface Underlying network interface
559  * @param[in] port Port number
560  * @return Link speed
561  **/
562 
563 uint32_t ksz8463GetLinkSpeed(NetInterface *interface, uint8_t port)
564 {
565  uint16_t status;
566  uint32_t linkSpeed;
567 
568  //Check port number
569  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
570  {
571  //Read port status register
572  status = ksz8463ReadSwitchReg(interface, KSZ8463_PnSR(port));
573 
574  //Retrieve current link speed
575  if((status & KSZ8463_PnSR_OP_SPEED) != 0)
576  {
577  linkSpeed = NIC_LINK_SPEED_100MBPS;
578  }
579  else
580  {
581  linkSpeed = NIC_LINK_SPEED_10MBPS;
582  }
583  }
584  else if(port == KSZ8463_PORT3)
585  {
586  //Read switch global control 3 register
587  status = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR3);
588 
589  //Retrieve host interface speed
590  if((status & KSZ8463_SGCR3_SW_MII_10BT) != 0)
591  {
592  linkSpeed = NIC_LINK_SPEED_10MBPS;
593  }
594  else
595  {
596  linkSpeed = NIC_LINK_SPEED_100MBPS;
597  }
598  }
599  else
600  {
601  //The specified port number is not valid
602  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
603  }
604 
605  //Return link status
606  return linkSpeed;
607 }
608 
609 
610 /**
611  * @brief Get duplex mode
612  * @param[in] interface Underlying network interface
613  * @param[in] port Port number
614  * @return Duplex mode
615  **/
616 
618 {
619  uint16_t status;
620  NicDuplexMode duplexMode;
621 
622  //Check port number
623  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
624  {
625  //Read port status register
626  status = ksz8463ReadSwitchReg(interface, KSZ8463_PnSR(port));
627 
628  //Retrieve current duplex mode
629  if((status & KSZ8463_PnSR_OP_DUPLEX) != 0)
630  {
631  duplexMode = NIC_FULL_DUPLEX_MODE;
632  }
633  else
634  {
635  duplexMode = NIC_HALF_DUPLEX_MODE;
636  }
637  }
638  else if(port == KSZ8463_PORT3)
639  {
640  //Read switch global control 3 register
641  status = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR3);
642 
643  //Retrieve host interface duplex mode
645  {
646  duplexMode = NIC_HALF_DUPLEX_MODE;
647  }
648  else
649  {
650  duplexMode = NIC_FULL_DUPLEX_MODE;
651  }
652  }
653  else
654  {
655  //The specified port number is not valid
656  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
657  }
658 
659  //Return duplex mode
660  return duplexMode;
661 }
662 
663 
664 /**
665  * @brief Set port state
666  * @param[in] interface Underlying network interface
667  * @param[in] port Port number
668  * @param[in] state Port state
669  **/
670 
671 void ksz8463SetPortState(NetInterface *interface, uint8_t port,
672  SwitchPortState state)
673 {
674  uint16_t temp;
675 
676  //Check port number
677  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
678  {
679  //Read port control 2 register
680  temp = ksz8463ReadSwitchReg(interface, KSZ8463_PnCR2(port));
681 
682  //Update port state
683  switch(state)
684  {
685  //Listening state
687  temp &= ~KSZ8463_PnCR2_TRANSMIT_EN;
688  temp |= KSZ8463_PnCR2_RECEIVE_EN;
690  break;
691 
692  //Learning state
694  temp &= ~KSZ8463_PnCR2_TRANSMIT_EN;
695  temp &= ~KSZ8463_PnCR2_RECEIVE_EN;
697  break;
698 
699  //Forwarding state
702  temp |= KSZ8463_PnCR2_RECEIVE_EN;
704  break;
705 
706  //Disabled state
707  default:
708  temp &= ~KSZ8463_PnCR2_TRANSMIT_EN;
709  temp &= ~KSZ8463_PnCR2_RECEIVE_EN;
711  break;
712  }
713 
714  //Write the value back to port control 2 register
715  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(port), temp);
716  }
717 }
718 
719 
720 /**
721  * @brief Get port state
722  * @param[in] interface Underlying network interface
723  * @param[in] port Port number
724  * @return Port state
725  **/
726 
728 {
729  uint16_t temp;
730  SwitchPortState state;
731 
732  //Check port number
733  if(port >= KSZ8463_PORT1 && port <= KSZ8463_PORT2)
734  {
735  //Read port control 2 register
736  temp = ksz8463ReadSwitchReg(interface, KSZ8463_PnCR2(port));
737 
738  //Check port state
739  if((temp & KSZ8463_PnCR2_TRANSMIT_EN) == 0 &&
740  (temp & KSZ8463_PnCR2_RECEIVE_EN) == 0 &&
741  (temp & KSZ8463_PnCR2_LEARNING_DIS) != 0)
742  {
743  //Disabled state
745  }
746  else if((temp & KSZ8463_PnCR2_TRANSMIT_EN) == 0 &&
747  (temp & KSZ8463_PnCR2_RECEIVE_EN) != 0 &&
748  (temp & KSZ8463_PnCR2_LEARNING_DIS) != 0)
749  {
750  //Listening state
752  }
753  else if((temp & KSZ8463_PnCR2_TRANSMIT_EN) == 0 &&
754  (temp & KSZ8463_PnCR2_RECEIVE_EN) == 0 &&
755  (temp & KSZ8463_PnCR2_LEARNING_DIS) == 0)
756  {
757  //Learning state
759  }
760  else if((temp & KSZ8463_PnCR2_TRANSMIT_EN) != 0 &&
761  (temp & KSZ8463_PnCR2_RECEIVE_EN) != 0 &&
762  (temp & KSZ8463_PnCR2_LEARNING_DIS) == 0)
763  {
764  //Forwarding state
766  }
767  else
768  {
769  //Unknown state
771  }
772  }
773  else
774  {
775  //The specified port number is not valid
777  }
778 
779  //Return port state
780  return state;
781 }
782 
783 
784 /**
785  * @brief Set aging time for dynamic filtering entries
786  * @param[in] interface Underlying network interface
787  * @param[in] agingTime Aging time, in seconds
788  **/
789 
790 void ksz8463SetAgingTime(NetInterface *interface, uint32_t agingTime)
791 {
792  //The aging period is fixed to 300 seconds
793 }
794 
795 
796 /**
797  * @brief Enable IGMP snooping
798  * @param[in] interface Underlying network interface
799  * @param[in] enable Enable or disable IGMP snooping
800  **/
801 
803 {
804  uint16_t temp;
805 
806  //Read switch global control 2 register
807  temp = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR2);
808 
809  //Enable or disable IGMP snooping
810  if(enable)
811  {
813  }
814  else
815  {
817  }
818 
819  //Write the value back to switch global control 2 register
820  ksz8463WriteSwitchReg(interface, KSZ8463_SGCR2, temp);
821 }
822 
823 
824 /**
825  * @brief Enable MLD snooping
826  * @param[in] interface Underlying network interface
827  * @param[in] enable Enable or disable MLD snooping
828  **/
829 
831 {
832  //Not implemented
833 }
834 
835 
836 /**
837  * @brief Enable reserved multicast table
838  * @param[in] interface Underlying network interface
839  * @param[in] enable Enable or disable reserved group addresses
840  **/
841 
843 {
844  //Not implemented
845 }
846 
847 
848 /**
849  * @brief Add a new entry to the static MAC table
850  * @param[in] interface Underlying network interface
851  * @param[in] entry Pointer to the forwarding database entry
852  * @return Error code
853  **/
854 
856  const SwitchFdbEntry *entry)
857 {
858  error_t error;
859  uint_t i;
860  uint_t j;
861  uint8_t *p;
862  SwitchFdbEntry currentEntry;
863  Ksz8463StaticMacEntry newEntry;
864 
865  //Keep track of the first free entry
867 
868  //Loop through the static MAC table
869  for(i = 0; i < KSZ8463_STATIC_MAC_TABLE_SIZE; i++)
870  {
871  //Read current entry
872  error = ksz8463GetStaticFdbEntry(interface, i, &currentEntry);
873 
874  //Valid entry?
875  if(!error)
876  {
877  //Check whether the table already contains the specified MAC address
878  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
879  {
880  j = i;
881  break;
882  }
883  }
884  else
885  {
886  //Keep track of the first free entry
888  {
889  j = i;
890  }
891  }
892  }
893 
894  //Any entry available?
896  {
897  //Format MAC entry
898  newEntry.reserved = 0;
899  newEntry.fidH = 0;
900  newEntry.fidL = 0;
901  newEntry.useFid = 0;
902  newEntry.override = entry->override;
903  newEntry.valid = TRUE;
904  newEntry.macAddr = entry->macAddr;
905 
906  //Set the relevant forward ports
907  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
908  {
909  newEntry.forwardPorts = KSZ8463_PORT3_MASK;
910  }
911  else
912  {
913  newEntry.forwardPorts = entry->destPorts & KSZ8463_PORT_MASK;
914  }
915 
916  //Point to the MAC entry
917  p = (uint8_t *) &newEntry;
918 
919  //Write indirect data registers
920  ksz8463WriteSwitchReg(interface, KSZ8463_IADR3, p[0] << 8 | p[1]);
921  ksz8463WriteSwitchReg(interface, KSZ8463_IADR2, p[2] << 8 | p[3]);
922  ksz8463WriteSwitchReg(interface, KSZ8463_IADR5, p[4] << 8 | p[5]);
923  ksz8463WriteSwitchReg(interface, KSZ8463_IADR4, p[6] << 8 | p[7]);
924 
925  //Trigger a write static MAC table operation
928 
929  //Successful processing
930  error = NO_ERROR;
931  }
932  else
933  {
934  //The static MAC table is full
935  error = ERROR_TABLE_FULL;
936  }
937 
938  //Return status code
939  return error;
940 }
941 
942 
943 /**
944  * @brief Remove an entry from the static MAC table
945  * @param[in] interface Underlying network interface
946  * @param[in] entry Forwarding database entry to remove from the table
947  * @return Error code
948  **/
949 
951  const SwitchFdbEntry *entry)
952 {
953  error_t error;
954  uint_t j;
955  SwitchFdbEntry currentEntry;
956 
957  //Loop through the static MAC table
958  for(j = 0; j < KSZ8463_STATIC_MAC_TABLE_SIZE; j++)
959  {
960  //Read current entry
961  error = ksz8463GetStaticFdbEntry(interface, j, &currentEntry);
962 
963  //Valid entry?
964  if(!error)
965  {
966  //Check whether the table contains the specified MAC address
967  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
968  {
969  break;
970  }
971  }
972  }
973 
974  //Any matching entry?
976  {
977  //Clear indirect data registers
978  ksz8463WriteSwitchReg(interface, KSZ8463_IADR3, 0);
979  ksz8463WriteSwitchReg(interface, KSZ8463_IADR2, 0);
980  ksz8463WriteSwitchReg(interface, KSZ8463_IADR5, 0);
981  ksz8463WriteSwitchReg(interface, KSZ8463_IADR4, 0);
982 
983  //Trigger a write static MAC table operation
986 
987  //Successful processing
988  error = NO_ERROR;
989  }
990  else
991  {
992  //The static MAC table does not contain the specified address
993  error = ERROR_NOT_FOUND;
994  }
995 
996  //Return status code
997  return error;
998 }
999 
1000 
1001 /**
1002  * @brief Read an entry from the static MAC table
1003  * @param[in] interface Underlying network interface
1004  * @param[in] index Zero-based index of the entry to read
1005  * @param[out] entry Pointer to the forwarding database entry
1006  * @return Error code
1007  **/
1008 
1010  SwitchFdbEntry *entry)
1011 {
1012  error_t error;
1013  uint16_t temp;
1014  uint8_t *p;
1015  Ksz8463StaticMacEntry currentEntry;
1016 
1017  //Check index parameter
1018  if(index < KSZ8463_STATIC_MAC_TABLE_SIZE)
1019  {
1020  //Trigger a read static MAC table operation
1023 
1024  //Point to the MAC entry
1025  p = (uint8_t *) &currentEntry;
1026 
1027  //Read indirect data registers
1028  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR3);
1029  p[0] = (temp >> 8) & 0xFF;
1030  p[1] = temp & 0xFF;
1031  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR2);
1032  p[2] = (temp >> 8) & 0xFF;
1033  p[3] = temp & 0xFF;
1034  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR5);
1035  p[4] = (temp >> 8) & 0xFF;
1036  p[5] = temp & 0xFF;
1037  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR4);
1038  p[6] = (temp >> 8) & 0xFF;
1039  p[7] = temp & 0xFF;
1040 
1041  //Valid entry?
1042  if(currentEntry.valid)
1043  {
1044  //Copy MAC entry
1045  entry->macAddr = currentEntry.macAddr;
1046  entry->srcPort = 0;
1047  entry->destPorts = currentEntry.forwardPorts & KSZ8463_PORT_MASK;
1048  entry->override = currentEntry.override;
1049 
1050  //Successful processing
1051  error = NO_ERROR;
1052  }
1053  else
1054  {
1055  //The entry is not valid
1056  error = ERROR_INVALID_ENTRY;
1057  }
1058  }
1059  else
1060  {
1061  //The end of the table has been reached
1062  error = ERROR_END_OF_TABLE;
1063  }
1064 
1065  //Return status code
1066  return error;
1067 }
1068 
1069 
1070 /**
1071  * @brief Flush static MAC table
1072  * @param[in] interface Underlying network interface
1073  **/
1074 
1076 {
1077  uint_t i;
1078  uint_t temp;
1079  uint16_t state[3];
1080 
1081  //Loop through the ports
1082  for(i = KSZ8463_PORT1; i <= KSZ8463_PORT3; i++)
1083  {
1084  //Save the current state of the port
1085  state[i - 1] = ksz8463ReadSwitchReg(interface, KSZ8463_PnCR2(i));
1086 
1087  //Turn off learning capability
1088  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(i),
1089  state[i - 1] | KSZ8463_PnCR2_LEARNING_DIS);
1090  }
1091 
1092  //All the entries associated with a port that has its learning capability
1093  //being turned off will be flushed
1094  temp = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR8);
1096  ksz8463WriteSwitchReg(interface, KSZ8463_SGCR8, temp);
1097 
1098  //Loop through the ports
1099  for(i = KSZ8463_PORT1; i <= KSZ8463_PORT3; i++)
1100  {
1101  //Restore the original state of the port
1102  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(i), state[i - 1]);
1103  }
1104 }
1105 
1106 
1107 /**
1108  * @brief Read an entry from the dynamic MAC table
1109  * @param[in] interface Underlying network interface
1110  * @param[in] index Zero-based index of the entry to read
1111  * @param[out] entry Pointer to the forwarding database entry
1112  * @return Error code
1113  **/
1114 
1116  SwitchFdbEntry *entry)
1117 {
1118  error_t error;
1119  uint16_t temp;
1120  uint_t n;
1121  uint8_t *p;
1122  Ksz8463DynamicMacEntry currentEntry;
1123 
1124  //Check index parameter
1125  if(index < KSZ8463_DYNAMIC_MAC_TABLE_SIZE)
1126  {
1127  //Read the MAC entry at the specified index
1128  do
1129  {
1130  //Trigger a read dynamic MAC table operation
1133 
1134  //Point to the MAC entry
1135  p = (uint8_t *) &currentEntry;
1136 
1137  //Read indirect data registers
1138  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR1);
1139  p[0] = temp & 0xFF;
1140  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR3);
1141  p[1] = (temp >> 8) & 0xFF;
1142  p[2] = temp & 0xFF;
1143  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR2);
1144  p[3] = (temp >> 8) & 0xFF;
1145  p[4] = temp & 0xFF;
1146  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR5);
1147  p[5] = (temp >> 8) & 0xFF;
1148  p[6] = temp & 0xFF;
1149  temp = ksz8463ReadSwitchReg(interface, KSZ8463_IADR4);
1150  p[7] = (temp >> 8) & 0xFF;
1151  p[8] = temp & 0xFF;
1152 
1153  //Retry until the entry is ready
1154  } while(currentEntry.dataNotReady);
1155 
1156  //Check whether there are valid entries in the table
1157  if(!currentEntry.macEmpty)
1158  {
1159  //Retrieve the number of valid entries
1160  n = ((currentEntry.numValidEntriesH << 8) |
1161  currentEntry.numValidEntriesL) + 1;
1162  }
1163  else
1164  {
1165  //The table is empty
1166  n = 0;
1167  }
1168 
1169  //Valid entry?
1170  if(index < n)
1171  {
1172  //Copy MAC entry
1173  entry->macAddr = currentEntry.macAddr;
1174  entry->srcPort = currentEntry.sourcePort + 1;
1175  entry->destPorts = 0;
1176  entry->override = FALSE;
1177 
1178  //Successful processing
1179  error = NO_ERROR;
1180  }
1181  else
1182  {
1183  //The end of the table has been reached
1184  error = ERROR_END_OF_TABLE;
1185  }
1186  }
1187  else
1188  {
1189  //The end of the table has been reached
1190  error = ERROR_END_OF_TABLE;
1191  }
1192 
1193  //Return status code
1194  return error;
1195 }
1196 
1197 
1198 /**
1199  * @brief Flush dynamic MAC table
1200  * @param[in] interface Underlying network interface
1201  * @param[in] port Port number
1202  **/
1203 
1205 {
1206  uint_t i;
1207  uint_t temp;
1208  uint16_t state[3];
1209 
1210  //Loop through the ports
1211  for(i = KSZ8463_PORT1; i <= KSZ8463_PORT3; i++)
1212  {
1213  //Matching port number?
1214  if(i == port || port == 0)
1215  {
1216  //Save the current state of the port
1217  state[i - 1] = ksz8463ReadSwitchReg(interface, KSZ8463_PnCR2(i));
1218 
1219  //Turn off learning capability
1220  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(i),
1221  state[i - 1] | KSZ8463_PnCR2_LEARNING_DIS);
1222  }
1223  }
1224 
1225  //All the entries associated with a port that has its learning capability
1226  //being turned off will be flushed
1227  temp = ksz8463ReadSwitchReg(interface, KSZ8463_SGCR8);
1229  ksz8463WriteSwitchReg(interface, KSZ8463_SGCR8, temp);
1230 
1231  //Loop through the ports
1232  for(i = KSZ8463_PORT1; i <= KSZ8463_PORT3; i++)
1233  {
1234  //Matching port number?
1235  if(i == port || port == 0)
1236  {
1237  //Restore the original state of the port
1238  ksz8463WriteSwitchReg(interface, KSZ8463_PnCR2(i), state[i - 1]);
1239  }
1240  }
1241 }
1242 
1243 
1244 /**
1245  * @brief Set forward ports for unknown multicast packets
1246  * @param[in] interface Underlying network interface
1247  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1248  * @param[in] forwardPorts Port map
1249  **/
1250 
1252  bool_t enable, uint32_t forwardPorts)
1253 {
1254  //Not implemented
1255 }
1256 
1257 
1258 /**
1259  * @brief Write PHY register
1260  * @param[in] interface Underlying network interface
1261  * @param[in] port Port number
1262  * @param[in] address PHY register address
1263  * @param[in] data Register value
1264  **/
1265 
1266 void ksz8463WritePhyReg(NetInterface *interface, uint8_t port,
1267  uint8_t address, uint16_t data)
1268 {
1269  //Write the specified PHY register
1270  if(interface->smiDriver != NULL)
1271  {
1272  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1273  }
1274  else
1275  {
1276  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1277  }
1278 }
1279 
1280 
1281 /**
1282  * @brief Read PHY register
1283  * @param[in] interface Underlying network interface
1284  * @param[in] port Port number
1285  * @param[in] address PHY register address
1286  * @return Register value
1287  **/
1288 
1289 uint16_t ksz8463ReadPhyReg(NetInterface *interface, uint8_t port,
1290  uint8_t address)
1291 {
1292  uint16_t data;
1293 
1294  //Read the specified PHY register
1295  if(interface->smiDriver != NULL)
1296  {
1297  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1298  }
1299  else
1300  {
1301  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1302  }
1303 
1304  //Return the value of the PHY register
1305  return data;
1306 }
1307 
1308 
1309 /**
1310  * @brief Dump PHY registers for debugging purpose
1311  * @param[in] interface Underlying network interface
1312  * @param[in] port Port number
1313  **/
1314 
1315 void ksz8463DumpPhyReg(NetInterface *interface, uint8_t port)
1316 {
1317  uint8_t i;
1318 
1319  //Loop through PHY registers
1320  for(i = 0; i < 32; i++)
1321  {
1322  //Display current PHY register
1323  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1324  ksz8463ReadPhyReg(interface, port, i));
1325  }
1326 
1327  //Terminate with a line feed
1328  TRACE_DEBUG("\r\n");
1329 }
1330 
1331 
1332 /**
1333  * @brief Write switch register
1334  * @param[in] interface Underlying network interface
1335  * @param[in] address Switch register address
1336  * @param[in] data Register value
1337  **/
1338 
1339 void ksz8463WriteSwitchReg(NetInterface *interface, uint16_t address,
1340  uint16_t data)
1341 {
1342  uint16_t command;
1343 
1344  //SPI slave mode?
1345  if(interface->spiDriver != NULL)
1346  {
1347  //Set up a write operation
1348  command = KSZ8463_SPI_CMD_WRITE;
1349 
1350  //The byte enable bits are set to indicate which bytes will be
1351  //transferred in the data phase
1352  if((address & 0x02) != 0)
1353  {
1355  }
1356  else
1357  {
1359  }
1360 
1361  //Set register address
1362  command |= (address << 4) & KSZ8463_SPI_CMD_ADDR;
1363 
1364  //Pull the CS pin low
1365  interface->spiDriver->assertCs();
1366 
1367  //Write 16-bit command
1368  interface->spiDriver->transfer(MSB(command));
1369  interface->spiDriver->transfer(LSB(command));
1370 
1371  //Write 16-bit data
1372  interface->spiDriver->transfer(LSB(data));
1373  interface->spiDriver->transfer(MSB(data));
1374 
1375  //Terminate the operation by raising the CS pin
1376  interface->spiDriver->deassertCs();
1377  }
1378  else
1379  {
1380  //The MDC/MDIO interface does not have access to all the configuration
1381  //registers. It can only access the standard MIIM registers
1382  }
1383 }
1384 
1385 
1386 /**
1387  * @brief Read switch register
1388  * @param[in] interface Underlying network interface
1389  * @param[in] address Switch register address
1390  * @return Register value
1391  **/
1392 
1393 uint16_t ksz8463ReadSwitchReg(NetInterface *interface, uint16_t address)
1394 {
1395  uint16_t data;
1396  uint16_t command;
1397 
1398  //SPI slave mode?
1399  if(interface->spiDriver != NULL)
1400  {
1401  //Set up a read operation
1402  command = KSZ8463_SPI_CMD_READ;
1403 
1404  //The byte enable bits are set to indicate which bytes will be
1405  //transferred in the data phase
1406  if((address & 0x02) != 0)
1407  {
1409  }
1410  else
1411  {
1413  }
1414 
1415  //Set register address
1416  command |= (address << 4) & KSZ8463_SPI_CMD_ADDR;
1417 
1418  //Pull the CS pin low
1419  interface->spiDriver->assertCs();
1420 
1421  //Write 16-bit command
1422  interface->spiDriver->transfer(MSB(command));
1423  interface->spiDriver->transfer(LSB(command));
1424 
1425  //Read 16-bit data
1426  data = interface->spiDriver->transfer(0xFF);
1427  data |= interface->spiDriver->transfer(0xFF) << 8;
1428 
1429  //Terminate the operation by raising the CS pin
1430  interface->spiDriver->deassertCs();
1431  }
1432  else
1433  {
1434  //The MDC/MDIO interface does not have access to all the configuration
1435  //registers. It can only access the standard MIIM registers
1436  data = 0;
1437  }
1438 
1439  //Return register value
1440  return data;
1441 }
1442 
1443 
1444 /**
1445  * @brief Dump switch registers for debugging purpose
1446  * @param[in] interface Underlying network interface
1447  **/
1448 
1450 {
1451  uint16_t i;
1452 
1453  //Loop through switch registers
1454  for(i = 0; i < 256; i += 2)
1455  {
1456  //Display current switch register
1457  TRACE_DEBUG("0x%02" PRIX16 " (%02" PRIu16 ") : 0x%04" PRIX16 "\r\n",
1458  i, i, ksz8463ReadSwitchReg(interface, i));
1459  }
1460 
1461  //Terminate with a line feed
1462  TRACE_DEBUG("\r\n");
1463 }
#define KSZ8463_PnCR2(port)
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:559
int bool_t
Definition: compiler_port.h:53
@ ERROR_NOT_FOUND
Definition: error.h:147
#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
#define netEvent
Definition: net_legacy.h:196
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:291
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:222
void ksz8463EnableIrq(NetInterface *interface)
Enable interrupts.
#define KSZ8463_TAIL_TAG_DEST_PORT1
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
void ksz8463EventHandler(NetInterface *interface)
KSZ8463 event handler.
#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 NET_INTERFACE_COUNT
Definition: net.h:114
#define KSZ8463_PnCR2_RECEIVE_EN
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_TABLE_FULL
Definition: error.h:290
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:223
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
#define netInterface
Definition: net_legacy.h:199
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.
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
@ 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:95
uint8_t length
Definition: tcp.h:368
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:267
#define TRACE_DEBUG(...)
Definition: debug.h:107
#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
@ ERROR_INVALID_ENTRY
Definition: error.h:289
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:325
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 ksz8463Tick(NetInterface *interface)
KSZ8463 timer handler.
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:50
#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