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