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