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