]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
1. Fix timer unit bug in MNP: default rx/tx timeout value should be 10,000,000 (10s...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
index 94bbe18847e37fb3e484bc646ba0152147cdd5d8..381f8b87b8bc68ba3cf48bfc27e8288041763a46 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Implementation of Managed Network Protocol private services.\r
 \r
-Copyright (c) 2005 - 2008, Intel Corporation. <BR> \r
+Copyright (c) 2005 - 2009, Intel Corporation. <BR> \r
 All rights reserved. This program and the accompanying materials are licensed \r
 and made available under the terms and conditions of the BSD License which \r
 accompanies this distribution. The full text of the license may be found at \r
@@ -32,8 +32,8 @@ EFI_MANAGED_NETWORK_PROTOCOL    mMnpProtocolTemplate = {
 };\r
 \r
 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {\r
-  10000,\r
-  10000,\r
+  10000000,\r
+  10000000,\r
   0,\r
   FALSE,\r
   FALSE,\r
@@ -44,169 +44,13 @@ EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {
   FALSE\r
 };\r
 \r
-/**\r
-  Configure the Snp receive filters according to the instances' receive filter\r
-  settings.\r
-\r
-  @param  MnpServiceData        Pointer to the mnp service context data.\r
-\r
-  @retval EFI_SUCCESS           The receive filters is configured.\r
-  @retval EFI_OUT_OF_RESOURCES  The receive filters can't be configured due to \r
-                                lack of memory resource.\r
-\r
-**/\r
-EFI_STATUS\r
-MnpConfigReceiveFilters (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData\r
-  )\r
-{\r
-  EFI_STATUS                  Status;\r
-  EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
-  EFI_MAC_ADDRESS             *MCastFilter;\r
-  UINT32                      MCastFilterCnt;\r
-  UINT32                      EnableFilterBits;\r
-  UINT32                      DisableFilterBits;\r
-  BOOLEAN                     ResetMCastFilters;\r
-  LIST_ENTRY                  *Entry;\r
-  UINT32                      Index;\r
-  MNP_GROUP_ADDRESS           *GroupAddress;\r
-\r
-  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
-\r
-  Snp = MnpServiceData->Snp;\r
-\r
-  //\r
-  // Initialize the enable filter and disable filter.\r
-  //\r
-  EnableFilterBits  = 0;\r
-  DisableFilterBits = Snp->Mode->ReceiveFilterMask;\r
-\r
-  if (MnpServiceData->UnicastCount != 0) {\r
-    //\r
-    // Enable unicast if any instance wants to receive unicast.\r
-    //\r
-    EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
-  }\r
-\r
-  if (MnpServiceData->BroadcastCount != 0) {\r
-    //\r
-    // Enable broadcast if any instance wants to receive broadcast.\r
-    //\r
-    EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
-  }\r
-\r
-  MCastFilter       = NULL;\r
-  MCastFilterCnt    = 0;\r
-  ResetMCastFilters = TRUE;\r
-\r
-  if ((MnpServiceData->MulticastCount != 0) && (MnpServiceData->GroupAddressCount != 0)) {\r
-    //\r
-    // There are instances configured to receive multicast and already some group\r
-    // addresses are joined.\r
-    //\r
-\r
-    ResetMCastFilters = FALSE;\r
-\r
-    if (MnpServiceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {\r
-      //\r
-      // The joind group address is less than simple network's maximum count.\r
-      // Just configure the snp to do the multicast filtering.\r
-      //\r
-\r
-      EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
-\r
-      //\r
-      // Allocate pool for the mulicast addresses.\r
-      //\r
-      MCastFilterCnt  = MnpServiceData->GroupAddressCount;\r
-      MCastFilter     = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);\r
-      if (MCastFilter == NULL) {\r
-\r
-        DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));\r
-        return EFI_OUT_OF_RESOURCES;\r
-      }\r
-\r
-      //\r
-      // Fill the multicast HW address buffer.\r
-      //\r
-      Index = 0;\r
-      NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {\r
-\r
-        GroupAddress            = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
-        CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));\r
-        Index++;\r
-\r
-        ASSERT (Index <= MCastFilterCnt);\r
-      }\r
-    } else {\r
-      //\r
-      // The maximum multicast is reached, set the filter to be promiscuous\r
-      // multicast.\r
-      //\r
-\r
-      if (Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {\r
-        EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
-      } else {\r
-        //\r
-        // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,\r
-        // set the NIC to be promiscuous although this will tremendously degrade\r
-        // the performance.\r
-        //\r
-        EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
-      }\r
-    }\r
-  }\r
-\r
-  if (MnpServiceData->PromiscuousCount != 0) {\r
-    //\r
-    // Enable promiscuous if any instance wants to receive promiscuous.\r
-    //\r
-    EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
-  }\r
-\r
-  //\r
-  // Set the disable filter.\r
-  //\r
-  DisableFilterBits ^= EnableFilterBits;\r
-\r
-  //\r
-  // Configure the receive filters of SNP.\r
-  //\r
-  Status = Snp->ReceiveFilters (\r
-                  Snp,\r
-                  EnableFilterBits,\r
-                  DisableFilterBits,\r
-                  ResetMCastFilters,\r
-                  MCastFilterCnt,\r
-                  MCastFilter\r
-                  );\r
-  DEBUG_CODE (\r
-    if (EFI_ERROR (Status)) {\r
-\r
-    DEBUG (\r
-      (EFI_D_ERROR,\r
-      "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",\r
-      Status)\r
-      );\r
-  }\r
-  );\r
-\r
-  if (MCastFilter != NULL) {\r
-    //\r
-    // Free the buffer used to hold the group addresses.\r
-    //\r
-    gBS->FreePool (MCastFilter);\r
-  }\r
-\r
-  return Status;\r
-}\r
 \r
 /**\r
   Add Count of net buffers to MnpServiceData->FreeNbufQue. The length of the net\r
   buffer is specified by MnpServiceData->BufferLength. \r
 \r
-  @param  MnpServiceData        Pointer to the MNP_SERVICE_DATA.\r
-  @param  Count                 Number of NET_BUFFERs to add.\r
+  @param[in, out]  MnpServiceData        Pointer to the MNP_SERVICE_DATA.\r
+  @param[in]       Count                 Number of NET_BUFFERs to add.\r
 \r
   @retval EFI_SUCCESS           The specified amount of NET_BUFs are allocated \r
                                 and added to MnpServiceData->FreeNbufQue.\r
@@ -215,8 +59,8 @@ MnpConfigReceiveFilters (
 **/\r
 EFI_STATUS\r
 MnpAddFreeNbuf (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData,\r
-  IN UINTN             Count\r
+  IN OUT MNP_SERVICE_DATA  *MnpServiceData,\r
+  IN UINTN                 Count\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -260,7 +104,7 @@ MnpAddFreeNbuf (
   in the queue, first try to allocate some and add them into the queue, then\r
   fetch the NET_BUF from the updated FreeNbufQue.\r
 \r
-  @param  MnpServiceData        Pointer to the MNP_SERVICE_DATA.\r
+  @param[in, out]  MnpServiceData        Pointer to the MNP_SERVICE_DATA.\r
 \r
   @return     Pointer to the allocated free NET_BUF structure, if NULL the \r
               operation is failed.\r
@@ -268,7 +112,7 @@ MnpAddFreeNbuf (
 **/\r
 NET_BUF *\r
 MnpAllocNbuf (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData\r
+  IN OUT MNP_SERVICE_DATA  *MnpServiceData\r
   )\r
 {\r
   EFI_STATUS    Status;\r
@@ -333,14 +177,14 @@ ON_EXIT:
 /**\r
   Try to reclaim the Nbuf into the buffer pool.\r
 \r
-  @param  MnpServiceData        Pointer to the mnp service context data.\r
-  @param  Nbuf                  Pointer to the NET_BUF to free.\r
+  @param[in, out]  MnpServiceData        Pointer to the mnp service context data.\r
+  @param[in, out]  Nbuf                  Pointer to the NET_BUF to free.\r
 \r
 **/\r
 VOID\r
 MnpFreeNbuf (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData,\r
-  IN NET_BUF           *Nbuf\r
+  IN OUT MNP_SERVICE_DATA  *MnpServiceData,\r
+  IN OUT NET_BUF           *Nbuf\r
   )\r
 {\r
   EFI_TPL  OldTpl;\r
@@ -367,19 +211,20 @@ MnpFreeNbuf (
 /**\r
   Initialize the mnp service context data.\r
 \r
-  @param  MnpServiceData        Pointer to the mnp service context data.\r
-  @param  ImageHandle           The driver image handle.\r
-  @param  ControllerHandle      Handle of device to bind driver to.\r
+  @param[in, out]  MnpServiceData     Pointer to the mnp service context data.\r
+  @param[in]       ImageHandle        The driver image handle.\r
+  @param[in]       ControllerHandle   Handle of device to bind driver to.\r
 \r
   @retval EFI_SUCCESS           The mnp service context is initialized.\r
-  @retval Other                 Some error occurs.\r
+  @retval EFI_UNSUPPORTED       ControllerHandle does not support Simple Network Protocol.\r
+  @retval Others                Other errors as indicated.\r
 \r
 **/\r
 EFI_STATUS\r
 MnpInitializeServiceData (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData,\r
-  IN EFI_HANDLE        ImageHandle,\r
-  IN EFI_HANDLE        ControllerHandle\r
+  IN OUT MNP_SERVICE_DATA  *MnpServiceData,\r
+  IN EFI_HANDLE            ImageHandle,\r
+  IN EFI_HANDLE            ControllerHandle\r
   )\r
 {\r
   EFI_STATUS                   Status;\r
@@ -553,14 +398,14 @@ ERROR:
 /**\r
   Flush the mnp service context data.\r
 \r
-  @param  MnpServiceData        Pointer to the mnp service context data.\r
-  @param  ImageHandle           The driver image handle.\r
+  @param[in, out]  MnpServiceData    Pointer to the mnp service context data.\r
+  @param[in]       ImageHandle       The driver image handle.\r
 \r
 **/\r
 VOID\r
 MnpFlushServiceData (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData,\r
-  IN EFI_HANDLE        ImageHandle\r
+  IN OUT MNP_SERVICE_DATA  *MnpServiceData,\r
+  IN EFI_HANDLE            ImageHandle\r
   )\r
 {\r
   NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
@@ -616,15 +461,15 @@ MnpFlushServiceData (
 /**\r
   Initialize the mnp instance context data.\r
 \r
-  @param  MnpServiceData        Pointer to the mnp service context data.\r
-  @param  Instance              Pointer to the mnp instance context data to\r
-                                initialize.\r
+  @param[in]       MnpServiceData   Pointer to the mnp service context data.\r
+  @param[in, out]  Instance         Pointer to the mnp instance context data \r
+                                    to initialize.\r
 \r
 **/\r
 VOID\r
 MnpInitializeInstanceData (\r
-  IN MNP_SERVICE_DATA   *MnpServiceData,\r
-  IN MNP_INSTANCE_DATA  *Instance\r
+  IN MNP_SERVICE_DATA       *MnpServiceData,\r
+  IN OUT MNP_INSTANCE_DATA  *Instance\r
   )\r
 {\r
   NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
@@ -665,11 +510,11 @@ MnpInitializeInstanceData (
 \r
 \r
 /**\r
-  Check whether the token specified by Arg maches the token in Item.\r
+  Check whether the token specified by Arg matches the token in Item.\r
 \r
-  @param  Map                   Pointer to the NET_MAP.\r
-  @param  Item                  Pointer to the NET_MAP_ITEM\r
-  @param  Arg                   Pointer to the Arg, it's a pointer to the token to\r
+  @param[in]  Map               Pointer to the NET_MAP.\r
+  @param[in]  Item              Pointer to the NET_MAP_ITEM.\r
+  @param[in]  Arg               Pointer to the Arg, it's a pointer to the token to\r
                                 check.\r
 \r
   @retval EFI_SUCCESS           The token specified by Arg is different from the\r
@@ -705,10 +550,10 @@ MnpTokenExist (
 /**\r
   Cancel the token specified by Arg if it matches the token in Item.\r
 \r
-  @param  Map               Pointer to the NET_MAP.\r
-  @param  Item              Pointer to the NET_MAP_ITEM\r
-  @param  Arg               Pointer to the Arg, it's a pointer to the token to \r
-                            cancel.\r
+  @param[in, out]  Map               Pointer to the NET_MAP.\r
+  @param[in, out]  Item              Pointer to the NET_MAP_ITEM.\r
+  @param[in]       Arg               Pointer to the Arg, it's a pointer to the \r
+                                     token to cancel.\r
 \r
   @retval EFI_SUCCESS       The Arg is NULL, and the token in Item is cancelled, \r
                             or the Arg isn't NULL, and the token in Item is\r
@@ -719,9 +564,9 @@ MnpTokenExist (
 **/\r
 EFI_STATUS\r
 MnpCancelTokens (\r
-  IN OUT NET_MAP   *Map,\r
-  IN NET_MAP_ITEM  *Item,\r
-  IN VOID          *Arg\r
+  IN OUT NET_MAP       *Map,\r
+  IN OUT NET_MAP_ITEM  *Item,\r
+  IN VOID              *Arg\r
   )\r
 {\r
   EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *TokenToCancel;\r
@@ -760,10 +605,10 @@ MnpCancelTokens (
 /**\r
   Start and initialize the simple network.\r
 \r
-  @param  Snp                   Pointer to the simple network protocol.\r
+  @param[in]  Snp               Pointer to the simple network protocol.\r
 \r
   @retval EFI_SUCCESS           The simple network protocol is started.\r
-  @retval Other                 Some error occurs.\r
+  @retval Others                Other errors as indicated.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -794,10 +639,10 @@ MnpStartSnp (
 /**\r
   Stop the simple network.\r
 \r
-  @param  Snp                   Pointer to the simple network protocol.\r
+  @param[in]  Snp               Pointer to the simple network protocol.\r
 \r
   @retval EFI_SUCCESS           The simple network is stopped.\r
-  @retval Other                 Some error occurs.\r
+  @retval Others                Other errors as indicated.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -829,21 +674,21 @@ MnpStopSnp (
   Start the managed network, this function is called when one instance is configured\r
   or reconfigured.\r
 \r
-  @param  MnpServiceData        Pointer to the mnp service context data.\r
-  @param  IsConfigUpdate        The instance is reconfigured or it's the first time\r
-                                the instanced is configured.\r
-  @param  EnableSystemPoll      Enable the system polling or not.\r
+  @param[in, out]  MnpServiceData       Pointer to the mnp service context data.\r
+  @param[in]       IsConfigUpdate       The instance is reconfigured or it's the first\r
+                                        time the instanced is configured.\r
+  @param[in]       EnableSystemPoll     Enable the system polling or not.\r
 \r
-  @retval EFI_SUCCESS           The managed network is started and some\r
-                                configuration is updated.\r
-  @retval Other                 Some error occurs.\r
+  @retval EFI_SUCCESS                   The managed network is started and some\r
+                                        configuration is updated.\r
+  @retval Others                        Other errors as indicated.\r
 \r
 **/\r
 EFI_STATUS\r
 MnpStart (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData,\r
-  IN BOOLEAN           IsConfigUpdate,\r
-  IN BOOLEAN           EnableSystemPoll\r
+  IN OUT MNP_SERVICE_DATA  *MnpServiceData,\r
+  IN BOOLEAN               IsConfigUpdate,\r
+  IN BOOLEAN               EnableSystemPoll\r
   )\r
 {\r
   EFI_STATUS      Status;\r
@@ -921,15 +766,15 @@ ErrorExit:
 /**\r
   Stop the managed network.\r
 \r
-  @param  MnpServiceData        Pointer to the mnp service context data.\r
+  @param[in, out]  MnpServiceData    Pointer to the mnp service context data.\r
 \r
-  @retval EFI_SUCCESS           The managed network is stopped.\r
-  @retval Other                 Some error occurs.\r
+  @retval EFI_SUCCESS                The managed network is stopped.\r
+  @retval Others                     Other errors as indicated.\r
 \r
 **/\r
 EFI_STATUS\r
 MnpStop (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData\r
+  IN OUT MNP_SERVICE_DATA  *MnpServiceData\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -984,12 +829,12 @@ MnpStop (
 /**\r
   Flush the instance's received data.\r
 \r
-  @param  Instance              Pointer to the mnp instance context data.\r
+  @param[in, out]  Instance              Pointer to the mnp instance context data.\r
 \r
 **/\r
 VOID\r
 MnpFlushRcvdDataQueue (\r
-  IN MNP_INSTANCE_DATA  *Instance\r
+  IN OUT MNP_INSTANCE_DATA  *Instance\r
   )\r
 {\r
   EFI_TPL          OldTpl;\r
@@ -1021,20 +866,20 @@ MnpFlushRcvdDataQueue (
 /**\r
   Configure the Instance using ConfigData.\r
 \r
-  @param  Instance              Pointer to the mnp instance context data.\r
-  @param  ConfigData            Pointer to the configuration data used to configure\r
+  @param[in, out]  Instance     Pointer to the mnp instance context data.\r
+  @param[in]       ConfigData   Pointer to the configuration data used to configure\r
                                 the isntance.\r
 \r
   @retval EFI_SUCCESS           The Instance is configured.\r
   @retval EFI_UNSUPPORTED       EnableReceiveTimestamps is on and the\r
                                 implementation doesn't support it.\r
-  @retval Other                 Some error occurs.\r
+  @retval Others                Other errors as indicated.\r
 \r
 **/\r
 EFI_STATUS\r
 MnpConfigureInstance (\r
-  IN MNP_INSTANCE_DATA                *Instance,\r
-  IN EFI_MANAGED_NETWORK_CONFIG_DATA  *ConfigData OPTIONAL\r
+  IN OUT MNP_INSTANCE_DATA              *Instance,\r
+  IN EFI_MANAGED_NETWORK_CONFIG_DATA    *ConfigData OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                      Status;\r
@@ -1156,29 +1001,185 @@ MnpConfigureInstance (
   return Status;\r
 }\r
 \r
+/**\r
+  Configure the Snp receive filters according to the instances' receive filter\r
+  settings.\r
+\r
+  @param[in]  MnpServiceData        Pointer to the mnp service context data.\r
+\r
+  @retval     EFI_SUCCESS           The receive filters is configured.\r
+  @retval     EFI_OUT_OF_RESOURCES  The receive filters can't be configured due \r
+                                    to lack of memory resource.\r
+\r
+**/\r
+EFI_STATUS\r
+MnpConfigReceiveFilters (\r
+  IN MNP_SERVICE_DATA  *MnpServiceData\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
+  EFI_MAC_ADDRESS             *MCastFilter;\r
+  UINT32                      MCastFilterCnt;\r
+  UINT32                      EnableFilterBits;\r
+  UINT32                      DisableFilterBits;\r
+  BOOLEAN                     ResetMCastFilters;\r
+  LIST_ENTRY                  *Entry;\r
+  UINT32                      Index;\r
+  MNP_GROUP_ADDRESS           *GroupAddress;\r
+\r
+  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
+\r
+  Snp = MnpServiceData->Snp;\r
+\r
+  //\r
+  // Initialize the enable filter and disable filter.\r
+  //\r
+  EnableFilterBits  = 0;\r
+  DisableFilterBits = Snp->Mode->ReceiveFilterMask;\r
+\r
+  if (MnpServiceData->UnicastCount != 0) {\r
+    //\r
+    // Enable unicast if any instance wants to receive unicast.\r
+    //\r
+    EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
+  }\r
+\r
+  if (MnpServiceData->BroadcastCount != 0) {\r
+    //\r
+    // Enable broadcast if any instance wants to receive broadcast.\r
+    //\r
+    EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
+  }\r
+\r
+  MCastFilter       = NULL;\r
+  MCastFilterCnt    = 0;\r
+  ResetMCastFilters = TRUE;\r
+\r
+  if ((MnpServiceData->MulticastCount != 0) && (MnpServiceData->GroupAddressCount != 0)) {\r
+    //\r
+    // There are instances configured to receive multicast and already some group\r
+    // addresses are joined.\r
+    //\r
+\r
+    ResetMCastFilters = FALSE;\r
+\r
+    if (MnpServiceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {\r
+      //\r
+      // The joind group address is less than simple network's maximum count.\r
+      // Just configure the snp to do the multicast filtering.\r
+      //\r
+\r
+      EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
+\r
+      //\r
+      // Allocate pool for the mulicast addresses.\r
+      //\r
+      MCastFilterCnt  = MnpServiceData->GroupAddressCount;\r
+      MCastFilter     = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);\r
+      if (MCastFilter == NULL) {\r
+\r
+        DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      //\r
+      // Fill the multicast HW address buffer.\r
+      //\r
+      Index = 0;\r
+      NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {\r
+\r
+        GroupAddress            = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
+        CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));\r
+        Index++;\r
+\r
+        ASSERT (Index <= MCastFilterCnt);\r
+      }\r
+    } else {\r
+      //\r
+      // The maximum multicast is reached, set the filter to be promiscuous\r
+      // multicast.\r
+      //\r
+\r
+      if ((Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {\r
+        EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
+      } else {\r
+        //\r
+        // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,\r
+        // set the NIC to be promiscuous although this will tremendously degrade\r
+        // the performance.\r
+        //\r
+        EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (MnpServiceData->PromiscuousCount != 0) {\r
+    //\r
+    // Enable promiscuous if any instance wants to receive promiscuous.\r
+    //\r
+    EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
+  }\r
+\r
+  //\r
+  // Set the disable filter.\r
+  //\r
+  DisableFilterBits ^= EnableFilterBits;\r
+\r
+  //\r
+  // Configure the receive filters of SNP.\r
+  //\r
+  Status = Snp->ReceiveFilters (\r
+                  Snp,\r
+                  EnableFilterBits,\r
+                  DisableFilterBits,\r
+                  ResetMCastFilters,\r
+                  MCastFilterCnt,\r
+                  MCastFilter\r
+                  );\r
+  DEBUG_CODE (\r
+    if (EFI_ERROR (Status)) {\r
+\r
+    DEBUG (\r
+      (EFI_D_ERROR,\r
+      "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",\r
+      Status)\r
+      );\r
+  }\r
+  );\r
+\r
+  if (MCastFilter != NULL) {\r
+    //\r
+    // Free the buffer used to hold the group addresses.\r
+    //\r
+    gBS->FreePool (MCastFilter);\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
 \r
 /**\r
   Add a group address control block which controls the MacAddress for\r
   this instance.\r
 \r
-  @param  Instance              Pointer to the mnp instance context data.\r
-  @param  CtrlBlk               Pointer to the group address control block.\r
-  @param  GroupAddress          Pointer to the group adress.\r
-  @param  MacAddress            Pointer to the mac address.\r
-  @param  HwAddressSize         The hardware address size.\r
+  @param[in, out]  Instance        Pointer to the mnp instance context data.\r
+  @param[in, out]  CtrlBlk         Pointer to the group address control block.\r
+  @param[in, out]  GroupAddress    Pointer to the group adress.\r
+  @param[in]       MacAddress      Pointer to the mac address.\r
+  @param[in]       HwAddressSize   The hardware address size.\r
 \r
-  @retval EFI_SUCCESS           The group address control block is added.\r
-  @retval EFI_OUT_OF_RESOURCE   Failed due to lack of memory resources.\r
+  @retval EFI_SUCCESS              The group address control block is added.\r
+  @retval EFI_OUT_OF_RESOURCES     Failed due to lack of memory resources.\r
 \r
 **/\r
 EFI_STATUS\r
 MnpGroupOpAddCtrlBlk (\r
-  IN MNP_INSTANCE_DATA        *Instance,\r
-  IN MNP_GROUP_CONTROL_BLOCK  *CtrlBlk,\r
-  IN MNP_GROUP_ADDRESS        *GroupAddress OPTIONAL,\r
-  IN EFI_MAC_ADDRESS          *MacAddress,\r
-  IN UINT32                   HwAddressSize\r
+  IN OUT MNP_INSTANCE_DATA        *Instance,\r
+  IN OUT MNP_GROUP_CONTROL_BLOCK  *CtrlBlk,\r
+  IN OUT MNP_GROUP_ADDRESS        *GroupAddress OPTIONAL,\r
+  IN EFI_MAC_ADDRESS              *MacAddress,\r
+  IN UINT32                       HwAddressSize\r
   )\r
 {\r
   MNP_SERVICE_DATA  *MnpServiceData;\r
@@ -1231,8 +1232,8 @@ MnpGroupOpAddCtrlBlk (
   Delete a group control block from the instance. If the controlled group address's\r
   reference count reaches zero, the group address is removed too.\r
 \r
-  @param  Instance              Pointer to the instance context data.\r
-  @param  CtrlBlk               Pointer to the group control block to delete.\r
+  @param[in]  Instance              Pointer to the instance context data.\r
+  @param[in]  CtrlBlk               Pointer to the group control block to delete.\r
 \r
   @return The group address controlled by the control block is no longer used or not.\r
 \r
@@ -1283,20 +1284,21 @@ MnpGroupOpDelCtrlBlk (
 /**\r
   Do the group operations for this instance.\r
 \r
-  @param  Instance              Pointer to the instance context data.\r
-  @param  JoinFlag              Set to TRUE to join a group. Set to TRUE to leave a\r
-                                group/groups.\r
-  @param  MacAddress            Pointer to the group address to join or leave.\r
-  @param  CtrlBlk               Pointer to the group control block if JoinFlag if\r
-                                FALSE.\r
+  @param[in, out]  Instance        Pointer to the instance context data.\r
+  @param[in]       JoinFlag        Set to TRUE to join a group. Set to TRUE to \r
+                                   leave a group/groups.\r
+  @param[in]       MacAddress      Pointer to the group address to join or leave.\r
+  @param[in]       CtrlBlk         Pointer to the group control block if JoinFlag \r
+                                   is FALSE.\r
 \r
-  @retval EFI_SUCCESS           The group operation finished.\r
-  @retval Other                 Some error occurs.\r
+  @retval EFI_SUCCESS              The group operation finished.\r
+  @retval EFI_OUT_OF_RESOURCES     Failed due to lack of memory resources.\r
+  @retval Others                   Other errors as indicated.\r
 \r
 **/\r
 EFI_STATUS\r
 MnpGroupOp (\r
-  IN MNP_INSTANCE_DATA        *Instance,\r
+  IN OUT MNP_INSTANCE_DATA    *Instance,\r
   IN BOOLEAN                  JoinFlag,\r
   IN EFI_MAC_ADDRESS          *MacAddress OPTIONAL,\r
   IN MNP_GROUP_CONTROL_BLOCK  *CtrlBlk OPTIONAL\r