]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
Fixed GCC 4.4 build issues due to EFIAPI not being used when required.
[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
e798cd87 825EFIAPI\r
8a67d61d 826MnpTokenExist (\r
779ae357 827 IN NET_MAP *Map,\r
828 IN NET_MAP_ITEM *Item,\r
829 IN VOID *Arg\r
8a67d61d 830 )\r
831{\r
832 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;\r
833 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;\r
834\r
835 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;\r
836 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
837\r
838 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {\r
839 //\r
840 // The token is the same either the two tokens equals or the Events in\r
841 // the two tokens are the same.\r
842 //\r
843 return EFI_ACCESS_DENIED;\r
844 }\r
845\r
846 return EFI_SUCCESS;\r
847}\r
848\r
8a67d61d 849/**\r
850 Cancel the token specified by Arg if it matches the token in Item.\r
851\r
6e4bac4d 852 @param[in, out] Map Pointer to the NET_MAP.\r
853 @param[in, out] Item Pointer to the NET_MAP_ITEM.\r
779ae357 854 @param[in] Arg Pointer to the Arg, it's a pointer to the\r
6e4bac4d 855 token to cancel.\r
8a67d61d 856\r
779ae357 857 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,\r
c57273b0 858 or the Arg isn't NULL, and the token in Item is\r
859 different from the Arg.\r
860 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the\r
861 Arg, and the token is cancelled.\r
8a67d61d 862\r
863**/\r
864EFI_STATUS\r
e798cd87 865EFIAPI\r
8a67d61d 866MnpCancelTokens (\r
779ae357 867 IN OUT NET_MAP *Map,\r
868 IN OUT NET_MAP_ITEM *Item,\r
869 IN VOID *Arg\r
8a67d61d 870 )\r
871{\r
872 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;\r
873\r
874 if ((Arg != NULL) && (Item->Key != Arg)) {\r
875 //\r
876 // The token in Item is not the token specified by Arg.\r
877 //\r
878 return EFI_SUCCESS;\r
879 }\r
880\r
779ae357 881 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
8a67d61d 882\r
883 //\r
36ee91ca 884 // Remove the item from the map.\r
8a67d61d 885 //\r
36ee91ca 886 NetMapRemoveItem (Map, Item, NULL);\r
8a67d61d 887\r
888 //\r
36ee91ca 889 // Cancel this token with status set to EFI_ABORTED.\r
8a67d61d 890 //\r
36ee91ca 891 TokenToCancel->Status = EFI_ABORTED;\r
892 gBS->SignalEvent (TokenToCancel->Event);\r
8a67d61d 893\r
894 if (Arg != NULL) {\r
895 //\r
896 // Only abort the token specified by Arg if Arg isn't NULL.\r
897 //\r
898 return EFI_ABORTED;\r
899 }\r
900\r
901 return EFI_SUCCESS;\r
902}\r
903\r
904\r
905/**\r
906 Start and initialize the simple network.\r
907\r
3e8c18da 908 @param[in] Snp Pointer to the simple network protocol.\r
8a67d61d 909\r
910 @retval EFI_SUCCESS The simple network protocol is started.\r
6e4bac4d 911 @retval Others Other errors as indicated.\r
8a67d61d 912\r
913**/\r
8a67d61d 914EFI_STATUS\r
915MnpStartSnp (\r
779ae357 916 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
8a67d61d 917 )\r
918{\r
919 EFI_STATUS Status;\r
920\r
921 ASSERT (Snp != NULL);\r
922\r
923 //\r
924 // Start the simple network.\r
925 //\r
926 Status = Snp->Start (Snp);\r
927\r
928 if (!EFI_ERROR (Status)) {\r
929 //\r
930 // Initialize the simple network.\r
931 //\r
779ae357 932 Status = Snp->Initialize (Snp, 0, 0);\r
8a67d61d 933 }\r
934\r
935 return Status;\r
936}\r
937\r
938\r
939/**\r
940 Stop the simple network.\r
941\r
3e8c18da 942 @param[in] Snp Pointer to the simple network protocol.\r
8a67d61d 943\r
944 @retval EFI_SUCCESS The simple network is stopped.\r
6e4bac4d 945 @retval Others Other errors as indicated.\r
8a67d61d 946\r
947**/\r
8a67d61d 948EFI_STATUS\r
949MnpStopSnp (\r
779ae357 950 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
8a67d61d 951 )\r
952{\r
953 EFI_STATUS Status;\r
954\r
955 ASSERT (Snp != NULL);\r
956\r
957 //\r
958 // Shut down the simple network.\r
959 //\r
779ae357 960 Status = Snp->Shutdown (Snp);\r
8a67d61d 961 if (!EFI_ERROR (Status)) {\r
962 //\r
963 // Stop the simple network.\r
964 //\r
965 Status = Snp->Stop (Snp);\r
966 }\r
967\r
968 return Status;\r
969}\r
970\r
971\r
972/**\r
973 Start the managed network, this function is called when one instance is configured\r
974 or reconfigured.\r
975\r
6e4bac4d 976 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
977 @param[in] IsConfigUpdate The instance is reconfigured or it's the first\r
978 time the instanced is configured.\r
979 @param[in] EnableSystemPoll Enable the system polling or not.\r
8a67d61d 980\r
6e4bac4d 981 @retval EFI_SUCCESS The managed network is started and some\r
982 configuration is updated.\r
983 @retval Others Other errors as indicated.\r
8a67d61d 984\r
985**/\r
8a67d61d 986EFI_STATUS\r
987MnpStart (\r
779ae357 988 IN OUT MNP_SERVICE_DATA *MnpServiceData,\r
989 IN BOOLEAN IsConfigUpdate,\r
990 IN BOOLEAN EnableSystemPoll\r
8a67d61d 991 )\r
992{\r
993 EFI_STATUS Status;\r
994 EFI_TIMER_DELAY TimerOpType;\r
779ae357 995 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 996\r
997 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
998\r
779ae357 999 Status = EFI_SUCCESS;\r
1000 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
8a67d61d 1001\r
1002 if (!IsConfigUpdate) {\r
1003 //\r
1004 // If it's not a configuration update, increase the configured children number.\r
1005 //\r
779ae357 1006 MnpDeviceData->ConfiguredChildrenNumber++;\r
8a67d61d 1007\r
779ae357 1008 if (MnpDeviceData->ConfiguredChildrenNumber == 1) {\r
8a67d61d 1009 //\r
1010 // It's the first configured child, start the simple network.\r
1011 //\r
779ae357 1012 Status = MnpStartSnp (MnpDeviceData->Snp);\r
8a67d61d 1013 if (EFI_ERROR (Status)) {\r
e48e37fc 1014 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));\r
779ae357 1015\r
8a67d61d 1016 goto ErrorExit;\r
1017 }\r
1018\r
1019 //\r
1020 // Start the timeout timer.\r
1021 //\r
1022 Status = gBS->SetTimer (\r
779ae357 1023 MnpDeviceData->TimeoutCheckTimer,\r
8a67d61d 1024 TimerPeriodic,\r
1025 MNP_TIMEOUT_CHECK_INTERVAL\r
1026 );\r
1027 if (EFI_ERROR (Status)) {\r
e48e37fc 1028 DEBUG (\r
1029 (EFI_D_ERROR,\r
1030 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",\r
8a67d61d 1031 Status)\r
1032 );\r
779ae357 1033\r
8a67d61d 1034 goto ErrorExit;\r
1035 }\r
dd29f3ed 1036\r
1037 //\r
1038 // Start the media detection timer.\r
1039 //\r
1040 Status = gBS->SetTimer (\r
1041 MnpDeviceData->MediaDetectTimer,\r
1042 TimerPeriodic,\r
1043 MNP_MEDIA_DETECT_INTERVAL\r
1044 );\r
1045 if (EFI_ERROR (Status)) {\r
1046 DEBUG (\r
1047 (EFI_D_ERROR,\r
1048 "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n",\r
1049 Status)\r
1050 );\r
1051\r
1052 goto ErrorExit;\r
1053 }\r
8a67d61d 1054 }\r
1055 }\r
1056\r
779ae357 1057 if (MnpDeviceData->EnableSystemPoll ^ EnableSystemPoll) {\r
8a67d61d 1058 //\r
1059 // The EnableSystemPoll differs with the current state, disable or enable\r
1060 // the system poll.\r
1061 //\r
1062 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;\r
1063\r
779ae357 1064 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);\r
8a67d61d 1065 if (EFI_ERROR (Status)) {\r
e48e37fc 1066 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));\r
779ae357 1067\r
8a67d61d 1068 goto ErrorExit;\r
1069 }\r
1070\r
779ae357 1071 MnpDeviceData->EnableSystemPoll = EnableSystemPoll;\r
8a67d61d 1072 }\r
1073\r
1074 //\r
1075 // Change the receive filters if need.\r
1076 //\r
779ae357 1077 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
8a67d61d 1078\r
1079ErrorExit:\r
8a67d61d 1080 return Status;\r
1081}\r
1082\r
1083\r
1084/**\r
1085 Stop the managed network.\r
1086\r
6e4bac4d 1087 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
8a67d61d 1088\r
6e4bac4d 1089 @retval EFI_SUCCESS The managed network is stopped.\r
1090 @retval Others Other errors as indicated.\r
8a67d61d 1091\r
1092**/\r
8a67d61d 1093EFI_STATUS\r
1094MnpStop (\r
779ae357 1095 IN OUT MNP_SERVICE_DATA *MnpServiceData\r
8a67d61d 1096 )\r
1097{\r
779ae357 1098 EFI_STATUS Status;\r
1099 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1100\r
1101 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
779ae357 1102 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1103 ASSERT (MnpDeviceData->ConfiguredChildrenNumber > 0);\r
8a67d61d 1104\r
1105 //\r
1106 // Configure the receive filters.\r
1107 //\r
779ae357 1108 MnpConfigReceiveFilters (MnpDeviceData);\r
8a67d61d 1109\r
1110 //\r
1111 // Decrease the children number.\r
1112 //\r
779ae357 1113 MnpDeviceData->ConfiguredChildrenNumber--;\r
8a67d61d 1114\r
779ae357 1115 if (MnpDeviceData->ConfiguredChildrenNumber > 0) {\r
8a67d61d 1116 //\r
1117 // If there are other configured chilren, return and keep the timers and\r
1118 // simple network unchanged.\r
1119 //\r
1120 return EFI_SUCCESS;\r
1121 }\r
1122\r
1123 //\r
1124 // No configured children now.\r
1125 //\r
779ae357 1126 if (MnpDeviceData->EnableSystemPoll) {\r
8a67d61d 1127 //\r
1128 // The system poll in on, cancel the poll timer.\r
1129 //\r
779ae357 1130 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerCancel, 0);\r
1131 MnpDeviceData->EnableSystemPoll = FALSE;\r
8a67d61d 1132 }\r
1133\r
1134 //\r
1135 // Cancel the timeout timer.\r
1136 //\r
779ae357 1137 Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0);\r
8a67d61d 1138\r
dd29f3ed 1139 //\r
1140 // Cancel the media detect timer.\r
1141 //\r
1142 Status = gBS->SetTimer (MnpDeviceData->MediaDetectTimer, TimerCancel, 0);\r
1143\r
8a67d61d 1144 //\r
1145 // Stop the simple network.\r
1146 //\r
779ae357 1147 Status = MnpStopSnp (MnpDeviceData->Snp);\r
8a67d61d 1148 return Status;\r
1149}\r
1150\r
1151\r
1152/**\r
1153 Flush the instance's received data.\r
1154\r
6e4bac4d 1155 @param[in, out] Instance Pointer to the mnp instance context data.\r
8a67d61d 1156\r
8a67d61d 1157**/\r
1158VOID\r
1159MnpFlushRcvdDataQueue (\r
779ae357 1160 IN OUT MNP_INSTANCE_DATA *Instance\r
8a67d61d 1161 )\r
1162{\r
779ae357 1163 EFI_TPL OldTpl;\r
8a67d61d 1164 MNP_RXDATA_WRAP *RxDataWrap;\r
1165\r
1166 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1167\r
e48e37fc 1168 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 1169\r
e48e37fc 1170 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {\r
8a67d61d 1171 //\r
1172 // Remove all the Wraps.\r
1173 //\r
1174 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);\r
1175\r
1176 //\r
1177 // Recycle the RxDataWrap.\r
1178 //\r
1179 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);\r
1180 Instance->RcvdPacketQueueSize--;\r
1181 }\r
1182\r
1183 ASSERT (Instance->RcvdPacketQueueSize == 0);\r
1184\r
e48e37fc 1185 gBS->RestoreTPL (OldTpl);\r
8a67d61d 1186}\r
1187\r
1188\r
1189/**\r
1190 Configure the Instance using ConfigData.\r
1191\r
6e4bac4d 1192 @param[in, out] Instance Pointer to the mnp instance context data.\r
1193 @param[in] ConfigData Pointer to the configuration data used to configure\r
8a67d61d 1194 the isntance.\r
1195\r
1196 @retval EFI_SUCCESS The Instance is configured.\r
1197 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the\r
1198 implementation doesn't support it.\r
6e4bac4d 1199 @retval Others Other errors as indicated.\r
8a67d61d 1200\r
1201**/\r
1202EFI_STATUS\r
1203MnpConfigureInstance (\r
779ae357 1204 IN OUT MNP_INSTANCE_DATA *Instance,\r
1205 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL\r
8a67d61d 1206 )\r
1207{\r
1208 EFI_STATUS Status;\r
1209 MNP_SERVICE_DATA *MnpServiceData;\r
779ae357 1210 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1211 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;\r
1212 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;\r
1213 BOOLEAN IsConfigUpdate;\r
1214\r
1215 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1216\r
1217 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {\r
1218 //\r
1219 // Don't support timestamp.\r
1220 //\r
1221 return EFI_UNSUPPORTED;\r
1222 }\r
1223\r
1224 Status = EFI_SUCCESS;\r
1225\r
1226 MnpServiceData = Instance->MnpServiceData;\r
779ae357 1227 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1228 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1229\r
1230 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));\r
1231\r
1232 OldConfigData = &Instance->ConfigData;\r
1233 NewConfigData = ConfigData;\r
1234 if (NewConfigData == NULL) {\r
1235 //\r
1236 // Restore back the default config data if a reset of this instance\r
1237 // is required.\r
1238 //\r
1239 NewConfigData = &mMnpDefaultConfigData;\r
1240 }\r
1241\r
1242 //\r
1243 // Reset the instance's receive filter.\r
1244 //\r
1245 Instance->ReceiveFilter = 0;\r
1246\r
1247 //\r
1248 // Clear the receive counters according to the old ConfigData.\r
1249 //\r
1250 if (OldConfigData->EnableUnicastReceive) {\r
779ae357 1251 MnpDeviceData->UnicastCount--;\r
8a67d61d 1252 }\r
1253\r
1254 if (OldConfigData->EnableMulticastReceive) {\r
779ae357 1255 MnpDeviceData->MulticastCount--;\r
8a67d61d 1256 }\r
1257\r
1258 if (OldConfigData->EnableBroadcastReceive) {\r
779ae357 1259 MnpDeviceData->BroadcastCount--;\r
8a67d61d 1260 }\r
1261\r
1262 if (OldConfigData->EnablePromiscuousReceive) {\r
779ae357 1263 MnpDeviceData->PromiscuousCount--;\r
8a67d61d 1264 }\r
1265\r
1266 //\r
1267 // Set the receive filter counters and the receive filter of the\r
1268 // instance according to the new ConfigData.\r
1269 //\r
1270 if (NewConfigData->EnableUnicastReceive) {\r
779ae357 1271 MnpDeviceData->UnicastCount++;\r
8a67d61d 1272 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;\r
1273 }\r
1274\r
1275 if (NewConfigData->EnableMulticastReceive) {\r
779ae357 1276 MnpDeviceData->MulticastCount++;\r
8a67d61d 1277 }\r
1278\r
1279 if (NewConfigData->EnableBroadcastReceive) {\r
779ae357 1280 MnpDeviceData->BroadcastCount++;\r
8a67d61d 1281 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;\r
1282 }\r
1283\r
1284 if (NewConfigData->EnablePromiscuousReceive) {\r
779ae357 1285 MnpDeviceData->PromiscuousCount++;\r
8a67d61d 1286 }\r
1287\r
1288 if (OldConfigData->FlushQueuesOnReset) {\r
8a67d61d 1289 MnpFlushRcvdDataQueue (Instance);\r
1290 }\r
1291\r
1292 if (ConfigData == NULL) {\r
36ee91ca 1293 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);\r
8a67d61d 1294 }\r
1295\r
1296 if (!NewConfigData->EnableMulticastReceive) {\r
8a67d61d 1297 MnpGroupOp (Instance, FALSE, NULL, NULL);\r
1298 }\r
1299\r
1300 //\r
1301 // Save the new configuration data.\r
1302 //\r
687a2e5f 1303 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));\r
8a67d61d 1304\r
779ae357 1305 Instance->Configured = (BOOLEAN) (ConfigData != NULL);\r
8a67d61d 1306 if (Instance->Configured) {\r
1307 //\r
1308 // The instance is configured, start the Mnp.\r
1309 //\r
1310 Status = MnpStart (\r
1311 MnpServiceData,\r
1312 IsConfigUpdate,\r
4eb65aff 1313 (BOOLEAN) !NewConfigData->DisableBackgroundPolling\r
8a67d61d 1314 );\r
1315 } else {\r
1316 //\r
1317 // The instance is changed to the unconfigured state, stop the Mnp.\r
1318 //\r
1319 Status = MnpStop (MnpServiceData);\r
1320 }\r
1321\r
1322 return Status;\r
1323}\r
1324\r
aeddd425 1325/**\r
1326 Configure the Snp receive filters according to the instances' receive filter\r
1327 settings.\r
1328\r
779ae357 1329 @param[in] MnpDeviceData Pointer to the mnp device context data.\r
aeddd425 1330\r
1331 @retval EFI_SUCCESS The receive filters is configured.\r
779ae357 1332 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due\r
aeddd425 1333 to lack of memory resource.\r
1334\r
1335**/\r
1336EFI_STATUS\r
1337MnpConfigReceiveFilters (\r
779ae357 1338 IN MNP_DEVICE_DATA *MnpDeviceData\r
aeddd425 1339 )\r
1340{\r
1341 EFI_STATUS Status;\r
1342 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
1343 EFI_MAC_ADDRESS *MCastFilter;\r
1344 UINT32 MCastFilterCnt;\r
1345 UINT32 EnableFilterBits;\r
1346 UINT32 DisableFilterBits;\r
1347 BOOLEAN ResetMCastFilters;\r
1348 LIST_ENTRY *Entry;\r
1349 UINT32 Index;\r
1350 MNP_GROUP_ADDRESS *GroupAddress;\r
1351\r
779ae357 1352 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
aeddd425 1353\r
779ae357 1354 Snp = MnpDeviceData->Snp;\r
aeddd425 1355\r
1356 //\r
1357 // Initialize the enable filter and disable filter.\r
1358 //\r
1359 EnableFilterBits = 0;\r
1360 DisableFilterBits = Snp->Mode->ReceiveFilterMask;\r
1361\r
779ae357 1362 if (MnpDeviceData->UnicastCount != 0) {\r
aeddd425 1363 //\r
1364 // Enable unicast if any instance wants to receive unicast.\r
1365 //\r
1366 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
1367 }\r
1368\r
779ae357 1369 if (MnpDeviceData->BroadcastCount != 0) {\r
aeddd425 1370 //\r
1371 // Enable broadcast if any instance wants to receive broadcast.\r
1372 //\r
1373 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
1374 }\r
1375\r
1376 MCastFilter = NULL;\r
1377 MCastFilterCnt = 0;\r
1378 ResetMCastFilters = TRUE;\r
1379\r
779ae357 1380 if ((MnpDeviceData->MulticastCount != 0) && (MnpDeviceData->GroupAddressCount != 0)) {\r
aeddd425 1381 //\r
1382 // There are instances configured to receive multicast and already some group\r
1383 // addresses are joined.\r
1384 //\r
1385\r
1386 ResetMCastFilters = FALSE;\r
1387\r
779ae357 1388 if (MnpDeviceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {\r
aeddd425 1389 //\r
1390 // The joind group address is less than simple network's maximum count.\r
1391 // Just configure the snp to do the multicast filtering.\r
1392 //\r
1393\r
1394 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
1395\r
1396 //\r
1397 // Allocate pool for the mulicast addresses.\r
1398 //\r
779ae357 1399 MCastFilterCnt = MnpDeviceData->GroupAddressCount;\r
aeddd425 1400 MCastFilter = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);\r
1401 if (MCastFilter == NULL) {\r
aeddd425 1402 DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));\r
779ae357 1403\r
aeddd425 1404 return EFI_OUT_OF_RESOURCES;\r
1405 }\r
1406\r
1407 //\r
1408 // Fill the multicast HW address buffer.\r
1409 //\r
1410 Index = 0;\r
779ae357 1411 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
aeddd425 1412\r
779ae357 1413 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
aeddd425 1414 CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));\r
1415 Index++;\r
1416\r
1417 ASSERT (Index <= MCastFilterCnt);\r
1418 }\r
1419 } else {\r
1420 //\r
1421 // The maximum multicast is reached, set the filter to be promiscuous\r
1422 // multicast.\r
1423 //\r
1424\r
1425 if ((Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {\r
1426 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
1427 } else {\r
1428 //\r
1429 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,\r
1430 // set the NIC to be promiscuous although this will tremendously degrade\r
1431 // the performance.\r
1432 //\r
1433 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
1434 }\r
1435 }\r
1436 }\r
1437\r
779ae357 1438 if (MnpDeviceData->PromiscuousCount != 0) {\r
aeddd425 1439 //\r
1440 // Enable promiscuous if any instance wants to receive promiscuous.\r
1441 //\r
1442 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
1443 }\r
1444\r
1445 //\r
1446 // Set the disable filter.\r
1447 //\r
1448 DisableFilterBits ^= EnableFilterBits;\r
1449\r
1450 //\r
1451 // Configure the receive filters of SNP.\r
1452 //\r
1453 Status = Snp->ReceiveFilters (\r
1454 Snp,\r
1455 EnableFilterBits,\r
1456 DisableFilterBits,\r
1457 ResetMCastFilters,\r
1458 MCastFilterCnt,\r
1459 MCastFilter\r
1460 );\r
1461 DEBUG_CODE (\r
1462 if (EFI_ERROR (Status)) {\r
779ae357 1463 DEBUG (\r
1464 (EFI_D_ERROR,\r
1465 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",\r
1466 Status)\r
1467 );\r
1468 }\r
aeddd425 1469 );\r
1470\r
1471 if (MCastFilter != NULL) {\r
1472 //\r
1473 // Free the buffer used to hold the group addresses.\r
1474 //\r
766c7483 1475 FreePool (MCastFilter);\r
aeddd425 1476 }\r
1477\r
1478 return Status;\r
1479}\r
8a67d61d 1480\r
8a67d61d 1481\r
1482/**\r
1483 Add a group address control block which controls the MacAddress for\r
1484 this instance.\r
1485\r
6e4bac4d 1486 @param[in, out] Instance Pointer to the mnp instance context data.\r
1487 @param[in, out] CtrlBlk Pointer to the group address control block.\r
1488 @param[in, out] GroupAddress Pointer to the group adress.\r
1489 @param[in] MacAddress Pointer to the mac address.\r
1490 @param[in] HwAddressSize The hardware address size.\r
8a67d61d 1491\r
6e4bac4d 1492 @retval EFI_SUCCESS The group address control block is added.\r
1493 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.\r
8a67d61d 1494\r
1495**/\r
8a67d61d 1496EFI_STATUS\r
1497MnpGroupOpAddCtrlBlk (\r
779ae357 1498 IN OUT MNP_INSTANCE_DATA *Instance,\r
1499 IN OUT MNP_GROUP_CONTROL_BLOCK *CtrlBlk,\r
1500 IN OUT MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,\r
1501 IN EFI_MAC_ADDRESS *MacAddress,\r
1502 IN UINT32 HwAddressSize\r
8a67d61d 1503 )\r
1504{\r
779ae357 1505 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1506\r
1507 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1508\r
779ae357 1509 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1510 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1511\r
1512 if (GroupAddress == NULL) {\r
8a67d61d 1513 ASSERT (MacAddress != NULL);\r
1514\r
1515 //\r
1516 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.\r
1517 //\r
e48e37fc 1518 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));\r
8a67d61d 1519 if (GroupAddress == NULL) {\r
1520\r
e48e37fc 1521 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));\r
8a67d61d 1522\r
1523 return EFI_OUT_OF_RESOURCES;\r
1524 }\r
1525\r
687a2e5f 1526 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));\r
779ae357 1527 GroupAddress->RefCnt = 0;\r
e48e37fc 1528 InsertTailList (\r
779ae357 1529 &MnpDeviceData->GroupAddressList,\r
8a67d61d 1530 &GroupAddress->AddrEntry\r
1531 );\r
779ae357 1532 MnpDeviceData->GroupAddressCount++;\r
8a67d61d 1533 }\r
1534\r
1535 //\r
1536 // Increase the RefCnt.\r
1537 //\r
1538 GroupAddress->RefCnt++;\r
1539\r
1540 //\r
1541 // Add the CtrlBlk into the instance's GroupCtrlBlkList.\r
1542 //\r
1543 CtrlBlk->GroupAddress = GroupAddress;\r
e48e37fc 1544 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);\r
8a67d61d 1545\r
1546 return EFI_SUCCESS;\r
1547}\r
1548\r
1549\r
1550/**\r
1551 Delete a group control block from the instance. If the controlled group address's\r
1552 reference count reaches zero, the group address is removed too.\r
1553\r
3e8c18da 1554 @param[in] Instance Pointer to the instance context data.\r
1555 @param[in] CtrlBlk Pointer to the group control block to delete.\r
8a67d61d 1556\r
1557 @return The group address controlled by the control block is no longer used or not.\r
1558\r
1559**/\r
8a67d61d 1560BOOLEAN\r
1561MnpGroupOpDelCtrlBlk (\r
779ae357 1562 IN MNP_INSTANCE_DATA *Instance,\r
1563 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk\r
8a67d61d 1564 )\r
1565{\r
779ae357 1566 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1567 MNP_GROUP_ADDRESS *GroupAddress;\r
1568\r
1569 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1570\r
779ae357 1571 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1572 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1573\r
1574 //\r
1575 // Remove and free the CtrlBlk.\r
1576 //\r
1577 GroupAddress = CtrlBlk->GroupAddress;\r
e48e37fc 1578 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);\r
766c7483 1579 FreePool (CtrlBlk);\r
8a67d61d 1580\r
1581 ASSERT (GroupAddress->RefCnt > 0);\r
1582\r
1583 //\r
1584 // Count down the RefCnt.\r
1585 //\r
1586 GroupAddress->RefCnt--;\r
1587\r
1588 if (GroupAddress->RefCnt == 0) {\r
1589 //\r
1590 // Free this GroupAddress entry if no instance uses it.\r
1591 //\r
779ae357 1592 MnpDeviceData->GroupAddressCount--;\r
e48e37fc 1593 RemoveEntryList (&GroupAddress->AddrEntry);\r
766c7483 1594 FreePool (GroupAddress);\r
8a67d61d 1595\r
1596 return TRUE;\r
1597 }\r
1598\r
1599 return FALSE;\r
1600}\r
1601\r
1602\r
1603/**\r
1604 Do the group operations for this instance.\r
1605\r
6e4bac4d 1606 @param[in, out] Instance Pointer to the instance context data.\r
779ae357 1607 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to\r
6e4bac4d 1608 leave a group/groups.\r
1609 @param[in] MacAddress Pointer to the group address to join or leave.\r
779ae357 1610 @param[in] CtrlBlk Pointer to the group control block if JoinFlag\r
6e4bac4d 1611 is FALSE.\r
8a67d61d 1612\r
6e4bac4d 1613 @retval EFI_SUCCESS The group operation finished.\r
1614 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.\r
1615 @retval Others Other errors as indicated.\r
8a67d61d 1616\r
1617**/\r
1618EFI_STATUS\r
1619MnpGroupOp (\r
779ae357 1620 IN OUT MNP_INSTANCE_DATA *Instance,\r
1621 IN BOOLEAN JoinFlag,\r
1622 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,\r
1623 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL\r
8a67d61d 1624 )\r
1625{\r
779ae357 1626 MNP_DEVICE_DATA *MnpDeviceData;\r
e48e37fc 1627 LIST_ENTRY *Entry;\r
1628 LIST_ENTRY *NextEntry;\r
8a67d61d 1629 MNP_GROUP_ADDRESS *GroupAddress;\r
1630 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
1631 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;\r
1632 EFI_STATUS Status;\r
1633 BOOLEAN AddressExist;\r
1634 BOOLEAN NeedUpdate;\r
1635\r
1636 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1637\r
779ae357 1638 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1639 SnpMode = MnpDeviceData->Snp->Mode;\r
8a67d61d 1640\r
1641 if (JoinFlag) {\r
1642 //\r
1643 // A new gropu address is to be added.\r
1644 //\r
8a67d61d 1645 GroupAddress = NULL;\r
1646 AddressExist = FALSE;\r
1647\r
1648 //\r
1649 // Allocate memory for the control block.\r
1650 //\r
779ae357 1651 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));\r
8a67d61d 1652 if (NewCtrlBlk == NULL) {\r
e48e37fc 1653 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));\r
779ae357 1654\r
8a67d61d 1655 return EFI_OUT_OF_RESOURCES;\r
1656 }\r
1657\r
779ae357 1658 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
8a67d61d 1659 //\r
1660 // Check whether the MacAddress is already joined by other instances.\r
1661 //\r
1662 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
779ae357 1663 if (CompareMem (MacAddress, &GroupAddress->Address, SnpMode->HwAddressSize) == 0) {\r
8a67d61d 1664 AddressExist = TRUE;\r
1665 break;\r
1666 }\r
1667 }\r
1668\r
1669 if (!AddressExist) {\r
1670 GroupAddress = NULL;\r
1671 }\r
1672\r
1673 //\r
1674 // Add the GroupAddress for this instance.\r
1675 //\r
1676 Status = MnpGroupOpAddCtrlBlk (\r
1677 Instance,\r
1678 NewCtrlBlk,\r
1679 GroupAddress,\r
1680 MacAddress,\r
1681 SnpMode->HwAddressSize\r
1682 );\r
1683 if (EFI_ERROR (Status)) {\r
8a67d61d 1684 return Status;\r
1685 }\r
1686\r
1687 NeedUpdate = TRUE;\r
1688 } else {\r
8a67d61d 1689 if (MacAddress != NULL) {\r
8a67d61d 1690 ASSERT (CtrlBlk != NULL);\r
1691\r
1692 //\r
1693 // Leave the specific multicast mac address.\r
1694 //\r
1695 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);\r
1696 } else {\r
1697 //\r
1698 // Leave all multicast mac addresses.\r
1699 //\r
1700 NeedUpdate = FALSE;\r
1701\r
1702 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {\r
1703\r
1704 NewCtrlBlk = NET_LIST_USER_STRUCT (\r
1705 Entry,\r
1706 MNP_GROUP_CONTROL_BLOCK,\r
1707 CtrlBlkEntry\r
1708 );\r
1709 //\r
1710 // Update is required if the group address left is no longer used\r
1711 // by other instances.\r
1712 //\r
1713 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);\r
1714 }\r
1715 }\r
1716 }\r
1717\r
1718 Status = EFI_SUCCESS;\r
1719\r
1720 if (NeedUpdate) {\r
1721 //\r
1722 // Reconfigure the receive filters if necessary.\r
1723 //\r
779ae357 1724 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
8a67d61d 1725 }\r
1726\r
1727 return Status;\r
1728}\r