ksz8775_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz8775_driver.c
3  * @brief KSZ8775 5-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.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 KSZ8775 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ8775)
75  **/
76 
77 const uint8_t ksz8775IngressTailTag[5] =
78 {
84 };
85 
86 
87 /**
88  * @brief KSZ8775 Ethernet switch initialization
89  * @param[in] interface Underlying network interface
90  * @return Error code
91  **/
92 
94 {
95  uint_t port;
96  uint8_t temp;
97 
98  //Debug message
99  TRACE_INFO("Initializing KSZ8775...\r\n");
100 
101  //SPI slave mode?
102  if(interface->spiDriver != NULL)
103  {
104  //Initialize SPI interface
105  interface->spiDriver->init();
106 
107  //Wait for the serial interface to be ready
108  do
109  {
110  //Read CHIP_ID0 register
111  temp = ksz8775ReadSwitchReg(interface, KSZ8775_CHIP_ID0);
112 
113  //The returned data is invalid until the serial interface is ready
114  } while(temp != KSZ8775_CHIP_ID0_FAMILY_ID_DEFAULT);
115 
116 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
117  //Enable tail tag feature
118  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL10);
121 
122  //Disable packet size check
123  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL2);
126 #else
127  //Disable tail tag feature
128  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL10);
131 
132  //Enable packet size check
133  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL2);
136 #endif
137 
138  //Loop through the ports
140  {
141 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
142  //Port separation mode?
143  if(interface->port != 0)
144  {
145  //Disable packet transmission and address learning
147  }
148  else
149 #endif
150  {
151  //Enable transmission, reception and address learning
153  }
154  }
155 
156  //Disable EEE next page exchange (silicon errata workaround 2)
160 
161  //Improve receiver settings (silicon errata workaround 3)
165 
166  //Improve transmitter settings (silicon errata workaround 4)
170 
171  //Dump switch registers for debugging purpose
172  ksz8775DumpSwitchReg(interface);
173  }
174  else
175  {
176  //Initialize serial management interface
177  if(interface->smiDriver != NULL)
178  {
179  interface->smiDriver->init();
180  }
181 
182  //Loop through the ports
184  {
185  //Debug message
186  TRACE_DEBUG("Port %u:\r\n", port);
187  //Dump PHY registers for debugging purpose
188  ksz8775DumpPhyReg(interface, port);
189  }
190  }
191 
192  //Perform custom configuration
193  ksz8775InitHook(interface);
194 
195  //Force the TCP/IP stack to poll the link state at startup
196  interface->phyEvent = TRUE;
197  //Notify the TCP/IP stack of the event
199 
200  //Successful initialization
201  return NO_ERROR;
202 }
203 
204 
205 /**
206  * @brief KSZ8775 custom configuration
207  * @param[in] interface Underlying network interface
208  **/
209 
210 __weak_func void ksz8775InitHook(NetInterface *interface)
211 {
212 }
213 
214 
215 /**
216  * @brief KSZ8775 timer handler
217  * @param[in] interface Underlying network interface
218  **/
219 
220 void ksz8775Tick(NetInterface *interface)
221 {
222  uint_t port;
223  bool_t linkState;
224 
225 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
226  //Port separation mode?
227  if(interface->port != 0)
228  {
229  uint_t i;
230  NetInterface *virtualInterface;
231 
232  //Loop through network interfaces
233  for(i = 0; i < NET_INTERFACE_COUNT; i++)
234  {
235  //Point to the current interface
236  virtualInterface = &netInterface[i];
237 
238  //Check whether the current virtual interface is attached to the
239  //physical interface
240  if(virtualInterface == interface ||
241  virtualInterface->parent == interface)
242  {
243  //Retrieve current link state
244  linkState = ksz8775GetLinkState(interface, virtualInterface->port);
245 
246  //Link up or link down event?
247  if(linkState != virtualInterface->linkState)
248  {
249  //Set event flag
250  interface->phyEvent = TRUE;
251  //Notify the TCP/IP stack of the event
253  }
254  }
255  }
256  }
257  else
258 #endif
259  {
260  //Initialize link state
261  linkState = FALSE;
262 
263  //Loop through the ports
265  {
266  //Retrieve current link state
267  if(ksz8775GetLinkState(interface, port))
268  {
269  linkState = TRUE;
270  }
271  }
272 
273  //Link up or link down event?
274  if(linkState != interface->linkState)
275  {
276  //Set event flag
277  interface->phyEvent = TRUE;
278  //Notify the TCP/IP stack of the event
280  }
281  }
282 }
283 
284 
285 /**
286  * @brief Enable interrupts
287  * @param[in] interface Underlying network interface
288  **/
289 
291 {
292 }
293 
294 
295 /**
296  * @brief Disable interrupts
297  * @param[in] interface Underlying network interface
298  **/
299 
301 {
302 }
303 
304 
305 /**
306  * @brief KSZ8775 event handler
307  * @param[in] interface Underlying network interface
308  **/
309 
311 {
312  uint_t port;
313  bool_t linkState;
314 
315 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
316  //Port separation mode?
317  if(interface->port != 0)
318  {
319  uint_t i;
320  NetInterface *virtualInterface;
321 
322  //Loop through network interfaces
323  for(i = 0; i < NET_INTERFACE_COUNT; i++)
324  {
325  //Point to the current interface
326  virtualInterface = &netInterface[i];
327 
328  //Check whether the current virtual interface is attached to the
329  //physical interface
330  if(virtualInterface == interface ||
331  virtualInterface->parent == interface)
332  {
333  //Get the port number associated with the current interface
334  port = virtualInterface->port;
335 
336  //Valid port?
337  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT4)
338  {
339  //Retrieve current link state
340  linkState = ksz8775GetLinkState(interface, port);
341 
342  //Link up event?
343  if(linkState && !virtualInterface->linkState)
344  {
345  //Retrieve host interface speed
346  interface->linkSpeed = ksz8775GetLinkSpeed(interface,
347  KSZ8775_PORT5);
348 
349  //Retrieve host interface duplex mode
350  interface->duplexMode = ksz8775GetDuplexMode(interface,
351  KSZ8775_PORT5);
352 
353  //Adjust MAC configuration parameters for proper operation
354  interface->nicDriver->updateMacConfig(interface);
355 
356  //Check current speed
357  virtualInterface->linkSpeed = ksz8775GetLinkSpeed(interface,
358  port);
359 
360  //Check current duplex mode
361  virtualInterface->duplexMode = ksz8775GetDuplexMode(interface,
362  port);
363 
364  //Update link state
365  virtualInterface->linkState = TRUE;
366 
367  //Process link state change event
368  nicNotifyLinkChange(virtualInterface);
369  }
370  //Link down event
371  else if(!linkState && virtualInterface->linkState)
372  {
373  //Update link state
374  virtualInterface->linkState = FALSE;
375 
376  //Process link state change event
377  nicNotifyLinkChange(virtualInterface);
378  }
379  }
380  }
381  }
382  }
383  else
384 #endif
385  {
386  //Initialize link state
387  linkState = FALSE;
388 
389  //Loop through the ports
391  {
392  //Retrieve current link state
393  if(ksz8775GetLinkState(interface, port))
394  {
395  linkState = TRUE;
396  }
397  }
398 
399  //Link up event?
400  if(linkState)
401  {
402  //Retrieve host interface speed
403  interface->linkSpeed = ksz8775GetLinkSpeed(interface, KSZ8775_PORT5);
404  //Retrieve host interface duplex mode
405  interface->duplexMode = ksz8775GetDuplexMode(interface, KSZ8775_PORT5);
406 
407  //Adjust MAC configuration parameters for proper operation
408  interface->nicDriver->updateMacConfig(interface);
409 
410  //Update link state
411  interface->linkState = TRUE;
412  }
413  else
414  {
415  //Update link state
416  interface->linkState = FALSE;
417  }
418 
419  //Process link state change event
420  nicNotifyLinkChange(interface);
421  }
422 }
423 
424 
425 /**
426  * @brief Add tail tag to Ethernet frame
427  * @param[in] interface Underlying network interface
428  * @param[in] buffer Multi-part buffer containing the payload
429  * @param[in,out] offset Offset to the first payload byte
430  * @param[in] ancillary Additional options passed to the stack along with
431  * the packet
432  * @return Error code
433  **/
434 
436  size_t *offset, NetTxAncillary *ancillary)
437 {
438  error_t error;
439 
440  //Initialize status code
441  error = NO_ERROR;
442 
443 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
444  //SPI slave mode?
445  if(interface->spiDriver != NULL)
446  {
447  //Valid port?
448  if(ancillary->port <= KSZ8775_PORT4)
449  {
450  size_t length;
451  const uint8_t *tailTag;
452 
453  //The one byte tail tagging is used to indicate the destination port
454  tailTag = &ksz8775IngressTailTag[ancillary->port];
455 
456  //Retrieve the length of the Ethernet frame
457  length = netBufferGetLength(buffer) - *offset;
458 
459  //The host controller should manually add padding to the packet before
460  //inserting the tail tag
461  error = ethPadFrame(buffer, &length);
462 
463  //Check status code
464  if(!error)
465  {
466  //The tail tag is inserted at the end of the packet, just before
467  //the CRC
468  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
469  }
470  }
471  else
472  {
473  //The port number is not valid
474  error = ERROR_INVALID_PORT;
475  }
476  }
477 #endif
478 
479  //Return status code
480  return error;
481 }
482 
483 
484 /**
485  * @brief Decode tail tag from incoming Ethernet frame
486  * @param[in] interface Underlying network interface
487  * @param[in,out] frame Pointer to the received Ethernet frame
488  * @param[in,out] length Length of the frame, in bytes
489  * @param[in,out] ancillary Additional options passed to the stack along with
490  * the packet
491  * @return Error code
492  **/
493 
494 error_t ksz8775UntagFrame(NetInterface *interface, uint8_t **frame,
495  size_t *length, NetRxAncillary *ancillary)
496 {
497  error_t error;
498 
499  //Initialize status code
500  error = NO_ERROR;
501 
502 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
503  //SPI slave mode?
504  if(interface->spiDriver != NULL)
505  {
506  //Valid Ethernet frame received?
507  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
508  {
509  uint8_t *tailTag;
510 
511  //The tail tag is inserted at the end of the packet, just before
512  //the CRC
513  tailTag = *frame + *length - sizeof(uint8_t);
514 
515  //The one byte tail tagging is used to indicate the source port
516  ancillary->port = (*tailTag & KSZ8775_TAIL_TAG_SRC_PORT) + 1;
517 
518  //Strip tail tag from Ethernet frame
519  *length -= sizeof(uint8_t);
520  }
521  else
522  {
523  //Drop the received frame
524  error = ERROR_INVALID_LENGTH;
525  }
526  }
527  else
528  {
529  //Tail tagging mode cannot be enabled through MDC/MDIO interface
530  ancillary->port = 0;
531  }
532 #endif
533 
534  //Return status code
535  return error;
536 }
537 
538 
539 /**
540  * @brief Get link state
541  * @param[in] interface Underlying network interface
542  * @param[in] port Port number
543  * @return Link state
544  **/
545 
547 {
548  uint16_t status;
549  bool_t linkState;
550 
551  //Check port number
552  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT3)
553  {
554  //SPI slave mode?
555  if(interface->spiDriver != NULL)
556  {
557  //Read port status 2 register
558  status = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_STAT2(port));
559 
560  //Retrieve current link state
561  linkState = (status & KSZ8775_PORTn_STAT2_LINK_GOOD) ? TRUE : FALSE;
562  }
563  else
564  {
565  //Read status register
566  status = ksz8775ReadPhyReg(interface, port, KSZ8775_BMSR);
567 
568  //Retrieve current link state
569  linkState = (status & KSZ8775_BMSR_LINK_STATUS) ? TRUE : FALSE;
570  }
571  }
572  else if(port == KSZ8775_PORT4)
573  {
574  //Port 4 is always up
575  linkState = TRUE;
576  }
577  else
578  {
579  //The specified port number is not valid
580  linkState = FALSE;
581  }
582 
583  //Return link status
584  return linkState;
585 }
586 
587 
588 /**
589  * @brief Get link speed
590  * @param[in] interface Underlying network interface
591  * @param[in] port Port number
592  * @return Link speed
593  **/
594 
595 uint32_t ksz8775GetLinkSpeed(NetInterface *interface, uint8_t port)
596 {
597  uint8_t type;
598  uint8_t value;
599  uint32_t linkSpeed;
600 
601  //SPI slave mode?
602  if(interface->spiDriver != NULL)
603  {
604  //Check port number
605  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT3)
606  {
607  //Read port status 1 register
609 
610  //Retrieve current link speed
612  {
613  linkSpeed = NIC_LINK_SPEED_100MBPS;
614  }
615  else
616  {
617  linkSpeed = NIC_LINK_SPEED_10MBPS;
618  }
619  }
620  else if(port == KSZ8775_PORT4)
621  {
622  //Read port 4 control 9 register
624 
625  //Retrieve current link speed
627  {
628  linkSpeed = NIC_LINK_SPEED_100MBPS;
629  }
630  else
631  {
632  linkSpeed = NIC_LINK_SPEED_10MBPS;
633  }
634  }
635  else if(port == KSZ8775_PORT5)
636  {
637  //Read port 5 interface control 6 register
639 
640  //Retrieve host interface type
642 
643  //Gigabit interface?
646  {
647  //1000 Mb/s mode
648  linkSpeed = NIC_LINK_SPEED_1GBPS;
649  }
650  else
651  {
652  //Read global control 4 register
654 
655  //Retrieve host interface speed
657  {
658  //10 Mb/s mode
659  linkSpeed = NIC_LINK_SPEED_10MBPS;
660  }
661  else
662  {
663  //100 Mb/s mode
664  linkSpeed = NIC_LINK_SPEED_100MBPS;
665  }
666  }
667  }
668  else
669  {
670  //The specified port number is not valid
671  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
672  }
673  }
674  else
675  {
676  //The MDC/MDIO interface does not have access to all the configuration
677  //registers. It can only access the standard MIIM registers
678  linkSpeed = NIC_LINK_SPEED_100MBPS;
679  }
680 
681  //Return link status
682  return linkSpeed;
683 }
684 
685 
686 /**
687  * @brief Get duplex mode
688  * @param[in] interface Underlying network interface
689  * @param[in] port Port number
690  * @return Duplex mode
691  **/
692 
694 {
695  uint8_t value;
696  NicDuplexMode duplexMode;
697 
698  //SPI slave mode?
699  if(interface->spiDriver != NULL)
700  {
701  //Check port number
702  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT3)
703  {
704  //Read port status 1 register
706 
707  //Retrieve current duplex mode
709  {
710  duplexMode = NIC_FULL_DUPLEX_MODE;
711  }
712  else
713  {
714  duplexMode = NIC_HALF_DUPLEX_MODE;
715  }
716  }
717  else if(port == KSZ8775_PORT4)
718  {
719  //Read port status 1 register
721 
722  //Retrieve current duplex mode
724  {
725  duplexMode = NIC_FULL_DUPLEX_MODE;
726  }
727  else
728  {
729  duplexMode = NIC_HALF_DUPLEX_MODE;
730  }
731  }
732  else if(port == KSZ8775_PORT5)
733  {
734  //Read global control 4 register
736 
737  //Retrieve host interface duplex mode
739  {
740  duplexMode = NIC_HALF_DUPLEX_MODE;
741  }
742  else
743  {
744  duplexMode = NIC_FULL_DUPLEX_MODE;
745  }
746  }
747  else
748  {
749  //The specified port number is not valid
750  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
751  }
752  }
753  else
754  {
755  //The MDC/MDIO interface does not have access to all the configuration
756  //registers. It can only access the standard MIIM registers
757  duplexMode = NIC_FULL_DUPLEX_MODE;
758  }
759 
760  //Return duplex mode
761  return duplexMode;
762 }
763 
764 
765 /**
766  * @brief Set port state
767  * @param[in] interface Underlying network interface
768  * @param[in] port Port number
769  * @param[in] state Port state
770  **/
771 
772 void ksz8775SetPortState(NetInterface *interface, uint8_t port,
773  SwitchPortState state)
774 {
775  uint8_t temp;
776 
777  //Check port number
778  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT4)
779  {
780  //Read port control 2 register
781  temp = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_CTRL2(port));
782 
783  //Update port state
784  switch(state)
785  {
786  //Listening state
791  break;
792 
793  //Learning state
798  break;
799 
800  //Forwarding state
805  break;
806 
807  //Disabled state
808  default:
812  break;
813  }
814 
815  //Write the value back to port control 2 register
817  }
818 }
819 
820 
821 /**
822  * @brief Get port state
823  * @param[in] interface Underlying network interface
824  * @param[in] port Port number
825  * @return Port state
826  **/
827 
829 {
830  uint8_t temp;
831  SwitchPortState state;
832 
833  //Check port number
834  if(port >= KSZ8775_PORT1 && port <= KSZ8775_PORT4)
835  {
836  //Read port control 2 register
837  temp = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_CTRL2(port));
838 
839  //Check port state
840  if((temp & KSZ8775_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
841  (temp & KSZ8775_PORTn_CTRL2_RECEIVE_EN) == 0 &&
842  (temp & KSZ8775_PORTn_CTRL2_LEARNING_DIS) != 0)
843  {
844  //Disabled state
846  }
847  else if((temp & KSZ8775_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
848  (temp & KSZ8775_PORTn_CTRL2_RECEIVE_EN) != 0 &&
849  (temp & KSZ8775_PORTn_CTRL2_LEARNING_DIS) != 0)
850  {
851  //Listening state
853  }
854  else if((temp & KSZ8775_PORTn_CTRL2_TRANSMIT_EN) == 0 &&
855  (temp & KSZ8775_PORTn_CTRL2_RECEIVE_EN) == 0 &&
856  (temp & KSZ8775_PORTn_CTRL2_LEARNING_DIS) == 0)
857  {
858  //Learning state
860  }
861  else if((temp & KSZ8775_PORTn_CTRL2_TRANSMIT_EN) != 0 &&
862  (temp & KSZ8775_PORTn_CTRL2_RECEIVE_EN) != 0 &&
863  (temp & KSZ8775_PORTn_CTRL2_LEARNING_DIS) == 0)
864  {
865  //Forwarding state
867  }
868  else
869  {
870  //Unknown state
872  }
873  }
874  else
875  {
876  //The specified port number is not valid
878  }
879 
880  //Return port state
881  return state;
882 }
883 
884 
885 /**
886  * @brief Set aging time for dynamic filtering entries
887  * @param[in] interface Underlying network interface
888  * @param[in] agingTime Aging time, in seconds
889  **/
890 
891 void ksz8775SetAgingTime(NetInterface *interface, uint32_t agingTime)
892 {
893  //The aging period is fixed to 300 seconds
894 }
895 
896 
897 /**
898  * @brief Enable IGMP snooping
899  * @param[in] interface Underlying network interface
900  * @param[in] enable Enable or disable IGMP snooping
901  **/
902 
904 {
905  uint8_t temp;
906 
907  //Read global control 3 register
908  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL3);
909 
910  //Enable or disable IGMP snooping
911  if(enable)
912  {
914  }
915  else
916  {
918  }
919 
920  //Write the value back to global control 3 register
922 }
923 
924 
925 /**
926  * @brief Enable MLD snooping
927  * @param[in] interface Underlying network interface
928  * @param[in] enable Enable or disable MLD snooping
929  **/
930 
932 {
933  uint8_t temp;
934 
935  //Read global control 21 register
936  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL21);
937 
938  //Enable or disable MLD snooping
939  if(enable)
940  {
942  }
943  else
944  {
946  }
947 
948  //Write the value back to global control 21 register
950 }
951 
952 
953 /**
954  * @brief Enable reserved multicast table
955  * @param[in] interface Underlying network interface
956  * @param[in] enable Enable or disable reserved group addresses
957  **/
958 
960 {
961  uint_t i;
962  SwitchFdbEntry entry;
963 
964  //The reserved group addresses are in the range of 01-80-C2-00-00-00 to
965  //01-80-C2-00-00-0F
966  for(i = 0; i <= 15; i++)
967  {
968  //Specify the reserved group address to be added or removed
969  entry.macAddr.b[0] = 0x01;
970  entry.macAddr.b[1] = 0x80;
971  entry.macAddr.b[2] = 0xC2;
972  entry.macAddr.b[3] = 0x00;
973  entry.macAddr.b[4] = 0x00;
974  entry.macAddr.b[5] = i;
975 
976  //Format forwarding database entry
977  entry.srcPort = 0;
979  entry.override = TRUE;
980 
981  //Update the static MAC table
982  if(enable)
983  {
984  ksz8775AddStaticFdbEntry(interface, &entry);
985  }
986  else
987  {
988  ksz8775DeleteStaticFdbEntry(interface, &entry);
989  }
990  }
991 }
992 
993 
994 /**
995  * @brief Add a new entry to the static MAC table
996  * @param[in] interface Underlying network interface
997  * @param[in] entry Pointer to the forwarding database entry
998  * @return Error code
999  **/
1000 
1002  const SwitchFdbEntry *entry)
1003 {
1004  error_t error;
1005  uint_t i;
1006  uint_t j;
1007  uint8_t *p;
1008  SwitchFdbEntry currentEntry;
1009  Ksz8775StaticMacEntryW newEntry;
1010 
1011  //Keep track of the first free entry
1013 
1014  //Loop through the static MAC table
1015  for(i = 0; i < KSZ8775_STATIC_MAC_TABLE_SIZE; i++)
1016  {
1017  //Read current entry
1018  error = ksz8775GetStaticFdbEntry(interface, i, &currentEntry);
1019 
1020  //Valid entry?
1021  if(!error)
1022  {
1023  //Check whether the table already contains the specified MAC address
1024  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1025  {
1026  j = i;
1027  break;
1028  }
1029  }
1030  else
1031  {
1032  //Keep track of the first free entry
1034  {
1035  j = i;
1036  }
1037  }
1038  }
1039 
1040  //Any entry available?
1042  {
1043  //Format MAC entry
1044  newEntry.fid = 0;
1045  newEntry.useFid = 0;
1046  newEntry.override = entry->override;
1047  newEntry.valid = TRUE;
1048  newEntry.macAddr = entry->macAddr;
1049 
1050  //Set the relevant forward ports
1051  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1052  {
1053  newEntry.forwardPorts = KSZ8775_PORT5_MASK;
1054  }
1055  else
1056  {
1057  newEntry.forwardPorts = entry->destPorts & KSZ8775_PORT_MASK;
1058  }
1059 
1060  //Select the static MAC address table
1064 
1065  //Point to the MAC entry
1066  p = (uint8_t *) &newEntry;
1067 
1068  //Write indirect data registers
1069  for(i = 0; i < sizeof(Ksz8775StaticMacEntryW); i++)
1070  {
1071  ksz8775WriteSwitchReg(interface, KSZ8775_INDIRECT_DATA7 + i, p[i]);
1072  }
1073 
1074  //Setup a write operation
1078 
1079  //Trigger the write operation
1081 
1082  //Successful processing
1083  error = NO_ERROR;
1084  }
1085  else
1086  {
1087  //The static MAC table is full
1088  error = ERROR_TABLE_FULL;
1089  }
1090 
1091  //Return status code
1092  return error;
1093 }
1094 
1095 
1096 /**
1097  * @brief Remove an entry from the static MAC table
1098  * @param[in] interface Underlying network interface
1099  * @param[in] entry Forwarding database entry to remove from the table
1100  * @return Error code
1101  **/
1102 
1104  const SwitchFdbEntry *entry)
1105 {
1106  error_t error;
1107  uint_t i;
1108  uint_t j;
1109  SwitchFdbEntry currentEntry;
1110 
1111  //Loop through the static MAC table
1112  for(j = 0; j < KSZ8775_STATIC_MAC_TABLE_SIZE; j++)
1113  {
1114  //Read current entry
1115  error = ksz8775GetStaticFdbEntry(interface, j, &currentEntry);
1116 
1117  //Valid entry?
1118  if(!error)
1119  {
1120  //Check whether the table contains the specified MAC address
1121  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1122  {
1123  break;
1124  }
1125  }
1126  }
1127 
1128  //Any matching entry?
1130  {
1131  //Select the static MAC address table
1135 
1136  //Clear indirect data registers
1137  for(i = 0; i < sizeof(Ksz8775StaticMacEntryW); i++)
1138  {
1139  ksz8775WriteSwitchReg(interface, KSZ8775_INDIRECT_DATA7 + i, 0);
1140  }
1141 
1142  //Setup a write operation
1146 
1147  //Trigger the write operation
1149 
1150  //Successful processing
1151  error = NO_ERROR;
1152  }
1153  else
1154  {
1155  //The static MAC table does not contain the specified address
1156  error = ERROR_NOT_FOUND;
1157  }
1158 
1159  //Return status code
1160  return error;
1161 }
1162 
1163 
1164 /**
1165  * @brief Read an entry from the static MAC table
1166  * @param[in] interface Underlying network interface
1167  * @param[in] index Zero-based index of the entry to read
1168  * @param[out] entry Pointer to the forwarding database entry
1169  * @return Error code
1170  **/
1171 
1173  SwitchFdbEntry *entry)
1174 {
1175  error_t error;
1176  uint_t i;
1177  uint8_t *p;
1178  Ksz8775StaticMacEntryR currentEntry;
1179 
1180  //Check index parameter
1181  if(index < KSZ8775_STATIC_MAC_TABLE_SIZE)
1182  {
1183  //Select the static MAC address table
1187 
1188  //Trigger the read operation
1189  ksz8775WriteSwitchReg(interface, KSZ8775_INDIRECT_CTRL1, index);
1190 
1191  //Point to the MAC entry
1192  p = (uint8_t *) &currentEntry;
1193 
1194  //Read indirect data registers
1195  for(i = 0; i < sizeof(Ksz8775StaticMacEntryR); i++)
1196  {
1197  p[i] = ksz8775ReadSwitchReg(interface, KSZ8775_INDIRECT_DATA7 + i);
1198  }
1199 
1200  //Valid entry?
1201  if(currentEntry.valid)
1202  {
1203  //Copy MAC entry
1204  entry->macAddr = currentEntry.macAddr;
1205  entry->srcPort = 0;
1206  entry->destPorts = currentEntry.forwardPorts & KSZ8775_PORT_MASK;
1207  entry->override = currentEntry.override;
1208 
1209  //Successful processing
1210  error = NO_ERROR;
1211  }
1212  else
1213  {
1214  //The entry is not valid
1215  error = ERROR_INVALID_ENTRY;
1216  }
1217  }
1218  else
1219  {
1220  //The end of the table has been reached
1221  error = ERROR_END_OF_TABLE;
1222  }
1223 
1224  //Return status code
1225  return error;
1226 }
1227 
1228 
1229 /**
1230  * @brief Flush static MAC table
1231  * @param[in] interface Underlying network interface
1232  **/
1233 
1235 {
1236  uint_t i;
1237  uint_t temp;
1238  uint8_t state[5];
1239 
1240  //Loop through the ports
1241  for(i = KSZ8775_PORT1; i <= KSZ8775_PORT5; i++)
1242  {
1243  //Save the current state of the port
1244  state[i - 1] = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_CTRL2(i));
1245 
1246  //Turn off learning capability
1248  state[i - 1] | KSZ8775_PORTn_CTRL2_LEARNING_DIS);
1249  }
1250 
1251  //All the entries associated with a port that has its learning capability
1252  //being turned off will be flushed
1253  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL0);
1255  ksz8775WriteSwitchReg(interface, KSZ8775_GLOBAL_CTRL0, temp);
1256 
1257  //Loop through the ports
1258  for(i = KSZ8775_PORT1; i <= KSZ8775_PORT5; i++)
1259  {
1260  //Restore the original state of the port
1261  ksz8775WriteSwitchReg(interface, KSZ8775_PORTn_CTRL2(i), state[i - 1]);
1262  }
1263 }
1264 
1265 
1266 /**
1267  * @brief Read an entry from the dynamic MAC table
1268  * @param[in] interface Underlying network interface
1269  * @param[in] index Zero-based index of the entry to read
1270  * @param[out] entry Pointer to the forwarding database entry
1271  * @return Error code
1272  **/
1273 
1275  SwitchFdbEntry *entry)
1276 {
1277  error_t error;
1278  uint_t i;
1279  uint_t n;
1280  uint8_t *p;
1281  Ksz8775DynamicMacEntry currentEntry;
1282 
1283  //Check index parameter
1284  if(index < KSZ8775_DYNAMIC_MAC_TABLE_SIZE)
1285  {
1286  //Read the MAC entry at the specified index
1287  do
1288  {
1289  //Select the dynamic MAC address table
1294 
1295  //Trigger the read operation
1296  ksz8775WriteSwitchReg(interface, KSZ8775_INDIRECT_CTRL1, LSB(index));
1297 
1298  //Point to the MAC entry
1299  p = (uint8_t *) &currentEntry;
1300 
1301  //Read indirect data registers
1302  for(i = 0; i < sizeof(Ksz8775DynamicMacEntry); i++)
1303  {
1304  p[i] = ksz8775ReadSwitchReg(interface, KSZ8775_INDIRECT_DATA8 + i);
1305  }
1306 
1307  //Retry until the entry is ready
1308  } while(currentEntry.dataNotReady);
1309 
1310  //Check whether there are valid entries in the table
1311  if(!currentEntry.macEmpty)
1312  {
1313  //Retrieve the number of valid entries
1314  n = ((currentEntry.numValidEntriesH << 3) |
1315  currentEntry.numValidEntriesL) + 1;
1316  }
1317  else
1318  {
1319  //The table is empty
1320  n = 0;
1321  }
1322 
1323  //Valid entry?
1324  if(index < n)
1325  {
1326  //Copy MAC entry
1327  entry->macAddr = currentEntry.macAddr;
1328  entry->srcPort = currentEntry.sourcePort + 1;
1329  entry->destPorts = 0;
1330  entry->override = FALSE;
1331 
1332  //Successful processing
1333  error = NO_ERROR;
1334  }
1335  else
1336  {
1337  //The end of the table has been reached
1338  error = ERROR_END_OF_TABLE;
1339  }
1340  }
1341  else
1342  {
1343  //The end of the table has been reached
1344  error = ERROR_END_OF_TABLE;
1345  }
1346 
1347  //Return status code
1348  return error;
1349 }
1350 
1351 
1352 /**
1353  * @brief Flush dynamic MAC table
1354  * @param[in] interface Underlying network interface
1355  * @param[in] port Port number
1356  **/
1357 
1359 {
1360  uint_t i;
1361  uint_t temp;
1362  uint8_t state[5];
1363 
1364  //Loop through the ports
1365  for(i = KSZ8775_PORT1; i <= KSZ8775_PORT5; i++)
1366  {
1367  //Matching port number?
1368  if(i == port || port == 0)
1369  {
1370  //Save the current state of the port
1371  state[i - 1] = ksz8775ReadSwitchReg(interface, KSZ8775_PORTn_CTRL2(i));
1372 
1373  //Turn off learning capability
1375  state[i - 1] | KSZ8775_PORTn_CTRL2_LEARNING_DIS);
1376  }
1377  }
1378 
1379  //All the entries associated with a port that has its learning capability
1380  //being turned off will be flushed
1381  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL0);
1383  ksz8775WriteSwitchReg(interface, KSZ8775_GLOBAL_CTRL0, temp);
1384 
1385  //Loop through the ports
1386  for(i = KSZ8775_PORT1; i <= KSZ8775_PORT5; i++)
1387  {
1388  //Matching port number?
1389  if(i == port || port == 0)
1390  {
1391  //Restore the original state of the port
1392  ksz8775WriteSwitchReg(interface, KSZ8775_PORTn_CTRL2(i), state[i - 1]);
1393  }
1394  }
1395 }
1396 
1397 
1398 /**
1399  * @brief Set forward ports for unknown multicast packets
1400  * @param[in] interface Underlying network interface
1401  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1402  * @param[in] forwardPorts Port map
1403  **/
1404 
1406  bool_t enable, uint32_t forwardPorts)
1407 {
1408  uint8_t temp;
1409 
1410  //Read global control 16 register
1411  temp = ksz8775ReadSwitchReg(interface, KSZ8775_GLOBAL_CTRL16);
1412 
1413  //Clear port map
1415 
1416  //Enable or disable forwarding of unknown multicast packets
1417  if(enable)
1418  {
1419  //Enable forwarding
1421 
1422  //Check whether unknown multicast packets should be forwarded to the CPU port
1423  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1424  {
1426  }
1427 
1428  //Select the desired forward ports
1429  temp |= forwardPorts & KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL;
1430  }
1431  else
1432  {
1433  //Disable forwarding
1435  }
1436 
1437  //Write the value back to global control 16 register
1438  ksz8775WriteSwitchReg(interface, KSZ8775_GLOBAL_CTRL16, temp);
1439 }
1440 
1441 
1442 /**
1443  * @brief Write PHY register
1444  * @param[in] interface Underlying network interface
1445  * @param[in] port Port number
1446  * @param[in] address PHY register address
1447  * @param[in] data Register value
1448  **/
1449 
1450 void ksz8775WritePhyReg(NetInterface *interface, uint8_t port,
1451  uint8_t address, uint16_t data)
1452 {
1453  //Write the specified PHY register
1454  if(interface->smiDriver != NULL)
1455  {
1456  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1457  }
1458  else
1459  {
1460  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1461  }
1462 }
1463 
1464 
1465 /**
1466  * @brief Read PHY register
1467  * @param[in] interface Underlying network interface
1468  * @param[in] port Port number
1469  * @param[in] address PHY register address
1470  * @return Register value
1471  **/
1472 
1473 uint16_t ksz8775ReadPhyReg(NetInterface *interface, uint8_t port,
1474  uint8_t address)
1475 {
1476  uint16_t data;
1477 
1478  //Read the specified PHY register
1479  if(interface->smiDriver != NULL)
1480  {
1481  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1482  }
1483  else
1484  {
1485  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1486  }
1487 
1488  //Return the value of the PHY register
1489  return data;
1490 }
1491 
1492 
1493 /**
1494  * @brief Dump PHY registers for debugging purpose
1495  * @param[in] interface Underlying network interface
1496  * @param[in] port Port number
1497  **/
1498 
1499 void ksz8775DumpPhyReg(NetInterface *interface, uint8_t port)
1500 {
1501  uint8_t i;
1502 
1503  //Loop through PHY registers
1504  for(i = 0; i < 32; i++)
1505  {
1506  //Display current PHY register
1507  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1508  ksz8775ReadPhyReg(interface, port, i));
1509  }
1510 
1511  //Terminate with a line feed
1512  TRACE_DEBUG("\r\n");
1513 }
1514 
1515 
1516 /**
1517  * @brief Write switch register
1518  * @param[in] interface Underlying network interface
1519  * @param[in] address Switch register address
1520  * @param[in] data Register value
1521  **/
1522 
1523 void ksz8775WriteSwitchReg(NetInterface *interface, uint16_t address,
1524  uint8_t data)
1525 {
1526  uint16_t command;
1527 
1528  //SPI slave mode?
1529  if(interface->spiDriver != NULL)
1530  {
1531  //Set up a write operation
1532  command = KSZ8775_SPI_CMD_WRITE;
1533  //Set register address
1534  command |= (address << 1) & KSZ8775_SPI_CMD_ADDR;
1535 
1536  //Pull the CS pin low
1537  interface->spiDriver->assertCs();
1538 
1539  //Write 16-bit command
1540  interface->spiDriver->transfer(MSB(command));
1541  interface->spiDriver->transfer(LSB(command));
1542 
1543  //Write data
1544  interface->spiDriver->transfer(data);
1545 
1546  //Terminate the operation by raising the CS pin
1547  interface->spiDriver->deassertCs();
1548  }
1549  else
1550  {
1551  //The MDC/MDIO interface does not have access to all the configuration
1552  //registers. It can only access the standard MIIM registers
1553  }
1554 }
1555 
1556 
1557 /**
1558  * @brief Read switch register
1559  * @param[in] interface Underlying network interface
1560  * @param[in] address Switch register address
1561  * @return Register value
1562  **/
1563 
1564 uint8_t ksz8775ReadSwitchReg(NetInterface *interface, uint16_t address)
1565 {
1566  uint8_t data;
1567  uint16_t command;
1568 
1569  //SPI slave mode?
1570  if(interface->spiDriver != NULL)
1571  {
1572  //Set up a read operation
1573  command = KSZ8775_SPI_CMD_READ;
1574  //Set register address
1575  command |= (address << 1) & KSZ8775_SPI_CMD_ADDR;
1576 
1577  //Pull the CS pin low
1578  interface->spiDriver->assertCs();
1579 
1580  //Write 16-bit command
1581  interface->spiDriver->transfer(MSB(command));
1582  interface->spiDriver->transfer(LSB(command));
1583 
1584  //Read data
1585  data = interface->spiDriver->transfer(0xFF);
1586 
1587  //Terminate the operation by raising the CS pin
1588  interface->spiDriver->deassertCs();
1589  }
1590  else
1591  {
1592  //The MDC/MDIO interface does not have access to all the configuration
1593  //registers. It can only access the standard MIIM registers
1594  data = 0;
1595  }
1596 
1597  //Return register value
1598  return data;
1599 }
1600 
1601 
1602 /**
1603  * @brief Dump switch registers for debugging purpose
1604  * @param[in] interface Underlying network interface
1605  **/
1606 
1608 {
1609  uint16_t i;
1610 
1611  //Loop through switch registers
1612  for(i = 0; i < 256; i++)
1613  {
1614  //Display current switch register
1615  TRACE_DEBUG("0x%02" PRIX16 " (%02" PRIu16 ") : 0x%02" PRIX8 "\r\n",
1616  i, i, ksz8775ReadSwitchReg(interface, i));
1617  }
1618 
1619  //Terminate with a line feed
1620  TRACE_DEBUG("\r\n");
1621 }
uint8_t type
Definition: coap_common.h:176
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint16_t port
Definition: dns_common.h:267
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_NOT_FOUND
Definition: error.h:147
@ ERROR_END_OF_TABLE
Definition: error.h:290
@ ERROR_INVALID_ENTRY
Definition: error.h:288
@ ERROR_TABLE_FULL
Definition: error.h:289
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint8_t data[]
Definition: ethernet.h:222
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
EthHeader
Definition: ethernet.h:223
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
Helper functions for Ethernet.
Ipv6Addr address[]
Definition: ipv6.h:316
void ksz8775EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
void ksz8775SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
void ksz8775SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
void ksz8775WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
error_t ksz8775GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
const uint8_t ksz8775IngressTailTag[5]
Tail tag rules (host to KSZ8775)
void ksz8775DisableIrq(NetInterface *interface)
Disable interrupts.
error_t ksz8775UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
void ksz8775EventHandler(NetInterface *interface)
KSZ8775 event handler.
uint32_t ksz8775GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
__weak_func void ksz8775InitHook(NetInterface *interface)
KSZ8775 custom configuration.
error_t ksz8775DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
void ksz8775DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
error_t ksz8775AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
error_t ksz8775Init(NetInterface *interface)
KSZ8775 Ethernet switch initialization.
error_t ksz8775TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
void ksz8775WriteSwitchReg(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register.
void ksz8775EnableIrq(NetInterface *interface)
Enable interrupts.
void ksz8775FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
SwitchPortState ksz8775GetPortState(NetInterface *interface, uint8_t port)
Get port state.
void ksz8775SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
bool_t ksz8775GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
NicDuplexMode ksz8775GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
const SwitchDriver ksz8775SwitchDriver
KSZ8775 Ethernet switch driver.
uint16_t ksz8775ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
uint8_t ksz8775ReadSwitchReg(NetInterface *interface, uint16_t address)
Read switch register.
void ksz8775DumpSwitchReg(NetInterface *interface)
Dump switch registers for debugging purpose.
void ksz8775EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
void ksz8775Tick(NetInterface *interface)
KSZ8775 timer handler.
void ksz8775FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
void ksz8775EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
error_t ksz8775GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
KSZ8775 5-port Ethernet switch driver.
#define KSZ8775_PORTn_CTRL9_FORCED_SPEED
#define KSZ8775_GLOBAL_CTRL4
#define KSZ8775_GLOBAL_CTRL3
#define KSZ8775_SPI_CMD_WRITE
#define KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD
#define KSZ8775_TAIL_TAG_DEST_PORT4
#define KSZ8775_GLOBAL_CTRL4_SW5_SPEED
#define KSZ8775_INDIRECT_DATA7
#define KSZ8775_PORTn_CTRL9(port)
#define KSZ8775_PORT5_MASK
#define KSZ8775_GLOBAL_CTRL2
#define KSZ8775_PORTn_IF_CTRL6_IF_MODE_SEL_RGMII
#define KSZ8775_PORT4_CTRL9
#define KSZ8775_PORTn_CTRL9_FORCED_DUPLEX
#define KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP
#define KSZ8775_PORTn_IF_CTRL6_IS_1GBPS
#define KSZ8775_PORTn_IF_CTRL6_IF_MODE_SEL
#define KSZ8775_GLOBAL_CTRL2_MAX_PKT_SIZE_CHECK_DIS
#define KSZ8775_PORT5_IF_CTRL6
#define KSZ8775_DYNAMIC_MAC_TABLE_SIZE
#define KSZ8775_STATIC_MAC_TABLE_SIZE
#define KSZ8775_INDIRECT_CTRL0_TABLE_SEL_DYNAMIC_MAC
#define KSZ8775_TAIL_TAG_DEST_PORT2
#define KSZ8775_INDIRECT_CTRL0_WRITE
#define KSZ8775_GLOBAL_CTRL3_SW5_IGMP_SNOOP_EN
#define KSZ8775_PORT5
#define KSZ8775_PORT_MASK
#define KSZ8775_TAIL_TAG_DEST_PORT1
#define KSZ8775_PORTn_CTRL2(port)
#define KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_PORT5
#define KSZ8775_INDIRECT_CTRL0
#define KSZ8775_GLOBAL_CTRL10_TAIL_TAG_EN
#define KSZ8775_GLOBAL_CTRL0_FLUSH_STATIC_MAC_TABLE
#define KSZ8775_PORT3
#define KSZ8775_BMSR_LINK_STATUS
#define KSZ8775_CHIP_ID0_FAMILY_ID_DEFAULT
#define KSZ8775_GLOBAL_CTRL0_FLUSH_DYNAMIC_MAC_TABLE
#define KSZ8775_PORTn_STAT2_LINK_GOOD
#define KSZ8775_TAIL_TAG_SRC_PORT
#define KSZ8775_GLOBAL_CTRL16
#define KSZ8775_GLOBAL_CTRL16_UNKNOWN_MCAST_FWD_MAP_ALL
#define KSZ8775_INDIRECT_DATA8
#define KSZ8775_GLOBAL_CTRL0
#define KSZ8775_CHIP_ID0
#define KSZ8775_GLOBAL_CTRL4_SW5_HALF_DUPLEX_MODE
#define KSZ8775_PORT1
#define KSZ8775_INDIRECT_CTRL0_READ
#define KSZ8775_TAIL_TAG_NORMAL_ADDR_LOOKUP
#define KSZ8775_TAIL_TAG_DEST_PORT3
#define KSZ8775_GLOBAL_CTRL10
#define KSZ8775_PORTn_STAT2(port)
#define KSZ8775_SPI_CMD_READ
#define KSZ8775_GLOBAL_CTRL21_MLD_SNOOP_EN
#define KSZ8775_INDIRECT_BYTE
#define KSZ8775_BMSR
#define KSZ8775_PORTn_CTRL2_RECEIVE_EN
#define KSZ8775_PORTn_STAT1_OP_DUPLEX
#define KSZ8775_INDIRECT_CTRL0_TABLE_SEL_STATIC_MAC
#define KSZ8775_PORTn_STAT1_OP_SPEED
#define KSZ8775_PORTn_CTRL2_TRANSMIT_EN
#define KSZ8775_PORTn_STAT1(port)
#define KSZ8775_PORT4
#define KSZ8775_INDIRECT_CTRL1
#define KSZ8775_SPI_CMD_ADDR
#define KSZ8775_PORTn_CTRL2_LEARNING_DIS
#define KSZ8775_GLOBAL_CTRL21
#define KSZ8775_TAIL_TAG_PORT_SEL
#define KSZ8775_INDIRECT_CTRL0_ADDR_9_8
uint8_t p
Definition: ndp.h:300
TCP/IP stack core.
#define NET_INTERFACE_COUNT
Definition: net.h:113
#define NetInterface
Definition: net.h:36
#define netInterface
Definition: net_legacy.h:199
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:588
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:548
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define SMI_OPCODE_READ
Definition: nic.h:67
NicDuplexMode
Duplex mode.
Definition: nic.h:122
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
SwitchPortState
Switch port state.
Definition: nic.h:134
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define LSB(x)
Definition: os_port.h:55
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define MSB(x)
Definition: os_port.h:59
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
Dynamic MAC table entry.
uint8_t numValidEntriesH
uint8_t sourcePort
MacAddr macAddr
uint8_t macEmpty
uint8_t numValidEntriesL
uint8_t dataNotReady
Static MAC table entry (read operation)
uint8_t forwardPorts
MacAddr macAddr
uint8_t valid
uint8_t override
Static MAC table entry (write operation)
uint8_t forwardPorts
MacAddr macAddr
uint8_t valid
uint8_t useFid
uint8_t override
uint8_t fid
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
Ethernet switch driver.
Definition: nic.h:322
Forwarding database entry.
Definition: nic.h:149
MacAddr macAddr
Definition: nic.h:150
uint32_t destPorts
Definition: nic.h:152
bool_t override
Definition: nic.h:153
uint8_t srcPort
Definition: nic.h:151
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369