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