]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
Fix GCC build fail issue for MdeModulePkg and NetworkPkg.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
index 9ed0f3ffd7bb4cd1306213041dd54583981ed969..046d4dfddccbc24b0f330389d7c16dec5075cb85 100644 (file)
@@ -1,10 +1,11 @@
 /** @file\r
   Implementation of Managed Network Protocol private services.\r
-  \r
-Copyright (c) 2005 - 2008, Intel Corporation.<BR>\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
+\r
+Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution.  The full\r
+text of the license may be found at<BR>\r
 http://opensource.org/licenses/bsd-license.php\r
 \r
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
@@ -12,8 +13,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 **/\r
 \r
-\r
 #include "MnpImpl.h"\r
+#include "MnpVlan.h"\r
 \r
 EFI_SERVICE_BINDING_PROTOCOL    mMnpServiceBindingProtocol = {\r
   MnpServiceBindingCreateChild,\r
@@ -32,8 +33,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
@@ -45,230 +46,70 @@ EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {
 };\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
+  Add Count of net buffers to MnpDeviceData->FreeNbufQue. The length of the net\r
+  buffer is specified by MnpDeviceData->BufferLength.\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
+  @param[in, out]  MnpDeviceData         Pointer to the MNP_DEVICE_DATA.\r
+  @param[in]       Count                 Number of NET_BUFFERs to add.\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[in]  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
+  @retval EFI_SUCCESS           The specified amount of NET_BUFs are allocated\r
+                                and added to MnpDeviceData->FreeNbufQue.\r
   @retval EFI_OUT_OF_RESOURCES  Failed to allocate a NET_BUF structure.\r
 \r
 **/\r
 EFI_STATUS\r
 MnpAddFreeNbuf (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData,\r
-  IN UINTN             Count\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData,\r
+  IN     UINTN             Count\r
   )\r
 {\r
   EFI_STATUS  Status;\r
   UINTN       Index;\r
   NET_BUF     *Nbuf;\r
 \r
-  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
-  ASSERT ((Count > 0) && (MnpServiceData->BufferLength > 0));\r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
+  ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));\r
 \r
   Status = EFI_SUCCESS;\r
-\r
   for (Index = 0; Index < Count; Index++) {\r
-\r
-    Nbuf = NetbufAlloc (MnpServiceData->BufferLength + MnpServiceData->PaddingSize);\r
+    Nbuf = NetbufAlloc (MnpDeviceData->BufferLength + MnpDeviceData->PaddingSize);\r
     if (Nbuf == NULL) {\r
-\r
       DEBUG ((EFI_D_ERROR, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));\r
+\r
       Status = EFI_OUT_OF_RESOURCES;\r
       break;\r
     }\r
 \r
-    if (MnpServiceData->PaddingSize > 0) {\r
+    if (MnpDeviceData->PaddingSize > 0) {\r
       //\r
       // Pad padding bytes before the media header\r
       //\r
-      NetbufAllocSpace (Nbuf, MnpServiceData->PaddingSize, NET_BUF_TAIL);\r
-      NetbufTrim (Nbuf, MnpServiceData->PaddingSize, NET_BUF_HEAD);\r
+      NetbufAllocSpace (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_TAIL);\r
+      NetbufTrim (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_HEAD);\r
     }\r
 \r
-    NetbufQueAppend (&MnpServiceData->FreeNbufQue, Nbuf);\r
+    NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);\r
   }\r
 \r
-  MnpServiceData->NbufCnt += Index;\r
-\r
+  MnpDeviceData->NbufCnt += Index;\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Allocate a free NET_BUF from MnpServiceData->FreeNbufQue. If there is none\r
+  Allocate a free NET_BUF from MnpDeviceData->FreeNbufQue. If there is none\r
   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[in]  MnpServiceData        Pointer to the MNP_SERVICE_DATA.\r
+  @param[in, out]  MnpDeviceData        Pointer to the MNP_DEVICE_DATA.\r
 \r
-  @return     Pointer to the allocated free NET_BUF structure, if NULL the \r
+  @return     Pointer to the allocated free NET_BUF structure, if NULL the\r
               operation is failed.\r
 \r
 **/\r
 NET_BUF *\r
 MnpAllocNbuf (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData\r
   )\r
 {\r
   EFI_STATUS    Status;\r
@@ -276,37 +117,34 @@ MnpAllocNbuf (
   NET_BUF       *Nbuf;\r
   EFI_TPL       OldTpl;\r
 \r
-  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
-\r
-  FreeNbufQue = &MnpServiceData->FreeNbufQue;\r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
 \r
-  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  FreeNbufQue = &MnpDeviceData->FreeNbufQue;\r
+  OldTpl      = gBS->RaiseTPL (TPL_NOTIFY);\r
 \r
   //\r
   // Check whether there are available buffers, or else try to add some.\r
   //\r
   if (FreeNbufQue->BufNum == 0) {\r
-\r
-    if ((MnpServiceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {\r
-\r
+    if ((MnpDeviceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {\r
       DEBUG (\r
         (EFI_D_ERROR,\r
         "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",\r
-        MnpServiceData)\r
+        MnpDeviceData)\r
         );\r
 \r
       Nbuf = NULL;\r
       goto ON_EXIT;\r
     }\r
 \r
-    Status = MnpAddFreeNbuf (MnpServiceData, MNP_NET_BUFFER_INCREASEMENT);\r
+    Status = MnpAddFreeNbuf (MnpDeviceData, MNP_NET_BUFFER_INCREASEMENT);\r
     if (EFI_ERROR (Status)) {\r
-\r
       DEBUG (\r
         (EFI_D_ERROR,\r
         "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",\r
         Status)\r
         );\r
+\r
       //\r
       // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but\r
       // the amount is less than MNP_NET_BUFFER_INCREASEMENT.\r
@@ -333,19 +171,19 @@ 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
-  \r
+  @param[in, out]  MnpDeviceData         Pointer to the mnp device 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_DEVICE_DATA   *MnpDeviceData,\r
+  IN OUT NET_BUF           *Nbuf\r
   )\r
 {\r
   EFI_TPL  OldTpl;\r
 \r
-  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
   ASSERT (Nbuf->RefCnt > 1);\r
 \r
   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
@@ -357,7 +195,15 @@ MnpFreeNbuf (
     // Trim all buffer contained in the Nbuf, then append it to the NbufQue.\r
     //\r
     NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_TAIL);\r
-    NetbufQueAppend (&MnpServiceData->FreeNbufQue, Nbuf);\r
+\r
+    if (NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD) != NULL) {\r
+      //\r
+      // There is space reserved for vlan tag in the head, reclaim it\r
+      //\r
+      NetbufTrim (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_TAIL);\r
+    }\r
+\r
+    NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);\r
   }\r
 \r
   gBS->RestoreTPL (OldTpl);\r
@@ -365,35 +211,36 @@ MnpFreeNbuf (
 \r
 \r
 /**\r
-  Initialize the mnp service context data.\r
+  Initialize the mnp device context data.\r
 \r
-  @param[in]  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
+  @param[in, out]  MnpDeviceData      Pointer to the mnp device 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
+MnpInitializeDeviceData (\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData,\r
+  IN     EFI_HANDLE        ImageHandle,\r
+  IN     EFI_HANDLE        ControllerHandle\r
   )\r
 {\r
-  EFI_STATUS                   Status;\r
-  EFI_SIMPLE_NETWORK_PROTOCOL  *Snp;\r
-  EFI_SIMPLE_NETWORK_MODE      *SnpMode;\r
-\r
-  MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;\r
+  EFI_STATUS                  Status;\r
+  EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
+  EFI_SIMPLE_NETWORK_MODE     *SnpMode;\r
 \r
-  MnpServiceData->ControllerHandle = ControllerHandle;\r
+  MnpDeviceData->Signature        = MNP_DEVICE_DATA_SIGNATURE;\r
+  MnpDeviceData->ImageHandle      = ImageHandle;\r
+  MnpDeviceData->ControllerHandle = ControllerHandle;\r
 \r
   //\r
-  // Copy the ServiceBinding structure.\r
+  // Copy the MNP Protocol interfaces from the template.\r
   //\r
-  MnpServiceData->ServiceBinding = mMnpServiceBindingProtocol;\r
+  CopyMem (&MnpDeviceData->VlanConfig, &mVlanConfigProtocolTemplate, sizeof (EFI_VLAN_CONFIG_PROTOCOL));\r
 \r
   //\r
   // Open the Simple Network protocol.\r
@@ -413,57 +260,65 @@ MnpInitializeServiceData (
   //\r
   // Get MTU from Snp.\r
   //\r
-  SnpMode             = Snp->Mode;\r
-  MnpServiceData->Snp = Snp;\r
-  MnpServiceData->Mtu = SnpMode->MaxPacketSize;\r
+  SnpMode            = Snp->Mode;\r
+  MnpDeviceData->Snp = Snp;\r
 \r
   //\r
   // Initialize the lists.\r
   //\r
-  InitializeListHead (&MnpServiceData->GroupAddressList);\r
-  InitializeListHead (&MnpServiceData->ChildrenList);\r
+  InitializeListHead (&MnpDeviceData->ServiceList);\r
+  InitializeListHead (&MnpDeviceData->GroupAddressList);\r
 \r
   //\r
   // Get the buffer length used to allocate NET_BUF to hold data received\r
   // from SNP. Do this before fill the FreeNetBufQue.\r
   //\r
-  MnpServiceData->BufferLength = MnpServiceData->Mtu + SnpMode->MediaHeaderSize + NET_ETHER_FCS_SIZE;\r
+  //\r
+  MnpDeviceData->BufferLength = SnpMode->MediaHeaderSize + NET_VLAN_TAG_LEN + SnpMode->MaxPacketSize + NET_ETHER_FCS_SIZE;\r
 \r
   //\r
   // Make sure the protocol headers immediately following the media header\r
-  // 4-byte aligned\r
+  // 4-byte aligned, and also preserve additional space for VLAN tag\r
+  //\r
+  MnpDeviceData->PaddingSize = ((4 - SnpMode->MediaHeaderSize) & 0x3) + NET_VLAN_TAG_LEN;\r
+\r
+  //\r
+  // Initialize MAC string which will be used as VLAN configuration variable name\r
   //\r
-  MnpServiceData->PaddingSize = (4 - SnpMode->MediaHeaderSize) & 0x3;\r
+  Status = NetLibGetMacString (ControllerHandle, ImageHandle, &MnpDeviceData->MacString);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR;\r
+  }\r
 \r
   //\r
   // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.\r
   //\r
-  NetbufQueInit (&MnpServiceData->FreeNbufQue);\r
-  Status = MnpAddFreeNbuf (MnpServiceData, MNP_INIT_NET_BUFFER_NUM);\r
+  NetbufQueInit (&MnpDeviceData->FreeNbufQue);\r
+  Status = MnpAddFreeNbuf (MnpDeviceData, MNP_INIT_NET_BUFFER_NUM);\r
   if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: MnpAddFreeNbuf failed, %r.\n", Status));\r
 \r
-    DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status));\r
     goto ERROR;\r
   }\r
+\r
   //\r
   // Get one NET_BUF from the FreeNbufQue for rx cache.\r
   //\r
-  MnpServiceData->RxNbufCache = MnpAllocNbuf (MnpServiceData);\r
+  MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);\r
   NetbufAllocSpace (\r
-    MnpServiceData->RxNbufCache,\r
-    MnpServiceData->BufferLength,\r
+    MnpDeviceData->RxNbufCache,\r
+    MnpDeviceData->BufferLength,\r
     NET_BUF_TAIL\r
     );\r
 \r
   //\r
   // Allocate buffer pool for tx.\r
   //\r
-  MnpServiceData->TxBuf = AllocatePool (MnpServiceData->Mtu + SnpMode->MediaHeaderSize);\r
-  if (MnpServiceData->TxBuf == NULL) {\r
+  MnpDeviceData->TxBuf = AllocatePool (MnpDeviceData->BufferLength);\r
+  if (MnpDeviceData->TxBuf == NULL) {\r
+    DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: AllocatePool failed.\n"));\r
 \r
-    DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: AllocatePool failed.\n"));\r
     Status = EFI_OUT_OF_RESOURCES;\r
-\r
     goto ERROR;\r
   }\r
 \r
@@ -474,12 +329,12 @@ MnpInitializeServiceData (
                   EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
                   TPL_CALLBACK,\r
                   MnpSystemPoll,\r
-                  MnpServiceData,\r
-                  &MnpServiceData->PollTimer\r
+                  MnpDeviceData,\r
+                  &MnpDeviceData->PollTimer\r
                   );\r
   if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for poll timer failed.\n"));\r
 \r
-    DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));\r
     goto ERROR;\r
   }\r
 \r
@@ -490,12 +345,28 @@ MnpInitializeServiceData (
                   EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
                   TPL_CALLBACK,\r
                   MnpCheckPacketTimeout,\r
-                  MnpServiceData,\r
-                  &MnpServiceData->TimeoutCheckTimer\r
+                  MnpDeviceData,\r
+                  &MnpDeviceData->TimeoutCheckTimer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for packet timeout check failed.\n"));\r
+\r
+    goto ERROR;\r
+  }\r
+\r
+  //\r
+  // Create the timer for media detection.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
+                  TPL_CALLBACK,\r
+                  MnpCheckMediaStatus,\r
+                  MnpDeviceData,\r
+                  &MnpDeviceData->MediaDetectTimer\r
                   );\r
   if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for media detection failed.\n"));\r
 \r
-    DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for packet timeout check failed.\n"));\r
     goto ERROR;\r
   }\r
 \r
@@ -507,124 +378,414 @@ MnpInitializeServiceData (
                   TPL_CALLBACK,\r
                   NULL,\r
                   NULL,\r
-                  &MnpServiceData->TxTimeoutEvent\r
+                  &MnpDeviceData->TxTimeoutEvent\r
                   );\r
   if (EFI_ERROR (Status)) {\r
-\r
-    DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for tx timeout event failed.\n"));\r
+    DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for tx timeout event failed.\n"));\r
   }\r
 \r
 ERROR:\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Free the dynamic allocated resources if necessary.\r
+    //\r
+    if (MnpDeviceData->MacString != NULL) {\r
+      FreePool (MnpDeviceData->MacString);\r
+    }\r
+\r
+    if (MnpDeviceData->TimeoutCheckTimer != NULL) {\r
+      gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
+    }\r
+\r
+    if (MnpDeviceData->MediaDetectTimer != NULL) {\r
+      gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
+    }\r
+\r
+    if (MnpDeviceData->PollTimer != NULL) {\r
+      gBS->CloseEvent (MnpDeviceData->PollTimer);\r
+    }\r
+\r
+    if (MnpDeviceData->TxBuf != NULL) {\r
+      FreePool (MnpDeviceData->TxBuf);\r
+    }\r
+\r
+    if (MnpDeviceData->RxNbufCache != NULL) {\r
+      MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
+    }\r
+\r
+    if (MnpDeviceData->FreeNbufQue.BufNum != 0) {\r
+      NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
+    }\r
+\r
+    //\r
+    // Close the Simple Network Protocol.\r
+    //\r
+    gBS->CloseProtocol (\r
+          ControllerHandle,\r
+          &gEfiSimpleNetworkProtocolGuid,\r
+          ImageHandle,\r
+          ControllerHandle\r
+          );\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Destroy the MNP device context data.\r
+\r
+  @param[in, out]  MnpDeviceData      Pointer to the mnp device context data.\r
+  @param[in]       ImageHandle        The driver image handle.\r
+\r
+**/\r
+VOID\r
+MnpDestroyDeviceData (\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData,\r
+  IN     EFI_HANDLE        ImageHandle\r
+  )\r
+{\r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
+\r
+  //\r
+  // Free Vlan Config variable name string\r
+  //\r
+  if (MnpDeviceData->MacString != NULL) {\r
+    FreePool (MnpDeviceData->MacString);\r
+  }\r
+\r
+  //\r
+  // The GroupAddressList must be empty.\r
+  //\r
+  ASSERT (IsListEmpty (&MnpDeviceData->GroupAddressList));\r
+\r
+  //\r
+  // Close the event.\r
+  //\r
+  gBS->CloseEvent (MnpDeviceData->TxTimeoutEvent);\r
+  gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
+  gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
+  gBS->CloseEvent (MnpDeviceData->PollTimer);\r
+\r
+  //\r
+  // Free the tx buffer.\r
+  //\r
+  FreePool (MnpDeviceData->TxBuf);\r
+\r
+  //\r
+  // Free the RxNbufCache.\r
+  //\r
+  MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
+\r
+  //\r
+  // Flush the FreeNbufQue.\r
+  //\r
+  MnpDeviceData->NbufCnt -= MnpDeviceData->FreeNbufQue.BufNum;\r
+  NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
+\r
+  //\r
+  // Close the Simple Network Protocol.\r
+  //\r
+  gBS->CloseProtocol (\r
+         MnpDeviceData->ControllerHandle,\r
+         &gEfiSimpleNetworkProtocolGuid,\r
+         ImageHandle,\r
+         MnpDeviceData->ControllerHandle\r
+         );\r
+}\r
+\r
+\r
+/**\r
+  Create mnp service context data.\r
+\r
+  @param[in]       MnpDeviceData      Pointer to the mnp device context data.\r
+  @param[in]       VlanId             The VLAN ID.\r
+  @param[in]       Priority           The VLAN priority. If VlanId is 0,\r
+                                      Priority is ignored.\r
+\r
+  @return A pointer to MNP_SERVICE_DATA or NULL if failed to create MNP service context.\r
+\r
+**/\r
+MNP_SERVICE_DATA *\r
+MnpCreateServiceData (\r
+  IN MNP_DEVICE_DATA     *MnpDeviceData,\r
+  IN UINT16              VlanId,\r
+  IN UINT8                Priority OPTIONAL\r
+  )\r
+{\r
+  EFI_HANDLE                MnpServiceHandle;\r
+  MNP_SERVICE_DATA          *MnpServiceData;\r
+  EFI_STATUS                Status;\r
+  EFI_SIMPLE_NETWORK_MODE   *SnpMode;\r
+  EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;\r
+\r
+  //\r
+  // Initialize the Mnp Service Data.\r
+  //\r
+  MnpServiceData = AllocateZeroPool (sizeof (MNP_SERVICE_DATA));\r
+  if (MnpServiceData == NULL) {\r
+    DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to allocate memory for the new Mnp Service Data.\n"));\r
+\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Add to MNP service list\r
+  //\r
+  InsertTailList (&MnpDeviceData->ServiceList, &MnpServiceData->Link);\r
+\r
+  MnpServiceData->Signature     = MNP_SERVICE_DATA_SIGNATURE;\r
+  MnpServiceData->MnpDeviceData = MnpDeviceData;\r
+\r
+  //\r
+  // Copy the ServiceBinding structure.\r
+  //\r
+  CopyMem (&MnpServiceData->ServiceBinding, &mMnpServiceBindingProtocol, sizeof (EFI_SERVICE_BINDING_PROTOCOL));\r
+\r
+  //\r
+  // Initialize the lists.\r
+  //\r
+  InitializeListHead (&MnpServiceData->ChildrenList);\r
+\r
+  SnpMode = MnpDeviceData->Snp->Mode;\r
+  if (VlanId != 0) {\r
+    //\r
+    // Create VLAN child handle\r
+    //\r
+    MnpServiceHandle = MnpCreateVlanChild (\r
+                         MnpDeviceData->ImageHandle,\r
+                         MnpDeviceData->ControllerHandle,\r
+                         VlanId,\r
+                         &MnpServiceData->DevicePath\r
+                         );\r
+    if (MnpServiceHandle == NULL) {\r
+      DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to create child handle.\n"));\r
+\r
+      return NULL;\r
+    }\r
+\r
+    //\r
+    // Open VLAN Config Protocol by child\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    MnpDeviceData->ControllerHandle,\r
+                    &gEfiVlanConfigProtocolGuid,\r
+                    (VOID **) &VlanConfig,\r
+                    MnpDeviceData->ImageHandle,\r
+                    MnpServiceHandle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Reduce MTU for VLAN device\r
+    //\r
+    MnpServiceData->Mtu = SnpMode->MaxPacketSize - NET_VLAN_TAG_LEN;\r
+  } else {\r
+    //\r
+    // VlanId set to 0 means rx/tx untagged frame\r
+    //\r
+    MnpServiceHandle    = MnpDeviceData->ControllerHandle;\r
+    MnpServiceData->Mtu = SnpMode->MaxPacketSize;\r
+  }\r
+\r
+  MnpServiceData->ServiceHandle = MnpServiceHandle;\r
+  MnpServiceData->VlanId        = VlanId;\r
+  MnpServiceData->Priority      = Priority;\r
+\r
+  //\r
+  // Install the MNP Service Binding Protocol\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &MnpServiceHandle,\r
+                  &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+                  &MnpServiceData->ServiceBinding,\r
+                  NULL\r
+                  );\r
+\r
+Exit:\r
+  if (EFI_ERROR (Status)) {\r
+    MnpDestroyServiceData (MnpServiceData);\r
+    MnpServiceData = NULL;\r
+  }\r
+\r
+  return MnpServiceData;\r
+}\r
+\r
+/**\r
+  Destroy the MNP service context data.\r
+\r
+  @param[in, out]  MnpServiceData    Pointer to the mnp service context data.\r
+\r
+  @retval EFI_SUCCESS           The mnp service context is destroyed.\r
+  @retval Others                Errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+MnpDestroyServiceData (\r
+  IN OUT MNP_SERVICE_DATA    *MnpServiceData\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Uninstall the MNP Service Binding Protocol\r
+  //\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                  MnpServiceData->ServiceHandle,\r
+                  &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+                  &MnpServiceData->ServiceBinding,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
-  if (EFI_ERROR (Status)) {\r
+  if (MnpServiceData->VlanId != 0) {\r
     //\r
-    // Free the dynamic allocated resources if necessary.\r
+    // Close VlanConfig Protocol opened by VLAN child handle\r
     //\r
-    if (MnpServiceData->TimeoutCheckTimer != NULL) {\r
-\r
-      gBS->CloseEvent (MnpServiceData->TimeoutCheckTimer);\r
-    }\r
-\r
-    if (MnpServiceData->PollTimer != NULL) {\r
-\r
-      gBS->CloseEvent (MnpServiceData->PollTimer);\r
+    Status = gBS->CloseProtocol (\r
+                    MnpServiceData->MnpDeviceData->ControllerHandle,\r
+                    &gEfiVlanConfigProtocolGuid,\r
+                    MnpServiceData->MnpDeviceData->ImageHandle,\r
+                    MnpServiceData->ServiceHandle\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
     }\r
 \r
-    if (MnpServiceData->TxBuf != NULL) {\r
-\r
-      gBS->FreePool (MnpServiceData->TxBuf);\r
+    //\r
+    // Uninstall Device Path Protocol to destroy the VLAN child handle\r
+    //\r
+    Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                    MnpServiceData->ServiceHandle,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    MnpServiceData->DevicePath,\r
+                    NULL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
     }\r
 \r
-    if (MnpServiceData->RxNbufCache != NULL) {\r
-\r
-      MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);\r
+    if (MnpServiceData->DevicePath != NULL) {\r
+      FreePool (MnpServiceData->DevicePath);\r
     }\r
+  }\r
 \r
-    if (MnpServiceData->FreeNbufQue.BufNum != 0) {\r
+  //\r
+  // Remove from MnpDeviceData service list\r
+  //\r
+  RemoveEntryList (&MnpServiceData->Link);\r
 \r
-      NetbufQueFlush (&MnpServiceData->FreeNbufQue);\r
-    }\r
-  }\r
+  FreePool (MnpServiceData);\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\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
+  Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
   \r
+  @param[in]    Entry           The entry to be removed.\r
+  @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
+\r
+  @retval EFI_SUCCESS           The entry has been removed successfully.\r
+  @retval Others                Fail to remove the entry.\r
+\r
 **/\r
-VOID\r
-MnpFlushServiceData (\r
-  IN MNP_SERVICE_DATA  *MnpServiceData,\r
-  IN EFI_HANDLE        ImageHandle\r
+EFI_STATUS\r
+EFIAPI\r
+MnpDestoryChildEntry (\r
+  IN LIST_ENTRY         *Entry,\r
+  IN VOID               *Context\r
   )\r
 {\r
-  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
+  MNP_INSTANCE_DATA             *Instance;\r
+  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
 \r
-  //\r
-  // The GroupAddressList must be empty.\r
-  //\r
-  ASSERT (IsListEmpty (&MnpServiceData->GroupAddressList));\r
+  ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *) Context;\r
+  Instance = CR (Entry, MNP_INSTANCE_DATA, InstEntry, MNP_INSTANCE_DATA_SIGNATURE);\r
+  return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
+}\r
 \r
-  //\r
-  // Close the event.\r
-  //\r
-  gBS->CloseEvent (&MnpServiceData->TxTimeoutEvent);\r
-  gBS->CloseEvent (&MnpServiceData->TimeoutCheckTimer);\r
-  gBS->CloseEvent (&MnpServiceData->PollTimer);\r
+/**\r
+  Destroy all child of the MNP service data.\r
 \r
-  //\r
-  // Free the tx buffer.\r
-  //\r
-  gBS->FreePool (MnpServiceData->TxBuf);\r
+  @param[in, out]  MnpServiceData    Pointer to the mnp service context data.\r
 \r
-  //\r
-  // Free the RxNbufCache.\r
-  //\r
-  MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);\r
+  @retval EFI_SUCCESS           All child are destroyed.\r
+  @retval Others                Failed to destroy all child.\r
 \r
-  //\r
-  // Flush the FreeNbufQue.\r
-  //\r
-  MnpServiceData->NbufCnt -= MnpServiceData->FreeNbufQue.BufNum;\r
-  NetbufQueFlush (&MnpServiceData->FreeNbufQue);\r
+**/\r
+EFI_STATUS\r
+MnpDestroyServiceChild (\r
+  IN OUT MNP_SERVICE_DATA    *MnpServiceData\r
+  )\r
+{\r
+  LIST_ENTRY                         *List;\r
+  EFI_STATUS                         Status;\r
+  UINTN                              ListLength;\r
+  \r
+  List = &MnpServiceData->ChildrenList;\r
+  \r
+  Status = NetDestroyLinkList (\r
+             List,\r
+             MnpDestoryChildEntry,\r
+             &MnpServiceData->ServiceBinding,\r
+             &ListLength\r
+             );\r
+  if (EFI_ERROR (Status) || ListLength != 0) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
 \r
-  DEBUG_CODE (\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Find the MNP Service Data for given VLAN ID.\r
+\r
+  @param[in]  MnpDeviceData      Pointer to the mnp device context data.\r
+  @param[in]  VlanId             The VLAN ID.\r
 \r
-  if (MnpServiceData->NbufCnt != 0) {\r
+  @return A pointer to MNP_SERVICE_DATA or NULL if not found.\r
 \r
-    DEBUG ((EFI_D_WARN, "MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));\r
+**/\r
+MNP_SERVICE_DATA *\r
+MnpFindServiceData (\r
+  IN MNP_DEVICE_DATA     *MnpDeviceData,\r
+  IN UINT16              VlanId\r
+  )\r
+{\r
+  LIST_ENTRY        *Entry;\r
+  MNP_SERVICE_DATA  *MnpServiceData;\r
+\r
+  NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {\r
+    //\r
+    // Check VLAN ID of each Mnp Service Data\r
+    //\r
+    MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
+    if (MnpServiceData->VlanId == VlanId) {\r
+      return MnpServiceData;\r
+    }\r
   }\r
-  );\r
 \r
-  //\r
-  // Close the Simple Network Protocol.\r
-  //\r
-  gBS->CloseProtocol (\r
-        MnpServiceData->ControllerHandle,\r
-        &gEfiSimpleNetworkProtocolGuid,\r
-        ImageHandle,\r
-        MnpServiceData->ControllerHandle\r
-        );\r
+  return NULL;\r
 }\r
 \r
-\r
 /**\r
   Initialize the mnp instance context data.\r
 \r
-  @param[in]  MnpServiceData    Pointer to the mnp service context data.\r
-  @param[in]  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,10 +826,10 @@ 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[in]  Map               Pointer to the NET_MAP.\r
-  @param[in]  Item              Pointer to the NET_MAP_ITEM\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
@@ -679,10 +840,11 @@ MnpInitializeInstanceData (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 MnpTokenExist (\r
-  IN NET_MAP       *Map,\r
-  IN NET_MAP_ITEM  *Item,\r
-  IN VOID          *Arg\r
+  IN NET_MAP         *Map,\r
+  IN NET_MAP_ITEM    *Item,\r
+  IN VOID            *Arg\r
   )\r
 {\r
   EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *Token;\r
@@ -705,12 +867,12 @@ MnpTokenExist (
 /**\r
   Cancel the token specified by Arg if it matches the token in Item.\r
 \r
-  @param[in, out]  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
-                                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
+  @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
                             different from the Arg.\r
   @retval EFI_ABORTED       The Arg isn't NULL, the token in Item mathces the\r
@@ -718,10 +880,11 @@ MnpTokenExist (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\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
@@ -733,7 +896,7 @@ MnpCancelTokens (
     return EFI_SUCCESS;\r
   }\r
 \r
-  TokenToCancel         = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
+  TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
 \r
   //\r
   // Remove the item from the map.\r
@@ -763,12 +926,12 @@ MnpCancelTokens (
   @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
 MnpStartSnp (\r
-  IN EFI_SIMPLE_NETWORK_PROTOCOL  *Snp\r
+  IN EFI_SIMPLE_NETWORK_PROTOCOL     *Snp\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -784,7 +947,7 @@ MnpStartSnp (
     //\r
     // Initialize the simple network.\r
     //\r
-    Status  = Snp->Initialize (Snp, 0, 0);\r
+    Status = Snp->Initialize (Snp, 0, 0);\r
   }\r
 \r
   return Status;\r
@@ -797,12 +960,12 @@ MnpStartSnp (
   @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
 MnpStopSnp (\r
-  IN EFI_SIMPLE_NETWORK_PROTOCOL  *Snp\r
+  IN EFI_SIMPLE_NETWORK_PROTOCOL     *Snp\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -812,8 +975,7 @@ MnpStopSnp (
   //\r
   // Shut down the simple network.\r
   //\r
-  Status = Snp->Shutdown (Snp);\r
-\r
+  Status  = Snp->Shutdown (Snp);\r
   if (!EFI_ERROR (Status)) {\r
     //\r
     // Stop the simple network.\r
@@ -829,44 +991,46 @@ MnpStopSnp (
   Start the managed network, this function is called when one instance is configured\r
   or reconfigured.\r
 \r
-  @param[in]  MnpServiceData    Pointer to the mnp service context data.\r
-  @param[in]  IsConfigUpdate    The instance is reconfigured or it's the first time\r
-                                the instanced is configured.\r
-  @param[in]  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
   EFI_TIMER_DELAY TimerOpType;\r
+  MNP_DEVICE_DATA *MnpDeviceData;\r
 \r
   NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
 \r
-  Status = EFI_SUCCESS;\r
+  Status        = EFI_SUCCESS;\r
+  MnpDeviceData = MnpServiceData->MnpDeviceData;\r
 \r
   if (!IsConfigUpdate) {\r
     //\r
     // If it's not a configuration update, increase the configured children number.\r
     //\r
-    MnpServiceData->ConfiguredChildrenNumber++;\r
+    MnpDeviceData->ConfiguredChildrenNumber++;\r
 \r
-    if (MnpServiceData->ConfiguredChildrenNumber == 1) {\r
+    if (MnpDeviceData->ConfiguredChildrenNumber == 1) {\r
       //\r
       // It's the first configured child, start the simple network.\r
       //\r
-      Status = MnpStartSnp (MnpServiceData->Snp);\r
+      Status = MnpStartSnp (MnpDeviceData->Snp);\r
       if (EFI_ERROR (Status)) {\r
-\r
         DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));\r
+\r
         goto ErrorExit;\r
       }\r
 \r
@@ -874,46 +1038,63 @@ MnpStart (
       // Start the timeout timer.\r
       //\r
       Status = gBS->SetTimer (\r
-                      MnpServiceData->TimeoutCheckTimer,\r
+                      MnpDeviceData->TimeoutCheckTimer,\r
                       TimerPeriodic,\r
                       MNP_TIMEOUT_CHECK_INTERVAL\r
                       );\r
       if (EFI_ERROR (Status)) {\r
-\r
         DEBUG (\r
           (EFI_D_ERROR,\r
           "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",\r
           Status)\r
           );\r
+\r
+        goto ErrorExit;\r
+      }\r
+\r
+      //\r
+      // Start the media detection timer.\r
+      //\r
+      Status = gBS->SetTimer (\r
+                      MnpDeviceData->MediaDetectTimer,\r
+                      TimerPeriodic,\r
+                      MNP_MEDIA_DETECT_INTERVAL\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG (\r
+          (EFI_D_ERROR,\r
+          "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n",\r
+          Status)\r
+          );\r
+\r
         goto ErrorExit;\r
       }\r
     }\r
   }\r
 \r
-  if (MnpServiceData->EnableSystemPoll ^ EnableSystemPoll) {\r
+  if (MnpDeviceData->EnableSystemPoll ^ EnableSystemPoll) {\r
     //\r
     // The EnableSystemPoll differs with the current state, disable or enable\r
     // the system poll.\r
     //\r
     TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;\r
 \r
-    Status      = gBS->SetTimer (MnpServiceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);\r
+    Status      = gBS->SetTimer (MnpDeviceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);\r
     if (EFI_ERROR (Status)) {\r
-\r
       DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));\r
+\r
       goto ErrorExit;\r
     }\r
 \r
-    MnpServiceData->EnableSystemPoll = EnableSystemPoll;\r
+    MnpDeviceData->EnableSystemPoll = EnableSystemPoll;\r
   }\r
 \r
   //\r
   // Change the receive filters if need.\r
   //\r
-  Status = MnpConfigReceiveFilters (MnpServiceData);\r
+  Status = MnpConfigReceiveFilters (MnpDeviceData);\r
 \r
 ErrorExit:\r
-\r
   return Status;\r
 }\r
 \r
@@ -921,33 +1102,35 @@ ErrorExit:
 /**\r
   Stop the managed network.\r
 \r
-  @param[in]  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
+  EFI_STATUS      Status;\r
+  MNP_DEVICE_DATA *MnpDeviceData;\r
 \r
   NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
-  ASSERT (MnpServiceData->ConfiguredChildrenNumber > 0);\r
+  MnpDeviceData = MnpServiceData->MnpDeviceData;\r
+  ASSERT (MnpDeviceData->ConfiguredChildrenNumber > 0);\r
 \r
   //\r
   // Configure the receive filters.\r
   //\r
-  MnpConfigReceiveFilters (MnpServiceData);\r
+  MnpConfigReceiveFilters (MnpDeviceData);\r
 \r
   //\r
   // Decrease the children number.\r
   //\r
-  MnpServiceData->ConfiguredChildrenNumber--;\r
+  MnpDeviceData->ConfiguredChildrenNumber--;\r
 \r
-  if (MnpServiceData->ConfiguredChildrenNumber > 0) {\r
+  if (MnpDeviceData->ConfiguredChildrenNumber > 0) {\r
     //\r
     // If there are other configured chilren, return and keep the timers and\r
     // simple network unchanged.\r
@@ -958,25 +1141,28 @@ MnpStop (
   //\r
   // No configured children now.\r
   //\r
-\r
-  if (MnpServiceData->EnableSystemPoll) {\r
+  if (MnpDeviceData->EnableSystemPoll) {\r
     //\r
     //  The system poll in on, cancel the poll timer.\r
     //\r
-    Status  = gBS->SetTimer (MnpServiceData->PollTimer, TimerCancel, 0);\r
-    MnpServiceData->EnableSystemPoll = FALSE;\r
+    Status  = gBS->SetTimer (MnpDeviceData->PollTimer, TimerCancel, 0);\r
+    MnpDeviceData->EnableSystemPoll = FALSE;\r
   }\r
 \r
   //\r
   // Cancel the timeout timer.\r
   //\r
-  Status  = gBS->SetTimer (MnpServiceData->TimeoutCheckTimer, TimerCancel, 0);\r
+  Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0);\r
 \r
   //\r
-  // Stop the simple network.\r
+  // Cancel the media detect timer.\r
   //\r
-  Status  = MnpStopSnp (MnpServiceData->Snp);\r
+  Status = gBS->SetTimer (MnpDeviceData->MediaDetectTimer, TimerCancel, 0);\r
 \r
+  //\r
+  // Stop the simple network.\r
+  //\r
+  Status = MnpStopSnp (MnpDeviceData->Snp);\r
   return Status;\r
 }\r
 \r
@@ -984,15 +1170,15 @@ 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
+  EFI_TPL         OldTpl;\r
   MNP_RXDATA_WRAP *RxDataWrap;\r
 \r
   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
@@ -1021,24 +1207,25 @@ MnpFlushRcvdDataQueue (
 /**\r
   Configure the Instance using ConfigData.\r
 \r
-  @param[in]  Instance          Pointer to the mnp instance context data.\r
-  @param[in]  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
   MNP_SERVICE_DATA                *MnpServiceData;\r
+  MNP_DEVICE_DATA                 *MnpDeviceData;\r
   EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;\r
   EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;\r
   BOOLEAN                         IsConfigUpdate;\r
@@ -1055,7 +1242,8 @@ MnpConfigureInstance (
   Status          = EFI_SUCCESS;\r
 \r
   MnpServiceData  = Instance->MnpServiceData;\r
-  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
+  MnpDeviceData   = MnpServiceData->MnpDeviceData;\r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
 \r
   IsConfigUpdate  = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));\r
 \r
@@ -1078,19 +1266,19 @@ MnpConfigureInstance (
   // Clear the receive counters according to the old ConfigData.\r
   //\r
   if (OldConfigData->EnableUnicastReceive) {\r
-    MnpServiceData->UnicastCount--;\r
+    MnpDeviceData->UnicastCount--;\r
   }\r
 \r
   if (OldConfigData->EnableMulticastReceive) {\r
-    MnpServiceData->MulticastCount--;\r
+    MnpDeviceData->MulticastCount--;\r
   }\r
 \r
   if (OldConfigData->EnableBroadcastReceive) {\r
-    MnpServiceData->BroadcastCount--;\r
+    MnpDeviceData->BroadcastCount--;\r
   }\r
 \r
   if (OldConfigData->EnablePromiscuousReceive) {\r
-    MnpServiceData->PromiscuousCount--;\r
+    MnpDeviceData->PromiscuousCount--;\r
   }\r
 \r
   //\r
@@ -1098,35 +1286,32 @@ MnpConfigureInstance (
   // instance according to the new ConfigData.\r
   //\r
   if (NewConfigData->EnableUnicastReceive) {\r
-    MnpServiceData->UnicastCount++;\r
+    MnpDeviceData->UnicastCount++;\r
     Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;\r
   }\r
 \r
   if (NewConfigData->EnableMulticastReceive) {\r
-    MnpServiceData->MulticastCount++;\r
+    MnpDeviceData->MulticastCount++;\r
   }\r
 \r
   if (NewConfigData->EnableBroadcastReceive) {\r
-    MnpServiceData->BroadcastCount++;\r
+    MnpDeviceData->BroadcastCount++;\r
     Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;\r
   }\r
 \r
   if (NewConfigData->EnablePromiscuousReceive) {\r
-    MnpServiceData->PromiscuousCount++;\r
+    MnpDeviceData->PromiscuousCount++;\r
   }\r
 \r
   if (OldConfigData->FlushQueuesOnReset) {\r
-\r
     MnpFlushRcvdDataQueue (Instance);\r
   }\r
 \r
   if (ConfigData == NULL) {\r
-\r
     Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);\r
   }\r
 \r
   if (!NewConfigData->EnableMulticastReceive) {\r
-\r
     MnpGroupOp (Instance, FALSE, NULL, NULL);\r
   }\r
 \r
@@ -1135,8 +1320,7 @@ MnpConfigureInstance (
   //\r
   CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));\r
 \r
-  Instance->Configured  = (BOOLEAN) (ConfigData != NULL);\r
-\r
+  Instance->Configured = (BOOLEAN) (ConfigData != NULL);\r
   if (Instance->Configured) {\r
     //\r
     // The instance is configured, start the Mnp.\r
@@ -1156,40 +1340,194 @@ MnpConfigureInstance (
   return Status;\r
 }\r
 \r
+/**\r
+  Configure the Snp receive filters according to the instances' receive filter\r
+  settings.\r
+\r
+  @param[in]  MnpDeviceData         Pointer to the mnp device 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_DEVICE_DATA     *MnpDeviceData\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 (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
+\r
+  Snp = MnpDeviceData->Snp;\r
+\r
+  //\r
+  // Initialize the enable filter and disable filter.\r
+  //\r
+  EnableFilterBits  = 0;\r
+  DisableFilterBits = Snp->Mode->ReceiveFilterMask;\r
+\r
+  if (MnpDeviceData->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 (MnpDeviceData->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 ((MnpDeviceData->MulticastCount != 0) && (MnpDeviceData->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 (MnpDeviceData->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  = MnpDeviceData->GroupAddressCount;\r
+      MCastFilter     = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);\r
+      if (MCastFilter == NULL) {\r
+        DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));\r
+\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, &MnpDeviceData->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 (MnpDeviceData->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
+      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
+    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[in]  Instance              Pointer to the mnp instance context data.\r
-  @param[in]  CtrlBlk               Pointer to the group address control block.\r
-  @param[in]  GroupAddress          Pointer to the group adress.\r
-  @param[in]  MacAddress            Pointer to the mac address.\r
-  @param[in]  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
+  MNP_DEVICE_DATA  *MnpDeviceData;\r
 \r
   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
 \r
-  MnpServiceData = Instance->MnpServiceData;\r
-  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
+  MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
 \r
   if (GroupAddress == NULL) {\r
-\r
     ASSERT (MacAddress != NULL);\r
 \r
     //\r
@@ -1204,12 +1542,12 @@ MnpGroupOpAddCtrlBlk (
     }\r
 \r
     CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));\r
-    GroupAddress->RefCnt  = 0;\r
+    GroupAddress->RefCnt = 0;\r
     InsertTailList (\r
-      &MnpServiceData->GroupAddressList,\r
+      &MnpDeviceData->GroupAddressList,\r
       &GroupAddress->AddrEntry\r
       );\r
-    MnpServiceData->GroupAddressCount++;\r
+    MnpDeviceData->GroupAddressCount++;\r
   }\r
 \r
   //\r
@@ -1239,24 +1577,24 @@ MnpGroupOpAddCtrlBlk (
 **/\r
 BOOLEAN\r
 MnpGroupOpDelCtrlBlk (\r
-  IN MNP_INSTANCE_DATA        *Instance,\r
-  IN MNP_GROUP_CONTROL_BLOCK  *CtrlBlk\r
+  IN MNP_INSTANCE_DATA           *Instance,\r
+  IN MNP_GROUP_CONTROL_BLOCK     *CtrlBlk\r
   )\r
 {\r
-  MNP_SERVICE_DATA  *MnpServiceData;\r
+  MNP_DEVICE_DATA   *MnpDeviceData;\r
   MNP_GROUP_ADDRESS *GroupAddress;\r
 \r
   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
 \r
-  MnpServiceData = Instance->MnpServiceData;\r
-  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
+  MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
 \r
   //\r
   // Remove and free the CtrlBlk.\r
   //\r
   GroupAddress = CtrlBlk->GroupAddress;\r
   RemoveEntryList (&CtrlBlk->CtrlBlkEntry);\r
-  gBS->FreePool (CtrlBlk);\r
+  FreePool (CtrlBlk);\r
 \r
   ASSERT (GroupAddress->RefCnt > 0);\r
 \r
@@ -1269,9 +1607,9 @@ MnpGroupOpDelCtrlBlk (
     //\r
     // Free this GroupAddress entry if no instance uses it.\r
     //\r
-    MnpServiceData->GroupAddressCount--;\r
+    MnpDeviceData->GroupAddressCount--;\r
     RemoveEntryList (&GroupAddress->AddrEntry);\r
-    gBS->FreePool (GroupAddress);\r
+    FreePool (GroupAddress);\r
 \r
     return TRUE;\r
   }\r
@@ -1283,26 +1621,27 @@ MnpGroupOpDelCtrlBlk (
 /**\r
   Do the group operations for this instance.\r
 \r
-  @param[in]  Instance          Pointer to the instance context data.\r
-  @param[in]  JoinFlag          Set to TRUE to join a group. Set to TRUE to leave a\r
-                                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 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 BOOLEAN                  JoinFlag,\r
-  IN EFI_MAC_ADDRESS          *MacAddress OPTIONAL,\r
-  IN MNP_GROUP_CONTROL_BLOCK  *CtrlBlk OPTIONAL\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
   )\r
 {\r
-  MNP_SERVICE_DATA        *MnpServiceData;\r
+  MNP_DEVICE_DATA         *MnpDeviceData;\r
   LIST_ENTRY              *Entry;\r
   LIST_ENTRY              *NextEntry;\r
   MNP_GROUP_ADDRESS       *GroupAddress;\r
@@ -1314,38 +1653,32 @@ MnpGroupOp (
 \r
   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
 \r
-  MnpServiceData  = Instance->MnpServiceData;\r
-  SnpMode         = MnpServiceData->Snp->Mode;\r
+  MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
+  SnpMode       = MnpDeviceData->Snp->Mode;\r
 \r
   if (JoinFlag) {\r
     //\r
     // A new gropu address is to be added.\r
     //\r
-\r
     GroupAddress  = NULL;\r
     AddressExist  = FALSE;\r
 \r
     //\r
     // Allocate memory for the control block.\r
     //\r
-    NewCtrlBlk    = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));\r
+    NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));\r
     if (NewCtrlBlk == NULL) {\r
-\r
       DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));\r
+\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
-    NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {\r
+    NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
       //\r
       // Check whether the MacAddress is already joined by other instances.\r
       //\r
       GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
-      if (0 == CompareMem (\r
-                MacAddress,\r
-                &GroupAddress->Address,\r
-                SnpMode->HwAddressSize\r
-                )) {\r
-\r
+      if (CompareMem (MacAddress, &GroupAddress->Address, SnpMode->HwAddressSize) == 0) {\r
         AddressExist = TRUE;\r
         break;\r
       }\r
@@ -1366,15 +1699,12 @@ MnpGroupOp (
               SnpMode->HwAddressSize\r
               );\r
     if (EFI_ERROR (Status)) {\r
-\r
       return Status;\r
     }\r
 \r
     NeedUpdate = TRUE;\r
   } else {\r
-\r
     if (MacAddress != NULL) {\r
-\r
       ASSERT (CtrlBlk != NULL);\r
 \r
       //\r
@@ -1409,7 +1739,7 @@ MnpGroupOp (
     //\r
     // Reconfigure the receive filters if necessary.\r
     //\r
-    Status = MnpConfigReceiveFilters (MnpServiceData);\r
+    Status = MnpConfigReceiveFilters (MnpDeviceData);\r
   }\r
 \r
   return Status;\r