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