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