mv88e6060_driver.c
Go to the documentation of this file.
1 /**
2  * @file mv88e6060_driver.c
3  * @brief 88E6060 6-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 88E6060 Ethernet switch driver
43  **/
44 
46 {
70 };
71 
72 
73 /**
74  * @brief Ingress trailer (CPU to 88E6060)
75  **/
76 
77 const uint32_t mv88e6060IngressTrailer[6] =
78 {
79  HTONL(0),
85 };
86 
87 
88 /**
89  * @brief 88E6060 Ethernet switch initialization
90  * @param[in] interface Underlying network interface
91  * @return Error code
92  **/
93 
95 {
96  uint_t port;
97  uint16_t temp;
98 
99  //Debug message
100  TRACE_INFO("Initializing 88E6060...\r\n");
101 
102  //Undefined PHY address?
103  if(interface->phyAddr >= 32)
104  {
105  //Use the default address
106  interface->phyAddr = MV88E6060_PHY_ADDR;
107  }
108 
109  //Initialize serial management interface
110  if(interface->smiDriver != NULL)
111  {
112  interface->smiDriver->init();
113  }
114 
115  //Wait for the serial interface to be ready
116  do
117  {
118  //Read switch identifier register
121 
122  //Retrieve device identifier
124 
125  //The returned data is invalid until the serial interface is ready
126  } while(temp != MV88E6060_SWITCH_ID_DEVICE_ID_DEFAULT);
127 
128 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
129  //Enable ingress and egress trailer mode
133 #else
134  //Disable ingress and egress trailer mode
137 #endif
138 
139  //Loop through the ports
141  {
142 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
143  //Port separation mode?
144  if(interface->port != 0)
145  {
146  //Use a separate address mapping database for each port
147  temp = ((port - 1) << 12) & MV88E6060_PORT_VLAN_MAP_DB_NUM;
148 
149  //The bits in the VLAN table are used to restrict which output ports
150  //this input port can send frames to
152  }
153  else
154 #endif
155  {
156  //Restore the VLAN table to its default value
157  temp = ~(1 << (port - 1)) & MV88E6060_PORT_VLAN_MAP_VLAN_TABLE;
158  }
159 
160  //Set port based VLAN map
162  temp);
163 
164  //For normal switch operation, the port's bit should be the only bit set
165  //in the port association vector
167  (1 << (port - 1)) & MV88E6060_PORT_ASSOC_VECTOR_PAV);
168 
169  //Enable transmission, reception and address learning
171  }
172 
173  //Restore default aging time
178 
179  //Flush static MAC table
180  mv88e6060FlushStaticFdbTable(interface);
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  mv88e6060DumpPhyReg(interface, port);
189  }
190 
191  //Perform custom configuration
192  mv88e6060InitHook(interface);
193 
194  //Force the TCP/IP stack to poll the link state at startup
195  interface->phyEvent = TRUE;
196  //Notify the TCP/IP stack of the event
198 
199  //Successful initialization
200  return NO_ERROR;
201 }
202 
203 
204 /**
205  * @brief 88E6060 custom configuration
206  * @param[in] interface Underlying network interface
207  **/
208 
209 __weak_func void mv88e6060InitHook(NetInterface *interface)
210 {
211 }
212 
213 
214 /**
215  * @brief 88E6060 timer handler
216  * @param[in] interface Underlying network interface
217  **/
218 
219 void mv88e6060Tick(NetInterface *interface)
220 {
221  uint_t port;
222  bool_t linkState;
223 
224 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
225  //Port separation mode?
226  if(interface->port != 0)
227  {
228  uint_t i;
229  NetInterface *virtualInterface;
230 
231  //Loop through network interfaces
232  for(i = 0; i < NET_INTERFACE_COUNT; i++)
233  {
234  //Point to the current interface
235  virtualInterface = &netInterface[i];
236 
237  //Check whether the current virtual interface is attached to the
238  //physical interface
239  if(virtualInterface == interface ||
240  virtualInterface->parent == interface)
241  {
242  //Retrieve current link state
243  linkState = mv88e6060GetLinkState(interface, virtualInterface->port);
244 
245  //Link up or link down event?
246  if(linkState != virtualInterface->linkState)
247  {
248  //Set event flag
249  interface->phyEvent = TRUE;
250  //Notify the TCP/IP stack of the event
252  }
253  }
254  }
255  }
256  else
257 #endif
258  {
259  //Initialize link state
260  linkState = FALSE;
261 
262  //Loop through the ports
264  {
265  //Retrieve current link state
266  if(mv88e6060GetLinkState(interface, port))
267  {
268  linkState = TRUE;
269  }
270  }
271 
272  //Link up or link down event?
273  if(linkState != interface->linkState)
274  {
275  //Set event flag
276  interface->phyEvent = TRUE;
277  //Notify the TCP/IP stack of the event
279  }
280  }
281 }
282 
283 
284 /**
285  * @brief Enable interrupts
286  * @param[in] interface Underlying network interface
287  **/
288 
290 {
291 }
292 
293 
294 /**
295  * @brief Disable interrupts
296  * @param[in] interface Underlying network interface
297  **/
298 
300 {
301 }
302 
303 
304 /**
305  * @brief 88E6060 event handler
306  * @param[in] interface Underlying network interface
307  **/
308 
310 {
311  uint_t port;
312  bool_t linkState;
313 
314 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
315  //Port separation mode?
316  if(interface->port != 0)
317  {
318  uint_t i;
319  NetInterface *virtualInterface;
320 
321  //Loop through network interfaces
322  for(i = 0; i < NET_INTERFACE_COUNT; i++)
323  {
324  //Point to the current interface
325  virtualInterface = &netInterface[i];
326 
327  //Check whether the current virtual interface is attached to the
328  //physical interface
329  if(virtualInterface == interface ||
330  virtualInterface->parent == interface)
331  {
332  //Get the port number associated with the current interface
333  port = virtualInterface->port;
334 
335  //Valid port?
337  {
338  //Retrieve current link state
339  linkState = mv88e6060GetLinkState(interface, port);
340 
341  //Link up event?
342  if(linkState && !virtualInterface->linkState)
343  {
344  //Adjust MAC configuration parameters for proper operation
345  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
346  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
347  interface->nicDriver->updateMacConfig(interface);
348 
349  //Check current speed
350  virtualInterface->linkSpeed = mv88e6060GetLinkSpeed(interface,
351  port);
352 
353  //Check current duplex mode
354  virtualInterface->duplexMode = mv88e6060GetDuplexMode(interface,
355  port);
356 
357  //Update link state
358  virtualInterface->linkState = TRUE;
359 
360  //Process link state change event
361  nicNotifyLinkChange(virtualInterface);
362  }
363  //Link down event
364  else if(!linkState && virtualInterface->linkState)
365  {
366  //Update link state
367  virtualInterface->linkState = FALSE;
368 
369  //Process link state change event
370  nicNotifyLinkChange(virtualInterface);
371  }
372  }
373  }
374  }
375  }
376  else
377 #endif
378  {
379  //Initialize link state
380  linkState = FALSE;
381 
382  //Loop through the ports
384  {
385  //Retrieve current link state
386  if(mv88e6060GetLinkState(interface, port))
387  {
388  linkState = TRUE;
389  }
390  }
391 
392  //Link up event?
393  if(linkState)
394  {
395  //Adjust MAC configuration parameters for proper operation
396  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
397  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
398  interface->nicDriver->updateMacConfig(interface);
399 
400  //Update link state
401  interface->linkState = TRUE;
402  }
403  else
404  {
405  //Update link state
406  interface->linkState = FALSE;
407  }
408 
409  //Process link state change event
410  nicNotifyLinkChange(interface);
411  }
412 }
413 
414 
415 /**
416  * @brief Add ingress trailer to Ethernet frame
417  * @param[in] interface Underlying network interface
418  * @param[in] buffer Multi-part buffer containing the payload
419  * @param[in,out] offset Offset to the first payload byte
420  * @param[in] ancillary Additional options passed to the stack along with
421  * the packet
422  * @return Error code
423  **/
424 
426  size_t *offset, NetTxAncillary *ancillary)
427 {
428  error_t error;
429 
430  //Initialize status code
431  error = NO_ERROR;
432 
433 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
434  //Valid port?
435  if(ancillary->port <= MV88E6060_PORT4)
436  {
437  size_t length;
438  const uint32_t *trailer;
439 
440  //The ingress trailer is used to indicate the destination port
441  trailer = &mv88e6060IngressTrailer[ancillary->port];
442 
443  //Retrieve the length of the Ethernet frame
444  length = netBufferGetLength(buffer) - *offset;
445 
446  //The host controller should manually add padding to the packet before
447  //inserting the ingress trailer
448  error = ethPadFrame(buffer, &length);
449 
450  //Check status code
451  if(!error)
452  {
453  //When the ingress trailer mode is enabled, four extra bytes are added
454  //to the end of the frame before the CRC
455  error = netBufferAppend(buffer, trailer, sizeof(uint32_t));
456  }
457  }
458  else
459  {
460  //The port number is not valid
461  error = ERROR_INVALID_PORT;
462  }
463 #endif
464 
465  //Return status code
466  return error;
467 }
468 
469 
470 /**
471  * @brief Decode egress trailer from incoming Ethernet frame
472  * @param[in] interface Underlying network interface
473  * @param[in,out] frame Pointer to the received Ethernet frame
474  * @param[in,out] length Length of the frame, in bytes
475  * @param[in,out] ancillary Additional options passed to the stack along with
476  * the packet
477  * @return Error code
478  **/
479 
480 error_t mv88e6060UntagFrame(NetInterface *interface, uint8_t **frame,
481  size_t *length, NetRxAncillary *ancillary)
482 {
483  error_t error;
484 
485  //Initialize status code
486  error = NO_ERROR;
487 
488 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
489  //Valid Ethernet frame received?
490  if(*length >= (sizeof(EthHeader) + sizeof(uint32_t)))
491  {
492  uint32_t n;
493  uint8_t *trailer;
494 
495  //When the egress trailer mode is enabled, four extra bytes are added
496  //to the end of the frame before the CRC
497  trailer = *frame + *length - sizeof(uint32_t);
498 
499  //Extract the SPID field from the egress trailer
500  n = LOAD32BE(trailer) & MV88E6060_EG_SPID;
501 
502  //The SPID field indicates the port where the frame was received
503  ancillary->port = (n >> 16) + 1;
504 
505  //Remove the trailer from the frame
506  *length -= sizeof(uint32_t);
507  }
508  else
509  {
510  //Drop the received frame
511  error = ERROR_INVALID_LENGTH;
512  }
513 #endif
514 
515  //Return status code
516  return error;
517 }
518 
519 
520 /**
521  * @brief Get link state
522  * @param[in] interface Underlying network interface
523  * @param[in] port Port number
524  * @return Link state
525  **/
526 
528 {
529  uint16_t status;
530  bool_t linkState;
531 
532  //Check port number
534  {
535  //Read port status register
537 
538  //Retrieve current link state
539  linkState = (status & MV88E6060_PORT_STAT_LINK) ? TRUE : FALSE;
540  }
541  else
542  {
543  //The specified port number is not valid
544  linkState = FALSE;
545  }
546 
547  //Return link status
548  return linkState;
549 }
550 
551 
552 /**
553  * @brief Get link speed
554  * @param[in] interface Underlying network interface
555  * @param[in] port Port number
556  * @return Link speed
557  **/
558 
559 uint32_t mv88e6060GetLinkSpeed(NetInterface *interface, uint8_t port)
560 {
561  uint16_t status;
562  uint32_t linkSpeed;
563 
564  //Check port number
566  {
567  //Read port status register
569 
570  //Retrieve current link speed
571  if((status & MV88E6060_PORT_STAT_SPEED) != 0)
572  {
573  linkSpeed = NIC_LINK_SPEED_100MBPS;
574  }
575  else
576  {
577  linkSpeed = NIC_LINK_SPEED_10MBPS;
578  }
579  }
580  else
581  {
582  //The specified port number is not valid
583  linkSpeed = NIC_LINK_SPEED_UNKNOWN;
584  }
585 
586  //Return link status
587  return linkSpeed;
588 }
589 
590 
591 /**
592  * @brief Get duplex mode
593  * @param[in] interface Underlying network interface
594  * @param[in] port Port number
595  * @return Duplex mode
596  **/
597 
599 {
600  uint16_t status;
601  NicDuplexMode duplexMode;
602 
603  //Check port number
605  {
606  //Read port status register
608 
609  //Retrieve current duplex mode
610  if((status & MV88E6060_PORT_STAT_DUPLEX) != 0)
611  {
612  duplexMode = NIC_FULL_DUPLEX_MODE;
613  }
614  else
615  {
616  duplexMode = NIC_HALF_DUPLEX_MODE;
617  }
618  }
619  else
620  {
621  //The specified port number is not valid
622  duplexMode = NIC_UNKNOWN_DUPLEX_MODE;
623  }
624 
625  //Return duplex mode
626  return duplexMode;
627 }
628 
629 
630 /**
631  * @brief Set port state
632  * @param[in] interface Underlying network interface
633  * @param[in] port Port number
634  * @param[in] state Port state
635  **/
636 
637 void mv88e6060SetPortState(NetInterface *interface, uint8_t port,
638  SwitchPortState state)
639 {
640  uint16_t temp;
641 
642  //Check port number
644  {
645  //Read port control register
647 
648  //Clear current configuration
650 
651  //Update port state
652  switch(state)
653  {
654  //Blocking state?
657  break;
658 
659  //Learning state?
662  break;
663 
664  //Forwarding state?
667  break;
668 
669  //Disabled state?
670  default:
672  break;
673  }
674 
675  //Write the value back to port control register
677  }
678 }
679 
680 
681 /**
682  * @brief Get port state
683  * @param[in] interface Underlying network interface
684  * @param[in] port Port number
685  * @return Port state
686  **/
687 
689 {
690  uint16_t temp;
691  SwitchPortState state;
692 
693  //Check port number
695  {
696  //Read port control register
698 
699  //Check port state
700  switch(temp & MV88E6060_PORT_CTRL_PORT_STATE)
701  {
702  //Blocking state?
705  break;
706 
707  //Learning state?
710  break;
711 
712  //Forwarding state?
715  break;
716 
717  //Disabled state?
718  default:
720  break;
721  }
722  }
723  else
724  {
725  //The specified port number is not valid
727  }
728 
729  //Return port state
730  return state;
731 }
732 
733 
734 /**
735  * @brief Set aging time for dynamic filtering entries
736  * @param[in] interface Underlying network interface
737  * @param[in] agingTime Aging time, in seconds
738  **/
739 
740 void mv88e6060SetAgingTime(NetInterface *interface, uint32_t agingTime)
741 {
742  uint16_t temp;
743 
744  //Read the ATU control register
746 
747  //The value in this register times 16 is the age time in seconds
748  agingTime = (agingTime + 15) / 16;
749 
750  //Limit the range of the parameter
751  agingTime = MAX(agingTime, 1);
752  agingTime = MIN(agingTime, 255);
753 
754  //Update the AgeTime field
755  temp = (temp & ~MV88E6060_ATU_CTRL_AGE_TIME) | (agingTime << 4);
756 
757  //Write the value back to ATU control register
759 }
760 
761 
762 /**
763  * @brief Enable IGMP snooping
764  * @param[in] interface Underlying network interface
765  * @param[in] enable Enable or disable IGMP snooping
766  **/
767 
769 {
770  //Not implemented
771 }
772 
773 
774 /**
775  * @brief Enable MLD snooping
776  * @param[in] interface Underlying network interface
777  * @param[in] enable Enable or disable MLD snooping
778  **/
779 
781 {
782  //Not implemented
783 }
784 
785 
786 /**
787  * @brief Enable reserved multicast table
788  * @param[in] interface Underlying network interface
789  * @param[in] enable Enable or disable reserved group addresses
790  **/
791 
793 {
794  uint_t i;
795  SwitchFdbEntry entry;
796 
797  //The reserved group addresses are in the range of 01-80-C2-00-00-00 to
798  //01-80-C2-00-00-0F
799  for(i = 0; i <= 15; i++)
800  {
801  //Specify the reserved group address to be added or removed
802  entry.macAddr.b[0] = 0x01;
803  entry.macAddr.b[1] = 0x80;
804  entry.macAddr.b[2] = 0xC2;
805  entry.macAddr.b[3] = 0x00;
806  entry.macAddr.b[4] = 0x00;
807  entry.macAddr.b[5] = i;
808 
809  //Format forwarding database entry
810  entry.srcPort = 0;
812  entry.override = TRUE;
813 
814  //Update the static MAC table
815  if(enable)
816  {
817  mv88e6060AddStaticFdbEntry(interface, &entry);
818  }
819  else
820  {
821  mv88e6060DeleteStaticFdbEntry(interface, &entry);
822  }
823  }
824 }
825 
826 
827 /**
828  * @brief Add a new entry to the static MAC table
829  * @param[in] interface Underlying network interface
830  * @param[in] entry Pointer to the forwarding database entry
831  * @return Error code
832  **/
833 
835  const SwitchFdbEntry *entry)
836 {
837  uint16_t value;
838 
839  //Make sure the ATU is available by checking the ATUBusy bit
840  do
841  {
842  //Read the ATU operation register
844 
845  //Poll the ATUBusy bit
846  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
847 
848  //Check whether the forward port is the CPU port
849  if(entry->destPorts == SWITCH_CPU_PORT_MASK)
850  {
852  }
853  else
854  {
855  value = (entry->destPorts << 4) & MV88E6060_ATU_DATA_DPV;
856  }
857 
858  //Multicast address?
859  if(macIsMulticastAddr(&entry->macAddr))
860  {
861  //The multicast address is locked and does not age
862  if(entry->override)
863  {
865  }
866  else
867  {
869  }
870  }
871  else
872  {
873  //The unicast address is locked and does not age
875  }
876 
877  //Load ATU data register
879 
880  //Load ATU MAC address register (bytes 0 and 1)
882  htons(entry->macAddr.w[0]));
883 
884  //Load ATU MAC address register (bytes 2 and 3)
886  htons(entry->macAddr.w[1]));
887 
888  //Load ATU MAC address register (bytes 4 and 5)
890  htons(entry->macAddr.w[2]));
891 
892  //Start the ATU load operation
896 
897  //Completion can be verified by polling the ATUBusy bit
898  do
899  {
900  //Read the ATU operation register
902 
903  //Poll the ATUBusy bit
904  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
905 
906  //Successful processing
907  return NO_ERROR;
908 }
909 
910 
911 /**
912  * @brief Remove an entry from the static MAC table
913  * @param[in] interface Underlying network interface
914  * @param[in] entry Forwarding database entry to remove from the table
915  * @return Error code
916  **/
917 
919  const SwitchFdbEntry *entry)
920 {
921  uint16_t value;
922 
923  //Make sure the ATU is available by checking the ATUBusy bit
924  do
925  {
926  //Read the ATU operation register
928 
929  //Poll the ATUBusy bit
930  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
931 
932  //Load ATU data register
935 
936  //Load ATU MAC address register (bytes 0 and 1)
938  htons(entry->macAddr.w[0]));
939 
940  //Load ATU MAC address register (bytes 2 and 3)
942  htons(entry->macAddr.w[1]));
943 
944  //Load ATU MAC address register (bytes 4 and 5)
946  htons(entry->macAddr.w[2]));
947 
948  //Start the ATU purge operation
952 
953  //Completion can be verified by polling the ATUBusy bit
954  do
955  {
956  //Read the ATU operation register
958 
959  //Poll the ATUBusy bit
960  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
961 
962  //Successful processing
963  return NO_ERROR;
964 }
965 
966 
967 /**
968  * @brief Read an entry from the static MAC table
969  * @param[in] interface Underlying network interface
970  * @param[in] index Zero-based index of the entry to read
971  * @param[out] entry Pointer to the forwarding database entry
972  * @return Error code
973  **/
974 
976  SwitchFdbEntry *entry)
977 {
978  uint16_t value;
979  uint16_t entryState;
980 
981  //Make sure the ATU is available by checking the ATUBusy bit
982  do
983  {
984  //Read the ATU operation register
986 
987  //Poll the ATUBusy bit
988  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
989 
990  //Loop through the ATU table
991  while(index < MV88E6060_ATU_TABLE_SIZE)
992  {
993  //First entry?
994  if(index == 0)
995  {
996  //Use an ATU MAC address of all ones to get the first or lowest active
997  //MAC address
998  entry->macAddr = MAC_BROADCAST_ADDR;
999  }
1000 
1001  //The get next operation starts with the MAC address contained in the ATU
1002  //MAC registers and returns the next higher active MAC address currently
1003  //active in the address database
1005  htons(entry->macAddr.w[0]));
1006 
1007  //Load ATU MAC address register (bytes 2 and 3)
1009  htons(entry->macAddr.w[1]));
1010 
1011  //Load ATU MAC address register (bytes 4 and 5)
1013  htons(entry->macAddr.w[2]));
1014 
1015  //Start the ATU get next operation
1019 
1020  //Completion can be verified by polling the ATUBusy bit
1021  do
1022  {
1023  //Read the ATU operation register
1025 
1026  //Poll the ATUBusy bit
1027  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
1028 
1029  //The returned MAC address and its data is accessible in the ATU MAC and
1030  //the ATU data registers
1032 
1033  //Read ATU MAC address register (bytes 0 and 1)
1034  entry->macAddr.w[0] = ntohs(mv88e6060ReadSwitchGlobalReg(interface,
1036 
1037  //Read ATU MAC address register (bytes 2 and 3)
1038  entry->macAddr.w[1] = ntohs(mv88e6060ReadSwitchGlobalReg(interface,
1040 
1041  //Read ATU MAC address register (bytes 4 and 5)
1042  entry->macAddr.w[2] = ntohs(mv88e6060ReadSwitchGlobalReg(interface,
1044 
1045  //When the returned MAC address is all ones, it always indicates that the
1046  //end of the table has been reached
1047  if(macCompAddr(&entry->macAddr, &MAC_BROADCAST_ADDR))
1048  {
1049  return ERROR_END_OF_TABLE;
1050  }
1051 
1052  //Retrieve entry state
1053  entryState = value & MV88E6060_ATU_DATA_ENTRY_STATE;
1054 
1055  //Multicast address?
1056  if(macIsMulticastAddr(&entry->macAddr))
1057  {
1058  //Static entry?
1061  {
1062  break;
1063  }
1064  }
1065  else
1066  {
1067  //Static entry?
1069  {
1070  break;
1071  }
1072  }
1073 
1074  //Skip dynamic entries
1075  index++;
1076  }
1077 
1078  //Store the data from the ATU MAC and the ATU data registers
1079  entry->srcPort = 0;
1080  entry->destPorts = (value & MV88E6060_ATU_DATA_DPV) >> 4;
1081 
1082  //Check entry state
1084  {
1085  entry->override = TRUE;
1086  }
1087  else
1088  {
1089  entry->override = FALSE;
1090  }
1091 
1092  //Successful processing
1093  return NO_ERROR;
1094 }
1095 
1096 
1097 /**
1098  * @brief Flush static MAC table
1099  * @param[in] interface Underlying network interface
1100  **/
1101 
1103 {
1104  error_t error;
1105  uint_t i;
1106  SwitchFdbEntry entry;
1107 
1108  //Loop through the ATU table
1109  for(i = 0; i < MV88E6060_ATU_TABLE_SIZE; i++)
1110  {
1111  //Read current entry
1112  error = mv88e6060GetStaticFdbEntry(interface, i, &entry);
1113 
1114  //Valid entry?
1115  if(!error)
1116  {
1117  //An entry can be deleted by setting the entry state to 0
1118  mv88e6060DeleteStaticFdbEntry(interface, &entry);
1119  }
1120  else
1121  {
1122  //The end of the table has been reached
1123  break;
1124  }
1125  }
1126 }
1127 
1128 
1129 /**
1130  * @brief Read an entry from the dynamic MAC table
1131  * @param[in] interface Underlying network interface
1132  * @param[in] index Zero-based index of the entry to read
1133  * @param[out] entry Pointer to the forwarding database entry
1134  * @return Error code
1135  **/
1136 
1138  SwitchFdbEntry *entry)
1139 {
1140  uint16_t value;
1141  uint16_t entryState;
1142 
1143  //Make sure the ATU is available by checking the ATUBusy bit
1144  do
1145  {
1146  //Read the ATU operation register
1148 
1149  //Poll the ATUBusy bit
1150  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
1151 
1152  //Loop through the ATU table
1153  while(index < MV88E6060_ATU_TABLE_SIZE)
1154  {
1155  //First entry?
1156  if(index == 0)
1157  {
1158  //Use an ATU MAC address of all ones to get the first or lowest active
1159  //MAC address
1160  entry->macAddr = MAC_BROADCAST_ADDR;
1161  }
1162 
1163  //The get next operation starts with the MAC address contained in the ATU
1164  //MAC registers and returns the next higher active MAC address currently
1165  //active in the address database
1167  htons(entry->macAddr.w[0]));
1168 
1169  //Load ATU MAC address register (bytes 2 and 3)
1171  htons(entry->macAddr.w[1]));
1172 
1173  //Load ATU MAC address register (bytes 4 and 5)
1175  htons(entry->macAddr.w[2]));
1176 
1177  //Start the ATU get next operation
1181 
1182  //Completion can be verified by polling the ATUBusy bit
1183  do
1184  {
1185  //Read the ATU operation register
1187 
1188  //Poll the ATUBusy bit
1189  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
1190 
1191  //The returned MAC address and its data is accessible in the ATU MAC and
1192  //the ATU data registers
1194 
1195  //Read ATU MAC address register (bytes 0 and 1)
1196  entry->macAddr.w[0] = ntohs(mv88e6060ReadSwitchGlobalReg(interface,
1198 
1199  //Read ATU MAC address register (bytes 2 and 3)
1200  entry->macAddr.w[1] = ntohs(mv88e6060ReadSwitchGlobalReg(interface,
1202 
1203  //Read ATU MAC address register (bytes 4 and 5)
1204  entry->macAddr.w[2] = ntohs(mv88e6060ReadSwitchGlobalReg(interface,
1206 
1207  //When the returned MAC address is all ones, it always indicates that the
1208  //end of the table has been reached
1209  if(macCompAddr(&entry->macAddr, &MAC_BROADCAST_ADDR))
1210  {
1211  return ERROR_END_OF_TABLE;
1212  }
1213 
1214  //Retrieve entry state
1215  entryState = value & MV88E6060_ATU_DATA_ENTRY_STATE;
1216 
1217  //Multicast address?
1218  if(macIsMulticastAddr(&entry->macAddr))
1219  {
1220  //Dynamic entry?
1221  if(entryState != MV88E6060_ATU_DATA_ENTRY_STATE_INVALID &&
1224  {
1225  break;
1226  }
1227  }
1228  else
1229  {
1230  //Dynamic entry?
1231  if(entryState != MV88E6060_ATU_DATA_ENTRY_STATE_INVALID &&
1233  {
1234  break;
1235  }
1236  }
1237 
1238  //Skip static entries
1239  index++;
1240  }
1241 
1242  //Store the data from the ATU MAC and the ATU data registers
1243  entry->srcPort = 0;
1244  entry->override = FALSE;
1245 
1246  //Retrieve the port associated with this MAC address
1247  switch(value & MV88E6060_ATU_DATA_DPV)
1248  {
1250  entry->srcPort = MV88E6060_PORT0;
1251  break;
1252 
1254  entry->srcPort = MV88E6060_PORT1;
1255  break;
1256 
1258  entry->srcPort = MV88E6060_PORT2;
1259  break;
1260 
1262  entry->srcPort = MV88E6060_PORT3;
1263  break;
1264 
1266  entry->srcPort = MV88E6060_PORT4;
1267  break;
1268 
1270  entry->srcPort = MV88E6060_PORT5;
1271  break;
1272 
1273  default:
1274  entry->srcPort = 0;
1275  break;
1276  }
1277 
1278  //Successful processing
1279  return NO_ERROR;
1280 }
1281 
1282 
1283 /**
1284  * @brief Flush dynamic MAC table
1285  * @param[in] interface Underlying network interface
1286  * @param[in] port Port number
1287  **/
1288 
1290 {
1291  error_t error;
1292  uint_t i;
1293  uint16_t value;
1294  SwitchFdbEntry entry;
1295 
1296  //Make sure the ATU is available by checking the ATUBusy bit
1297  do
1298  {
1299  //Read the ATU operation register
1301 
1302  //Poll the ATUBusy bit
1303  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
1304 
1305  //Valid port number?
1306  if(port > 0)
1307  {
1308  //Loop through the ATU table
1309  for(i = 0; i < MV88E6060_ATU_TABLE_SIZE; i++)
1310  {
1311  //Read current entry
1312  error = mv88e6060GetDynamicFdbEntry(interface, i, &entry);
1313 
1314  //Valid entry?
1315  if(!error)
1316  {
1317  //Matching port number?
1318  if(entry.srcPort == port)
1319  {
1320  //Load ATU data register
1323 
1324  //Load ATU MAC address register (bytes 0 and 1)
1327 
1328  //Load ATU MAC address register (bytes 2 and 3)
1331 
1332  //Load ATU MAC address register (bytes 4 and 5)
1335 
1336  //Start the ATU purge operation
1340 
1341  //Completion can be verified by polling the ATUBusy bit
1342  do
1343  {
1344  //Read the ATU operation register
1345  value = mv88e6060ReadSwitchGlobalReg(interface,
1347 
1348  //Poll the ATUBusy bit
1349  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
1350  }
1351  }
1352  else
1353  {
1354  //The end of the table has been reached
1355  break;
1356  }
1357  }
1358  }
1359  else
1360  {
1361  //Flush all unlocked entries
1365 
1366  //Completion can be verified by polling the ATUBusy bit
1367  do
1368  {
1369  //Read the ATU operation register
1371 
1372  //Poll the ATUBusy bit
1373  } while((value & MV88E6060_ATU_OPERATION_ATU_BUSY) != 0);
1374  }
1375 }
1376 
1377 
1378 /**
1379  * @brief Set forward ports for unknown multicast packets
1380  * @param[in] interface Underlying network interface
1381  * @param[in] enable Enable or disable forwarding of unknown multicast packets
1382  * @param[in] forwardPorts Port map
1383  **/
1384 
1386  bool_t enable, uint32_t forwardPorts)
1387 {
1388  //Not implemented
1389 }
1390 
1391 
1392 /**
1393  * @brief Write SMI register
1394  * @param[in] interface Underlying network interface
1395  * @param[in] deviceAddr SMI device address
1396  * @param[in] regAddr Register address
1397  * @param[in] data Register value
1398  **/
1399 
1400 void mv88e6060WriteSmiReg(NetInterface *interface, uint8_t deviceAddr,
1401  uint8_t regAddr, uint16_t data)
1402 {
1403  //The device uses 16 of the 32 possible SMI port addresses. The ones that
1404  //are used are selectable using the EE_CLK/ADDR4 configuration pin
1405  if(interface->smiDriver != NULL)
1406  {
1407  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE,
1408  interface->phyAddr + deviceAddr, regAddr, data);
1409  }
1410  else
1411  {
1412  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE,
1413  interface->phyAddr + deviceAddr, regAddr, data);
1414  }
1415 }
1416 
1417 
1418 /**
1419  * @brief Read SMI register
1420  * @param[in] interface Underlying network interface
1421  * @param[in] deviceAddr SMI device address
1422  * @param[in] regAddr Register address
1423  * @return Register value
1424  **/
1425 
1426 uint16_t mv88e6060ReadSmiReg(NetInterface *interface, uint8_t deviceAddr,
1427  uint8_t regAddr)
1428 {
1429  uint16_t data;
1430 
1431  //The device uses 16 of the 32 possible SMI port addresses. The ones that
1432  //are used are selectable using the EE_CLK/ADDR4 configuration pin
1433  if(interface->smiDriver != NULL)
1434  {
1435  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ,
1436  interface->phyAddr + deviceAddr, regAddr);
1437  }
1438  else
1439  {
1440  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ,
1441  interface->phyAddr + deviceAddr, regAddr);
1442  }
1443 
1444  //Return the value of the SMI register
1445  return data;
1446 }
1447 
1448 
1449 /**
1450  * @brief Write PHY register
1451  * @param[in] interface Underlying network interface
1452  * @param[in] port Port number
1453  * @param[in] address PHY register address
1454  * @param[in] data Register value
1455  **/
1456 
1457 void mv88e6060WritePhyReg(NetInterface *interface, uint8_t port,
1458  uint8_t address, uint16_t data)
1459 {
1460  //Valid port number?
1462  {
1463  //PHY registers are accessible using SMI device addresses 0x00 to 0x04 (or
1464  //0x10 to 0x14) depending upon the value of the EE_CLK/ADDR4 pin at reset
1465  mv88e6060WriteSmiReg(interface, port - 1, address, data);
1466  }
1467  else
1468  {
1469  //The specified port number is not valid
1470  }
1471 }
1472 
1473 
1474 /**
1475  * @brief Read PHY register
1476  * @param[in] interface Underlying network interface
1477  * @param[in] port Port number
1478  * @param[in] address PHY register address
1479  * @return Register value
1480  **/
1481 
1482 uint16_t mv88e6060ReadPhyReg(NetInterface *interface, uint8_t port,
1483  uint8_t address)
1484 {
1485  uint16_t data;
1486 
1487  //Valid port number?
1489  {
1490  //PHY registers are accessible using SMI device addresses 0x00 to 0x04 (or
1491  //0x10 to 0x14) depending upon the value of the EE_CLK/ADDR4 pin at reset
1492  data = mv88e6060ReadSmiReg(interface, port - 1, address);
1493  }
1494  else
1495  {
1496  //The specified port number is not valid
1497  data = 0;
1498  }
1499 
1500  //Return the value of the switch port register
1501  return data;
1502 }
1503 
1504 
1505 /**
1506  * @brief Dump PHY registers for debugging purpose
1507  * @param[in] interface Underlying network interface
1508  * @param[in] port Port number
1509  **/
1510 
1511 void mv88e6060DumpPhyReg(NetInterface *interface, uint8_t port)
1512 {
1513  uint8_t i;
1514 
1515  //Loop through PHY registers
1516  for(i = 0; i < 32; i++)
1517  {
1518  //Display current PHY register
1519  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
1520  mv88e6060ReadPhyReg(interface, port, i));
1521  }
1522 
1523  //Terminate with a line feed
1524  TRACE_DEBUG("\r\n");
1525 }
1526 
1527 
1528 /**
1529  * @brief Write switch port register
1530  * @param[in] interface Underlying network interface
1531  * @param[in] port Port number
1532  * @param[in] address Switch port register address
1533  * @param[in] data Register value
1534  **/
1535 
1537  uint8_t address, uint16_t data)
1538 {
1539  //Valid port number?
1541  {
1542  //Switch port registers are accessible using SMI device addresses 0x08
1543  //to 0x0D (or 0x18 to 0x1D) depending upon the value of the EE_CLK/ADDR4
1544  //pin at reset
1545  mv88e6060WriteSmiReg(interface, port + 7, address, data);
1546  }
1547  else
1548  {
1549  //The specified port number is not valid
1550  }
1551 }
1552 
1553 
1554 /**
1555  * @brief Read switch port register
1556  * @param[in] interface Underlying network interface
1557  * @param[in] port Port number
1558  * @param[in] address Switch port register address
1559  * @return Register value
1560  **/
1561 
1562 uint16_t mv88e6060ReadSwitchPortReg(NetInterface *interface, uint8_t port,
1563  uint8_t address)
1564 {
1565  uint16_t data;
1566 
1567  //Valid port number?
1569  {
1570  //Switch port registers are accessible using SMI device addresses 0x08
1571  //to 0x0D (or 0x18 to 0x1D) depending upon the value of the EE_CLK/ADDR4
1572  //pin at reset
1573  data = mv88e6060ReadSmiReg(interface, port + 7, address);
1574  }
1575  else
1576  {
1577  //The specified port number is not valid
1578  data = 0;
1579  }
1580 
1581  //Return the value of the switch port register
1582  return data;
1583 }
1584 
1585 
1586 /**
1587  * @brief Write switch global register
1588  * @param[in] interface Underlying network interface
1589  * @param[in] address Switch global register address
1590  * @param[in] data Register value
1591  **/
1592 
1594  uint16_t data)
1595 {
1596  //Switch global registers are accessible using SMI device address 0x0F (or
1597  //0x1F) depending upon the value of the EE_CLK/ADDR4 pin at reset
1598  mv88e6060WriteSmiReg(interface, 15, address, data);
1599 }
1600 
1601 
1602 /**
1603  * @brief Read switch global register
1604  * @param[in] interface Underlying network interface
1605  * @param[in] address Switch global register address
1606  * @return Register value
1607  **/
1608 
1610 {
1611  //Switch global registers are accessible using SMI device address 0x0F (or
1612  //0x1F) depending upon the value of the EE_CLK/ADDR4 pin at reset
1613  return mv88e6060ReadSmiReg(interface, 15, address);
1614 }
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define LOAD32BE(p)
Definition: cpu_endian.h:210
#define htons(value)
Definition: cpu_endian.h:413
#define ntohs(value)
Definition: cpu_endian.h:421
#define HTONL(value)
Definition: cpu_endian.h:411
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_END_OF_TABLE
Definition: error.h:290
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
const MacAddr MAC_BROADCAST_ADDR
Definition: ethernet.c:55
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
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
uint16_t regAddr
uint16_t mv88e6060ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
uint16_t mv88e6060ReadSwitchPortReg(NetInterface *interface, uint8_t port, uint8_t address)
Read switch port register.
void mv88e6060DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
void mv88e6060EnableMldSnooping(NetInterface *interface, bool_t enable)
Enable MLD snooping.
void mv88e6060SetAgingTime(NetInterface *interface, uint32_t agingTime)
Set aging time for dynamic filtering entries.
void mv88e6060WriteSmiReg(NetInterface *interface, uint8_t deviceAddr, uint8_t regAddr, uint16_t data)
Write SMI register.
error_t mv88e6060GetStaticFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the static MAC table.
void mv88e6060Tick(NetInterface *interface)
88E6060 timer handler
error_t mv88e6060GetDynamicFdbEntry(NetInterface *interface, uint_t index, SwitchFdbEntry *entry)
Read an entry from the dynamic MAC table.
error_t mv88e6060UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, NetRxAncillary *ancillary)
Decode egress trailer from incoming Ethernet frame.
void mv88e6060SetUnknownMcastFwdPorts(NetInterface *interface, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
void mv88e6060SetPortState(NetInterface *interface, uint8_t port, SwitchPortState state)
Set port state.
uint16_t mv88e6060ReadSwitchGlobalReg(NetInterface *interface, uint8_t address)
Read switch global register.
void mv88e6060WriteSwitchGlobalReg(NetInterface *interface, uint8_t address, uint16_t data)
Write switch global register.
bool_t mv88e6060GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
void mv88e6060EventHandler(NetInterface *interface)
88E6060 event handler
error_t mv88e6060AddStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Add a new entry to the static MAC table.
void mv88e6060FlushStaticFdbTable(NetInterface *interface)
Flush static MAC table.
uint32_t mv88e6060GetLinkSpeed(NetInterface *interface, uint8_t port)
Get link speed.
NicDuplexMode mv88e6060GetDuplexMode(NetInterface *interface, uint8_t port)
Get duplex mode.
void mv88e6060WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
void mv88e6060WriteSwitchPortReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write switch port register.
void mv88e6060FlushDynamicFdbTable(NetInterface *interface, uint8_t port)
Flush dynamic MAC table.
const uint32_t mv88e6060IngressTrailer[6]
Ingress trailer (CPU to 88E6060)
const SwitchDriver mv88e6060SwitchDriver
88E6060 Ethernet switch driver
SwitchPortState mv88e6060GetPortState(NetInterface *interface, uint8_t port)
Get port state.
void mv88e6060EnableIgmpSnooping(NetInterface *interface, bool_t enable)
Enable IGMP snooping.
void mv88e6060DisableIrq(NetInterface *interface)
Disable interrupts.
uint16_t mv88e6060ReadSmiReg(NetInterface *interface, uint8_t deviceAddr, uint8_t regAddr)
Read SMI register.
error_t mv88e6060DeleteStaticFdbEntry(NetInterface *interface, const SwitchFdbEntry *entry)
Remove an entry from the static MAC table.
error_t mv88e6060TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, NetTxAncillary *ancillary)
Add ingress trailer to Ethernet frame.
__weak_func void mv88e6060InitHook(NetInterface *interface)
88E6060 custom configuration
void mv88e6060EnableRsvdMcastTable(NetInterface *interface, bool_t enable)
Enable reserved multicast table.
error_t mv88e6060Init(NetInterface *interface)
88E6060 Ethernet switch initialization
void mv88e6060EnableIrq(NetInterface *interface)
Enable interrupts.
88E6060 6-port Ethernet switch driver
#define MV88E6060_PORT_STAT_LINK
#define MV88E6060_ATU_CTRL
#define MV88E6060_PORT_ASSOC_VECTOR_PAV
#define MV88E6060_PORT_VLAN_MAP_DB_NUM
#define MV88E6060_ATU_DATA_ENTRY_STATE_LOCKED_MGMT
#define MV88E6060_ATU_DATA_DPV_PORT4
#define MV88E6060_IG_DPV_PORT4
#define MV88E6060_PORT2
#define MV88E6060_PORT_CTRL_PORT_STATE_DISABLED
#define MV88E6060_SWITCH_ID
#define MV88E6060_PORT0
#define MV88E6060_ATU_DATA_DPV_PORT5
#define MV88E6060_ATU_DATA
#define MV88E6060_PORT_CTRL_PORT_STATE_FORWARDING
#define MV88E6060_PORT4
#define MV88E6060_PORT_VLAN_MAP_VLAN_TABLE
#define MV88E6060_PORT1
#define MV88E6060_IG_MGMT
#define MV88E6060_ATU_TABLE_SIZE
#define MV88E6060_PORT_CTRL_PORT_STATE_LEARNING
#define MV88E6060_IG_DPV_PORT3
#define MV88E6060_ATU_OPERATION_ATU_OP_FLUSH_UNLOCKED
#define MV88E6060_ATU_DATA_ENTRY_STATE_LOCKED_MULTICAST
#define MV88E6060_ATU_DATA_ENTRY_STATE
#define MV88E6060_IG_DPV_PORT0
#define MV88E6060_ATU_DATA_DPV
#define MV88E6060_ATU_OPERATION_ATU_OP_GET_NEXT_DB
#define MV88E6060_PORT_VLAN_MAP
#define MV88E6060_ATU_MAC_ADDR_0_1
#define MV88E6060_ATU_DATA_DPV_PORT3
#define MV88E6060_PORT_STAT_DUPLEX
#define MV88E6060_ATU_CTRL_AGE_TIME_DEFAULT
#define MV88E6060_ATU_CTRL_AGE_TIME
#define MV88E6060_PORT_CTRL_TRAILER
#define MV88E6060_ATU_DATA_DPV_PORT0
#define MV88E6060_PHY_ADDR
#define MV88E6060_IG_OVERRIDE
#define MV88E6060_PORT_STAT_SPEED
#define MV88E6060_ATU_MAC_ADDR_2_3
#define MV88E6060_EG_SPID
#define MV88E6060_ATU_DATA_DPV_PORT2
#define MV88E6060_SWITCH_ID_DEVICE_ID_DEFAULT
#define MV88E6060_ATU_OPERATION
#define MV88E6060_PORT_CTRL_PORT_STATE
#define MV88E6060_PORT3
#define MV88E6060_IG_DPV_PORT1
#define MV88E6060_PORT_VLAN_MAP_VLAN_TABLE_PORT5
#define MV88E6060_IG_DPV_PORT2
#define MV88E6060_PORT_STAT
#define MV88E6060_ATU_OPERATION_ATU_OP_LOAD_PURGE
#define MV88E6060_ATU_DATA_ENTRY_STATE_INVALID
#define MV88E6060_ATU_DATA_ENTRY_STATE_LOCKED_UNICAST
#define MV88E6060_PORT5
#define MV88E6060_ATU_DATA_DPV_PORT1
#define MV88E6060_PORT_CTRL_INGRESS_MODE
#define MV88E6060_PORT_CTRL_PORT_STATE_BLOCKING
#define MV88E6060_PORT_CTRL
#define MV88E6060_PORT_ASSOC_VECTOR
#define MV88E6060_ATU_OPERATION_ATU_BUSY
#define MV88E6060_ATU_MAC_ADDR_4_5
#define MV88E6060_SWITCH_ID_DEVICE_ID
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_FORWARDING
Definition: nic.h:140
@ SWITCH_PORT_STATE_BLOCKING
Definition: nic.h:137
@ 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
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define MAX(a, b)
Definition: os_port.h:67
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
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