]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
For network dynamic media support:
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
CommitLineData
8a67d61d 1/** @file\r
c57273b0 2 Implementation of Managed Network Protocol private services.\r
6e4bac4d 3\r
dd29f3ed 4Copyright (c) 2005 - 2010, Intel Corporation.<BR>\r
779ae357 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions\r
7of the BSD License which accompanies this distribution. The full\r
8text of the license may be found at<BR>\r
9http://opensource.org/licenses/bsd-license.php\r
8a67d61d 10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
8a67d61d 14**/\r
15\r
8a67d61d 16#include "MnpImpl.h"\r
779ae357 17#include "MnpVlan.h"\r
8a67d61d 18\r
19EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol = {\r
20 MnpServiceBindingCreateChild,\r
21 MnpServiceBindingDestroyChild\r
22};\r
23\r
24EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate = {\r
25 MnpGetModeData,\r
26 MnpConfigure,\r
27 MnpMcastIpToMac,\r
28 MnpGroups,\r
29 MnpTransmit,\r
30 MnpReceive,\r
31 MnpCancel,\r
32 MnpPoll\r
33};\r
34\r
35EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {\r
87f89c08 36 10000000,\r
37 10000000,\r
8a67d61d 38 0,\r
39 FALSE,\r
40 FALSE,\r
41 FALSE,\r
42 FALSE,\r
43 FALSE,\r
44 FALSE,\r
45 FALSE\r
46};\r
47\r
8a67d61d 48\r
49/**\r
779ae357 50 Add Count of net buffers to MnpDeviceData->FreeNbufQue. The length of the net\r
51 buffer is specified by MnpDeviceData->BufferLength.\r
8a67d61d 52\r
779ae357 53 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
6e4bac4d 54 @param[in] Count Number of NET_BUFFERs to add.\r
8a67d61d 55\r
779ae357 56 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated\r
57 and added to MnpDeviceData->FreeNbufQue.\r
8a67d61d 58 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.\r
59\r
60**/\r
8a67d61d 61EFI_STATUS\r
62MnpAddFreeNbuf (\r
779ae357 63 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
64 IN UINTN Count\r
8a67d61d 65 )\r
66{\r
67 EFI_STATUS Status;\r
68 UINTN Index;\r
69 NET_BUF *Nbuf;\r
70\r
779ae357 71 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
72 ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));\r
8a67d61d 73\r
74 Status = EFI_SUCCESS;\r
8a67d61d 75 for (Index = 0; Index < Count; Index++) {\r
779ae357 76 Nbuf = NetbufAlloc (MnpDeviceData->BufferLength + MnpDeviceData->PaddingSize);\r
8a67d61d 77 if (Nbuf == NULL) {\r
e48e37fc 78 DEBUG ((EFI_D_ERROR, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));\r
779ae357 79\r
8a67d61d 80 Status = EFI_OUT_OF_RESOURCES;\r
81 break;\r
82 }\r
83\r
779ae357 84 if (MnpDeviceData->PaddingSize > 0) {\r
772db4bb 85 //\r
86 // Pad padding bytes before the media header\r
87 //\r
779ae357 88 NetbufAllocSpace (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_TAIL);\r
89 NetbufTrim (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_HEAD);\r
772db4bb 90 }\r
91\r
779ae357 92 NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);\r
8a67d61d 93 }\r
94\r
779ae357 95 MnpDeviceData->NbufCnt += Index;\r
8a67d61d 96 return Status;\r
97}\r
98\r
99\r
100/**\r
779ae357 101 Allocate a free NET_BUF from MnpDeviceData->FreeNbufQue. If there is none\r
8a67d61d 102 in the queue, first try to allocate some and add them into the queue, then\r
103 fetch the NET_BUF from the updated FreeNbufQue.\r
104\r
779ae357 105 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
8a67d61d 106\r
779ae357 107 @return Pointer to the allocated free NET_BUF structure, if NULL the\r
c57273b0 108 operation is failed.\r
8a67d61d 109\r
110**/\r
111NET_BUF *\r
112MnpAllocNbuf (\r
779ae357 113 IN OUT MNP_DEVICE_DATA *MnpDeviceData\r
8a67d61d 114 )\r
115{\r
116 EFI_STATUS Status;\r
117 NET_BUF_QUEUE *FreeNbufQue;\r
118 NET_BUF *Nbuf;\r
119 EFI_TPL OldTpl;\r
120\r
779ae357 121 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 122\r
779ae357 123 FreeNbufQue = &MnpDeviceData->FreeNbufQue;\r
124 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 125\r
126 //\r
127 // Check whether there are available buffers, or else try to add some.\r
128 //\r
129 if (FreeNbufQue->BufNum == 0) {\r
779ae357 130 if ((MnpDeviceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {\r
e48e37fc 131 DEBUG (\r
132 (EFI_D_ERROR,\r
133 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",\r
779ae357 134 MnpDeviceData)\r
8a67d61d 135 );\r
136\r
137 Nbuf = NULL;\r
138 goto ON_EXIT;\r
139 }\r
140\r
779ae357 141 Status = MnpAddFreeNbuf (MnpDeviceData, MNP_NET_BUFFER_INCREASEMENT);\r
8a67d61d 142 if (EFI_ERROR (Status)) {\r
e48e37fc 143 DEBUG (\r
144 (EFI_D_ERROR,\r
145 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",\r
8a67d61d 146 Status)\r
147 );\r
779ae357 148\r
8a67d61d 149 //\r
150 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but\r
151 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.\r
152 //\r
153 }\r
154 }\r
155\r
156 Nbuf = NetbufQueRemove (FreeNbufQue);\r
157\r
158 //\r
159 // Increase the RefCnt.\r
160 //\r
161 if (Nbuf != NULL) {\r
162 NET_GET_REF (Nbuf);\r
163 }\r
164\r
165ON_EXIT:\r
e48e37fc 166 gBS->RestoreTPL (OldTpl);\r
8a67d61d 167\r
168 return Nbuf;\r
169}\r
170\r
171\r
172/**\r
173 Try to reclaim the Nbuf into the buffer pool.\r
174\r
779ae357 175 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
5fe2f07f 176 @param[in, out] Nbuf Pointer to the NET_BUF to free.\r
6e4bac4d 177\r
8a67d61d 178**/\r
179VOID\r
180MnpFreeNbuf (\r
779ae357 181 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
6e4bac4d 182 IN OUT NET_BUF *Nbuf\r
8a67d61d 183 )\r
184{\r
185 EFI_TPL OldTpl;\r
186\r
779ae357 187 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 188 ASSERT (Nbuf->RefCnt > 1);\r
189\r
e48e37fc 190 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 191\r
192 NET_PUT_REF (Nbuf);\r
193\r
194 if (Nbuf->RefCnt == 1) {\r
195 //\r
196 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.\r
197 //\r
198 NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_TAIL);\r
779ae357 199\r
200 if (NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD) != NULL) {\r
201 //\r
202 // There is space reserved for vlan tag in the head, reclaim it\r
203 //\r
204 NetbufTrim (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_TAIL);\r
205 }\r
206\r
207 NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);\r
8a67d61d 208 }\r
209\r
e48e37fc 210 gBS->RestoreTPL (OldTpl);\r
8a67d61d 211}\r
212\r
213\r
214/**\r
779ae357 215 Initialize the mnp device context data.\r
8a67d61d 216\r
779ae357 217 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
6e4bac4d 218 @param[in] ImageHandle The driver image handle.\r
219 @param[in] ControllerHandle Handle of device to bind driver to.\r
8a67d61d 220\r
221 @retval EFI_SUCCESS The mnp service context is initialized.\r
6e4bac4d 222 @retval EFI_UNSUPPORTED ControllerHandle does not support Simple Network Protocol.\r
223 @retval Others Other errors as indicated.\r
8a67d61d 224\r
225**/\r
226EFI_STATUS\r
779ae357 227MnpInitializeDeviceData (\r
228 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
229 IN EFI_HANDLE ImageHandle,\r
230 IN EFI_HANDLE ControllerHandle\r
8a67d61d 231 )\r
232{\r
779ae357 233 EFI_STATUS Status;\r
234 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
235 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
8a67d61d 236\r
779ae357 237 MnpDeviceData->Signature = MNP_DEVICE_DATA_SIGNATURE;\r
238 MnpDeviceData->ImageHandle = ImageHandle;\r
239 MnpDeviceData->ControllerHandle = ControllerHandle;\r
8a67d61d 240\r
241 //\r
779ae357 242 // Copy the MNP Protocol interfaces from the template.\r
8a67d61d 243 //\r
779ae357 244 CopyMem (&MnpDeviceData->VlanConfig, &mVlanConfigProtocolTemplate, sizeof (EFI_VLAN_CONFIG_PROTOCOL));\r
8a67d61d 245\r
246 //\r
247 // Open the Simple Network protocol.\r
248 //\r
249 Status = gBS->OpenProtocol (\r
250 ControllerHandle,\r
251 &gEfiSimpleNetworkProtocolGuid,\r
252 (VOID **) &Snp,\r
253 ImageHandle,\r
254 ControllerHandle,\r
255 EFI_OPEN_PROTOCOL_BY_DRIVER\r
256 );\r
257 if (EFI_ERROR (Status)) {\r
258 return EFI_UNSUPPORTED;\r
259 }\r
260\r
261 //\r
262 // Get MTU from Snp.\r
263 //\r
779ae357 264 SnpMode = Snp->Mode;\r
265 MnpDeviceData->Snp = Snp;\r
8a67d61d 266\r
267 //\r
268 // Initialize the lists.\r
269 //\r
779ae357 270 InitializeListHead (&MnpDeviceData->ServiceList);\r
271 InitializeListHead (&MnpDeviceData->GroupAddressList);\r
8a67d61d 272\r
273 //\r
274 // Get the buffer length used to allocate NET_BUF to hold data received\r
275 // from SNP. Do this before fill the FreeNetBufQue.\r
276 //\r
779ae357 277 //\r
278 MnpDeviceData->BufferLength = SnpMode->MediaHeaderSize + NET_VLAN_TAG_LEN + SnpMode->MaxPacketSize + NET_ETHER_FCS_SIZE;\r
8a67d61d 279\r
772db4bb 280 //\r
e48e37fc 281 // Make sure the protocol headers immediately following the media header\r
779ae357 282 // 4-byte aligned, and also preserve additional space for VLAN tag\r
772db4bb 283 //\r
779ae357 284 MnpDeviceData->PaddingSize = ((4 - SnpMode->MediaHeaderSize) & 0x3) + NET_VLAN_TAG_LEN;\r
285\r
286 //\r
287 // Initialize MAC string which will be used as VLAN configuration variable name\r
288 //\r
289 Status = NetLibGetMacString (ControllerHandle, ImageHandle, &MnpDeviceData->MacString);\r
290 if (EFI_ERROR (Status)) {\r
291 goto ERROR;\r
292 }\r
772db4bb 293\r
8a67d61d 294 //\r
295 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.\r
296 //\r
779ae357 297 NetbufQueInit (&MnpDeviceData->FreeNbufQue);\r
298 Status = MnpAddFreeNbuf (MnpDeviceData, MNP_INIT_NET_BUFFER_NUM);\r
8a67d61d 299 if (EFI_ERROR (Status)) {\r
779ae357 300 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: MnpAddFreeNbuf failed, %r.\n", Status));\r
8a67d61d 301\r
8a67d61d 302 goto ERROR;\r
303 }\r
779ae357 304\r
8a67d61d 305 //\r
306 // Get one NET_BUF from the FreeNbufQue for rx cache.\r
307 //\r
779ae357 308 MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);\r
8a67d61d 309 NetbufAllocSpace (\r
779ae357 310 MnpDeviceData->RxNbufCache,\r
311 MnpDeviceData->BufferLength,\r
8a67d61d 312 NET_BUF_TAIL\r
313 );\r
314\r
315 //\r
316 // Allocate buffer pool for tx.\r
317 //\r
779ae357 318 MnpDeviceData->TxBuf = AllocatePool (MnpDeviceData->BufferLength);\r
319 if (MnpDeviceData->TxBuf == NULL) {\r
320 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: AllocatePool failed.\n"));\r
8a67d61d 321\r
8a67d61d 322 Status = EFI_OUT_OF_RESOURCES;\r
8a67d61d 323 goto ERROR;\r
324 }\r
325\r
326 //\r
327 // Create the system poll timer.\r
328 //\r
329 Status = gBS->CreateEvent (\r
330 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 331 TPL_CALLBACK,\r
8a67d61d 332 MnpSystemPoll,\r
779ae357 333 MnpDeviceData,\r
334 &MnpDeviceData->PollTimer\r
8a67d61d 335 );\r
336 if (EFI_ERROR (Status)) {\r
779ae357 337 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for poll timer failed.\n"));\r
8a67d61d 338\r
8a67d61d 339 goto ERROR;\r
340 }\r
341\r
342 //\r
343 // Create the timer for packet timeout check.\r
344 //\r
345 Status = gBS->CreateEvent (\r
346 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 347 TPL_CALLBACK,\r
8a67d61d 348 MnpCheckPacketTimeout,\r
779ae357 349 MnpDeviceData,\r
350 &MnpDeviceData->TimeoutCheckTimer\r
8a67d61d 351 );\r
352 if (EFI_ERROR (Status)) {\r
779ae357 353 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for packet timeout check failed.\n"));\r
8a67d61d 354\r
8a67d61d 355 goto ERROR;\r
356 }\r
357\r
dd29f3ed 358 //\r
359 // Create the timer for media detection.\r
360 //\r
361 Status = gBS->CreateEvent (\r
362 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
363 TPL_CALLBACK,\r
364 MnpCheckMediaStatus,\r
365 MnpDeviceData,\r
366 &MnpDeviceData->MediaDetectTimer\r
367 );\r
368 if (EFI_ERROR (Status)) {\r
369 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for media detection failed.\n"));\r
370\r
371 goto ERROR;\r
372 }\r
373\r
8a67d61d 374 //\r
375 // Create the timer for tx timeout check.\r
376 //\r
377 Status = gBS->CreateEvent (\r
378 EVT_TIMER,\r
e48e37fc 379 TPL_CALLBACK,\r
8a67d61d 380 NULL,\r
381 NULL,\r
779ae357 382 &MnpDeviceData->TxTimeoutEvent\r
8a67d61d 383 );\r
384 if (EFI_ERROR (Status)) {\r
779ae357 385 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for tx timeout event failed.\n"));\r
8a67d61d 386 }\r
387\r
388ERROR:\r
8a67d61d 389 if (EFI_ERROR (Status)) {\r
390 //\r
391 // Free the dynamic allocated resources if necessary.\r
392 //\r
779ae357 393 if (MnpDeviceData->MacString != NULL) {\r
394 FreePool (MnpDeviceData->MacString);\r
8a67d61d 395 }\r
396\r
779ae357 397 if (MnpDeviceData->TimeoutCheckTimer != NULL) {\r
398 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
8a67d61d 399 }\r
400\r
dd29f3ed 401 if (MnpDeviceData->MediaDetectTimer != NULL) {\r
402 gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
403 }\r
404\r
779ae357 405 if (MnpDeviceData->PollTimer != NULL) {\r
406 gBS->CloseEvent (MnpDeviceData->PollTimer);\r
8a67d61d 407 }\r
408\r
779ae357 409 if (MnpDeviceData->TxBuf != NULL) {\r
410 FreePool (MnpDeviceData->TxBuf);\r
8a67d61d 411 }\r
412\r
779ae357 413 if (MnpDeviceData->RxNbufCache != NULL) {\r
414 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
415 }\r
8a67d61d 416\r
779ae357 417 if (MnpDeviceData->FreeNbufQue.BufNum != 0) {\r
418 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
8a67d61d 419 }\r
779ae357 420\r
421 //\r
422 // Close the Simple Network Protocol.\r
423 //\r
424 gBS->CloseProtocol (\r
425 ControllerHandle,\r
426 &gEfiSimpleNetworkProtocolGuid,\r
427 ImageHandle,\r
428 ControllerHandle\r
429 );\r
8a67d61d 430 }\r
431\r
432 return Status;\r
433}\r
434\r
435\r
436/**\r
779ae357 437 Destroy the MNP device context data.\r
8a67d61d 438\r
779ae357 439 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
440 @param[in] ImageHandle The driver image handle.\r
6e4bac4d 441\r
8a67d61d 442**/\r
443VOID\r
779ae357 444MnpDestroyDeviceData (\r
445 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
446 IN EFI_HANDLE ImageHandle\r
8a67d61d 447 )\r
448{\r
779ae357 449 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
450\r
451 //\r
452 // Free Vlan Config variable name string\r
453 //\r
454 if (MnpDeviceData->MacString != NULL) {\r
455 FreePool (MnpDeviceData->MacString);\r
456 }\r
8a67d61d 457\r
458 //\r
459 // The GroupAddressList must be empty.\r
460 //\r
779ae357 461 ASSERT (IsListEmpty (&MnpDeviceData->GroupAddressList));\r
8a67d61d 462\r
463 //\r
464 // Close the event.\r
465 //\r
dd29f3ed 466 gBS->CloseEvent (MnpDeviceData->TxTimeoutEvent);\r
467 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
468 gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
469 gBS->CloseEvent (MnpDeviceData->PollTimer);\r
8a67d61d 470\r
471 //\r
472 // Free the tx buffer.\r
473 //\r
779ae357 474 FreePool (MnpDeviceData->TxBuf);\r
8a67d61d 475\r
476 //\r
477 // Free the RxNbufCache.\r
478 //\r
779ae357 479 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
8a67d61d 480\r
481 //\r
482 // Flush the FreeNbufQue.\r
483 //\r
779ae357 484 MnpDeviceData->NbufCnt -= MnpDeviceData->FreeNbufQue.BufNum;\r
485 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
8a67d61d 486\r
779ae357 487 //\r
488 // Close the Simple Network Protocol.\r
489 //\r
490 gBS->CloseProtocol (\r
491 MnpDeviceData->ControllerHandle,\r
492 &gEfiSimpleNetworkProtocolGuid,\r
493 ImageHandle,\r
494 MnpDeviceData->ControllerHandle\r
495 );\r
496}\r
497\r
498\r
499/**\r
500 Create mnp service context data.\r
501\r
502 @param[in] MnpDeviceData Pointer to the mnp device context data.\r
503 @param[in] VlanId The VLAN ID.\r
504 @param[in] Priority The VLAN priority. If VlanId is 0,\r
505 Priority is ignored.\r
506\r
507 @return A pointer to MNP_SERVICE_DATA or NULL if failed to create MNP service context.\r
8a67d61d 508\r
779ae357 509**/\r
510MNP_SERVICE_DATA *\r
511MnpCreateServiceData (\r
512 IN MNP_DEVICE_DATA *MnpDeviceData,\r
513 IN UINT16 VlanId,\r
514 IN UINT8 Priority OPTIONAL\r
515 )\r
516{\r
517 EFI_HANDLE MnpServiceHandle;\r
518 MNP_SERVICE_DATA *MnpServiceData;\r
519 EFI_STATUS Status;\r
520 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
521 EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;\r
8a67d61d 522\r
779ae357 523 //\r
524 // Initialize the Mnp Service Data.\r
525 //\r
526 MnpServiceData = AllocateZeroPool (sizeof (MNP_SERVICE_DATA));\r
527 if (MnpServiceData == NULL) {\r
528 DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to allocate memory for the new Mnp Service Data.\n"));\r
529\r
530 return NULL;\r
8a67d61d 531 }\r
e21ef3a2 532\r
533 //\r
779ae357 534 // Add to MNP service list\r
e21ef3a2 535 //\r
779ae357 536 InsertTailList (&MnpDeviceData->ServiceList, &MnpServiceData->Link);\r
537\r
538 MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;\r
539 MnpServiceData->MnpDeviceData = MnpDeviceData;\r
540\r
541 //\r
542 // Copy the ServiceBinding structure.\r
543 //\r
544 CopyMem (&MnpServiceData->ServiceBinding, &mMnpServiceBindingProtocol, sizeof (EFI_SERVICE_BINDING_PROTOCOL));\r
545\r
546 //\r
547 // Initialize the lists.\r
548 //\r
549 InitializeListHead (&MnpServiceData->ChildrenList);\r
550\r
551 SnpMode = MnpDeviceData->Snp->Mode;\r
552 if (VlanId != 0) {\r
553 //\r
554 // Create VLAN child handle\r
555 //\r
556 MnpServiceHandle = MnpCreateVlanChild (\r
557 MnpDeviceData->ImageHandle,\r
558 MnpDeviceData->ControllerHandle,\r
559 VlanId,\r
560 &MnpServiceData->DevicePath\r
561 );\r
562 if (MnpServiceHandle == NULL) {\r
563 DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to create child handle.\n"));\r
564\r
565 return NULL;\r
566 }\r
567\r
568 //\r
569 // Open VLAN Config Protocol by child\r
570 //\r
571 Status = gBS->OpenProtocol (\r
572 MnpDeviceData->ControllerHandle,\r
573 &gEfiVlanConfigProtocolGuid,\r
574 (VOID **) &VlanConfig,\r
575 MnpDeviceData->ImageHandle,\r
576 MnpServiceHandle,\r
577 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
578 );\r
579 if (EFI_ERROR (Status)) {\r
580 goto Exit;\r
581 }\r
582\r
583 //\r
584 // Reduce MTU for VLAN device\r
585 //\r
586 MnpServiceData->Mtu = SnpMode->MaxPacketSize - NET_VLAN_TAG_LEN;\r
587 } else {\r
588 //\r
589 // VlanId set to 0 means rx/tx untagged frame\r
590 //\r
591 MnpServiceHandle = MnpDeviceData->ControllerHandle;\r
592 MnpServiceData->Mtu = SnpMode->MaxPacketSize;\r
593 }\r
594\r
595 MnpServiceData->ServiceHandle = MnpServiceHandle;\r
596 MnpServiceData->VlanId = VlanId;\r
597 MnpServiceData->Priority = Priority;\r
598\r
599 //\r
600 // Install the MNP Service Binding Protocol\r
601 //\r
602 Status = gBS->InstallMultipleProtocolInterfaces (\r
603 &MnpServiceHandle,\r
604 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
605 &MnpServiceData->ServiceBinding,\r
606 NULL\r
607 );\r
608\r
609Exit:\r
610 if (EFI_ERROR (Status)) {\r
611 MnpDestroyServiceData (MnpServiceData);\r
612 MnpServiceData = NULL;\r
613 }\r
614\r
615 return MnpServiceData;\r
616}\r
617\r
618/**\r
619 Destroy the MNP service context data.\r
620\r
621 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
622\r
623 @retval EFI_SUCCESS The mnp service context is destroyed.\r
624 @retval Others Errors as indicated.\r
625\r
626**/\r
627EFI_STATUS\r
628MnpDestroyServiceData (\r
629 IN OUT MNP_SERVICE_DATA *MnpServiceData\r
630 )\r
631{\r
632 EFI_STATUS Status;\r
633\r
634 //\r
635 // Uninstall the MNP Service Binding Protocol\r
636 //\r
637 Status = gBS->UninstallMultipleProtocolInterfaces (\r
638 MnpServiceData->ServiceHandle,\r
639 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
640 &MnpServiceData->ServiceBinding,\r
641 NULL\r
642 );\r
643 if (EFI_ERROR (Status)) {\r
644 return Status;\r
645 }\r
646\r
647 if (MnpServiceData->VlanId != 0) {\r
648 //\r
649 // Close VlanConfig Protocol opened by VLAN child handle\r
650 //\r
651 Status = gBS->CloseProtocol (\r
652 MnpServiceData->MnpDeviceData->ControllerHandle,\r
653 &gEfiVlanConfigProtocolGuid,\r
654 MnpServiceData->MnpDeviceData->ImageHandle,\r
655 MnpServiceData->ServiceHandle\r
656 );\r
657 if (EFI_ERROR (Status)) {\r
658 return Status;\r
659 }\r
660\r
661 //\r
662 // Uninstall Device Path Protocol to destroy the VLAN child handle\r
663 //\r
664 Status = gBS->UninstallMultipleProtocolInterfaces (\r
665 MnpServiceData->ServiceHandle,\r
666 &gEfiDevicePathProtocolGuid,\r
667 MnpServiceData->DevicePath,\r
668 NULL\r
669 );\r
670 if (EFI_ERROR (Status)) {\r
671 return Status;\r
672 }\r
673\r
674 if (MnpServiceData->DevicePath != NULL) {\r
675 FreePool (MnpServiceData->DevicePath);\r
676 }\r
677 }\r
678\r
679 //\r
680 // Remove from MnpDeviceData service list\r
681 //\r
682 RemoveEntryList (&MnpServiceData->Link);\r
683\r
684 FreePool (MnpServiceData);\r
685\r
686 return Status;\r
8a67d61d 687}\r
688\r
779ae357 689/**\r
690 Destroy all child of the MNP service data.\r
691\r
692 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
693\r
694 @retval EFI_SUCCESS All child are destroyed.\r
695 @retval Others Failed to destroy all child.\r
696\r
697**/\r
698EFI_STATUS\r
699MnpDestroyServiceChild (\r
700 IN OUT MNP_SERVICE_DATA *MnpServiceData\r
701 )\r
702{\r
703 EFI_STATUS Status;\r
704 MNP_INSTANCE_DATA *Instance;\r
705 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
706\r
707 ServiceBinding = &MnpServiceData->ServiceBinding;\r
708 while (!IsListEmpty (&MnpServiceData->ChildrenList)) {\r
709 //\r
710 // Don't use NetListRemoveHead here, the remove opreration will be done\r
711 // in ServiceBindingDestroyChild.\r
712 //\r
713 Instance = NET_LIST_HEAD (\r
714 &MnpServiceData->ChildrenList,\r
715 MNP_INSTANCE_DATA,\r
716 InstEntry\r
717 );\r
718\r
719 Status = ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
720 if (EFI_ERROR (Status)) {\r
721 return Status;\r
722 }\r
723 }\r
724\r
725 return EFI_SUCCESS;\r
726}\r
727\r
728/**\r
729 Find the MNP Service Data for given VLAN ID.\r
730\r
731 @param[in] MnpDeviceData Pointer to the mnp device context data.\r
732 @param[in] VlanId The VLAN ID.\r
733\r
734 @return A pointer to MNP_SERVICE_DATA or NULL if not found.\r
735\r
736**/\r
737MNP_SERVICE_DATA *\r
738MnpFindServiceData (\r
739 IN MNP_DEVICE_DATA *MnpDeviceData,\r
740 IN UINT16 VlanId\r
741 )\r
742{\r
743 LIST_ENTRY *Entry;\r
744 MNP_SERVICE_DATA *MnpServiceData;\r
745\r
746 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {\r
747 //\r
748 // Check VLAN ID of each Mnp Service Data\r
749 //\r
750 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
751 if (MnpServiceData->VlanId == VlanId) {\r
752 return MnpServiceData;\r
753 }\r
754 }\r
755\r
756 return NULL;\r
757}\r
8a67d61d 758\r
759/**\r
760 Initialize the mnp instance context data.\r
761\r
6e4bac4d 762 @param[in] MnpServiceData Pointer to the mnp service context data.\r
779ae357 763 @param[in, out] Instance Pointer to the mnp instance context data\r
6e4bac4d 764 to initialize.\r
8a67d61d 765\r
8a67d61d 766**/\r
767VOID\r
768MnpInitializeInstanceData (\r
779ae357 769 IN MNP_SERVICE_DATA *MnpServiceData,\r
770 IN OUT MNP_INSTANCE_DATA *Instance\r
8a67d61d 771 )\r
772{\r
773 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
774 ASSERT (Instance != NULL);\r
775\r
776 //\r
777 // Set the signature.\r
778 //\r
779 Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;\r
780\r
781 //\r
782 // Copy the MNP Protocol interfaces from the template.\r
783 //\r
687a2e5f 784 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));\r
8a67d61d 785\r
786 //\r
787 // Copy the default config data.\r
788 //\r
687a2e5f 789 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));\r
8a67d61d 790\r
791 //\r
792 // Initialize the lists.\r
793 //\r
e48e37fc 794 InitializeListHead (&Instance->GroupCtrlBlkList);\r
795 InitializeListHead (&Instance->RcvdPacketQueue);\r
796 InitializeListHead (&Instance->RxDeliveredPacketQueue);\r
8a67d61d 797\r
798 //\r
799 // Initialize the RxToken Map.\r
800 //\r
801 NetMapInit (&Instance->RxTokenMap);\r
802\r
803 //\r
804 // Save the MnpServiceData info.\r
805 //\r
806 Instance->MnpServiceData = MnpServiceData;\r
807}\r
808\r
809\r
810/**\r
6e4bac4d 811 Check whether the token specified by Arg matches the token in Item.\r
8a67d61d 812\r
3e8c18da 813 @param[in] Map Pointer to the NET_MAP.\r
6e4bac4d 814 @param[in] Item Pointer to the NET_MAP_ITEM.\r
3e8c18da 815 @param[in] Arg Pointer to the Arg, it's a pointer to the token to\r
8a67d61d 816 check.\r
817\r
818 @retval EFI_SUCCESS The token specified by Arg is different from the\r
819 token in Item.\r
820 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in\r
821 Item.\r
822\r
823**/\r
824EFI_STATUS\r
825MnpTokenExist (\r
779ae357 826 IN NET_MAP *Map,\r
827 IN NET_MAP_ITEM *Item,\r
828 IN VOID *Arg\r
8a67d61d 829 )\r
830{\r
831 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;\r
832 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;\r
833\r
834 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;\r
835 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
836\r
837 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {\r
838 //\r
839 // The token is the same either the two tokens equals or the Events in\r
840 // the two tokens are the same.\r
841 //\r
842 return EFI_ACCESS_DENIED;\r
843 }\r
844\r
845 return EFI_SUCCESS;\r
846}\r
847\r
8a67d61d 848/**\r
849 Cancel the token specified by Arg if it matches the token in Item.\r
850\r
6e4bac4d 851 @param[in, out] Map Pointer to the NET_MAP.\r
852 @param[in, out] Item Pointer to the NET_MAP_ITEM.\r
779ae357 853 @param[in] Arg Pointer to the Arg, it's a pointer to the\r
6e4bac4d 854 token to cancel.\r
8a67d61d 855\r
779ae357 856 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,\r
c57273b0 857 or the Arg isn't NULL, and the token in Item is\r
858 different from the Arg.\r
859 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the\r
860 Arg, and the token is cancelled.\r
8a67d61d 861\r
862**/\r
863EFI_STATUS\r
864MnpCancelTokens (\r
779ae357 865 IN OUT NET_MAP *Map,\r
866 IN OUT NET_MAP_ITEM *Item,\r
867 IN VOID *Arg\r
8a67d61d 868 )\r
869{\r
870 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;\r
871\r
872 if ((Arg != NULL) && (Item->Key != Arg)) {\r
873 //\r
874 // The token in Item is not the token specified by Arg.\r
875 //\r
876 return EFI_SUCCESS;\r
877 }\r
878\r
779ae357 879 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
8a67d61d 880\r
881 //\r
36ee91ca 882 // Remove the item from the map.\r
8a67d61d 883 //\r
36ee91ca 884 NetMapRemoveItem (Map, Item, NULL);\r
8a67d61d 885\r
886 //\r
36ee91ca 887 // Cancel this token with status set to EFI_ABORTED.\r
8a67d61d 888 //\r
36ee91ca 889 TokenToCancel->Status = EFI_ABORTED;\r
890 gBS->SignalEvent (TokenToCancel->Event);\r
8a67d61d 891\r
892 if (Arg != NULL) {\r
893 //\r
894 // Only abort the token specified by Arg if Arg isn't NULL.\r
895 //\r
896 return EFI_ABORTED;\r
897 }\r
898\r
899 return EFI_SUCCESS;\r
900}\r
901\r
902\r
903/**\r
904 Start and initialize the simple network.\r
905\r
3e8c18da 906 @param[in] Snp Pointer to the simple network protocol.\r
8a67d61d 907\r
908 @retval EFI_SUCCESS The simple network protocol is started.\r
6e4bac4d 909 @retval Others Other errors as indicated.\r
8a67d61d 910\r
911**/\r
8a67d61d 912EFI_STATUS\r
913MnpStartSnp (\r
779ae357 914 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
8a67d61d 915 )\r
916{\r
917 EFI_STATUS Status;\r
918\r
919 ASSERT (Snp != NULL);\r
920\r
921 //\r
922 // Start the simple network.\r
923 //\r
924 Status = Snp->Start (Snp);\r
925\r
926 if (!EFI_ERROR (Status)) {\r
927 //\r
928 // Initialize the simple network.\r
929 //\r
779ae357 930 Status = Snp->Initialize (Snp, 0, 0);\r
8a67d61d 931 }\r
932\r
933 return Status;\r
934}\r
935\r
936\r
937/**\r
938 Stop the simple network.\r
939\r
3e8c18da 940 @param[in] Snp Pointer to the simple network protocol.\r
8a67d61d 941\r
942 @retval EFI_SUCCESS The simple network is stopped.\r
6e4bac4d 943 @retval Others Other errors as indicated.\r
8a67d61d 944\r
945**/\r
8a67d61d 946EFI_STATUS\r
947MnpStopSnp (\r
779ae357 948 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
8a67d61d 949 )\r
950{\r
951 EFI_STATUS Status;\r
952\r
953 ASSERT (Snp != NULL);\r
954\r
955 //\r
956 // Shut down the simple network.\r
957 //\r
779ae357 958 Status = Snp->Shutdown (Snp);\r
8a67d61d 959 if (!EFI_ERROR (Status)) {\r
960 //\r
961 // Stop the simple network.\r
962 //\r
963 Status = Snp->Stop (Snp);\r
964 }\r
965\r
966 return Status;\r
967}\r
968\r
969\r
970/**\r
971 Start the managed network, this function is called when one instance is configured\r
972 or reconfigured.\r
973\r
6e4bac4d 974 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
975 @param[in] IsConfigUpdate The instance is reconfigured or it's the first\r
976 time the instanced is configured.\r
977 @param[in] EnableSystemPoll Enable the system polling or not.\r
8a67d61d 978\r
6e4bac4d 979 @retval EFI_SUCCESS The managed network is started and some\r
980 configuration is updated.\r
981 @retval Others Other errors as indicated.\r
8a67d61d 982\r
983**/\r
8a67d61d 984EFI_STATUS\r
985MnpStart (\r
779ae357 986 IN OUT MNP_SERVICE_DATA *MnpServiceData,\r
987 IN BOOLEAN IsConfigUpdate,\r
988 IN BOOLEAN EnableSystemPoll\r
8a67d61d 989 )\r
990{\r
991 EFI_STATUS Status;\r
992 EFI_TIMER_DELAY TimerOpType;\r
779ae357 993 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 994\r
995 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
996\r
779ae357 997 Status = EFI_SUCCESS;\r
998 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
8a67d61d 999\r
1000 if (!IsConfigUpdate) {\r
1001 //\r
1002 // If it's not a configuration update, increase the configured children number.\r
1003 //\r
779ae357 1004 MnpDeviceData->ConfiguredChildrenNumber++;\r
8a67d61d 1005\r
779ae357 1006 if (MnpDeviceData->ConfiguredChildrenNumber == 1) {\r
8a67d61d 1007 //\r
1008 // It's the first configured child, start the simple network.\r
1009 //\r
779ae357 1010 Status = MnpStartSnp (MnpDeviceData->Snp);\r
8a67d61d 1011 if (EFI_ERROR (Status)) {\r
e48e37fc 1012 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));\r
779ae357 1013\r
8a67d61d 1014 goto ErrorExit;\r
1015 }\r
1016\r
1017 //\r
1018 // Start the timeout timer.\r
1019 //\r
1020 Status = gBS->SetTimer (\r
779ae357 1021 MnpDeviceData->TimeoutCheckTimer,\r
8a67d61d 1022 TimerPeriodic,\r
1023 MNP_TIMEOUT_CHECK_INTERVAL\r
1024 );\r
1025 if (EFI_ERROR (Status)) {\r
e48e37fc 1026 DEBUG (\r
1027 (EFI_D_ERROR,\r
1028 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",\r
8a67d61d 1029 Status)\r
1030 );\r
779ae357 1031\r
8a67d61d 1032 goto ErrorExit;\r
1033 }\r
dd29f3ed 1034\r
1035 //\r
1036 // Start the media detection timer.\r
1037 //\r
1038 Status = gBS->SetTimer (\r
1039 MnpDeviceData->MediaDetectTimer,\r
1040 TimerPeriodic,\r
1041 MNP_MEDIA_DETECT_INTERVAL\r
1042 );\r
1043 if (EFI_ERROR (Status)) {\r
1044 DEBUG (\r
1045 (EFI_D_ERROR,\r
1046 "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n",\r
1047 Status)\r
1048 );\r
1049\r
1050 goto ErrorExit;\r
1051 }\r
8a67d61d 1052 }\r
1053 }\r
1054\r
779ae357 1055 if (MnpDeviceData->EnableSystemPoll ^ EnableSystemPoll) {\r
8a67d61d 1056 //\r
1057 // The EnableSystemPoll differs with the current state, disable or enable\r
1058 // the system poll.\r
1059 //\r
1060 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;\r
1061\r
779ae357 1062 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);\r
8a67d61d 1063 if (EFI_ERROR (Status)) {\r
e48e37fc 1064 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));\r
779ae357 1065\r
8a67d61d 1066 goto ErrorExit;\r
1067 }\r
1068\r
779ae357 1069 MnpDeviceData->EnableSystemPoll = EnableSystemPoll;\r
8a67d61d 1070 }\r
1071\r
1072 //\r
1073 // Change the receive filters if need.\r
1074 //\r
779ae357 1075 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
8a67d61d 1076\r
1077ErrorExit:\r
8a67d61d 1078 return Status;\r
1079}\r
1080\r
1081\r
1082/**\r
1083 Stop the managed network.\r
1084\r
6e4bac4d 1085 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
8a67d61d 1086\r
6e4bac4d 1087 @retval EFI_SUCCESS The managed network is stopped.\r
1088 @retval Others Other errors as indicated.\r
8a67d61d 1089\r
1090**/\r
8a67d61d 1091EFI_STATUS\r
1092MnpStop (\r
779ae357 1093 IN OUT MNP_SERVICE_DATA *MnpServiceData\r
8a67d61d 1094 )\r
1095{\r
779ae357 1096 EFI_STATUS Status;\r
1097 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1098\r
1099 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
779ae357 1100 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1101 ASSERT (MnpDeviceData->ConfiguredChildrenNumber > 0);\r
8a67d61d 1102\r
1103 //\r
1104 // Configure the receive filters.\r
1105 //\r
779ae357 1106 MnpConfigReceiveFilters (MnpDeviceData);\r
8a67d61d 1107\r
1108 //\r
1109 // Decrease the children number.\r
1110 //\r
779ae357 1111 MnpDeviceData->ConfiguredChildrenNumber--;\r
8a67d61d 1112\r
779ae357 1113 if (MnpDeviceData->ConfiguredChildrenNumber > 0) {\r
8a67d61d 1114 //\r
1115 // If there are other configured chilren, return and keep the timers and\r
1116 // simple network unchanged.\r
1117 //\r
1118 return EFI_SUCCESS;\r
1119 }\r
1120\r
1121 //\r
1122 // No configured children now.\r
1123 //\r
779ae357 1124 if (MnpDeviceData->EnableSystemPoll) {\r
8a67d61d 1125 //\r
1126 // The system poll in on, cancel the poll timer.\r
1127 //\r
779ae357 1128 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerCancel, 0);\r
1129 MnpDeviceData->EnableSystemPoll = FALSE;\r
8a67d61d 1130 }\r
1131\r
1132 //\r
1133 // Cancel the timeout timer.\r
1134 //\r
779ae357 1135 Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0);\r
8a67d61d 1136\r
dd29f3ed 1137 //\r
1138 // Cancel the media detect timer.\r
1139 //\r
1140 Status = gBS->SetTimer (MnpDeviceData->MediaDetectTimer, TimerCancel, 0);\r
1141\r
8a67d61d 1142 //\r
1143 // Stop the simple network.\r
1144 //\r
779ae357 1145 Status = MnpStopSnp (MnpDeviceData->Snp);\r
8a67d61d 1146 return Status;\r
1147}\r
1148\r
1149\r
1150/**\r
1151 Flush the instance's received data.\r
1152\r
6e4bac4d 1153 @param[in, out] Instance Pointer to the mnp instance context data.\r
8a67d61d 1154\r
8a67d61d 1155**/\r
1156VOID\r
1157MnpFlushRcvdDataQueue (\r
779ae357 1158 IN OUT MNP_INSTANCE_DATA *Instance\r
8a67d61d 1159 )\r
1160{\r
779ae357 1161 EFI_TPL OldTpl;\r
8a67d61d 1162 MNP_RXDATA_WRAP *RxDataWrap;\r
1163\r
1164 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1165\r
e48e37fc 1166 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 1167\r
e48e37fc 1168 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {\r
8a67d61d 1169 //\r
1170 // Remove all the Wraps.\r
1171 //\r
1172 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);\r
1173\r
1174 //\r
1175 // Recycle the RxDataWrap.\r
1176 //\r
1177 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);\r
1178 Instance->RcvdPacketQueueSize--;\r
1179 }\r
1180\r
1181 ASSERT (Instance->RcvdPacketQueueSize == 0);\r
1182\r
e48e37fc 1183 gBS->RestoreTPL (OldTpl);\r
8a67d61d 1184}\r
1185\r
1186\r
1187/**\r
1188 Configure the Instance using ConfigData.\r
1189\r
6e4bac4d 1190 @param[in, out] Instance Pointer to the mnp instance context data.\r
1191 @param[in] ConfigData Pointer to the configuration data used to configure\r
8a67d61d 1192 the isntance.\r
1193\r
1194 @retval EFI_SUCCESS The Instance is configured.\r
1195 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the\r
1196 implementation doesn't support it.\r
6e4bac4d 1197 @retval Others Other errors as indicated.\r
8a67d61d 1198\r
1199**/\r
1200EFI_STATUS\r
1201MnpConfigureInstance (\r
779ae357 1202 IN OUT MNP_INSTANCE_DATA *Instance,\r
1203 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL\r
8a67d61d 1204 )\r
1205{\r
1206 EFI_STATUS Status;\r
1207 MNP_SERVICE_DATA *MnpServiceData;\r
779ae357 1208 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1209 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;\r
1210 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;\r
1211 BOOLEAN IsConfigUpdate;\r
1212\r
1213 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1214\r
1215 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {\r
1216 //\r
1217 // Don't support timestamp.\r
1218 //\r
1219 return EFI_UNSUPPORTED;\r
1220 }\r
1221\r
1222 Status = EFI_SUCCESS;\r
1223\r
1224 MnpServiceData = Instance->MnpServiceData;\r
779ae357 1225 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1226 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1227\r
1228 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));\r
1229\r
1230 OldConfigData = &Instance->ConfigData;\r
1231 NewConfigData = ConfigData;\r
1232 if (NewConfigData == NULL) {\r
1233 //\r
1234 // Restore back the default config data if a reset of this instance\r
1235 // is required.\r
1236 //\r
1237 NewConfigData = &mMnpDefaultConfigData;\r
1238 }\r
1239\r
1240 //\r
1241 // Reset the instance's receive filter.\r
1242 //\r
1243 Instance->ReceiveFilter = 0;\r
1244\r
1245 //\r
1246 // Clear the receive counters according to the old ConfigData.\r
1247 //\r
1248 if (OldConfigData->EnableUnicastReceive) {\r
779ae357 1249 MnpDeviceData->UnicastCount--;\r
8a67d61d 1250 }\r
1251\r
1252 if (OldConfigData->EnableMulticastReceive) {\r
779ae357 1253 MnpDeviceData->MulticastCount--;\r
8a67d61d 1254 }\r
1255\r
1256 if (OldConfigData->EnableBroadcastReceive) {\r
779ae357 1257 MnpDeviceData->BroadcastCount--;\r
8a67d61d 1258 }\r
1259\r
1260 if (OldConfigData->EnablePromiscuousReceive) {\r
779ae357 1261 MnpDeviceData->PromiscuousCount--;\r
8a67d61d 1262 }\r
1263\r
1264 //\r
1265 // Set the receive filter counters and the receive filter of the\r
1266 // instance according to the new ConfigData.\r
1267 //\r
1268 if (NewConfigData->EnableUnicastReceive) {\r
779ae357 1269 MnpDeviceData->UnicastCount++;\r
8a67d61d 1270 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;\r
1271 }\r
1272\r
1273 if (NewConfigData->EnableMulticastReceive) {\r
779ae357 1274 MnpDeviceData->MulticastCount++;\r
8a67d61d 1275 }\r
1276\r
1277 if (NewConfigData->EnableBroadcastReceive) {\r
779ae357 1278 MnpDeviceData->BroadcastCount++;\r
8a67d61d 1279 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;\r
1280 }\r
1281\r
1282 if (NewConfigData->EnablePromiscuousReceive) {\r
779ae357 1283 MnpDeviceData->PromiscuousCount++;\r
8a67d61d 1284 }\r
1285\r
1286 if (OldConfigData->FlushQueuesOnReset) {\r
8a67d61d 1287 MnpFlushRcvdDataQueue (Instance);\r
1288 }\r
1289\r
1290 if (ConfigData == NULL) {\r
36ee91ca 1291 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);\r
8a67d61d 1292 }\r
1293\r
1294 if (!NewConfigData->EnableMulticastReceive) {\r
8a67d61d 1295 MnpGroupOp (Instance, FALSE, NULL, NULL);\r
1296 }\r
1297\r
1298 //\r
1299 // Save the new configuration data.\r
1300 //\r
687a2e5f 1301 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));\r
8a67d61d 1302\r
779ae357 1303 Instance->Configured = (BOOLEAN) (ConfigData != NULL);\r
8a67d61d 1304 if (Instance->Configured) {\r
1305 //\r
1306 // The instance is configured, start the Mnp.\r
1307 //\r
1308 Status = MnpStart (\r
1309 MnpServiceData,\r
1310 IsConfigUpdate,\r
4eb65aff 1311 (BOOLEAN) !NewConfigData->DisableBackgroundPolling\r
8a67d61d 1312 );\r
1313 } else {\r
1314 //\r
1315 // The instance is changed to the unconfigured state, stop the Mnp.\r
1316 //\r
1317 Status = MnpStop (MnpServiceData);\r
1318 }\r
1319\r
1320 return Status;\r
1321}\r
1322\r
aeddd425 1323/**\r
1324 Configure the Snp receive filters according to the instances' receive filter\r
1325 settings.\r
1326\r
779ae357 1327 @param[in] MnpDeviceData Pointer to the mnp device context data.\r
aeddd425 1328\r
1329 @retval EFI_SUCCESS The receive filters is configured.\r
779ae357 1330 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due\r
aeddd425 1331 to lack of memory resource.\r
1332\r
1333**/\r
1334EFI_STATUS\r
1335MnpConfigReceiveFilters (\r
779ae357 1336 IN MNP_DEVICE_DATA *MnpDeviceData\r
aeddd425 1337 )\r
1338{\r
1339 EFI_STATUS Status;\r
1340 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
1341 EFI_MAC_ADDRESS *MCastFilter;\r
1342 UINT32 MCastFilterCnt;\r
1343 UINT32 EnableFilterBits;\r
1344 UINT32 DisableFilterBits;\r
1345 BOOLEAN ResetMCastFilters;\r
1346 LIST_ENTRY *Entry;\r
1347 UINT32 Index;\r
1348 MNP_GROUP_ADDRESS *GroupAddress;\r
1349\r
779ae357 1350 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
aeddd425 1351\r
779ae357 1352 Snp = MnpDeviceData->Snp;\r
aeddd425 1353\r
1354 //\r
1355 // Initialize the enable filter and disable filter.\r
1356 //\r
1357 EnableFilterBits = 0;\r
1358 DisableFilterBits = Snp->Mode->ReceiveFilterMask;\r
1359\r
779ae357 1360 if (MnpDeviceData->UnicastCount != 0) {\r
aeddd425 1361 //\r
1362 // Enable unicast if any instance wants to receive unicast.\r
1363 //\r
1364 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
1365 }\r
1366\r
779ae357 1367 if (MnpDeviceData->BroadcastCount != 0) {\r
aeddd425 1368 //\r
1369 // Enable broadcast if any instance wants to receive broadcast.\r
1370 //\r
1371 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
1372 }\r
1373\r
1374 MCastFilter = NULL;\r
1375 MCastFilterCnt = 0;\r
1376 ResetMCastFilters = TRUE;\r
1377\r
779ae357 1378 if ((MnpDeviceData->MulticastCount != 0) && (MnpDeviceData->GroupAddressCount != 0)) {\r
aeddd425 1379 //\r
1380 // There are instances configured to receive multicast and already some group\r
1381 // addresses are joined.\r
1382 //\r
1383\r
1384 ResetMCastFilters = FALSE;\r
1385\r
779ae357 1386 if (MnpDeviceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {\r
aeddd425 1387 //\r
1388 // The joind group address is less than simple network's maximum count.\r
1389 // Just configure the snp to do the multicast filtering.\r
1390 //\r
1391\r
1392 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
1393\r
1394 //\r
1395 // Allocate pool for the mulicast addresses.\r
1396 //\r
779ae357 1397 MCastFilterCnt = MnpDeviceData->GroupAddressCount;\r
aeddd425 1398 MCastFilter = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);\r
1399 if (MCastFilter == NULL) {\r
aeddd425 1400 DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));\r
779ae357 1401\r
aeddd425 1402 return EFI_OUT_OF_RESOURCES;\r
1403 }\r
1404\r
1405 //\r
1406 // Fill the multicast HW address buffer.\r
1407 //\r
1408 Index = 0;\r
779ae357 1409 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
aeddd425 1410\r
779ae357 1411 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
aeddd425 1412 CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));\r
1413 Index++;\r
1414\r
1415 ASSERT (Index <= MCastFilterCnt);\r
1416 }\r
1417 } else {\r
1418 //\r
1419 // The maximum multicast is reached, set the filter to be promiscuous\r
1420 // multicast.\r
1421 //\r
1422\r
1423 if ((Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {\r
1424 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
1425 } else {\r
1426 //\r
1427 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,\r
1428 // set the NIC to be promiscuous although this will tremendously degrade\r
1429 // the performance.\r
1430 //\r
1431 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
1432 }\r
1433 }\r
1434 }\r
1435\r
779ae357 1436 if (MnpDeviceData->PromiscuousCount != 0) {\r
aeddd425 1437 //\r
1438 // Enable promiscuous if any instance wants to receive promiscuous.\r
1439 //\r
1440 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
1441 }\r
1442\r
1443 //\r
1444 // Set the disable filter.\r
1445 //\r
1446 DisableFilterBits ^= EnableFilterBits;\r
1447\r
1448 //\r
1449 // Configure the receive filters of SNP.\r
1450 //\r
1451 Status = Snp->ReceiveFilters (\r
1452 Snp,\r
1453 EnableFilterBits,\r
1454 DisableFilterBits,\r
1455 ResetMCastFilters,\r
1456 MCastFilterCnt,\r
1457 MCastFilter\r
1458 );\r
1459 DEBUG_CODE (\r
1460 if (EFI_ERROR (Status)) {\r
779ae357 1461 DEBUG (\r
1462 (EFI_D_ERROR,\r
1463 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",\r
1464 Status)\r
1465 );\r
1466 }\r
aeddd425 1467 );\r
1468\r
1469 if (MCastFilter != NULL) {\r
1470 //\r
1471 // Free the buffer used to hold the group addresses.\r
1472 //\r
766c7483 1473 FreePool (MCastFilter);\r
aeddd425 1474 }\r
1475\r
1476 return Status;\r
1477}\r
8a67d61d 1478\r
8a67d61d 1479\r
1480/**\r
1481 Add a group address control block which controls the MacAddress for\r
1482 this instance.\r
1483\r
6e4bac4d 1484 @param[in, out] Instance Pointer to the mnp instance context data.\r
1485 @param[in, out] CtrlBlk Pointer to the group address control block.\r
1486 @param[in, out] GroupAddress Pointer to the group adress.\r
1487 @param[in] MacAddress Pointer to the mac address.\r
1488 @param[in] HwAddressSize The hardware address size.\r
8a67d61d 1489\r
6e4bac4d 1490 @retval EFI_SUCCESS The group address control block is added.\r
1491 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.\r
8a67d61d 1492\r
1493**/\r
8a67d61d 1494EFI_STATUS\r
1495MnpGroupOpAddCtrlBlk (\r
779ae357 1496 IN OUT MNP_INSTANCE_DATA *Instance,\r
1497 IN OUT MNP_GROUP_CONTROL_BLOCK *CtrlBlk,\r
1498 IN OUT MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,\r
1499 IN EFI_MAC_ADDRESS *MacAddress,\r
1500 IN UINT32 HwAddressSize\r
8a67d61d 1501 )\r
1502{\r
779ae357 1503 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1504\r
1505 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1506\r
779ae357 1507 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1508 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1509\r
1510 if (GroupAddress == NULL) {\r
8a67d61d 1511 ASSERT (MacAddress != NULL);\r
1512\r
1513 //\r
1514 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.\r
1515 //\r
e48e37fc 1516 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));\r
8a67d61d 1517 if (GroupAddress == NULL) {\r
1518\r
e48e37fc 1519 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));\r
8a67d61d 1520\r
1521 return EFI_OUT_OF_RESOURCES;\r
1522 }\r
1523\r
687a2e5f 1524 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));\r
779ae357 1525 GroupAddress->RefCnt = 0;\r
e48e37fc 1526 InsertTailList (\r
779ae357 1527 &MnpDeviceData->GroupAddressList,\r
8a67d61d 1528 &GroupAddress->AddrEntry\r
1529 );\r
779ae357 1530 MnpDeviceData->GroupAddressCount++;\r
8a67d61d 1531 }\r
1532\r
1533 //\r
1534 // Increase the RefCnt.\r
1535 //\r
1536 GroupAddress->RefCnt++;\r
1537\r
1538 //\r
1539 // Add the CtrlBlk into the instance's GroupCtrlBlkList.\r
1540 //\r
1541 CtrlBlk->GroupAddress = GroupAddress;\r
e48e37fc 1542 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);\r
8a67d61d 1543\r
1544 return EFI_SUCCESS;\r
1545}\r
1546\r
1547\r
1548/**\r
1549 Delete a group control block from the instance. If the controlled group address's\r
1550 reference count reaches zero, the group address is removed too.\r
1551\r
3e8c18da 1552 @param[in] Instance Pointer to the instance context data.\r
1553 @param[in] CtrlBlk Pointer to the group control block to delete.\r
8a67d61d 1554\r
1555 @return The group address controlled by the control block is no longer used or not.\r
1556\r
1557**/\r
8a67d61d 1558BOOLEAN\r
1559MnpGroupOpDelCtrlBlk (\r
779ae357 1560 IN MNP_INSTANCE_DATA *Instance,\r
1561 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk\r
8a67d61d 1562 )\r
1563{\r
779ae357 1564 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1565 MNP_GROUP_ADDRESS *GroupAddress;\r
1566\r
1567 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1568\r
779ae357 1569 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1570 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1571\r
1572 //\r
1573 // Remove and free the CtrlBlk.\r
1574 //\r
1575 GroupAddress = CtrlBlk->GroupAddress;\r
e48e37fc 1576 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);\r
766c7483 1577 FreePool (CtrlBlk);\r
8a67d61d 1578\r
1579 ASSERT (GroupAddress->RefCnt > 0);\r
1580\r
1581 //\r
1582 // Count down the RefCnt.\r
1583 //\r
1584 GroupAddress->RefCnt--;\r
1585\r
1586 if (GroupAddress->RefCnt == 0) {\r
1587 //\r
1588 // Free this GroupAddress entry if no instance uses it.\r
1589 //\r
779ae357 1590 MnpDeviceData->GroupAddressCount--;\r
e48e37fc 1591 RemoveEntryList (&GroupAddress->AddrEntry);\r
766c7483 1592 FreePool (GroupAddress);\r
8a67d61d 1593\r
1594 return TRUE;\r
1595 }\r
1596\r
1597 return FALSE;\r
1598}\r
1599\r
1600\r
1601/**\r
1602 Do the group operations for this instance.\r
1603\r
6e4bac4d 1604 @param[in, out] Instance Pointer to the instance context data.\r
779ae357 1605 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to\r
6e4bac4d 1606 leave a group/groups.\r
1607 @param[in] MacAddress Pointer to the group address to join or leave.\r
779ae357 1608 @param[in] CtrlBlk Pointer to the group control block if JoinFlag\r
6e4bac4d 1609 is FALSE.\r
8a67d61d 1610\r
6e4bac4d 1611 @retval EFI_SUCCESS The group operation finished.\r
1612 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.\r
1613 @retval Others Other errors as indicated.\r
8a67d61d 1614\r
1615**/\r
1616EFI_STATUS\r
1617MnpGroupOp (\r
779ae357 1618 IN OUT MNP_INSTANCE_DATA *Instance,\r
1619 IN BOOLEAN JoinFlag,\r
1620 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,\r
1621 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL\r
8a67d61d 1622 )\r
1623{\r
779ae357 1624 MNP_DEVICE_DATA *MnpDeviceData;\r
e48e37fc 1625 LIST_ENTRY *Entry;\r
1626 LIST_ENTRY *NextEntry;\r
8a67d61d 1627 MNP_GROUP_ADDRESS *GroupAddress;\r
1628 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
1629 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;\r
1630 EFI_STATUS Status;\r
1631 BOOLEAN AddressExist;\r
1632 BOOLEAN NeedUpdate;\r
1633\r
1634 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1635\r
779ae357 1636 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1637 SnpMode = MnpDeviceData->Snp->Mode;\r
8a67d61d 1638\r
1639 if (JoinFlag) {\r
1640 //\r
1641 // A new gropu address is to be added.\r
1642 //\r
8a67d61d 1643 GroupAddress = NULL;\r
1644 AddressExist = FALSE;\r
1645\r
1646 //\r
1647 // Allocate memory for the control block.\r
1648 //\r
779ae357 1649 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));\r
8a67d61d 1650 if (NewCtrlBlk == NULL) {\r
e48e37fc 1651 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));\r
779ae357 1652\r
8a67d61d 1653 return EFI_OUT_OF_RESOURCES;\r
1654 }\r
1655\r
779ae357 1656 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
8a67d61d 1657 //\r
1658 // Check whether the MacAddress is already joined by other instances.\r
1659 //\r
1660 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
779ae357 1661 if (CompareMem (MacAddress, &GroupAddress->Address, SnpMode->HwAddressSize) == 0) {\r
8a67d61d 1662 AddressExist = TRUE;\r
1663 break;\r
1664 }\r
1665 }\r
1666\r
1667 if (!AddressExist) {\r
1668 GroupAddress = NULL;\r
1669 }\r
1670\r
1671 //\r
1672 // Add the GroupAddress for this instance.\r
1673 //\r
1674 Status = MnpGroupOpAddCtrlBlk (\r
1675 Instance,\r
1676 NewCtrlBlk,\r
1677 GroupAddress,\r
1678 MacAddress,\r
1679 SnpMode->HwAddressSize\r
1680 );\r
1681 if (EFI_ERROR (Status)) {\r
8a67d61d 1682 return Status;\r
1683 }\r
1684\r
1685 NeedUpdate = TRUE;\r
1686 } else {\r
8a67d61d 1687 if (MacAddress != NULL) {\r
8a67d61d 1688 ASSERT (CtrlBlk != NULL);\r
1689\r
1690 //\r
1691 // Leave the specific multicast mac address.\r
1692 //\r
1693 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);\r
1694 } else {\r
1695 //\r
1696 // Leave all multicast mac addresses.\r
1697 //\r
1698 NeedUpdate = FALSE;\r
1699\r
1700 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {\r
1701\r
1702 NewCtrlBlk = NET_LIST_USER_STRUCT (\r
1703 Entry,\r
1704 MNP_GROUP_CONTROL_BLOCK,\r
1705 CtrlBlkEntry\r
1706 );\r
1707 //\r
1708 // Update is required if the group address left is no longer used\r
1709 // by other instances.\r
1710 //\r
1711 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);\r
1712 }\r
1713 }\r
1714 }\r
1715\r
1716 Status = EFI_SUCCESS;\r
1717\r
1718 if (NeedUpdate) {\r
1719 //\r
1720 // Reconfigure the receive filters if necessary.\r
1721 //\r
779ae357 1722 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
8a67d61d 1723 }\r
1724\r
1725 return Status;\r
1726}\r