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