ksz9477_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz9477_driver.c
3  * @brief KSZ9477 7-port Gigabit 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 KSZ9477 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Tail tag rules (host to KSZ9477)
75  **/
76 
77 const uint16_t ksz9477IngressTailTag[8] =
78 {
85  HTONS(0),
87 };
88 
89 
90 /**
91  * @brief KSZ9477 Ethernet switch initialization
92  * @param[in] interface Underlying network interface
93  * @return Error code
94  **/
95 
97 {
98  uint_t port;
99  uint8_t temp;
100 
101  //Debug message
102  TRACE_INFO("Initializing KSZ9477...\r\n");
103 
104  //SPI slave mode?
105  if(interface->spiDriver != NULL)
106  {
107  //Initialize SPI interface
108  interface->spiDriver->init();
109 
110  //Wait for the serial interface to be ready
111  do
112  {
113  //Read CHIP_ID1 register
114  temp = ksz9477ReadSwitchReg8(interface, KSZ9477_CHIP_ID1);
115 
116  //The returned data is invalid until the serial interface is ready
117  } while(temp != KSZ9477_CHIP_ID1_DEFAULT);
118 
119 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
120  //Enable tail tag feature
124 
125  //Disable frame length check (silicon errata workaround 16)
129 #else
130  //Disable tail tag feature
134 
135  //Enable frame length check
139 #endif
140 
141  //Loop through the ports
143  {
144  //Skip host port
145  if(port != KSZ9477_PORT6)
146  {
147 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
148  //Port separation mode?
149  if(interface->port != 0)
150  {
151  //Disable packet transmission and address learning
152  ksz9477SetPortState(interface, port,
154  }
155  else
156 #endif
157  {
158  //Enable transmission, reception and address learning
159  ksz9477SetPortState(interface, port,
161  }
162  }
163  }
164 
165  //Restore default age count
169 
170  //Restore default age period
173 
174  //Add internal delay to ingress and egress RGMII clocks
179 
180  //Reset SGMII registers (silicon errata workaround 16)
184 
185  //Start switch operation
188  }
189  else if(interface->smiDriver != NULL)
190  {
191  //Initialize serial management interface
192  interface->smiDriver->init();
193  }
194  else
195  {
196  //Just for sanity
197  }
198 
199  //Loop through the ports
201  {
202  //Improve PHY receive performance (silicon errata workaround 1)
203  ksz9477WriteMmdReg(interface, port, 0x01, 0x6F, 0xDD0B);
204  ksz9477WriteMmdReg(interface, port, 0x01, 0x8F, 0x6032);
205  ksz9477WriteMmdReg(interface, port, 0x01, 0x9D, 0x248C);
206  ksz9477WriteMmdReg(interface, port, 0x01, 0x75, 0x0060);
207  ksz9477WriteMmdReg(interface, port, 0x01, 0xD3, 0x7777);
208  ksz9477WriteMmdReg(interface, port, 0x1C, 0x06, 0x3008);
209  ksz9477WriteMmdReg(interface, port, 0x1C, 0x08, 0x2001);
210 
211  //Improve transmit waveform amplitude (silicon errata workaround 2)
212  ksz9477WriteMmdReg(interface, port, 0x1C, 0x04, 0x00D0);
213 
214  //EEE must be manually disabled (silicon errata workaround 4)
216 
217  //Adjust power supply settings (silicon errata workaround 9)
218  ksz9477WriteMmdReg(interface, port, 0x1C, 0x13, 0x6EFF);
219  ksz9477WriteMmdReg(interface, port, 0x1C, 0x14, 0xE6FF);
220  ksz9477WriteMmdReg(interface, port, 0x1C, 0x15, 0x6EFF);
221  ksz9477WriteMmdReg(interface, port, 0x1C, 0x16, 0xE6FF);
222  ksz9477WriteMmdReg(interface, port, 0x1C, 0x17, 0x00FF);
223  ksz9477WriteMmdReg(interface, port, 0x1C, 0x18, 0x43FF);
224  ksz9477WriteMmdReg(interface, port, 0x1C, 0x19, 0xC3FF);
225  ksz9477WriteMmdReg(interface, port, 0x1C, 0x1A, 0x6FFF);
226  ksz9477WriteMmdReg(interface, port, 0x1C, 0x1B, 0x07FF);
227  ksz9477WriteMmdReg(interface, port, 0x1C, 0x1C, 0x0FFF);
228  ksz9477WriteMmdReg(interface, port, 0x1C, 0x1D, 0xE7FF);
229  ksz9477WriteMmdReg(interface, port, 0x1C, 0x1E, 0xEFFF);
230  ksz9477WriteMmdReg(interface, port, 0x1C, 0x20, 0xEEEE);
231 
232  //Select tri-color dual-LED mode (silicon errata workaround 19)
236 
237  //Debug message
238  TRACE_DEBUG("Port %u:\r\n", port);
239  //Dump PHY registers for debugging purpose
240  ksz9477DumpPhyReg(interface, port);
241  }
242 
243  //Perform custom configuration
244  ksz9477InitHook(interface);
245 
246  //Force the TCP/IP stack to poll the link state at startup
247  interface->phyEvent = TRUE;
248  //Notify the TCP/IP stack of the event
249  osSetEvent(&interface->netContext->event);
250 
251  //Successful initialization
252  return NO_ERROR;
253 }
254 
255 
256 /**
257  * @brief KSZ9477 custom configuration
258  * @param[in] interface Underlying network interface
259  **/
260 
261 __weak_func void ksz9477InitHook(NetInterface *interface)
262 {
263 }
264 
265 
266 /**
267  * @brief KSZ9477 timer handler
268  * @param[in] interface Underlying network interface
269  **/
270 
271 __weak_func void ksz9477Tick(NetInterface *interface)
272 {
273  uint_t port;
274  bool_t linkState;
275 
276 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
277  //Port separation mode?
278  if(interface->port != 0)
279  {
280  uint_t i;
281  NetContext *context;
282  NetInterface *virtualInterface;
283 
284  //Point to the TCP/IP stack context
285  context = interface->netContext;
286 
287  //Loop through network interfaces
288  for(i = 0; i < context->numInterfaces; i++)
289  {
290  //Point to the current interface
291  virtualInterface = &context->interfaces[i];
292 
293  //Check whether the current virtual interface is attached to the
294  //physical interface
295  if(virtualInterface == interface ||
296  virtualInterface->parent == interface)
297  {
298  //Retrieve current link state
299  linkState = ksz9477GetLinkState(interface, virtualInterface->port);
300 
301  //Link up or link down event?
302  if(linkState != virtualInterface->linkState)
303  {
304  //Set event flag
305  interface->phyEvent = TRUE;
306  //Notify the TCP/IP stack of the event
307  osSetEvent(&interface->netContext->event);
308  }
309  }
310  }
311  }
312  else
313 #endif
314  {
315  //Initialize link state
316  linkState = FALSE;
317 
318  //Loop through the ports
320  {
321  //Skip host port
322  if(port != KSZ9477_PORT6)
323  {
324  //Retrieve current link state
325  if(ksz9477GetLinkState(interface, port))
326  {
327  linkState = TRUE;
328  }
329  }
330  }
331 
332  //Link up or link down event?
333  if(linkState != interface->linkState)
334  {
335  //Set event flag
336  interface->phyEvent = TRUE;
337  //Notify the TCP/IP stack of the event
338  osSetEvent(&interface->netContext->event);
339  }
340  }
341 }
342 
343 
344 /**
345  * @brief Enable interrupts
346  * @param[in] interface Underlying network interface
347  **/
348 
350 {
351 }
352 
353 
354 /**
355  * @brief Disable interrupts
356  * @param[in] interface Underlying network interface
357  **/
358 
360 {
361 }
362 
363 
364 /**
365  * @brief KSZ9477 event handler
366  * @param[in] interface Underlying network interface
367  **/
368 
369 __weak_func void ksz9477EventHandler(NetInterface *interface)
370 {
371  uint_t port;
372  bool_t linkState;
373 
374 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
375  //Port separation mode?
376  if(interface->port != 0)
377  {
378  uint_t i;
379  NetContext *context;
380  NetInterface *virtualInterface;
381 
382  //Point to the TCP/IP stack context
383  context = interface->netContext;
384 
385  //Loop through network interfaces
386  for(i = 0; i < context->numInterfaces; i++)
387  {
388  //Point to the current interface
389  virtualInterface = &context->interfaces[i];
390 
391  //Check whether the current virtual interface is attached to the
392  //physical interface
393  if(virtualInterface == interface ||
394  virtualInterface->parent == interface)
395  {
396  //Get the port number associated with the current interface
397  port = virtualInterface->port;
398 
399  //Valid port?
400  if((port >= KSZ9477_PORT1 && port <= KSZ9477_PORT5) ||
401  port == KSZ9477_PORT7)
402  {
403  //Retrieve current link state
404  linkState = ksz9477GetLinkState(interface, port);
405 
406  //Link up event?
407  if(linkState && !virtualInterface->linkState)
408  {
409  //Retrieve host interface speed
410  interface->linkSpeed = ksz9477GetLinkSpeed(interface,
411  KSZ9477_PORT6);
412 
413  //Retrieve host interface duplex mode
414  interface->duplexMode = ksz9477GetDuplexMode(interface,
415  KSZ9477_PORT6);
416 
417  //Adjust MAC configuration parameters for proper operation
418  interface->nicDriver->updateMacConfig(interface);
419 
420  //Check current speed
421  virtualInterface->linkSpeed = ksz9477GetLinkSpeed(interface,
422  port);
423 
424  //Check current duplex mode
425  virtualInterface->duplexMode = ksz9477GetDuplexMode(interface,
426  port);
427 
428  //Update link state
429  virtualInterface->linkState = TRUE;
430 
431  //Process link state change event
432  nicNotifyLinkChange(virtualInterface);
433  }
434  //Link down event
435  else if(!linkState && virtualInterface->linkState)
436  {
437  //Update link state
438  virtualInterface->linkState = FALSE;
439 
440  //Process link state change event
441  nicNotifyLinkChange(virtualInterface);
442  }
443  }
444  }
445  }
446  }
447  else
448 #endif
449  {
450  //Initialize link state
451  linkState = FALSE;
452 
453  //Loop through the ports
455  {
456  //Skip host port
457  if(port != KSZ9477_PORT6)
458  {
459  //Retrieve current link state
460  if(ksz9477GetLinkState(interface, port))
461  {
462  linkState = TRUE;
463  }
464  }
465  }
466 
467  //Link up event?
468  if(linkState)
469  {
470  //Retrieve host interface speed
471  interface->linkSpeed = ksz9477GetLinkSpeed(interface, KSZ9477_PORT6);
472  //Retrieve host interface duplex mode
473  interface->duplexMode = ksz9477GetDuplexMode(interface, KSZ9477_PORT6);
474 
475  //Adjust MAC configuration parameters for proper operation
476  interface->nicDriver->updateMacConfig(interface);
477 
478  //Update link state
479  interface->linkState = TRUE;
480  }
481  else
482  {
483  //Update link state
484  interface->linkState = FALSE;
485  }
486 
487  //Process link state change event
488  nicNotifyLinkChange(interface);
489  }
490 }
491 
492 
493 /**
494  * @brief Add tail tag to Ethernet frame
495  * @param[in] interface Underlying network interface
496  * @param[in] buffer Multi-part buffer containing the payload
497  * @param[in,out] offset Offset to the first payload byte
498  * @param[in] ancillary Additional options passed to the stack along with
499  * the packet
500  * @return Error code
501  **/
502 
504  size_t *offset, NetTxAncillary *ancillary)
505 {
506  error_t error;
507 
508  //Initialize status code
509  error = NO_ERROR;
510 
511 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
512  //SPI slave mode?
513  if(interface->spiDriver != NULL)
514  {
515  //Valid port?
516  if(ancillary->port <= KSZ9477_PORT7)
517  {
518  size_t length;
519  const uint16_t *tailTag;
520 
521  //The two-byte tail tagging is used to indicate the destination port
522  tailTag = &ksz9477IngressTailTag[ancillary->port];
523 
524  //Retrieve the length of the Ethernet frame
525  length = netBufferGetLength(buffer) - *offset;
526 
527  //The host controller should manually add padding to the packet before
528  //inserting the tail tag
529  error = ethPadFrame(buffer, &length);
530 
531  //Check status code
532  if(!error)
533  {
534  //The tail tag is inserted at the end of the packet, just before
535  //the CRC
536  error = netBufferAppend(buffer, tailTag, sizeof(uint16_t));
537  }
538  }
539  else
540  {
541  //The port number is not valid
542  error = ERROR_INVALID_PORT;
543  }
544  }
545 #endif
546 
547  //Return status code
548  return error;
549 }
550 
551 
552 /**
553  * @brief Decode tail tag from incoming Ethernet frame
554  * @param[in] interface Underlying network interface
555  * @param[in,out] frame Pointer to the received Ethernet frame
556  * @param[in,out] length Length of the frame, in bytes
557  * @param[in,out] ancillary Additional options passed to the stack along with
558  * the packet
559  * @return Error code
560  **/
561 
562 error_t ksz9477UntagFrame(NetInterface *interface, uint8_t **frame,
563  size_t *length, NetRxAncillary *ancillary)
564 {
565  error_t error;
566 
567  //Initialize status code
568  error = NO_ERROR;
569 
570 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
571  //SPI slave mode?
572  if(interface->spiDriver != NULL)
573  {
574  //Valid Ethernet frame received?
575  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
576  {
577  uint8_t *tailTag;
578 
579  //The tail tag is inserted at the end of the packet, just before
580  //the CRC
581  tailTag = *frame + *length - sizeof(uint8_t);
582 
583  //The one byte tail tagging is used to indicate the source port
584  ancillary->port = (*tailTag & KSZ9477_TAIL_TAG_SRC_PORT) + 1;
585 
586  //Strip tail tag from Ethernet frame
587  *length -= sizeof(uint8_t);
588  }
589  else
590  {
591  //Drop the received frame
592  error = ERROR_INVALID_LENGTH;
593  }
594  }
595  else
596  {
597  //Tail tagging mode cannot be enabled through MDC/MDIO interface
598  ancillary->port = 0;
599  }
600 #endif
601 
602  //Return status code
603  return error;
604 }
605 
606 
607 /**
608  * @brief Get link state
609  * @param[in] interface Underlying network interface
610  * @param[in] port Port number
611  * @return Link state
612  **/
613 
615 {
616  uint16_t value;
617  bool_t linkState;
618 
619  //Check port number
620  if(port >= KSZ9477_PORT1 && port <= KSZ9477_PORT5)
621  {
622  //Any link failure condition is latched in the BMSR register. Reading
623  //the register twice will always return the actual link status
624  value = ksz9477ReadPhyReg(interface, port, KSZ9477_BMSR);
625  value = ksz9477ReadPhyReg(interface, port, KSZ9477_BMSR);
626 
627  //Retrieve current link state
628  linkState = (value & KSZ9477_BMSR_LINK_STATUS) ? TRUE : FALSE;
629  }
630  else if(port == KSZ9477_PORT7)
631  {
632  //An external PHY can optionally be connected to port 7
633  linkState = ksz9477GetPort7LinkState(interface);
634  }
635  else
636  {
637  //The specified port number is not valid
638  linkState = FALSE;
639  }
640 
641  //Return link status
642  return linkState;
643 }
644 
645 
646 /**
647  * @brief Get link speed
648  * @param[in] interface Underlying network interface
649  * @param[in] port Port number
650  * @return Link speed
651  **/
652 
653 uint32_t ksz9477GetLinkSpeed(NetInterface *interface, uint8_t port)
654 {
655  uint8_t type;
656  uint16_t value;
657  uint32_t linkSpeed;
658 
659  //Check port number
660  if(port >= KSZ9477_PORT1 && port <= KSZ9477_PORT5)
661  {
662  //Read PHY control register
664 
665  //Retrieve current link speed
667  {
668  //1000BASE-T
669  linkSpeed = NIC_LINK_SPEED_1GBPS;
670  }
671  else if((value & KSZ9477_PHYCON_SPEED_100BTX) != 0)
672  {
673  //100BASE-TX
674  linkSpeed = NIC_LINK_SPEED_100MBPS;
675  }
676  else if((value & KSZ9477_PHYCON_SPEED_10BT) != 0)
677  {
678  //10BASE-T
679  linkSpeed = NIC_LINK_SPEED_10MBPS;
680  }
681  else
682  {
683  //The link speed is not valid
684  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
685  }
686  }
687  else if(port == KSZ9477_PORT6)
688  {
689  //SPI slave mode?
690  if(interface->spiDriver != NULL)
691  {
692  //Read port 6 XMII control 1 register
694 
695  //Retrieve host interface type
697 
698  //Gigabit interface?
701  {
702  //1000 Mb/s mode
703  linkSpeed = NIC_LINK_SPEED_1GBPS;
704  }
705  else
706  {
707  //Read port 6 XMII control 0 register
709 
710  //Retrieve host interface speed
712  {
713  //100 Mb/s mode
714  linkSpeed = NIC_LINK_SPEED_100MBPS;
715  }
716  else
717  {
718  //10 Mb/s mode
719  linkSpeed = NIC_LINK_SPEED_10MBPS;
720  }
721  }
722  }
723  else
724  {
725  //The MDC/MDIO interface does not have access to all the configuration
726  //registers. It can only access the standard MIIM registers
727  linkSpeed = NIC_LINK_SPEED_100MBPS;
728  }
729  }
730  else if(port == KSZ9477_PORT7)
731  {
732  //An external PHY can optionally be connected to port 7
733  linkSpeed = ksz9477GetPort7LinkSpeed(interface);
734  }
735  else
736  {
737  //The specified port number is not valid
738  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
739  }
740 
741  //Return link speed
742  return linkSpeed;
743 }
744 
745 
746 /**
747  * @brief Get duplex mode
748  * @param[in] interface Underlying network interface
749  * @param[in] port Port number
750  * @return Duplex mode
751  **/
752 
754 {
755  uint16_t value;
756  NicDuplexMode duplexMode;
757 
758  //Check port number
759  if(port >= KSZ9477_PORT1 && port <= KSZ9477_PORT5)
760  {
761  //Read PHY control register
763 
764  //Retrieve current duplex mode
766  {
767  duplexMode = NIC_FULL_DUPLEX_MODE;
768  }
769  else
770  {
771  duplexMode = NIC_HALF_DUPLEX_MODE;
772  }
773  }
774  else if(port == KSZ9477_PORT6)
775  {
776  //SPI slave mode?
777  if(interface->spiDriver != NULL)
778  {
779  //Read port 6 XMII control 0 register
781 
782  //Retrieve host interface duplex mode
784  {
785  duplexMode = NIC_FULL_DUPLEX_MODE;
786  }
787  else
788  {
789  duplexMode = NIC_HALF_DUPLEX_MODE;
790  }
791  }
792  else
793  {
794  //The MDC/MDIO interface does not have access to all the configuration
795  //registers. It can only access the standard MIIM registers
796  duplexMode = NIC_FULL_DUPLEX_MODE;
797  }
798  }
799  else if(port == KSZ9477_PORT7)
800  {
801  //An external PHY can optionally be connected to port 7
802  duplexMode = ksz9477GetPort7DuplexMode(interface);
803  }
804  else
805  {
806  //The specified port number is not valid
807  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
808  }
809 
810  //Return duplex mode
811  return duplexMode;
812 }
813 
814 
815 /**
816  * @brief Get port 7 link state
817  * @param[in] interface Underlying network interface
818  * @return Link state
819  **/
820 
822 {
823  uint16_t value;
824  bool_t linkState;
825 
826  //Read SGMII Status register
828 
829  //Check whether the SGMII link is up
831  {
832  //Read SGMII Auto-Negotiation Status register
834 
835  //Check the link status reported by the PHY-side device
837  {
838  //The link is up
839  linkState = TRUE;
840  }
841  else
842  {
843  //The link is down
844  linkState = FALSE;
845  }
846  }
847  else
848  {
849  //The SGMII link is down
850  linkState = FALSE;
851  }
852 
853  //Return current link status
854  return linkState;
855 }
856 
857 
858 /**
859  * @brief Get port 7 link speed
860  * @param[in] interface Underlying network interface
861  * @return Link speed
862  **/
863 
864 __weak_func uint32_t ksz9477GetPort7LinkSpeed(NetInterface *interface)
865 {
866  uint16_t value;
867  uint32_t linkSpeed;
868 
869  //Read SGMII Auto-Negotiation Status register
871 
872  //Retrieve current link speed
874  {
875  //10 Mbps?
877  linkSpeed = NIC_LINK_SPEED_10MBPS;
878  break;
879 
880  //100 Mbps?
882  linkSpeed = NIC_LINK_SPEED_100MBPS;
883  break;
884 
885  //1000 Mbps?
887  linkSpeed = NIC_LINK_SPEED_1GBPS;
888  break;
889 
890  //Unknown speed?
891  default:
892  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
893  break;
894  }
895 
896  //Read SGMII Control register
898 
899  //If the SGMII speed is variable or less than 1000 Mbps, software must
900  //update GMAC parameters when there is a change to the link speed (silicon
901  //errata workaround 8)
902  if(linkSpeed == NIC_LINK_SPEED_10MBPS)
903  {
906  }
907  else if(linkSpeed == NIC_LINK_SPEED_100MBPS)
908  {
911  }
912  else if(linkSpeed == NIC_LINK_SPEED_1GBPS)
913  {
916  }
917  else
918  {
919  }
920 
921  //Write the modified value to the SGMII Control register
923 
924  //Return current link speed
925  return linkSpeed;
926 }
927 
928 
929 /**
930  * @brief Get port 7 duplex mode
931  * @param[in] interface Underlying network interface
932  * @return Duplex mode
933  **/
934 
936 {
937  uint16_t value;
938  NicDuplexMode duplexMode;
939 
940  //Read SGMII Auto-Negotiation Status register
942 
943  //Retrieve current duplex mode
945  {
946  duplexMode = NIC_FULL_DUPLEX_MODE;
947  }
948  else
949  {
950  duplexMode = NIC_HALF_DUPLEX_MODE;
951  }
952 
953  //Read SGMII Control register
955 
956  //Update GMAC duplex mode (silicon errata workaround 8)
957  if(duplexMode == NIC_FULL_DUPLEX_MODE)
958  {
960  }
961  else
962  {
964  }
965 
966  //Write the modified value to the SGMII Control register
968 
969  //Return current duplex mode
970  return duplexMode;
971 }
972 
973 
974 /**
975  * @brief Set port state
976  * @param[in] interface Underlying network interface
977  * @param[in] port Port number
978  * @param[in] state Port state
979  **/
980 
981 void ksz9477SetPortState(NetInterface *interface, uint8_t port,
982  SwitchPortState state)
983 {
984  uint8_t temp;
985 
986  //Check port number
987  if((port >= KSZ9477_PORT1 && port <= KSZ9477_PORT5) ||
988  port == KSZ9477_PORT7)
989  {
990  //Read MSTP state register
992 
993  //Update port state
994  switch(state)
995  {
996  //Listening state
1001  break;
1002 
1003  //Learning state
1008  break;
1009 
1010  //Forwarding state
1015  break;
1016 
1017  //Disabled state
1018  default:
1022  break;
1023  }
1024 
1025  //Write the value back to MSTP state register
1027  }
1028 }
1029 
1030 
1031 /**
1032  * @brief Get port state
1033  * @param[in] interface Underlying network interface
1034  * @param[in] port Port number
1035  * @return Port state
1036  **/
1037 
1039 {
1040  uint8_t temp;
1041  SwitchPortState state;
1042 
1043  //Check port number
1044  if((port >= KSZ9477_PORT1 && port <= KSZ9477_PORT5) ||
1045  port == KSZ9477_PORT7)
1046  {
1047  //Read MSTP state register
1049 
1050  //Check port state
1051  if((temp & KSZ9477_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
1052  (temp & KSZ9477_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
1054  {
1055  //Disabled state
1057  }
1058  else if((temp & KSZ9477_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
1059  (temp & KSZ9477_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
1061  {
1062  //Listening state
1064  }
1065  else if((temp & KSZ9477_PORTn_MSTP_STATE_TRANSMIT_EN) == 0 &&
1066  (temp & KSZ9477_PORTn_MSTP_STATE_RECEIVE_EN) == 0 &&
1068  {
1069  //Learning state
1071  }
1072  else if((temp & KSZ9477_PORTn_MSTP_STATE_TRANSMIT_EN) != 0 &&
1073  (temp & KSZ9477_PORTn_MSTP_STATE_RECEIVE_EN) != 0 &&
1075  {
1076  //Forwarding state
1078  }
1079  else
1080  {
1081  //Unknown state
1082  state = SWITCH_PORT_STATE_UNKNOWN;
1083  }
1084  }
1085  else
1086  {
1087  //The specified port number is not valid
1089  }
1090 
1091  //Return port state
1092  return state;
1093 }
1094 
1095 
1096 /**
1097  * @brief Set aging time for dynamic filtering entries
1098  * @param[in] interface Underlying network interface
1099  * @param[in] agingTime Aging time, in seconds
1100  **/
1101 
1102 void ksz9477SetAgingTime(NetInterface *interface, uint32_t agingTime)
1103 {
1104  //The Age Period in combination with the Age Count field determines the
1105  //aging time of dynamic entries in the address lookup table
1106  agingTime = (agingTime + 3) / 4;
1107 
1108  //Limit the range of the parameter
1109  agingTime = MIN(agingTime, 255);
1110 
1111  //Write the value to Switch Lookup Engine Control 3 register
1113  (uint8_t) agingTime);
1114 }
1115 
1116 
1117 /**
1118  * @brief Enable IGMP snooping
1119  * @param[in] interface Underlying network interface
1120  * @param[in] enable Enable or disable IGMP snooping
1121  **/
1122 
1124 {
1125  uint8_t temp;
1126 
1127  //Read the Global Port Mirroring and Snooping Control register
1128  temp = ksz9477ReadSwitchReg8(interface,
1130 
1131  //Enable or disable IGMP snooping
1132  if(enable)
1133  {
1135  }
1136  else
1137  {
1139  }
1140 
1141  //Write the value back to Global Port Mirroring and Snooping Control register
1143  temp);
1144 }
1145 
1146 
1147 /**
1148  * @brief Enable MLD snooping
1149  * @param[in] interface Underlying network interface
1150  * @param[in] enable Enable or disable MLD snooping
1151  **/
1152 
1154 {
1155  uint8_t temp;
1156 
1157  //Read the Global Port Mirroring and Snooping Control register
1158  temp = ksz9477ReadSwitchReg8(interface,
1160 
1161  //Enable or disable MLD snooping
1162  if(enable)
1163  {
1165  }
1166  else
1167  {
1169  }
1170 
1171  //Write the value back to Global Port Mirroring and Snooping Control register
1173  temp);
1174 }
1175 
1176 
1177 /**
1178  * @brief Enable reserved multicast table
1179  * @param[in] interface Underlying network interface
1180  * @param[in] enable Enable or disable reserved group addresses
1181  **/
1182 
1184 {
1185  uint8_t temp;
1186 
1187  //Read the Switch Lookup Engine Control 0 register
1189 
1190  //Enable or disable the reserved multicast table
1191  if(enable)
1192  {
1194  }
1195  else
1196  {
1198  }
1199 
1200  //Write the value back to Switch Lookup Engine Control 0 register
1202 }
1203 
1204 
1205 /**
1206  * @brief Add a new entry to the static MAC table
1207  * @param[in] interface Underlying network interface
1208  * @param[in] entry Pointer to the forwarding database entry
1209  * @return Error code
1210  **/
1211 
1213  const SwitchFdbEntry *entry)
1214 {
1215  error_t error;
1216  uint_t i;
1217  uint_t j;
1218  uint32_t value;
1219  SwitchFdbEntry currentEntry;
1220 
1221  //Keep track of the first free entry
1223 
1224  //Loop through the static MAC table
1225  for(i = 0; i < KSZ9477_STATIC_MAC_TABLE_SIZE; i++)
1226  {
1227  //Read current entry
1228  error = ksz9477GetStaticFdbEntry(interface, i, &currentEntry);
1229 
1230  //Valid entry?
1231  if(!error)
1232  {
1233  //Check whether the table already contains the specified MAC address
1234  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1235  {
1236  j = i;
1237  break;
1238  }
1239  }
1240  else
1241  {
1242  //Keep track of the first free entry
1244  {
1245  j = i;
1246  }
1247  }
1248  }
1249 
1250  //Any entry available?
1252  {
1253  //Write the Static Address Table Entry 1 register
1256 
1257  //Set the relevant forward ports
1258  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
1259  {
1261  }
1262  else
1263  {
1264  value = entry->destPorts & KSZ9477_PORT_MASK;
1265  }
1266 
1267  //Enable overriding of port state
1268  if(entry->override)
1269  {
1271  }
1272 
1273  //Write the Static Address Table Entry 2 register
1275 
1276  //Copy MAC address (first 16 bits)
1277  value = (entry->macAddr.b[0] << 8) | entry->macAddr.b[1];
1278 
1279  //Write the Static Address Table Entry 3 register
1281 
1282  //Copy MAC address (last 32 bits)
1283  value = (entry->macAddr.b[2] << 24) | (entry->macAddr.b[3] << 16) |
1284  (entry->macAddr.b[4] << 8) | entry->macAddr.b[5];
1285 
1286  //Write the Static Address Table Entry 4 register
1288 
1289  //Write the TABLE_INDEX field with the 4-bit index value
1291  //Set the TABLE_SELECT bit to 0 to select the static address table
1293  //Set the ACTION bit to 0 to indicate a write operation
1295  //Set the START_FINISH bit to 1 to initiate the operation
1297 
1298  //Start the write operation
1300  value);
1301 
1302  //When the operation is complete, the START_FINISH bit will be cleared
1303  //automatically
1304  do
1305  {
1306  //Read the Static Address and Reserved Multicast Table Control register
1307  value = ksz9477ReadSwitchReg32(interface,
1309 
1310  //Poll the START_FINISH bit
1312 
1313  //Successful processing
1314  error = NO_ERROR;
1315  }
1316  else
1317  {
1318  //The static MAC table is full
1319  error = ERROR_TABLE_FULL;
1320  }
1321 
1322  //Return status code
1323  return error;
1324 }
1325 
1326 
1327 /**
1328  * @brief Remove an entry from the static MAC table
1329  * @param[in] interface Underlying network interface
1330  * @param[in] entry Forwarding database entry to remove from the table
1331  * @return Error code
1332  **/
1333 
1335  const SwitchFdbEntry *entry)
1336 {
1337  error_t error;
1338  uint_t j;
1339  uint32_t value;
1340  SwitchFdbEntry currentEntry;
1341 
1342  //Loop through the static MAC table
1343  for(j = 0; j < KSZ9477_STATIC_MAC_TABLE_SIZE; j++)
1344  {
1345  //Read current entry
1346  error = ksz9477GetStaticFdbEntry(interface, j, &currentEntry);
1347 
1348  //Valid entry?
1349  if(!error)
1350  {
1351  //Check whether the table contains the specified MAC address
1352  if(macCompAddr(&currentEntry.macAddr, &entry->macAddr))
1353  {
1354  break;
1355  }
1356  }
1357  }
1358 
1359  //Any matching entry?
1361  {
1362  //Clear Static Address Table Entry registers
1367 
1368  //Write the TABLE_INDEX field with the 4-bit index value
1370  //Set the TABLE_SELECT bit to 0 to select the static address table
1372  //Set the ACTION bit to 0 to indicate a write operation
1374  //Set the START_FINISH bit to 1 to initiate the operation
1376 
1377  //Start the write operation
1379  value);
1380 
1381  //When the operation is complete, the START_FINISH bit will be cleared
1382  //automatically
1383  do
1384  {
1385  //Read the Static Address and Reserved Multicast Table Control register
1386  value = ksz9477ReadSwitchReg32(interface,
1388 
1389  //Poll the START_FINISH bit
1391 
1392  //Successful processing
1393  error = NO_ERROR;
1394  }
1395  else
1396  {
1397  //The static MAC table does not contain the specified address
1398  error = ERROR_NOT_FOUND;
1399  }
1400 
1401  //Return status code
1402  return error;
1403 }
1404 
1405 
1406 /**
1407  * @brief Read an entry from the static MAC table
1408  * @param[in] interface Underlying network interface
1409  * @param[in] index Zero-based index of the entry to read
1410  * @param[out] entry Pointer to the forwarding database entry
1411  * @return Error code
1412  **/
1413 
1415  SwitchFdbEntry *entry)
1416 {
1417  error_t error;
1418  uint32_t value;
1419 
1420  //Check index parameter
1421  if(index < KSZ9477_STATIC_MAC_TABLE_SIZE)
1422  {
1423  //Write the TABLE_INDEX field with the 4-bit index value
1425  //Set the TABLE_SELECT bit to 0 to select the static address table
1427  //Set the ACTION bit to 1 to indicate a read operation
1429  //Set the START_FINISH bit to 1 to initiate the operation
1431 
1432  //Start the read operation
1434  value);
1435 
1436  //When the operation is complete, the START_FINISH bit will be cleared
1437  //automatically
1438  do
1439  {
1440  //Read the Static Address and Reserved Multicast Table Control register
1441  value = ksz9477ReadSwitchReg32(interface,
1443 
1444  //Poll the START_FINISH bit
1446 
1447  //Read the Static Address Table Entry 1 register
1449 
1450  //Valid entry?
1452  {
1453  //Read the Static Address Table Entry 2 register
1455 
1456  //Retrieve the ports associated with this MAC address
1457  entry->srcPort = 0;
1459 
1460  //Check the value of the OVERRIDE bit
1462  {
1463  entry->override = TRUE;
1464  }
1465  else
1466  {
1467  entry->override = FALSE;
1468  }
1469 
1470  //Read the Static Address Table Entry 3 register
1472 
1473  //Copy MAC address (first 16 bits)
1474  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1475  entry->macAddr.b[1] = value & 0xFF;
1476 
1477  //Read the Static Address Table Entry 4 register
1479 
1480  //Copy MAC address (last 32 bits)
1481  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1482  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1483  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1484  entry->macAddr.b[5] = value & 0xFF;
1485 
1486  //Successful processing
1487  error = NO_ERROR;
1488  }
1489  else
1490  {
1491  //The entry is not valid
1492  error = ERROR_INVALID_ENTRY;
1493  }
1494  }
1495  else
1496  {
1497  //The end of the table has been reached
1498  error = ERROR_END_OF_TABLE;
1499  }
1500 
1501  //Return status code
1502  return error;
1503 }
1504 
1505 
1506 /**
1507  * @brief Flush static MAC table
1508  * @param[in] interface Underlying network interface
1509  **/
1510 
1512 {
1513  uint_t i;
1514  uint32_t value;
1515 
1516  //Loop through the static MAC table
1517  for(i = 0; i < KSZ9477_STATIC_MAC_TABLE_SIZE; i++)
1518  {
1519  //Clear Static Address Table Entry registers
1524 
1525  //Write the TABLE_INDEX field with the 4-bit index value
1527  //Set the TABLE_SELECT bit to 0 to select the static address table
1529  //Set the ACTION bit to 0 to indicate a write operation
1531  //Set the START_FINISH bit to 1 to initiate the operation
1533 
1534  //Start the write operation
1536  value);
1537 
1538  //When the operation is complete, the START_FINISH bit will be cleared
1539  //automatically
1540  do
1541  {
1542  //Read the Static Address and Reserved Multicast Table Control register
1543  value = ksz9477ReadSwitchReg32(interface,
1545 
1546  //Poll the START_FINISH bit
1548  }
1549 }
1550 
1551 
1552 /**
1553  * @brief Read an entry from the dynamic MAC table
1554  * @param[in] interface Underlying network interface
1555  * @param[in] index Zero-based index of the entry to read
1556  * @param[out] entry Pointer to the forwarding database entry
1557  * @return Error code
1558  **/
1559 
1561  SwitchFdbEntry *entry)
1562 {
1563  error_t error;
1564  uint32_t value;
1565 
1566  //First entry?
1567  if(index == 0)
1568  {
1569  //Clear the ALU Table Access Control register to stop any operation
1571 
1572  //Start the search operation
1576  }
1577 
1578  //Poll the VALID_ENTRY_OR_SEARCH_END bit until it is set
1579  do
1580  {
1581  //Read the ALU Table Access Control register
1583 
1584  //This bit goes high to indicate either a new valid entry is returned or
1585  //the search is complete
1587 
1588  //Check whether the next valid entry is ready
1589  if((value & KSZ9477_ALU_TABLE_CTRL_VALID) != 0)
1590  {
1591  //Store the data from the ALU table entry
1592  entry->destPorts = 0;
1593  entry->override = FALSE;
1594 
1595  //Read the ALU Table Entry 1 and 2 registers
1598 
1599  //Retrieve the port associated with this MAC address
1601  {
1603  entry->srcPort = KSZ9477_PORT1;
1604  break;
1606  entry->srcPort = KSZ9477_PORT2;
1607  break;
1609  entry->srcPort = KSZ9477_PORT3;
1610  break;
1612  entry->srcPort = KSZ9477_PORT4;
1613  break;
1615  entry->srcPort = KSZ9477_PORT5;
1616  break;
1618  entry->srcPort = KSZ9477_PORT6;
1619  break;
1621  entry->srcPort = KSZ9477_PORT7;
1622  break;
1623  default:
1624  entry->srcPort = 0;
1625  break;
1626  }
1627 
1628  //Read the ALU Table Entry 3 register
1630 
1631  //Copy MAC address (first 16 bits)
1632  entry->macAddr.b[0] = (value >> 8) & 0xFF;
1633  entry->macAddr.b[1] = value & 0xFF;
1634 
1635  //Read the ALU Table Entry 4 register
1637 
1638  //Copy MAC address (last 32 bits)
1639  entry->macAddr.b[2] = (value >> 24) & 0xFF;
1640  entry->macAddr.b[3] = (value >> 16) & 0xFF;
1641  entry->macAddr.b[4] = (value >> 8) & 0xFF;
1642  entry->macAddr.b[5] = value & 0xFF;
1643 
1644  //Successful processing
1645  error = NO_ERROR;
1646  }
1647  else
1648  {
1649  //The search can be stopped any time by setting the START_FINISH bit to 0
1651 
1652  //The end of the table has been reached
1653  error = ERROR_END_OF_TABLE;
1654  }
1655 
1656  //Return status code
1657  return error;
1658 }
1659 
1660 
1661 /**
1662  * @brief Flush dynamic MAC table
1663  * @param[in] interface Underlying network interface
1664  * @param[in] port Port number
1665  **/
1666 
1668 {
1669  uint_t temp;
1670  uint8_t state;
1671 
1672  //Flush only dynamic table entries
1677 
1678  //Valid port number?
1679  if(port >= KSZ9477_PORT1 && port <= KSZ9477_PORT7)
1680  {
1681  //Save the current state of the port
1683 
1684  //Turn off learning capability
1687 
1688  //All the entries associated with a port that has its learning capability
1689  //being turned off will be flushed
1693 
1694  //Restore the original state of the port
1696  }
1697  else
1698  {
1699  //Trigger a flush of the entire address lookup table
1703  }
1704 }
1705 
1706 
1707 /**
1708  * @brief Set forward ports for unknown multicast packets
1709  * @param[in] interface Underlying network interface
1710  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1711  * @param[in] forwardPorts Port map
1712  **/
1713 
1715  bool_t enable, uint32_t forwardPorts)
1716 {
1717  uint32_t temp;
1718 
1719  //Read Unknown Multicast Control register
1721 
1722  //Clear port map
1724 
1725  //Enable or disable forwarding of unknown multicast packets
1726  if(enable)
1727  {
1728  //Enable forwarding
1730 
1731  //Check whether unknown multicast packets should be forwarded to the CPU port
1732  if((forwardPorts & SWITCH_CPU_PORT_MASK) != 0)
1733  {
1735  }
1736 
1737  //Select the desired forward ports
1738  temp |= forwardPorts & KSZ9477_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL;
1739  }
1740  else
1741  {
1742  //Disable forwarding
1744  }
1745 
1746  //Write the value back to Unknown Multicast Control register
1748 }
1749 
1750 
1751 /**
1752  * @brief Write PHY register
1753  * @param[in] interface Underlying network interface
1754  * @param[in] port Port number
1755  * @param[in] address PHY register address
1756  * @param[in] data Register value
1757  **/
1758 
1759 void ksz9477WritePhyReg(NetInterface *interface, uint8_t port,
1760  uint8_t address, uint16_t data)
1761 {
1762  uint16_t n;
1763 
1764  //SPI slave mode?
1765  if(interface->spiDriver != NULL)
1766  {
1767  //The SPI interface provides access to all PHY registers
1769  //Write the 16-bit value
1770  ksz9477WriteSwitchReg16(interface, n, data);
1771  }
1772  else if(interface->smiDriver != NULL)
1773  {
1774  //Write the specified PHY register
1775  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1776  }
1777  else
1778  {
1779  //Write the specified PHY register
1780  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
1781  }
1782 }
1783 
1784 
1785 /**
1786  * @brief Read PHY register
1787  * @param[in] interface Underlying network interface
1788  * @param[in] port Port number
1789  * @param[in] address PHY register address
1790  * @return Register value
1791  **/
1792 
1793 uint16_t ksz9477ReadPhyReg(NetInterface *interface, uint8_t port,
1794  uint8_t address)
1795 {
1796  uint16_t n;
1797  uint16_t data;
1798 
1799  //SPI slave mode?
1800  if(interface->spiDriver != NULL)
1801  {
1802  //The SPI interface provides access to all PHY registers
1804  //Read the 16-bit value
1805  data = ksz9477ReadSwitchReg16(interface, n);
1806  }
1807  else if(interface->smiDriver != NULL)
1808  {
1809  //Read the specified PHY register
1810  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1811  }
1812  else
1813  {
1814  //Read the specified PHY register
1815  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
1816  }
1817 
1818  //Return register value
1819  return data;
1820 }
1821 
1822 
1823 /**
1824  * @brief Dump PHY registers for debugging purpose
1825  * @param[in] interface Underlying network interface
1826  * @param[in] port Port number
1827  **/
1828 
1829 void ksz9477DumpPhyReg(NetInterface *interface, uint8_t port)
1830 {
1831  uint8_t i;
1832 
1833  //Loop through PHY registers
1834  for(i = 0; i < 32; i++)
1835  {
1836  //Display current PHY register
1837  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1838  ksz9477ReadPhyReg(interface, port, i));
1839  }
1840 
1841  //Terminate with a line feed
1842  TRACE_DEBUG("\r\n");
1843 }
1844 
1845 
1846 /**
1847  * @brief Write MMD register
1848  * @param[in] interface Underlying network interface
1849  * @param[in] port Port number
1850  * @param[in] devAddr Device address
1851  * @param[in] regAddr Register address
1852  * @param[in] data Register value
1853  **/
1854 
1855 void ksz9477WriteMmdReg(NetInterface *interface, uint8_t port,
1856  uint8_t devAddr, uint16_t regAddr, uint16_t data)
1857 {
1858  //Select register operation
1861 
1862  //Write MMD register address
1864 
1865  //Select data operation
1868 
1869  //Write the content of the MMD register
1871 }
1872 
1873 
1874 /**
1875  * @brief Read MMD register
1876  * @param[in] interface Underlying network interface
1877  * @param[in] port Port number
1878  * @param[in] devAddr Device address
1879  * @param[in] regAddr Register address
1880  * @return Register value
1881  **/
1882 
1883 uint16_t ksz9477ReadMmdReg(NetInterface *interface, uint8_t port,
1884  uint8_t devAddr, uint16_t regAddr)
1885 {
1886  //Select register operation
1889 
1890  //Write MMD register address
1892 
1893  //Select data operation
1896 
1897  //Read the content of the MMD register
1898  return ksz9477ReadPhyReg(interface, port, KSZ9477_MMDAADR);
1899 }
1900 
1901 
1902 /**
1903  * @brief Write SGMII register
1904  * @param[in] interface Underlying network interface
1905  * @param[in] address SGMII register address
1906  * @param[in] data Register value
1907  **/
1908 
1909 void ksz9477WriteSgmiiReg(NetInterface *interface, uint32_t address,
1910  uint16_t data)
1911 {
1912  //Write the SGMII register address to the Port SGMII Address register
1914 
1915  //Write the SGMII register data to the Port SGMII Data register
1917 }
1918 
1919 
1920 /**
1921  * @brief Read SGMII register
1922  * @param[in] interface Underlying network interface
1923  * @param[in] address SGMII register address
1924  * @return Register value
1925  **/
1926 
1927 uint16_t ksz9477ReadSgmiiReg(NetInterface *interface, uint32_t address)
1928 {
1929  //Write the SGMII register address to the Port SGMII Address register
1931 
1932  //Read the SGMII register data from the Port SGMII Data register
1934 }
1935 
1936 
1937 /**
1938  * @brief Write switch register (8 bits)
1939  * @param[in] interface Underlying network interface
1940  * @param[in] address Switch register address
1941  * @param[in] data Register value
1942  **/
1943 
1944 void ksz9477WriteSwitchReg8(NetInterface *interface, uint16_t address,
1945  uint8_t data)
1946 {
1947  uint32_t command;
1948 
1949  //SPI slave mode?
1950  if(interface->spiDriver != NULL)
1951  {
1952  //Set up a write operation
1953  command = KSZ9477_SPI_CMD_WRITE;
1954  //Set register address
1955  command |= (address << 5) & KSZ9477_SPI_CMD_ADDR;
1956 
1957  //Pull the CS pin low
1958  interface->spiDriver->assertCs();
1959 
1960  //Write 32-bit command
1961  interface->spiDriver->transfer((command >> 24) & 0xFF);
1962  interface->spiDriver->transfer((command >> 16) & 0xFF);
1963  interface->spiDriver->transfer((command >> 8) & 0xFF);
1964  interface->spiDriver->transfer(command & 0xFF);
1965 
1966  //Write 8-bit data
1967  interface->spiDriver->transfer(data);
1968 
1969  //Terminate the operation by raising the CS pin
1970  interface->spiDriver->deassertCs();
1971  }
1972  else
1973  {
1974  //The MDC/MDIO interface does not have access to all the configuration
1975  //registers. It can only access the standard MIIM registers
1976  }
1977 }
1978 
1979 
1980 /**
1981  * @brief Read switch register (8 bits)
1982  * @param[in] interface Underlying network interface
1983  * @param[in] address Switch register address
1984  * @return Register value
1985  **/
1986 
1987 uint8_t ksz9477ReadSwitchReg8(NetInterface *interface, uint16_t address)
1988 {
1989  uint8_t data;
1990  uint32_t command;
1991 
1992  //SPI slave mode?
1993  if(interface->spiDriver != NULL)
1994  {
1995  //Set up a read operation
1996  command = KSZ9477_SPI_CMD_READ;
1997  //Set register address
1998  command |= (address << 5) & KSZ9477_SPI_CMD_ADDR;
1999 
2000  //Pull the CS pin low
2001  interface->spiDriver->assertCs();
2002 
2003  //Write 32-bit command
2004  interface->spiDriver->transfer((command >> 24) & 0xFF);
2005  interface->spiDriver->transfer((command >> 16) & 0xFF);
2006  interface->spiDriver->transfer((command >> 8) & 0xFF);
2007  interface->spiDriver->transfer(command & 0xFF);
2008 
2009  //Read 8-bit data
2010  data = interface->spiDriver->transfer(0xFF);
2011 
2012  //Terminate the operation by raising the CS pin
2013  interface->spiDriver->deassertCs();
2014  }
2015  else
2016  {
2017  //The MDC/MDIO interface does not have access to all the configuration
2018  //registers. It can only access the standard MIIM registers
2019  data = 0;
2020  }
2021 
2022  //Return register value
2023  return data;
2024 }
2025 
2026 
2027 /**
2028  * @brief Write switch register (16 bits)
2029  * @param[in] interface Underlying network interface
2030  * @param[in] address Switch register address
2031  * @param[in] data Register value
2032  **/
2033 
2035  uint16_t data)
2036 {
2037  uint32_t command;
2038 
2039  //SPI slave mode?
2040  if(interface->spiDriver != NULL)
2041  {
2042  //Set up a write operation
2043  command = KSZ9477_SPI_CMD_WRITE;
2044  //Set register address
2045  command |= (address << 5) & KSZ9477_SPI_CMD_ADDR;
2046 
2047  //Pull the CS pin low
2048  interface->spiDriver->assertCs();
2049 
2050  //Write 32-bit command
2051  interface->spiDriver->transfer((command >> 24) & 0xFF);
2052  interface->spiDriver->transfer((command >> 16) & 0xFF);
2053  interface->spiDriver->transfer((command >> 8) & 0xFF);
2054  interface->spiDriver->transfer(command & 0xFF);
2055 
2056  //Write 16-bit data
2057  interface->spiDriver->transfer((data >> 8) & 0xFF);
2058  interface->spiDriver->transfer(data & 0xFF);
2059 
2060  //Terminate the operation by raising the CS pin
2061  interface->spiDriver->deassertCs();
2062  }
2063  else
2064  {
2065  //The MDC/MDIO interface does not have access to all the configuration
2066  //registers. It can only access the standard MIIM registers
2067  }
2068 }
2069 
2070 
2071 /**
2072  * @brief Read switch register (16 bits)
2073  * @param[in] interface Underlying network interface
2074  * @param[in] address Switch register address
2075  * @return Register value
2076  **/
2077 
2078 uint16_t ksz9477ReadSwitchReg16(NetInterface *interface, uint16_t address)
2079 {
2080  uint16_t data;
2081  uint32_t command;
2082 
2083  //SPI slave mode?
2084  if(interface->spiDriver != NULL)
2085  {
2086  //Set up a read operation
2087  command = KSZ9477_SPI_CMD_READ;
2088  //Set register address
2089  command |= (address << 5) & KSZ9477_SPI_CMD_ADDR;
2090 
2091  //Pull the CS pin low
2092  interface->spiDriver->assertCs();
2093 
2094  //Write 32-bit command
2095  interface->spiDriver->transfer((command >> 24) & 0xFF);
2096  interface->spiDriver->transfer((command >> 16) & 0xFF);
2097  interface->spiDriver->transfer((command >> 8) & 0xFF);
2098  interface->spiDriver->transfer(command & 0xFF);
2099 
2100  //Read 16-bit data
2101  data = interface->spiDriver->transfer(0xFF) << 8;
2102  data |= interface->spiDriver->transfer(0xFF);
2103 
2104  //Terminate the operation by raising the CS pin
2105  interface->spiDriver->deassertCs();
2106  }
2107  else
2108  {
2109  //The MDC/MDIO interface does not have access to all the configuration
2110  //registers. It can only access the standard MIIM registers
2111  data = 0;
2112  }
2113 
2114  //Return register value
2115  return data;
2116 }
2117 
2118 
2119 /**
2120  * @brief Write switch register (32 bits)
2121  * @param[in] interface Underlying network interface
2122  * @param[in] address Switch register address
2123  * @param[in] data Register value
2124  **/
2125 
2127  uint32_t data)
2128 {
2129  uint32_t command;
2130 
2131  //SPI slave mode?
2132  if(interface->spiDriver != NULL)
2133  {
2134  //Set up a write operation
2135  command = KSZ9477_SPI_CMD_WRITE;
2136  //Set register address
2137  command |= (address << 5) & KSZ9477_SPI_CMD_ADDR;
2138 
2139  //Pull the CS pin low
2140  interface->spiDriver->assertCs();
2141 
2142  //Write 32-bit command
2143  interface->spiDriver->transfer((command >> 24) & 0xFF);
2144  interface->spiDriver->transfer((command >> 16) & 0xFF);
2145  interface->spiDriver->transfer((command >> 8) & 0xFF);
2146  interface->spiDriver->transfer(command & 0xFF);
2147 
2148  //Write 32-bit data
2149  interface->spiDriver->transfer((data >> 24) & 0xFF);
2150  interface->spiDriver->transfer((data >> 16) & 0xFF);
2151  interface->spiDriver->transfer((data >> 8) & 0xFF);
2152  interface->spiDriver->transfer(data & 0xFF);
2153 
2154  //Terminate the operation by raising the CS pin
2155  interface->spiDriver->deassertCs();
2156  }
2157  else
2158  {
2159  //The MDC/MDIO interface does not have access to all the configuration
2160  //registers. It can only access the standard MIIM registers
2161  }
2162 }
2163 
2164 
2165 /**
2166  * @brief Read switch register (32 bits)
2167  * @param[in] interface Underlying network interface
2168  * @param[in] address Switch register address
2169  * @return Register value
2170  **/
2171 
2172 uint32_t ksz9477ReadSwitchReg32(NetInterface *interface, uint16_t address)
2173 {
2174  uint32_t data;
2175  uint32_t command;
2176 
2177  //SPI slave mode?
2178  if(interface->spiDriver != NULL)
2179  {
2180  //Set up a read operation
2181  command = KSZ9477_SPI_CMD_READ;
2182  //Set register address
2183  command |= (address << 5) & KSZ9477_SPI_CMD_ADDR;
2184 
2185  //Pull the CS pin low
2186  interface->spiDriver->assertCs();
2187 
2188  //Write 32-bit command
2189  interface->spiDriver->transfer((command >> 24) & 0xFF);
2190  interface->spiDriver->transfer((command >> 16) & 0xFF);
2191  interface->spiDriver->transfer((command >> 8) & 0xFF);
2192  interface->spiDriver->transfer(command & 0xFF);
2193 
2194  //Read 32-bit data
2195  data = interface->spiDriver->transfer(0xFF) << 24;
2196  data |= interface->spiDriver->transfer(0xFF) << 16;
2197  data |= interface->spiDriver->transfer(0xFF) << 8;
2198  data |= interface->spiDriver->transfer(0xFF);
2199 
2200  //Terminate the operation by raising the CS pin
2201  interface->spiDriver->deassertCs();
2202  }
2203  else
2204  {
2205  //The MDC/MDIO interface does not have access to all the configuration
2206  //registers. It can only access the standard MIIM registers
2207  data = 0;
2208  }
2209 
2210  //Return register value
2211  return data;
2212 }
#define KSZ9477_PORT2
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:601
uint8_t ksz9477ReadSwitchReg8(NetInterface *interface, uint16_t address)
Read switch register (8 bits)
#define KSZ9477_SGMII_AN_STATUS_FULL_DUPLEX
error_t ksz9477Init(NetInterface *interface)
KSZ9477 Ethernet switch initialization.
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
error_t ksz9477TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add tail tag to Ethernet frame.
#define KSZ9477_PORT6_XMII_CTRL1
#define NetContext
Definition: net.h:36
#define KSZ9477_ALU_TABLE_ENTRY1
#define KSZ9477_PORTn_XMII_CTRL1_IF_TYPE
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
#define KSZ9477_SPI_CMD_ADDR
uint32_t destPorts
Definition: nic.h:152
#define KSZ9477_STATIC_TABLE_ENTRY1_VALID
#define KSZ9477_SWITCH_LUE_CTRL3
#define KSZ9477_SGMII_CTRL_SOFT_RESET
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define KSZ9477_ALU_TABLE_ENTRY2_PORT1_FORWARD
#define KSZ9477_TAIL_TAG_PORT_BLOCKING_OVERRIDE
@ SWITCH_PORT_STATE_LISTENING
Definition: nic.h:138
#define KSZ9477_PORT5
#define KSZ9477_GLOBAL_PORT_MIRROR_SNOOP_CTRL_IGMP_SNOOP_EN
#define KSZ9477_PORT1
#define KSZ9477_STATIC_MCAST_TABLE_CTRL_TABLE_SELECT
#define KSZ9477_ALU_TABLE_CTRL
#define KSZ9477_ALU_TABLE_ENTRY4
#define KSZ9477_MMDAADR
@ ERROR_END_OF_TABLE
Definition: error.h:292
#define KSZ9477_UNKONWN_MULTICAST_CTRL
@ SWITCH_PORT_STATE_DISABLED
Definition: nic.h:136
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define KSZ9477_PORT_MASK
#define TRUE
Definition: os_port.h:50
#define KSZ9477_PORTn_OP_CTRL0_TAIL_TAG_EN
#define KSZ9477_UNKONWN_MULTICAST_CTRL_FWD_MAP_PORT6
void ksz9477EnableIrq(NetInterface *interface)
Enable interrupts.
uint8_t data[]
Definition: ethernet.h:224
#define KSZ9477_SWITCH_LUE_CTRL0
#define KSZ9477_STATIC_TABLE_ENTRY2_OVERRIDE
@ SWITCH_PORT_STATE_LEARNING
Definition: nic.h:139
#define KSZ9477_SWITCH_MAC_CTRL0_FRAME_LEN_CHECK_EN
uint8_t type
Definition: coap_common.h:176
#define KSZ9477_ALU_TABLE_ENTRY2
void ksz9477SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
uint16_t ksz9477ReadSwitchReg16(NetInterface *interface, uint16_t address)
Read switch register (16 bits)
#define KSZ9477_STATIC_TABLE_ENTRY4
const uint16_t ksz9477IngressTailTag[8]
Tail tag rules (host to KSZ9477)
#define KSZ9477_PORT7_SGMII_ADDR
@ ERROR_INVALID_PORT
Definition: error.h:104
#define KSZ9477_SWITCH_LUE_CTRL2_FLUSH_OPTION_DYNAMIC
#define KSZ9477_SGMII_STATUS_LINK_STATUS
#define KSZ9477_ALU_TABLE_ENTRY2_PORT7_FORWARD
#define KSZ9477_SWITCH_OP
#define KSZ9477_ALU_TABLE_CTRL_START_FINISH
@ ERROR_TABLE_FULL
Definition: error.h:291
#define KSZ9477_PORT3
#define KSZ9477_TAIL_TAG_DEST_PORT7
EthHeader
Definition: ethernet.h:225
#define KSZ9477_SGMII_AN_STATUS
void ksz9477EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
#define KSZ9477_STATIC_MAC_TABLE_SIZE
#define KSZ9477_PORT7_SGMII_DATA
#define KSZ9477_SPI_CMD_WRITE
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define KSZ9477_SGMII_AN_STATUS_LINK_SPEED_1000MBPS
#define KSZ9477_PHYCON
#define KSZ9477_SGMII_AN_STATUS_LINK_SPEED_10MBPS
__weak_func uint32_t ksz9477GetPort7LinkSpeed(NetInterface *interface)
Get port 7 link speed.
#define KSZ9477_TAIL_TAG_SRC_PORT
#define KSZ9477_STATIC_TABLE_ENTRY3
@ SWITCH_PORT_STATE_UNKNOWN
Definition: nic.h:135
#define KSZ9477_PHYCON_SPEED_1000BT
#define KSZ9477_ALU_TABLE_ENTRY3
#define KSZ9477_ALU_TABLE_ENTRY2_PORT4_FORWARD
#define FALSE
Definition: os_port.h:46
#define KSZ9477_GLOBAL_PORT_MIRROR_SNOOP_CTRL
#define KSZ9477_PORTn_XMII_CTRL1_RGMII_ID_IG
uint16_t ksz9477ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
#define KSZ9477_PORT7
#define KSZ9477_PORTn_MSTP_STATE(port)
#define KSZ9477_UNKONWN_MULTICAST_CTRL_FWD
error_t
Error codes.
Definition: error.h:43
#define KSZ9477_ALU_TABLE_ENTRY2_PORT_FORWARD
#define KSZ9477_PORTn_MSTP_STATE_TRANSMIT_EN
__weak_func bool_t ksz9477GetPort7LinkState(NetInterface *interface)
Get port 7 link state.
#define KSZ9477_SWITCH_LUE_CTRL0_AGE_COUNT_DEFAULT
#define KSZ9477_SWITCH_OP_START_SWITCH
error_t ksz9477GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
#define KSZ9477_CHIP_ID1
void ksz9477SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
#define KSZ9477_ALU_TABLE_ENTRY2_PORT3_FORWARD
#define KSZ9477_GLOBAL_PORT_MIRROR_SNOOP_CTRL_MLD_SNOOP_EN
#define KSZ9477_PORTn_MSTP_STATE_RECEIVE_EN
#define KSZ9477_PHYCON_SPEED_100BTX
void ksz9477WriteSwitchReg16(NetInterface *interface, uint16_t address, uint16_t data)
Write switch register (16 bits)
#define KSZ9477_TAIL_TAG_DEST_PORT1
uint16_t ksz9477ReadSgmiiReg(NetInterface *interface, uint32_t address)
Read SGMII register.
#define KSZ9477_TAIL_TAG_DEST_PORT4
#define KSZ9477_CHIP_ID1_DEFAULT
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:40
void ksz9477FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
uint16_t ksz9477ReadMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr)
Read MMD register.
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
#define KSZ9477_TAIL_TAG_DEST_PORT2
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define KSZ9477_PHYCON_SPEED_10BT
#define KSZ9477_STATIC_TABLE_ENTRY1
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
bool_t ksz9477GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
void ksz9477WriteSwitchReg32(NetInterface *interface, uint16_t address, uint32_t data)
Write switch register (32 bits)
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
SwitchPortState
Switch port state.
Definition: nic.h:134
#define KSZ9477_SWITCH_LUE_CTRL0_HASH_OPTION_CRC
#define KSZ9477_MMD_LED_MODE_RESERVED_DEFAULT
void ksz9477DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
#define KSZ9477_UNKONWN_MULTICAST_CTRL_FWD_MAP
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
#define KSZ9477_TAIL_TAG_NORMAL_ADDR_LOOKUP
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define KSZ9477_STATIC_TABLE_ENTRY2_PORT_FORWARD
#define KSZ9477_BMSR_LINK_STATUS
#define MIN(a, b)
Definition: os_port.h:63
#define KSZ9477_SGMII_CTRL_AN_EN
#define KSZ9477_ALU_TABLE_ENTRY2_PORT5_FORWARD
#define KSZ9477_SWITCH_LUE_CTRL1
#define KSZ9477_SGMII_AN_STATUS_LINK_SPEED
#define KSZ9477_SGMII_AN_STATUS_LINK_STATUS
#define KSZ9477_ALU_TABLE_ENTRY2_PORT2_FORWARD
error_t ksz9477AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
#define KSZ9477_SGMII_STATUS
#define KSZ9477_MMD_LED_MODE
void ksz9477FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
uint32_t ksz9477GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
#define KSZ9477_SPI_CMD_READ
void ksz9477WriteSwitchReg8(NetInterface *interface, uint16_t address, uint8_t data)
Write switch register (8 bits)
__weak_func NicDuplexMode ksz9477GetPort7DuplexMode(NetInterface *interface)
Get port 7 duplex mode.
#define KSZ9477_SWITCH_LUE_CTRL1_FLUSH_ALU_TABLE
@ SWITCH_PORT_STATE_FORWARDING
Definition: nic.h:140
void ksz9477EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
uint16_t port
Definition: dns_common.h:270
#define KSZ9477_SWITCH_LUE_CTRL0_RESERVED_MCAST_LOOKUP_EN
#define KSZ9477_PORT6_OP_CTRL0
#define KSZ9477_PORTn_ETH_PHY_REG(port, addr)
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define KSZ9477_PORT6_MASK
#define KSZ9477_SWITCH_LUE_CTRL2_FLUSH_OPTION
#define KSZ9477_PORTn_XMII_CTRL1_SPEED_1000
uint32_t ksz9477ReadSwitchReg32(NetInterface *interface, uint16_t address)
Read switch register (32 bits)
void ksz9477WriteMmdReg(NetInterface *interface, uint8_t port, uint8_t devAddr, uint16_t regAddr, uint16_t data)
Write MMD register.
#define KSZ9477_UNKONWN_MULTICAST_CTRL_FWD_MAP_ALL
NicDuplexMode ksz9477GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
uint16_t regAddr
__weak_func void ksz9477EventHandler(NetInterface *interface)
KSZ9477 event handler.
const SwitchDriver ksz9477SwitchDriver
KSZ9477 Ethernet switch driver.
Ethernet switch driver.
Definition: nic.h:325
void ksz9477EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
#define HTONS(value)
Definition: cpu_endian.h:410
uint8_t n
#define KSZ9477_PORTn_XMII_CTRL1_RGMII_ID_EG
@ 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
SwitchPortState ksz9477GetPortState(NetInterface *interface, uint8_t port)
Get port state.
#define KSZ9477_PORT6_XMII_CTRL0
#define KSZ9477_SGMII_AN_STATUS_LINK_SPEED_100MBPS
#define KSZ9477_SWITCH_LUE_CTRL2
NicDuplexMode
Duplex mode.
Definition: nic.h:122
MacAddr macAddr
Definition: nic.h:150
#define KSZ9477_ALU_TABLE_ENTRY2_PORT6_FORWARD
#define KSZ9477_BMSR
uint8_t srcPort
Definition: nic.h:151
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
#define KSZ9477_SGMII_CTRL_SPEED_SEL_MSB
uint8_t value[]
Definition: tcp.h:376
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
#define KSZ9477_MMDACR
#define KSZ9477_STATIC_TABLE_ENTRY2
void ksz9477WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
#define KSZ9477_STATIC_MCAST_TABLE_CTRL
@ NIC_UNKNOWN_DUPLEX_MODE
Definition: nic.h:123
#define KSZ9477_MMD_EEE_ADV
#define KSZ9477_SWITCH_MAC_CTRL0
__weak_func void ksz9477InitHook(NetInterface *interface)
KSZ9477 custom configuration.
#define KSZ9477_PORTn_XMII_CTRL0_SPEED_10_100
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
KSZ9477 7-port Gigabit Ethernet switch driver.
error_t ksz9477UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode tail tag from incoming Ethernet frame.
#define KSZ9477_STATIC_MCAST_TABLE_CTRL_START_FINISH
#define KSZ9477_SGMII_CTRL_SPEED_SEL_LSB
#define KSZ9477_ALU_TABLE_CTRL_VALID
#define KSZ9477_SWITCH_LUE_CTRL3_AGE_PERIOD_DEFAULT
#define KSZ9477_PHYCON_DUPLEX_STATUS
#define KSZ9477_PORTn_XMII_CTRL0_DUPLEX
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define KSZ9477_SGMII_CTRL_DUPLEX_MODE
#define KSZ9477_MMDACR_FUNC_ADDR
#define KSZ9477_PORT6
#define KSZ9477_MMDACR_DEVAD
void ksz9477SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
#define KSZ9477_SWITCH_LUE_CTRL1_FLUSH_MSTP_ENTRIES
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
#define KSZ9477_TAIL_TAG_DEST_PORT3
__weak_func void ksz9477Tick(NetInterface *interface)
KSZ9477 timer handler.
#define KSZ9477_MMD_LED_MODE_LED_MODE_TRI_COLOR_DUAL
#define KSZ9477_TAIL_TAG_DEST_PORT5
#define KSZ9477_ALU_TABLE_CTRL_VALID_ENTRY_OR_SEARCH_END
void ksz9477WriteSgmiiReg(NetInterface *interface, uint32_t address, uint16_t data)
Write SGMII register.
void ksz9477DisableIrq(NetInterface *interface)
Disable interrupts.
Helper functions for Ethernet.
#define KSZ9477_SGMII_CTRL
#define KSZ9477_STATIC_MCAST_TABLE_CTRL_ACTION
#define KSZ9477_PORTn_XMII_CTRL1_IF_TYPE_RGMII
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
#define KSZ9477_ALU_TABLE_CTRL_ACTION_SEARCH
Debugging facilities.
#define KSZ9477_PORTn_MSTP_STATE_LEARNING_DIS
Forwarding database entry.
Definition: nic.h:149
#define KSZ9477_PORT4
error_t ksz9477GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
error_t ksz9477DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
#define KSZ9477_STATIC_MCAST_TABLE_CTRL_TABLE_INDEX
#define KSZ9477_MMDACR_FUNC_DATA_NO_POST_INC