]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
Change the file headers and some function comments.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
CommitLineData
8a67d61d 1/** @file\r
c57273b0 2 Implementation of Managed Network Protocol private services.\r
8a67d61d 3\r
c57273b0 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
b6c4ecad 51 @param MnpServiceData Pointer to the mnp service context data.\r
8a67d61d 52\r
b6c4ecad 53 @retval EFI_SUCCESS The receive filters is configured.\r
c57273b0 54 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due to \r
55 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
147 if (Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {\r
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
208 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.\r
209 @param Count Number of NET_BUFFERs to add.\r
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
218 IN MNP_SERVICE_DATA *MnpServiceData,\r
219 IN UINTN Count\r
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
263 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.\r
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
271 IN MNP_SERVICE_DATA *MnpServiceData\r
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
336 @param MnpServiceData Pointer to the mnp service context data.\r
337 @param Nbuf Pointer to the NET_BUF to free.\r
338\r
8a67d61d 339**/\r
340VOID\r
341MnpFreeNbuf (\r
342 IN MNP_SERVICE_DATA *MnpServiceData,\r
343 IN NET_BUF *Nbuf\r
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
370 @param MnpServiceData Pointer to the mnp service context data.\r
b6c4ecad 371 @param ImageHandle The driver image handle.\r
372 @param ControllerHandle Handle of device to bind driver to.\r
8a67d61d 373\r
374 @retval EFI_SUCCESS The mnp service context is initialized.\r
375 @retval Other Some error occurs.\r
376\r
377**/\r
378EFI_STATUS\r
379MnpInitializeServiceData (\r
380 IN MNP_SERVICE_DATA *MnpServiceData,\r
381 IN EFI_HANDLE ImageHandle,\r
382 IN EFI_HANDLE ControllerHandle\r
383 )\r
384{\r
385 EFI_STATUS Status;\r
386 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
387 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
388\r
389 MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;\r
390\r
391 MnpServiceData->ControllerHandle = ControllerHandle;\r
392\r
393 //\r
394 // Copy the ServiceBinding structure.\r
395 //\r
396 MnpServiceData->ServiceBinding = mMnpServiceBindingProtocol;\r
397\r
398 //\r
399 // Open the Simple Network protocol.\r
400 //\r
401 Status = gBS->OpenProtocol (\r
402 ControllerHandle,\r
403 &gEfiSimpleNetworkProtocolGuid,\r
404 (VOID **) &Snp,\r
405 ImageHandle,\r
406 ControllerHandle,\r
407 EFI_OPEN_PROTOCOL_BY_DRIVER\r
408 );\r
409 if (EFI_ERROR (Status)) {\r
410 return EFI_UNSUPPORTED;\r
411 }\r
412\r
413 //\r
414 // Get MTU from Snp.\r
415 //\r
416 SnpMode = Snp->Mode;\r
417 MnpServiceData->Snp = Snp;\r
418 MnpServiceData->Mtu = SnpMode->MaxPacketSize;\r
419\r
420 //\r
421 // Initialize the lists.\r
422 //\r
e48e37fc 423 InitializeListHead (&MnpServiceData->GroupAddressList);\r
424 InitializeListHead (&MnpServiceData->ChildrenList);\r
8a67d61d 425\r
426 //\r
427 // Get the buffer length used to allocate NET_BUF to hold data received\r
428 // from SNP. Do this before fill the FreeNetBufQue.\r
429 //\r
430 MnpServiceData->BufferLength = MnpServiceData->Mtu + SnpMode->MediaHeaderSize + NET_ETHER_FCS_SIZE;\r
431\r
772db4bb 432 //\r
e48e37fc 433 // Make sure the protocol headers immediately following the media header\r
772db4bb 434 // 4-byte aligned\r
435 //\r
436 MnpServiceData->PaddingSize = (4 - SnpMode->MediaHeaderSize) & 0x3;\r
437\r
8a67d61d 438 //\r
439 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.\r
440 //\r
441 NetbufQueInit (&MnpServiceData->FreeNbufQue);\r
442 Status = MnpAddFreeNbuf (MnpServiceData, MNP_INIT_NET_BUFFER_NUM);\r
443 if (EFI_ERROR (Status)) {\r
444\r
e48e37fc 445 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status));\r
8a67d61d 446 goto ERROR;\r
447 }\r
448 //\r
449 // Get one NET_BUF from the FreeNbufQue for rx cache.\r
450 //\r
451 MnpServiceData->RxNbufCache = MnpAllocNbuf (MnpServiceData);\r
452 NetbufAllocSpace (\r
453 MnpServiceData->RxNbufCache,\r
454 MnpServiceData->BufferLength,\r
455 NET_BUF_TAIL\r
456 );\r
457\r
458 //\r
459 // Allocate buffer pool for tx.\r
460 //\r
e48e37fc 461 MnpServiceData->TxBuf = AllocatePool (MnpServiceData->Mtu + SnpMode->MediaHeaderSize);\r
8a67d61d 462 if (MnpServiceData->TxBuf == NULL) {\r
463\r
e48e37fc 464 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: AllocatePool failed.\n"));\r
8a67d61d 465 Status = EFI_OUT_OF_RESOURCES;\r
466\r
467 goto ERROR;\r
468 }\r
469\r
470 //\r
471 // Create the system poll timer.\r
472 //\r
473 Status = gBS->CreateEvent (\r
474 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 475 TPL_CALLBACK,\r
8a67d61d 476 MnpSystemPoll,\r
477 MnpServiceData,\r
478 &MnpServiceData->PollTimer\r
479 );\r
480 if (EFI_ERROR (Status)) {\r
481\r
e48e37fc 482 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));\r
8a67d61d 483 goto ERROR;\r
484 }\r
485\r
486 //\r
487 // Create the timer for packet timeout check.\r
488 //\r
489 Status = gBS->CreateEvent (\r
490 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 491 TPL_CALLBACK,\r
8a67d61d 492 MnpCheckPacketTimeout,\r
493 MnpServiceData,\r
494 &MnpServiceData->TimeoutCheckTimer\r
495 );\r
496 if (EFI_ERROR (Status)) {\r
497\r
e48e37fc 498 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for packet timeout check failed.\n"));\r
8a67d61d 499 goto ERROR;\r
500 }\r
501\r
502 //\r
503 // Create the timer for tx timeout check.\r
504 //\r
505 Status = gBS->CreateEvent (\r
506 EVT_TIMER,\r
e48e37fc 507 TPL_CALLBACK,\r
8a67d61d 508 NULL,\r
509 NULL,\r
510 &MnpServiceData->TxTimeoutEvent\r
511 );\r
512 if (EFI_ERROR (Status)) {\r
513\r
e48e37fc 514 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for tx timeout event failed.\n"));\r
8a67d61d 515 }\r
516\r
517ERROR:\r
518\r
519 if (EFI_ERROR (Status)) {\r
520 //\r
521 // Free the dynamic allocated resources if necessary.\r
522 //\r
523 if (MnpServiceData->TimeoutCheckTimer != NULL) {\r
524\r
525 gBS->CloseEvent (MnpServiceData->TimeoutCheckTimer);\r
526 }\r
527\r
528 if (MnpServiceData->PollTimer != NULL) {\r
529\r
530 gBS->CloseEvent (MnpServiceData->PollTimer);\r
531 }\r
532\r
533 if (MnpServiceData->TxBuf != NULL) {\r
534\r
e48e37fc 535 gBS->FreePool (MnpServiceData->TxBuf);\r
8a67d61d 536 }\r
537\r
538 if (MnpServiceData->RxNbufCache != NULL) {\r
539\r
540 MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);\r
541 }\r
542\r
543 if (MnpServiceData->FreeNbufQue.BufNum != 0) {\r
544\r
545 NetbufQueFlush (&MnpServiceData->FreeNbufQue);\r
546 }\r
547 }\r
548\r
549 return Status;\r
550}\r
551\r
552\r
553/**\r
554 Flush the mnp service context data.\r
555\r
556 @param MnpServiceData Pointer to the mnp service context data.\r
b6c4ecad 557 @param ImageHandle The driver image handle.\r
8a67d61d 558\r
559**/\r
560VOID\r
561MnpFlushServiceData (\r
3ec64ac5 562 IN MNP_SERVICE_DATA *MnpServiceData,\r
563 IN EFI_HANDLE ImageHandle\r
8a67d61d 564 )\r
565{\r
566 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
567\r
568 //\r
569 // The GroupAddressList must be empty.\r
570 //\r
e48e37fc 571 ASSERT (IsListEmpty (&MnpServiceData->GroupAddressList));\r
8a67d61d 572\r
573 //\r
574 // Close the event.\r
575 //\r
576 gBS->CloseEvent (&MnpServiceData->TxTimeoutEvent);\r
577 gBS->CloseEvent (&MnpServiceData->TimeoutCheckTimer);\r
578 gBS->CloseEvent (&MnpServiceData->PollTimer);\r
579\r
580 //\r
581 // Free the tx buffer.\r
582 //\r
e48e37fc 583 gBS->FreePool (MnpServiceData->TxBuf);\r
8a67d61d 584\r
585 //\r
586 // Free the RxNbufCache.\r
587 //\r
588 MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);\r
589\r
590 //\r
591 // Flush the FreeNbufQue.\r
592 //\r
593 MnpServiceData->NbufCnt -= MnpServiceData->FreeNbufQue.BufNum;\r
594 NetbufQueFlush (&MnpServiceData->FreeNbufQue);\r
595\r
596 DEBUG_CODE (\r
597\r
e48e37fc 598 if (MnpServiceData->NbufCnt != 0) {\r
8a67d61d 599\r
e48e37fc 600 DEBUG ((EFI_D_WARN, "MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));\r
8a67d61d 601 }\r
602 );\r
e21ef3a2 603\r
604 //\r
605 // Close the Simple Network Protocol.\r
606 //\r
607 gBS->CloseProtocol (\r
608 MnpServiceData->ControllerHandle,\r
609 &gEfiSimpleNetworkProtocolGuid,\r
3ec64ac5 610 ImageHandle,\r
e21ef3a2 611 MnpServiceData->ControllerHandle\r
612 );\r
8a67d61d 613}\r
614\r
615\r
616/**\r
617 Initialize the mnp instance context data.\r
618\r
619 @param MnpServiceData Pointer to the mnp service context data.\r
620 @param Instance Pointer to the mnp instance context data to\r
621 initialize.\r
622\r
8a67d61d 623**/\r
624VOID\r
625MnpInitializeInstanceData (\r
626 IN MNP_SERVICE_DATA *MnpServiceData,\r
627 IN MNP_INSTANCE_DATA *Instance\r
628 )\r
629{\r
630 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
631 ASSERT (Instance != NULL);\r
632\r
633 //\r
634 // Set the signature.\r
635 //\r
636 Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;\r
637\r
638 //\r
639 // Copy the MNP Protocol interfaces from the template.\r
640 //\r
687a2e5f 641 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));\r
8a67d61d 642\r
643 //\r
644 // Copy the default config data.\r
645 //\r
687a2e5f 646 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));\r
8a67d61d 647\r
648 //\r
649 // Initialize the lists.\r
650 //\r
e48e37fc 651 InitializeListHead (&Instance->GroupCtrlBlkList);\r
652 InitializeListHead (&Instance->RcvdPacketQueue);\r
653 InitializeListHead (&Instance->RxDeliveredPacketQueue);\r
8a67d61d 654\r
655 //\r
656 // Initialize the RxToken Map.\r
657 //\r
658 NetMapInit (&Instance->RxTokenMap);\r
659\r
660 //\r
661 // Save the MnpServiceData info.\r
662 //\r
663 Instance->MnpServiceData = MnpServiceData;\r
664}\r
665\r
666\r
667/**\r
668 Check whether the token specified by Arg maches the token in Item.\r
669\r
670 @param Map Pointer to the NET_MAP.\r
671 @param Item Pointer to the NET_MAP_ITEM\r
672 @param Arg Pointer to the Arg, it's a pointer to the token to\r
673 check.\r
674\r
675 @retval EFI_SUCCESS The token specified by Arg is different from the\r
676 token in Item.\r
677 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in\r
678 Item.\r
679\r
680**/\r
681EFI_STATUS\r
682MnpTokenExist (\r
683 IN NET_MAP *Map,\r
684 IN NET_MAP_ITEM *Item,\r
685 IN VOID *Arg\r
686 )\r
687{\r
688 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;\r
689 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;\r
690\r
691 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;\r
692 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
693\r
694 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {\r
695 //\r
696 // The token is the same either the two tokens equals or the Events in\r
697 // the two tokens are the same.\r
698 //\r
699 return EFI_ACCESS_DENIED;\r
700 }\r
701\r
702 return EFI_SUCCESS;\r
703}\r
704\r
8a67d61d 705/**\r
706 Cancel the token specified by Arg if it matches the token in Item.\r
707\r
c57273b0 708 @param Map Pointer to the NET_MAP.\r
709 @param Item Pointer to the NET_MAP_ITEM\r
710 @param Arg Pointer to the Arg, it's a pointer to the token to \r
711 cancel.\r
8a67d61d 712\r
c57273b0 713 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled, \r
714 or the Arg isn't NULL, and the token in Item is\r
715 different from the Arg.\r
716 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the\r
717 Arg, and the token is cancelled.\r
8a67d61d 718\r
719**/\r
720EFI_STATUS\r
721MnpCancelTokens (\r
c57273b0 722 IN OUT NET_MAP *Map,\r
8a67d61d 723 IN NET_MAP_ITEM *Item,\r
724 IN VOID *Arg\r
725 )\r
726{\r
727 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;\r
728\r
729 if ((Arg != NULL) && (Item->Key != Arg)) {\r
730 //\r
731 // The token in Item is not the token specified by Arg.\r
732 //\r
733 return EFI_SUCCESS;\r
734 }\r
735\r
736 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
737\r
738 //\r
36ee91ca 739 // Remove the item from the map.\r
8a67d61d 740 //\r
36ee91ca 741 NetMapRemoveItem (Map, Item, NULL);\r
8a67d61d 742\r
743 //\r
36ee91ca 744 // Cancel this token with status set to EFI_ABORTED.\r
8a67d61d 745 //\r
36ee91ca 746 TokenToCancel->Status = EFI_ABORTED;\r
747 gBS->SignalEvent (TokenToCancel->Event);\r
8a67d61d 748\r
749 if (Arg != NULL) {\r
750 //\r
751 // Only abort the token specified by Arg if Arg isn't NULL.\r
752 //\r
753 return EFI_ABORTED;\r
754 }\r
755\r
756 return EFI_SUCCESS;\r
757}\r
758\r
759\r
760/**\r
761 Start and initialize the simple network.\r
762\r
763 @param Snp Pointer to the simple network protocol.\r
764\r
765 @retval EFI_SUCCESS The simple network protocol is started.\r
766 @retval Other Some error occurs.\r
767\r
768**/\r
8a67d61d 769EFI_STATUS\r
770MnpStartSnp (\r
771 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
772 )\r
773{\r
774 EFI_STATUS Status;\r
775\r
776 ASSERT (Snp != NULL);\r
777\r
778 //\r
779 // Start the simple network.\r
780 //\r
781 Status = Snp->Start (Snp);\r
782\r
783 if (!EFI_ERROR (Status)) {\r
784 //\r
785 // Initialize the simple network.\r
786 //\r
787 Status = Snp->Initialize (Snp, 0, 0);\r
788 }\r
789\r
790 return Status;\r
791}\r
792\r
793\r
794/**\r
795 Stop the simple network.\r
796\r
797 @param Snp Pointer to the simple network protocol.\r
798\r
799 @retval EFI_SUCCESS The simple network is stopped.\r
800 @retval Other Some error occurs.\r
801\r
802**/\r
8a67d61d 803EFI_STATUS\r
804MnpStopSnp (\r
805 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
806 )\r
807{\r
808 EFI_STATUS Status;\r
809\r
810 ASSERT (Snp != NULL);\r
811\r
812 //\r
813 // Shut down the simple network.\r
814 //\r
815 Status = Snp->Shutdown (Snp);\r
816\r
817 if (!EFI_ERROR (Status)) {\r
818 //\r
819 // Stop the simple network.\r
820 //\r
821 Status = Snp->Stop (Snp);\r
822 }\r
823\r
824 return Status;\r
825}\r
826\r
827\r
828/**\r
829 Start the managed network, this function is called when one instance is configured\r
830 or reconfigured.\r
831\r
832 @param MnpServiceData Pointer to the mnp service context data.\r
833 @param IsConfigUpdate The instance is reconfigured or it's the first time\r
c57273b0 834 the instanced is configured.\r
8a67d61d 835 @param EnableSystemPoll Enable the system polling or not.\r
836\r
837 @retval EFI_SUCCESS The managed network is started and some\r
838 configuration is updated.\r
839 @retval Other Some error occurs.\r
840\r
841**/\r
8a67d61d 842EFI_STATUS\r
843MnpStart (\r
844 IN MNP_SERVICE_DATA *MnpServiceData,\r
845 IN BOOLEAN IsConfigUpdate,\r
846 IN BOOLEAN EnableSystemPoll\r
847 )\r
848{\r
849 EFI_STATUS Status;\r
850 EFI_TIMER_DELAY TimerOpType;\r
851\r
852 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
853\r
854 Status = EFI_SUCCESS;\r
855\r
856 if (!IsConfigUpdate) {\r
857 //\r
858 // If it's not a configuration update, increase the configured children number.\r
859 //\r
860 MnpServiceData->ConfiguredChildrenNumber++;\r
861\r
862 if (MnpServiceData->ConfiguredChildrenNumber == 1) {\r
863 //\r
864 // It's the first configured child, start the simple network.\r
865 //\r
866 Status = MnpStartSnp (MnpServiceData->Snp);\r
867 if (EFI_ERROR (Status)) {\r
868\r
e48e37fc 869 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));\r
8a67d61d 870 goto ErrorExit;\r
871 }\r
872\r
873 //\r
874 // Start the timeout timer.\r
875 //\r
876 Status = gBS->SetTimer (\r
877 MnpServiceData->TimeoutCheckTimer,\r
878 TimerPeriodic,\r
879 MNP_TIMEOUT_CHECK_INTERVAL\r
880 );\r
881 if (EFI_ERROR (Status)) {\r
882\r
e48e37fc 883 DEBUG (\r
884 (EFI_D_ERROR,\r
885 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",\r
8a67d61d 886 Status)\r
887 );\r
888 goto ErrorExit;\r
889 }\r
890 }\r
891 }\r
892\r
893 if (MnpServiceData->EnableSystemPoll ^ EnableSystemPoll) {\r
894 //\r
895 // The EnableSystemPoll differs with the current state, disable or enable\r
896 // the system poll.\r
897 //\r
898 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;\r
899\r
900 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);\r
901 if (EFI_ERROR (Status)) {\r
902\r
e48e37fc 903 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));\r
8a67d61d 904 goto ErrorExit;\r
905 }\r
906\r
907 MnpServiceData->EnableSystemPoll = EnableSystemPoll;\r
908 }\r
909\r
910 //\r
911 // Change the receive filters if need.\r
912 //\r
913 Status = MnpConfigReceiveFilters (MnpServiceData);\r
914\r
915ErrorExit:\r
916\r
917 return Status;\r
918}\r
919\r
920\r
921/**\r
922 Stop the managed network.\r
923\r
924 @param MnpServiceData Pointer to the mnp service context data.\r
925\r
926 @retval EFI_SUCCESS The managed network is stopped.\r
927 @retval Other Some error occurs.\r
928\r
929**/\r
8a67d61d 930EFI_STATUS\r
931MnpStop (\r
932 IN MNP_SERVICE_DATA *MnpServiceData\r
933 )\r
934{\r
935 EFI_STATUS Status;\r
936\r
937 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
938 ASSERT (MnpServiceData->ConfiguredChildrenNumber > 0);\r
939\r
940 //\r
941 // Configure the receive filters.\r
942 //\r
943 MnpConfigReceiveFilters (MnpServiceData);\r
944\r
945 //\r
946 // Decrease the children number.\r
947 //\r
948 MnpServiceData->ConfiguredChildrenNumber--;\r
949\r
950 if (MnpServiceData->ConfiguredChildrenNumber > 0) {\r
951 //\r
952 // If there are other configured chilren, return and keep the timers and\r
953 // simple network unchanged.\r
954 //\r
955 return EFI_SUCCESS;\r
956 }\r
957\r
958 //\r
959 // No configured children now.\r
960 //\r
961\r
962 if (MnpServiceData->EnableSystemPoll) {\r
963 //\r
964 // The system poll in on, cancel the poll timer.\r
965 //\r
966 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerCancel, 0);\r
967 MnpServiceData->EnableSystemPoll = FALSE;\r
968 }\r
969\r
970 //\r
971 // Cancel the timeout timer.\r
972 //\r
973 Status = gBS->SetTimer (MnpServiceData->TimeoutCheckTimer, TimerCancel, 0);\r
974\r
975 //\r
976 // Stop the simple network.\r
977 //\r
978 Status = MnpStopSnp (MnpServiceData->Snp);\r
979\r
980 return Status;\r
981}\r
982\r
983\r
984/**\r
985 Flush the instance's received data.\r
986\r
987 @param Instance Pointer to the mnp instance context data.\r
988\r
8a67d61d 989**/\r
990VOID\r
991MnpFlushRcvdDataQueue (\r
992 IN MNP_INSTANCE_DATA *Instance\r
993 )\r
994{\r
995 EFI_TPL OldTpl;\r
996 MNP_RXDATA_WRAP *RxDataWrap;\r
997\r
998 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
999\r
e48e37fc 1000 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 1001\r
e48e37fc 1002 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {\r
8a67d61d 1003 //\r
1004 // Remove all the Wraps.\r
1005 //\r
1006 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);\r
1007\r
1008 //\r
1009 // Recycle the RxDataWrap.\r
1010 //\r
1011 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);\r
1012 Instance->RcvdPacketQueueSize--;\r
1013 }\r
1014\r
1015 ASSERT (Instance->RcvdPacketQueueSize == 0);\r
1016\r
e48e37fc 1017 gBS->RestoreTPL (OldTpl);\r
8a67d61d 1018}\r
1019\r
1020\r
1021/**\r
1022 Configure the Instance using ConfigData.\r
1023\r
1024 @param Instance Pointer to the mnp instance context data.\r
1025 @param ConfigData Pointer to the configuration data used to configure\r
1026 the isntance.\r
1027\r
1028 @retval EFI_SUCCESS The Instance is configured.\r
1029 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the\r
1030 implementation doesn't support it.\r
1031 @retval Other Some error occurs.\r
1032\r
1033**/\r
1034EFI_STATUS\r
1035MnpConfigureInstance (\r
1036 IN MNP_INSTANCE_DATA *Instance,\r
1037 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL\r
1038 )\r
1039{\r
1040 EFI_STATUS Status;\r
1041 MNP_SERVICE_DATA *MnpServiceData;\r
1042 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;\r
1043 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;\r
1044 BOOLEAN IsConfigUpdate;\r
1045\r
1046 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1047\r
1048 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {\r
1049 //\r
1050 // Don't support timestamp.\r
1051 //\r
1052 return EFI_UNSUPPORTED;\r
1053 }\r
1054\r
1055 Status = EFI_SUCCESS;\r
1056\r
1057 MnpServiceData = Instance->MnpServiceData;\r
1058 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
1059\r
1060 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));\r
1061\r
1062 OldConfigData = &Instance->ConfigData;\r
1063 NewConfigData = ConfigData;\r
1064 if (NewConfigData == NULL) {\r
1065 //\r
1066 // Restore back the default config data if a reset of this instance\r
1067 // is required.\r
1068 //\r
1069 NewConfigData = &mMnpDefaultConfigData;\r
1070 }\r
1071\r
1072 //\r
1073 // Reset the instance's receive filter.\r
1074 //\r
1075 Instance->ReceiveFilter = 0;\r
1076\r
1077 //\r
1078 // Clear the receive counters according to the old ConfigData.\r
1079 //\r
1080 if (OldConfigData->EnableUnicastReceive) {\r
1081 MnpServiceData->UnicastCount--;\r
1082 }\r
1083\r
1084 if (OldConfigData->EnableMulticastReceive) {\r
1085 MnpServiceData->MulticastCount--;\r
1086 }\r
1087\r
1088 if (OldConfigData->EnableBroadcastReceive) {\r
1089 MnpServiceData->BroadcastCount--;\r
1090 }\r
1091\r
1092 if (OldConfigData->EnablePromiscuousReceive) {\r
1093 MnpServiceData->PromiscuousCount--;\r
1094 }\r
1095\r
1096 //\r
1097 // Set the receive filter counters and the receive filter of the\r
1098 // instance according to the new ConfigData.\r
1099 //\r
1100 if (NewConfigData->EnableUnicastReceive) {\r
1101 MnpServiceData->UnicastCount++;\r
1102 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;\r
1103 }\r
1104\r
1105 if (NewConfigData->EnableMulticastReceive) {\r
1106 MnpServiceData->MulticastCount++;\r
1107 }\r
1108\r
1109 if (NewConfigData->EnableBroadcastReceive) {\r
1110 MnpServiceData->BroadcastCount++;\r
1111 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;\r
1112 }\r
1113\r
1114 if (NewConfigData->EnablePromiscuousReceive) {\r
1115 MnpServiceData->PromiscuousCount++;\r
1116 }\r
1117\r
1118 if (OldConfigData->FlushQueuesOnReset) {\r
1119\r
1120 MnpFlushRcvdDataQueue (Instance);\r
1121 }\r
1122\r
1123 if (ConfigData == NULL) {\r
1124\r
36ee91ca 1125 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);\r
8a67d61d 1126 }\r
1127\r
1128 if (!NewConfigData->EnableMulticastReceive) {\r
1129\r
1130 MnpGroupOp (Instance, FALSE, NULL, NULL);\r
1131 }\r
1132\r
1133 //\r
1134 // Save the new configuration data.\r
1135 //\r
687a2e5f 1136 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));\r
8a67d61d 1137\r
1138 Instance->Configured = (BOOLEAN) (ConfigData != NULL);\r
1139\r
1140 if (Instance->Configured) {\r
1141 //\r
1142 // The instance is configured, start the Mnp.\r
1143 //\r
1144 Status = MnpStart (\r
1145 MnpServiceData,\r
1146 IsConfigUpdate,\r
4eb65aff 1147 (BOOLEAN) !NewConfigData->DisableBackgroundPolling\r
8a67d61d 1148 );\r
1149 } else {\r
1150 //\r
1151 // The instance is changed to the unconfigured state, stop the Mnp.\r
1152 //\r
1153 Status = MnpStop (MnpServiceData);\r
1154 }\r
1155\r
1156 return Status;\r
1157}\r
1158\r
1159\r
8a67d61d 1160\r
1161/**\r
1162 Add a group address control block which controls the MacAddress for\r
1163 this instance.\r
1164\r
1165 @param Instance Pointer to the mnp instance context data.\r
1166 @param CtrlBlk Pointer to the group address control block.\r
1167 @param GroupAddress Pointer to the group adress.\r
1168 @param MacAddress Pointer to the mac address.\r
1169 @param HwAddressSize The hardware address size.\r
1170\r
1171 @retval EFI_SUCCESS The group address control block is added.\r
1172 @retval EFI_OUT_OF_RESOURCE Failed due to lack of memory resources.\r
1173\r
1174**/\r
8a67d61d 1175EFI_STATUS\r
1176MnpGroupOpAddCtrlBlk (\r
1177 IN MNP_INSTANCE_DATA *Instance,\r
1178 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk,\r
1179 IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,\r
1180 IN EFI_MAC_ADDRESS *MacAddress,\r
1181 IN UINT32 HwAddressSize\r
1182 )\r
1183{\r
1184 MNP_SERVICE_DATA *MnpServiceData;\r
1185\r
1186 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1187\r
1188 MnpServiceData = Instance->MnpServiceData;\r
1189 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
1190\r
1191 if (GroupAddress == NULL) {\r
1192\r
1193 ASSERT (MacAddress != NULL);\r
1194\r
1195 //\r
1196 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.\r
1197 //\r
e48e37fc 1198 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));\r
8a67d61d 1199 if (GroupAddress == NULL) {\r
1200\r
e48e37fc 1201 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));\r
8a67d61d 1202\r
1203 return EFI_OUT_OF_RESOURCES;\r
1204 }\r
1205\r
687a2e5f 1206 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));\r
8a67d61d 1207 GroupAddress->RefCnt = 0;\r
e48e37fc 1208 InsertTailList (\r
8a67d61d 1209 &MnpServiceData->GroupAddressList,\r
1210 &GroupAddress->AddrEntry\r
1211 );\r
1212 MnpServiceData->GroupAddressCount++;\r
1213 }\r
1214\r
1215 //\r
1216 // Increase the RefCnt.\r
1217 //\r
1218 GroupAddress->RefCnt++;\r
1219\r
1220 //\r
1221 // Add the CtrlBlk into the instance's GroupCtrlBlkList.\r
1222 //\r
1223 CtrlBlk->GroupAddress = GroupAddress;\r
e48e37fc 1224 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);\r
8a67d61d 1225\r
1226 return EFI_SUCCESS;\r
1227}\r
1228\r
1229\r
1230/**\r
1231 Delete a group control block from the instance. If the controlled group address's\r
1232 reference count reaches zero, the group address is removed too.\r
1233\r
1234 @param Instance Pointer to the instance context data.\r
1235 @param CtrlBlk Pointer to the group control block to delete.\r
1236\r
1237 @return The group address controlled by the control block is no longer used or not.\r
1238\r
1239**/\r
8a67d61d 1240BOOLEAN\r
1241MnpGroupOpDelCtrlBlk (\r
1242 IN MNP_INSTANCE_DATA *Instance,\r
1243 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk\r
1244 )\r
1245{\r
1246 MNP_SERVICE_DATA *MnpServiceData;\r
1247 MNP_GROUP_ADDRESS *GroupAddress;\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 //\r
1255 // Remove and free the CtrlBlk.\r
1256 //\r
1257 GroupAddress = CtrlBlk->GroupAddress;\r
e48e37fc 1258 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);\r
1259 gBS->FreePool (CtrlBlk);\r
8a67d61d 1260\r
1261 ASSERT (GroupAddress->RefCnt > 0);\r
1262\r
1263 //\r
1264 // Count down the RefCnt.\r
1265 //\r
1266 GroupAddress->RefCnt--;\r
1267\r
1268 if (GroupAddress->RefCnt == 0) {\r
1269 //\r
1270 // Free this GroupAddress entry if no instance uses it.\r
1271 //\r
1272 MnpServiceData->GroupAddressCount--;\r
e48e37fc 1273 RemoveEntryList (&GroupAddress->AddrEntry);\r
1274 gBS->FreePool (GroupAddress);\r
8a67d61d 1275\r
1276 return TRUE;\r
1277 }\r
1278\r
1279 return FALSE;\r
1280}\r
1281\r
1282\r
1283/**\r
1284 Do the group operations for this instance.\r
1285\r
1286 @param Instance Pointer to the instance context data.\r
1287 @param JoinFlag Set to TRUE to join a group. Set to TRUE to leave a\r
1288 group/groups.\r
1289 @param MacAddress Pointer to the group address to join or leave.\r
1290 @param CtrlBlk Pointer to the group control block if JoinFlag if\r
1291 FALSE.\r
1292\r
1293 @retval EFI_SUCCESS The group operation finished.\r
1294 @retval Other Some error occurs.\r
1295\r
1296**/\r
1297EFI_STATUS\r
1298MnpGroupOp (\r
1299 IN MNP_INSTANCE_DATA *Instance,\r
1300 IN BOOLEAN JoinFlag,\r
1301 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,\r
1302 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL\r
1303 )\r
1304{\r
1305 MNP_SERVICE_DATA *MnpServiceData;\r
e48e37fc 1306 LIST_ENTRY *Entry;\r
1307 LIST_ENTRY *NextEntry;\r
8a67d61d 1308 MNP_GROUP_ADDRESS *GroupAddress;\r
1309 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
1310 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;\r
1311 EFI_STATUS Status;\r
1312 BOOLEAN AddressExist;\r
1313 BOOLEAN NeedUpdate;\r
1314\r
1315 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1316\r
1317 MnpServiceData = Instance->MnpServiceData;\r
1318 SnpMode = MnpServiceData->Snp->Mode;\r
1319\r
1320 if (JoinFlag) {\r
1321 //\r
1322 // A new gropu address is to be added.\r
1323 //\r
1324\r
1325 GroupAddress = NULL;\r
1326 AddressExist = FALSE;\r
1327\r
1328 //\r
1329 // Allocate memory for the control block.\r
1330 //\r
e48e37fc 1331 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));\r
8a67d61d 1332 if (NewCtrlBlk == NULL) {\r
1333\r
e48e37fc 1334 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));\r
8a67d61d 1335 return EFI_OUT_OF_RESOURCES;\r
1336 }\r
1337\r
1338 NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {\r
1339 //\r
1340 // Check whether the MacAddress is already joined by other instances.\r
1341 //\r
1342 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
e48e37fc 1343 if (0 == CompareMem (\r
8a67d61d 1344 MacAddress,\r
1345 &GroupAddress->Address,\r
1346 SnpMode->HwAddressSize\r
1347 )) {\r
1348\r
1349 AddressExist = TRUE;\r
1350 break;\r
1351 }\r
1352 }\r
1353\r
1354 if (!AddressExist) {\r
1355 GroupAddress = NULL;\r
1356 }\r
1357\r
1358 //\r
1359 // Add the GroupAddress for this instance.\r
1360 //\r
1361 Status = MnpGroupOpAddCtrlBlk (\r
1362 Instance,\r
1363 NewCtrlBlk,\r
1364 GroupAddress,\r
1365 MacAddress,\r
1366 SnpMode->HwAddressSize\r
1367 );\r
1368 if (EFI_ERROR (Status)) {\r
1369\r
1370 return Status;\r
1371 }\r
1372\r
1373 NeedUpdate = TRUE;\r
1374 } else {\r
1375\r
1376 if (MacAddress != NULL) {\r
1377\r
1378 ASSERT (CtrlBlk != NULL);\r
1379\r
1380 //\r
1381 // Leave the specific multicast mac address.\r
1382 //\r
1383 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);\r
1384 } else {\r
1385 //\r
1386 // Leave all multicast mac addresses.\r
1387 //\r
1388 NeedUpdate = FALSE;\r
1389\r
1390 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {\r
1391\r
1392 NewCtrlBlk = NET_LIST_USER_STRUCT (\r
1393 Entry,\r
1394 MNP_GROUP_CONTROL_BLOCK,\r
1395 CtrlBlkEntry\r
1396 );\r
1397 //\r
1398 // Update is required if the group address left is no longer used\r
1399 // by other instances.\r
1400 //\r
1401 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);\r
1402 }\r
1403 }\r
1404 }\r
1405\r
1406 Status = EFI_SUCCESS;\r
1407\r
1408 if (NeedUpdate) {\r
1409 //\r
1410 // Reconfigure the receive filters if necessary.\r
1411 //\r
1412 Status = MnpConfigReceiveFilters (MnpServiceData);\r
1413 }\r
1414\r
1415 return Status;\r
1416}\r