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