]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
... / ...
CommitLineData
1/** @file\r
2 Implementation of Managed Network Protocol private services.\r
3\r
4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions\r
7of the BSD License which accompanies this distribution. The full\r
8text of the license may be found at<BR>\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "MnpImpl.h"\r
17#include "MnpVlan.h"\r
18\r
19EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol = {\r
20 MnpServiceBindingCreateChild,\r
21 MnpServiceBindingDestroyChild\r
22};\r
23\r
24EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate = {\r
25 MnpGetModeData,\r
26 MnpConfigure,\r
27 MnpMcastIpToMac,\r
28 MnpGroups,\r
29 MnpTransmit,\r
30 MnpReceive,\r
31 MnpCancel,\r
32 MnpPoll\r
33};\r
34\r
35EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {\r
36 10000000,\r
37 10000000,\r
38 0,\r
39 FALSE,\r
40 FALSE,\r
41 FALSE,\r
42 FALSE,\r
43 FALSE,\r
44 FALSE,\r
45 FALSE\r
46};\r
47\r
48/**\r
49 Add Count of net buffers to MnpDeviceData->FreeNbufQue. The length of the net\r
50 buffer is specified by MnpDeviceData->BufferLength.\r
51\r
52 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
53 @param[in] Count Number of NET_BUFFERs to add.\r
54\r
55 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated\r
56 and added to MnpDeviceData->FreeNbufQue.\r
57 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.\r
58\r
59**/\r
60EFI_STATUS\r
61MnpAddFreeNbuf (\r
62 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
63 IN UINTN Count\r
64 )\r
65{\r
66 EFI_STATUS Status;\r
67 UINTN Index;\r
68 NET_BUF *Nbuf;\r
69\r
70 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
71 ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));\r
72\r
73 Status = EFI_SUCCESS;\r
74 for (Index = 0; Index < Count; Index++) {\r
75 Nbuf = NetbufAlloc (MnpDeviceData->BufferLength + MnpDeviceData->PaddingSize);\r
76 if (Nbuf == NULL) {\r
77 DEBUG ((EFI_D_ERROR, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));\r
78\r
79 Status = EFI_OUT_OF_RESOURCES;\r
80 break;\r
81 }\r
82\r
83 if (MnpDeviceData->PaddingSize > 0) {\r
84 //\r
85 // Pad padding bytes before the media header\r
86 //\r
87 NetbufAllocSpace (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_TAIL);\r
88 NetbufTrim (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_HEAD);\r
89 }\r
90\r
91 NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);\r
92 }\r
93\r
94 MnpDeviceData->NbufCnt += Index;\r
95 return Status;\r
96}\r
97\r
98\r
99/**\r
100 Allocate a free NET_BUF from MnpDeviceData->FreeNbufQue. If there is none\r
101 in the queue, first try to allocate some and add them into the queue, then\r
102 fetch the NET_BUF from the updated FreeNbufQue.\r
103\r
104 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
105\r
106 @return Pointer to the allocated free NET_BUF structure, if NULL the\r
107 operation is failed.\r
108\r
109**/\r
110NET_BUF *\r
111MnpAllocNbuf (\r
112 IN OUT MNP_DEVICE_DATA *MnpDeviceData\r
113 )\r
114{\r
115 EFI_STATUS Status;\r
116 NET_BUF_QUEUE *FreeNbufQue;\r
117 NET_BUF *Nbuf;\r
118 EFI_TPL OldTpl;\r
119\r
120 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
121\r
122 FreeNbufQue = &MnpDeviceData->FreeNbufQue;\r
123 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
124\r
125 //\r
126 // Check whether there are available buffers, or else try to add some.\r
127 //\r
128 if (FreeNbufQue->BufNum == 0) {\r
129 if ((MnpDeviceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {\r
130 DEBUG (\r
131 (EFI_D_ERROR,\r
132 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",\r
133 MnpDeviceData)\r
134 );\r
135\r
136 Nbuf = NULL;\r
137 goto ON_EXIT;\r
138 }\r
139\r
140 Status = MnpAddFreeNbuf (MnpDeviceData, MNP_NET_BUFFER_INCREASEMENT);\r
141 if (EFI_ERROR (Status)) {\r
142 DEBUG (\r
143 (EFI_D_ERROR,\r
144 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",\r
145 Status)\r
146 );\r
147\r
148 //\r
149 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but\r
150 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.\r
151 //\r
152 }\r
153 }\r
154\r
155 Nbuf = NetbufQueRemove (FreeNbufQue);\r
156\r
157 //\r
158 // Increase the RefCnt.\r
159 //\r
160 if (Nbuf != NULL) {\r
161 NET_GET_REF (Nbuf);\r
162 }\r
163\r
164ON_EXIT:\r
165 gBS->RestoreTPL (OldTpl);\r
166\r
167 return Nbuf;\r
168}\r
169\r
170\r
171/**\r
172 Try to reclaim the Nbuf into the buffer pool.\r
173\r
174 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
175 @param[in, out] Nbuf Pointer to the NET_BUF to free.\r
176\r
177**/\r
178VOID\r
179MnpFreeNbuf (\r
180 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
181 IN OUT NET_BUF *Nbuf\r
182 )\r
183{\r
184 EFI_TPL OldTpl;\r
185\r
186 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
187 ASSERT (Nbuf->RefCnt > 1);\r
188\r
189 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
190\r
191 NET_PUT_REF (Nbuf);\r
192\r
193 if (Nbuf->RefCnt == 1) {\r
194 //\r
195 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.\r
196 //\r
197 NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_TAIL);\r
198\r
199 if (NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD) != NULL) {\r
200 //\r
201 // There is space reserved for vlan tag in the head, reclaim it\r
202 //\r
203 NetbufTrim (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_TAIL);\r
204 }\r
205\r
206 NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);\r
207 }\r
208\r
209 gBS->RestoreTPL (OldTpl);\r
210}\r
211\r
212/**\r
213 Add Count of TX buffers to MnpDeviceData->AllTxBufList and MnpDeviceData->FreeTxBufList.\r
214 The length of the buffer is specified by MnpDeviceData->BufferLength.\r
215\r
216 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
217 @param[in] Count Number of TX buffers to add.\r
218\r
219 @retval EFI_SUCCESS The specified amount of TX buffers are allocated.\r
220 @retval EFI_OUT_OF_RESOURCES Failed to allocate a TX buffer.\r
221\r
222**/\r
223EFI_STATUS\r
224MnpAddFreeTxBuf (\r
225 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
226 IN UINTN Count\r
227 )\r
228{\r
229 EFI_STATUS Status;\r
230 UINT32 Index;\r
231 MNP_TX_BUF_WRAP *TxBufWrap;\r
232\r
233 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
234 ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));\r
235\r
236 Status = EFI_SUCCESS;\r
237 for (Index = 0; Index < Count; Index++) {\r
238 TxBufWrap = (MNP_TX_BUF_WRAP*) AllocatePool (OFFSET_OF (MNP_TX_BUF_WRAP, TxBuf) + MnpDeviceData->BufferLength );\r
239 if (TxBufWrap == NULL) {\r
240 DEBUG ((EFI_D_ERROR, "MnpAddFreeTxBuf: TxBuf Alloc failed.\n"));\r
241\r
242 Status = EFI_OUT_OF_RESOURCES;\r
243 break;\r
244 }\r
245 DEBUG ((EFI_D_INFO, "MnpAddFreeTxBuf: Add TxBufWrap %p, TxBuf %p\n", TxBufWrap, TxBufWrap->TxBuf));\r
246 TxBufWrap->Signature = MNP_TX_BUF_WRAP_SIGNATURE;\r
247 TxBufWrap->InUse = FALSE;\r
248 InsertTailList (&MnpDeviceData->FreeTxBufList, &TxBufWrap->WrapEntry);\r
249 InsertTailList (&MnpDeviceData->AllTxBufList, &TxBufWrap->AllEntry);\r
250 }\r
251\r
252 MnpDeviceData->TxBufCount += Index;\r
253 return Status;\r
254}\r
255\r
256/**\r
257 Allocate a free TX buffer from MnpDeviceData->FreeTxBufList. If there is none\r
258 in the queue, first try to recycle some from SNP, then try to allocate some and add\r
259 them into the queue, then fetch the NET_BUF from the updated FreeTxBufList.\r
260\r
261 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
262\r
263 @return Pointer to the allocated free NET_BUF structure, if NULL the\r
264 operation is failed.\r
265\r
266**/\r
267UINT8 *\r
268MnpAllocTxBuf (\r
269 IN OUT MNP_DEVICE_DATA *MnpDeviceData\r
270 )\r
271{\r
272 EFI_TPL OldTpl;\r
273 UINT8 *TxBuf;\r
274 EFI_STATUS Status;\r
275 LIST_ENTRY *Entry;\r
276 MNP_TX_BUF_WRAP *TxBufWrap;\r
277\r
278 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
279\r
280 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
281\r
282 if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {\r
283 //\r
284 // First try to recycle some TX buffer from SNP\r
285 //\r
286 Status = MnpRecycleTxBuf (MnpDeviceData);\r
287 if (EFI_ERROR (Status)) {\r
288 TxBuf = NULL;\r
289 goto ON_EXIT;\r
290 }\r
291\r
292 //\r
293 // If still no free TX buffer, allocate more.\r
294 //\r
295 if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {\r
296 if ((MnpDeviceData->TxBufCount + MNP_TX_BUFFER_INCREASEMENT) > MNP_MAX_TX_BUFFER_NUM) {\r
297 DEBUG (\r
298 (EFI_D_ERROR,\r
299 "MnpAllocTxBuf: The maximum TxBuf size is reached for MNP driver instance %p.\n",\r
300 MnpDeviceData)\r
301 );\r
302\r
303 TxBuf = NULL;\r
304 goto ON_EXIT;\r
305 }\r
306\r
307 Status = MnpAddFreeTxBuf (MnpDeviceData, MNP_TX_BUFFER_INCREASEMENT);\r
308 if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {\r
309 DEBUG (\r
310 (EFI_D_ERROR,\r
311 "MnpAllocNbuf: Failed to add TxBuf into the FreeTxBufList, %r.\n",\r
312 Status)\r
313 );\r
314\r
315 TxBuf = NULL;\r
316 goto ON_EXIT;\r
317 }\r
318 }\r
319 }\r
320\r
321 ASSERT (!IsListEmpty (&MnpDeviceData->FreeTxBufList));\r
322 Entry = MnpDeviceData->FreeTxBufList.ForwardLink;\r
323 RemoveEntryList (MnpDeviceData->FreeTxBufList.ForwardLink);\r
324 TxBufWrap = NET_LIST_USER_STRUCT_S (Entry, MNP_TX_BUF_WRAP, WrapEntry, MNP_TX_BUF_WRAP_SIGNATURE);\r
325 TxBufWrap->InUse = TRUE;\r
326 TxBuf = TxBufWrap->TxBuf;\r
327\r
328ON_EXIT:\r
329 gBS->RestoreTPL (OldTpl);\r
330\r
331 return TxBuf;\r
332}\r
333\r
334/**\r
335 Try to reclaim the TX buffer into the buffer pool.\r
336\r
337 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
338 @param[in, out] TxBuf Pointer to the TX buffer to free.\r
339\r
340**/\r
341VOID\r
342MnpFreeTxBuf (\r
343 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
344 IN OUT UINT8 *TxBuf\r
345 )\r
346{\r
347 MNP_TX_BUF_WRAP *TxBufWrap;\r
348 EFI_TPL OldTpl;\r
349\r
350 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
351\r
352 if (TxBuf == NULL) {\r
353 return;\r
354 }\r
355\r
356 TxBufWrap = NET_LIST_USER_STRUCT (TxBuf, MNP_TX_BUF_WRAP, TxBuf);\r
357 if (TxBufWrap->Signature != MNP_TX_BUF_WRAP_SIGNATURE) {\r
358 DEBUG (\r
359 (EFI_D_ERROR,\r
360 "MnpFreeTxBuf: Signature check failed in MnpFreeTxBuf.\n")\r
361 );\r
362 return;\r
363 }\r
364\r
365 if (!TxBufWrap->InUse) {\r
366 DEBUG (\r
367 (EFI_D_WARN,\r
368 "MnpFreeTxBuf: Duplicated recycle report from SNP.\n")\r
369 );\r
370 return;\r
371 }\r
372\r
373 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
374 InsertTailList (&MnpDeviceData->FreeTxBufList, &TxBufWrap->WrapEntry);\r
375 TxBufWrap->InUse = FALSE;\r
376 gBS->RestoreTPL (OldTpl);\r
377}\r
378\r
379/**\r
380 Try to recycle all the transmitted buffer address from SNP.\r
381\r
382 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
383\r
384 @retval EFI_SUCCESS Successed to recyclethe transmitted buffer address.\r
385 @retval Others Failed to recyclethe transmitted buffer address.\r
386\r
387**/\r
388EFI_STATUS\r
389MnpRecycleTxBuf (\r
390 IN OUT MNP_DEVICE_DATA *MnpDeviceData\r
391 )\r
392{\r
393 UINT8 *TxBuf;\r
394 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
395 EFI_STATUS Status;\r
396\r
397 Snp = MnpDeviceData->Snp;\r
398 ASSERT (Snp != NULL);\r
399\r
400 do {\r
401 TxBuf = NULL;\r
402 Status = Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);\r
403 if (EFI_ERROR (Status)) {\r
404 return Status;\r
405 }\r
406\r
407 if (TxBuf != NULL) {\r
408 MnpFreeTxBuf (MnpDeviceData, TxBuf);\r
409 }\r
410 } while (TxBuf != NULL);\r
411\r
412 return EFI_SUCCESS;\r
413}\r
414\r
415/**\r
416 Initialize the mnp device context data.\r
417\r
418 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
419 @param[in] ImageHandle The driver image handle.\r
420 @param[in] ControllerHandle Handle of device to bind driver to.\r
421\r
422 @retval EFI_SUCCESS The mnp service context is initialized.\r
423 @retval EFI_UNSUPPORTED ControllerHandle does not support Simple Network Protocol.\r
424 @retval Others Other errors as indicated.\r
425\r
426**/\r
427EFI_STATUS\r
428MnpInitializeDeviceData (\r
429 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
430 IN EFI_HANDLE ImageHandle,\r
431 IN EFI_HANDLE ControllerHandle\r
432 )\r
433{\r
434 EFI_STATUS Status;\r
435 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
436 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
437\r
438 MnpDeviceData->Signature = MNP_DEVICE_DATA_SIGNATURE;\r
439 MnpDeviceData->ImageHandle = ImageHandle;\r
440 MnpDeviceData->ControllerHandle = ControllerHandle;\r
441\r
442 //\r
443 // Copy the MNP Protocol interfaces from the template.\r
444 //\r
445 CopyMem (&MnpDeviceData->VlanConfig, &mVlanConfigProtocolTemplate, sizeof (EFI_VLAN_CONFIG_PROTOCOL));\r
446\r
447 //\r
448 // Open the Simple Network protocol.\r
449 //\r
450 Status = gBS->OpenProtocol (\r
451 ControllerHandle,\r
452 &gEfiSimpleNetworkProtocolGuid,\r
453 (VOID **) &Snp,\r
454 ImageHandle,\r
455 ControllerHandle,\r
456 EFI_OPEN_PROTOCOL_BY_DRIVER\r
457 );\r
458 if (EFI_ERROR (Status)) {\r
459 return EFI_UNSUPPORTED;\r
460 }\r
461\r
462 //\r
463 // Get MTU from Snp.\r
464 //\r
465 SnpMode = Snp->Mode;\r
466 MnpDeviceData->Snp = Snp;\r
467\r
468 //\r
469 // Initialize the lists.\r
470 //\r
471 InitializeListHead (&MnpDeviceData->ServiceList);\r
472 InitializeListHead (&MnpDeviceData->GroupAddressList);\r
473\r
474 //\r
475 // Get the buffer length used to allocate NET_BUF to hold data received\r
476 // from SNP. Do this before fill the FreeNetBufQue.\r
477 //\r
478 //\r
479 MnpDeviceData->BufferLength = SnpMode->MediaHeaderSize + NET_VLAN_TAG_LEN + SnpMode->MaxPacketSize + NET_ETHER_FCS_SIZE;\r
480\r
481 //\r
482 // Make sure the protocol headers immediately following the media header\r
483 // 4-byte aligned, and also preserve additional space for VLAN tag\r
484 //\r
485 MnpDeviceData->PaddingSize = ((4 - SnpMode->MediaHeaderSize) & 0x3) + NET_VLAN_TAG_LEN;\r
486\r
487 //\r
488 // Initialize MAC string which will be used as VLAN configuration variable name\r
489 //\r
490 Status = NetLibGetMacString (ControllerHandle, ImageHandle, &MnpDeviceData->MacString);\r
491 if (EFI_ERROR (Status)) {\r
492 goto ERROR;\r
493 }\r
494\r
495 //\r
496 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.\r
497 //\r
498 NetbufQueInit (&MnpDeviceData->FreeNbufQue);\r
499 Status = MnpAddFreeNbuf (MnpDeviceData, MNP_INIT_NET_BUFFER_NUM);\r
500 if (EFI_ERROR (Status)) {\r
501 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: MnpAddFreeNbuf failed, %r.\n", Status));\r
502\r
503 goto ERROR;\r
504 }\r
505\r
506 //\r
507 // Get one NET_BUF from the FreeNbufQue for rx cache.\r
508 //\r
509 MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);\r
510 NetbufAllocSpace (\r
511 MnpDeviceData->RxNbufCache,\r
512 MnpDeviceData->BufferLength,\r
513 NET_BUF_TAIL\r
514 );\r
515\r
516 //\r
517 // Allocate buffer pool for tx.\r
518 //\r
519 InitializeListHead (&MnpDeviceData->FreeTxBufList);\r
520 InitializeListHead (&MnpDeviceData->AllTxBufList);\r
521 MnpDeviceData->TxBufCount = 0;\r
522\r
523 //\r
524 // Create the system poll timer.\r
525 //\r
526 Status = gBS->CreateEvent (\r
527 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
528 TPL_CALLBACK,\r
529 MnpSystemPoll,\r
530 MnpDeviceData,\r
531 &MnpDeviceData->PollTimer\r
532 );\r
533 if (EFI_ERROR (Status)) {\r
534 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for poll timer failed.\n"));\r
535\r
536 goto ERROR;\r
537 }\r
538\r
539 //\r
540 // Create the timer for packet timeout check.\r
541 //\r
542 Status = gBS->CreateEvent (\r
543 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
544 TPL_CALLBACK,\r
545 MnpCheckPacketTimeout,\r
546 MnpDeviceData,\r
547 &MnpDeviceData->TimeoutCheckTimer\r
548 );\r
549 if (EFI_ERROR (Status)) {\r
550 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for packet timeout check failed.\n"));\r
551\r
552 goto ERROR;\r
553 }\r
554\r
555 //\r
556 // Create the timer for media detection.\r
557 //\r
558 Status = gBS->CreateEvent (\r
559 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
560 TPL_CALLBACK,\r
561 MnpCheckMediaStatus,\r
562 MnpDeviceData,\r
563 &MnpDeviceData->MediaDetectTimer\r
564 );\r
565 if (EFI_ERROR (Status)) {\r
566 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for media detection failed.\n"));\r
567\r
568 goto ERROR;\r
569 }\r
570\r
571ERROR:\r
572 if (EFI_ERROR (Status)) {\r
573 //\r
574 // Free the dynamic allocated resources if necessary.\r
575 //\r
576 if (MnpDeviceData->MacString != NULL) {\r
577 FreePool (MnpDeviceData->MacString);\r
578 }\r
579\r
580 if (MnpDeviceData->TimeoutCheckTimer != NULL) {\r
581 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
582 }\r
583\r
584 if (MnpDeviceData->MediaDetectTimer != NULL) {\r
585 gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
586 }\r
587\r
588 if (MnpDeviceData->PollTimer != NULL) {\r
589 gBS->CloseEvent (MnpDeviceData->PollTimer);\r
590 }\r
591\r
592 if (MnpDeviceData->RxNbufCache != NULL) {\r
593 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
594 }\r
595\r
596 if (MnpDeviceData->FreeNbufQue.BufNum != 0) {\r
597 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
598 }\r
599\r
600 //\r
601 // Close the Simple Network Protocol.\r
602 //\r
603 gBS->CloseProtocol (\r
604 ControllerHandle,\r
605 &gEfiSimpleNetworkProtocolGuid,\r
606 ImageHandle,\r
607 ControllerHandle\r
608 );\r
609 }\r
610\r
611 return Status;\r
612}\r
613\r
614\r
615/**\r
616 Destroy the MNP device context data.\r
617\r
618 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
619 @param[in] ImageHandle The driver image handle.\r
620\r
621**/\r
622VOID\r
623MnpDestroyDeviceData (\r
624 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
625 IN EFI_HANDLE ImageHandle\r
626 )\r
627{\r
628 LIST_ENTRY *Entry;\r
629 LIST_ENTRY *NextEntry;\r
630 MNP_TX_BUF_WRAP *TxBufWrap;\r
631\r
632 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
633\r
634 //\r
635 // Free Vlan Config variable name string\r
636 //\r
637 if (MnpDeviceData->MacString != NULL) {\r
638 FreePool (MnpDeviceData->MacString);\r
639 }\r
640\r
641 //\r
642 // The GroupAddressList must be empty.\r
643 //\r
644 ASSERT (IsListEmpty (&MnpDeviceData->GroupAddressList));\r
645\r
646 //\r
647 // Close the event.\r
648 //\r
649 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
650 gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
651 gBS->CloseEvent (MnpDeviceData->PollTimer);\r
652\r
653 //\r
654 // Free the Tx buffer pool.\r
655 //\r
656 NET_LIST_FOR_EACH_SAFE(Entry, NextEntry, &MnpDeviceData->AllTxBufList) {\r
657 TxBufWrap = NET_LIST_USER_STRUCT (Entry, MNP_TX_BUF_WRAP, AllEntry);\r
658 RemoveEntryList (Entry);\r
659 FreePool (TxBufWrap);\r
660 MnpDeviceData->TxBufCount--;\r
661 }\r
662 ASSERT (IsListEmpty (&MnpDeviceData->AllTxBufList));\r
663 ASSERT (MnpDeviceData->TxBufCount == 0);\r
664\r
665 //\r
666 // Free the RxNbufCache.\r
667 //\r
668 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
669\r
670 //\r
671 // Flush the FreeNbufQue.\r
672 //\r
673 MnpDeviceData->NbufCnt -= MnpDeviceData->FreeNbufQue.BufNum;\r
674 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
675\r
676 //\r
677 // Close the Simple Network Protocol.\r
678 //\r
679 gBS->CloseProtocol (\r
680 MnpDeviceData->ControllerHandle,\r
681 &gEfiSimpleNetworkProtocolGuid,\r
682 ImageHandle,\r
683 MnpDeviceData->ControllerHandle\r
684 );\r
685}\r
686\r
687\r
688/**\r
689 Create mnp service context data.\r
690\r
691 @param[in] MnpDeviceData Pointer to the mnp device context data.\r
692 @param[in] VlanId The VLAN ID.\r
693 @param[in] Priority The VLAN priority. If VlanId is 0,\r
694 Priority is ignored.\r
695\r
696 @return A pointer to MNP_SERVICE_DATA or NULL if failed to create MNP service context.\r
697\r
698**/\r
699MNP_SERVICE_DATA *\r
700MnpCreateServiceData (\r
701 IN MNP_DEVICE_DATA *MnpDeviceData,\r
702 IN UINT16 VlanId,\r
703 IN UINT8 Priority OPTIONAL\r
704 )\r
705{\r
706 EFI_HANDLE MnpServiceHandle;\r
707 MNP_SERVICE_DATA *MnpServiceData;\r
708 EFI_STATUS Status;\r
709 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
710 EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;\r
711\r
712 //\r
713 // Initialize the Mnp Service Data.\r
714 //\r
715 MnpServiceData = AllocateZeroPool (sizeof (MNP_SERVICE_DATA));\r
716 if (MnpServiceData == NULL) {\r
717 DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to allocate memory for the new Mnp Service Data.\n"));\r
718\r
719 return NULL;\r
720 }\r
721\r
722 //\r
723 // Add to MNP service list\r
724 //\r
725 InsertTailList (&MnpDeviceData->ServiceList, &MnpServiceData->Link);\r
726\r
727 MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;\r
728 MnpServiceData->MnpDeviceData = MnpDeviceData;\r
729\r
730 //\r
731 // Copy the ServiceBinding structure.\r
732 //\r
733 CopyMem (&MnpServiceData->ServiceBinding, &mMnpServiceBindingProtocol, sizeof (EFI_SERVICE_BINDING_PROTOCOL));\r
734\r
735 //\r
736 // Initialize the lists.\r
737 //\r
738 InitializeListHead (&MnpServiceData->ChildrenList);\r
739\r
740 SnpMode = MnpDeviceData->Snp->Mode;\r
741 if (VlanId != 0) {\r
742 //\r
743 // Create VLAN child handle\r
744 //\r
745 MnpServiceHandle = MnpCreateVlanChild (\r
746 MnpDeviceData->ImageHandle,\r
747 MnpDeviceData->ControllerHandle,\r
748 VlanId,\r
749 &MnpServiceData->DevicePath\r
750 );\r
751 if (MnpServiceHandle == NULL) {\r
752 DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to create child handle.\n"));\r
753\r
754 return NULL;\r
755 }\r
756\r
757 //\r
758 // Open VLAN Config Protocol by child\r
759 //\r
760 Status = gBS->OpenProtocol (\r
761 MnpDeviceData->ControllerHandle,\r
762 &gEfiVlanConfigProtocolGuid,\r
763 (VOID **) &VlanConfig,\r
764 MnpDeviceData->ImageHandle,\r
765 MnpServiceHandle,\r
766 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
767 );\r
768 if (EFI_ERROR (Status)) {\r
769 goto Exit;\r
770 }\r
771\r
772 //\r
773 // Reduce MTU for VLAN device\r
774 //\r
775 MnpServiceData->Mtu = SnpMode->MaxPacketSize - NET_VLAN_TAG_LEN;\r
776 } else {\r
777 //\r
778 // VlanId set to 0 means rx/tx untagged frame\r
779 //\r
780 MnpServiceHandle = MnpDeviceData->ControllerHandle;\r
781 MnpServiceData->Mtu = SnpMode->MaxPacketSize;\r
782 }\r
783\r
784 MnpServiceData->ServiceHandle = MnpServiceHandle;\r
785 MnpServiceData->VlanId = VlanId;\r
786 MnpServiceData->Priority = Priority;\r
787\r
788 //\r
789 // Install the MNP Service Binding Protocol\r
790 //\r
791 Status = gBS->InstallMultipleProtocolInterfaces (\r
792 &MnpServiceHandle,\r
793 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
794 &MnpServiceData->ServiceBinding,\r
795 NULL\r
796 );\r
797\r
798Exit:\r
799 if (EFI_ERROR (Status)) {\r
800 MnpDestroyServiceData (MnpServiceData);\r
801 MnpServiceData = NULL;\r
802 }\r
803\r
804 return MnpServiceData;\r
805}\r
806\r
807/**\r
808 Destroy the MNP service context data.\r
809\r
810 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
811\r
812 @retval EFI_SUCCESS The mnp service context is destroyed.\r
813 @retval Others Errors as indicated.\r
814\r
815**/\r
816EFI_STATUS\r
817MnpDestroyServiceData (\r
818 IN OUT MNP_SERVICE_DATA *MnpServiceData\r
819 )\r
820{\r
821 EFI_STATUS Status;\r
822\r
823 //\r
824 // Uninstall the MNP Service Binding Protocol\r
825 //\r
826 Status = gBS->UninstallMultipleProtocolInterfaces (\r
827 MnpServiceData->ServiceHandle,\r
828 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
829 &MnpServiceData->ServiceBinding,\r
830 NULL\r
831 );\r
832 if (EFI_ERROR (Status)) {\r
833 return Status;\r
834 }\r
835\r
836 if (MnpServiceData->VlanId != 0) {\r
837 //\r
838 // Close VlanConfig Protocol opened by VLAN child handle\r
839 //\r
840 Status = gBS->CloseProtocol (\r
841 MnpServiceData->MnpDeviceData->ControllerHandle,\r
842 &gEfiVlanConfigProtocolGuid,\r
843 MnpServiceData->MnpDeviceData->ImageHandle,\r
844 MnpServiceData->ServiceHandle\r
845 );\r
846 if (EFI_ERROR (Status)) {\r
847 return Status;\r
848 }\r
849\r
850 //\r
851 // Uninstall Device Path Protocol to destroy the VLAN child handle\r
852 //\r
853 Status = gBS->UninstallMultipleProtocolInterfaces (\r
854 MnpServiceData->ServiceHandle,\r
855 &gEfiDevicePathProtocolGuid,\r
856 MnpServiceData->DevicePath,\r
857 NULL\r
858 );\r
859 if (EFI_ERROR (Status)) {\r
860 return Status;\r
861 }\r
862\r
863 if (MnpServiceData->DevicePath != NULL) {\r
864 FreePool (MnpServiceData->DevicePath);\r
865 }\r
866 }\r
867\r
868 //\r
869 // Remove from MnpDeviceData service list\r
870 //\r
871 RemoveEntryList (&MnpServiceData->Link);\r
872\r
873 FreePool (MnpServiceData);\r
874\r
875 return Status;\r
876}\r
877\r
878/**\r
879 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
880\r
881 @param[in] Entry The entry to be removed.\r
882 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
883\r
884 @retval EFI_SUCCESS The entry has been removed successfully.\r
885 @retval Others Fail to remove the entry.\r
886\r
887**/\r
888EFI_STATUS\r
889EFIAPI\r
890MnpDestoryChildEntry (\r
891 IN LIST_ENTRY *Entry,\r
892 IN VOID *Context\r
893 )\r
894{\r
895 MNP_INSTANCE_DATA *Instance;\r
896 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
897\r
898 ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *) Context;\r
899 Instance = CR (Entry, MNP_INSTANCE_DATA, InstEntry, MNP_INSTANCE_DATA_SIGNATURE);\r
900 return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
901}\r
902\r
903/**\r
904 Destroy all child of the MNP service data.\r
905\r
906 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
907\r
908 @retval EFI_SUCCESS All child are destroyed.\r
909 @retval Others Failed to destroy all child.\r
910\r
911**/\r
912EFI_STATUS\r
913MnpDestroyServiceChild (\r
914 IN OUT MNP_SERVICE_DATA *MnpServiceData\r
915 )\r
916{\r
917 LIST_ENTRY *List;\r
918 EFI_STATUS Status;\r
919 UINTN ListLength;\r
920\r
921 List = &MnpServiceData->ChildrenList;\r
922\r
923 Status = NetDestroyLinkList (\r
924 List,\r
925 MnpDestoryChildEntry,\r
926 &MnpServiceData->ServiceBinding,\r
927 &ListLength\r
928 );\r
929 if (EFI_ERROR (Status) || ListLength != 0) {\r
930 return EFI_DEVICE_ERROR;\r
931 }\r
932\r
933 return EFI_SUCCESS;\r
934}\r
935\r
936/**\r
937 Find the MNP Service Data for given VLAN ID.\r
938\r
939 @param[in] MnpDeviceData Pointer to the mnp device context data.\r
940 @param[in] VlanId The VLAN ID.\r
941\r
942 @return A pointer to MNP_SERVICE_DATA or NULL if not found.\r
943\r
944**/\r
945MNP_SERVICE_DATA *\r
946MnpFindServiceData (\r
947 IN MNP_DEVICE_DATA *MnpDeviceData,\r
948 IN UINT16 VlanId\r
949 )\r
950{\r
951 LIST_ENTRY *Entry;\r
952 MNP_SERVICE_DATA *MnpServiceData;\r
953\r
954 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {\r
955 //\r
956 // Check VLAN ID of each Mnp Service Data\r
957 //\r
958 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
959 if (MnpServiceData->VlanId == VlanId) {\r
960 return MnpServiceData;\r
961 }\r
962 }\r
963\r
964 return NULL;\r
965}\r
966\r
967/**\r
968 Initialize the mnp instance context data.\r
969\r
970 @param[in] MnpServiceData Pointer to the mnp service context data.\r
971 @param[in, out] Instance Pointer to the mnp instance context data\r
972 to initialize.\r
973\r
974**/\r
975VOID\r
976MnpInitializeInstanceData (\r
977 IN MNP_SERVICE_DATA *MnpServiceData,\r
978 IN OUT MNP_INSTANCE_DATA *Instance\r
979 )\r
980{\r
981 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
982 ASSERT (Instance != NULL);\r
983\r
984 //\r
985 // Set the signature.\r
986 //\r
987 Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;\r
988\r
989 //\r
990 // Copy the MNP Protocol interfaces from the template.\r
991 //\r
992 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));\r
993\r
994 //\r
995 // Copy the default config data.\r
996 //\r
997 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));\r
998\r
999 //\r
1000 // Initialize the lists.\r
1001 //\r
1002 InitializeListHead (&Instance->GroupCtrlBlkList);\r
1003 InitializeListHead (&Instance->RcvdPacketQueue);\r
1004 InitializeListHead (&Instance->RxDeliveredPacketQueue);\r
1005\r
1006 //\r
1007 // Initialize the RxToken Map.\r
1008 //\r
1009 NetMapInit (&Instance->RxTokenMap);\r
1010\r
1011 //\r
1012 // Save the MnpServiceData info.\r
1013 //\r
1014 Instance->MnpServiceData = MnpServiceData;\r
1015}\r
1016\r
1017\r
1018/**\r
1019 Check whether the token specified by Arg matches the token in Item.\r
1020\r
1021 @param[in] Map Pointer to the NET_MAP.\r
1022 @param[in] Item Pointer to the NET_MAP_ITEM.\r
1023 @param[in] Arg Pointer to the Arg, it's a pointer to the token to\r
1024 check.\r
1025\r
1026 @retval EFI_SUCCESS The token specified by Arg is different from the\r
1027 token in Item.\r
1028 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in\r
1029 Item.\r
1030\r
1031**/\r
1032EFI_STATUS\r
1033EFIAPI\r
1034MnpTokenExist (\r
1035 IN NET_MAP *Map,\r
1036 IN NET_MAP_ITEM *Item,\r
1037 IN VOID *Arg\r
1038 )\r
1039{\r
1040 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;\r
1041 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;\r
1042\r
1043 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;\r
1044 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
1045\r
1046 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {\r
1047 //\r
1048 // The token is the same either the two tokens equals or the Events in\r
1049 // the two tokens are the same.\r
1050 //\r
1051 return EFI_ACCESS_DENIED;\r
1052 }\r
1053\r
1054 return EFI_SUCCESS;\r
1055}\r
1056\r
1057/**\r
1058 Cancel the token specified by Arg if it matches the token in Item.\r
1059\r
1060 @param[in, out] Map Pointer to the NET_MAP.\r
1061 @param[in, out] Item Pointer to the NET_MAP_ITEM.\r
1062 @param[in] Arg Pointer to the Arg, it's a pointer to the\r
1063 token to cancel.\r
1064\r
1065 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,\r
1066 or the Arg isn't NULL, and the token in Item is\r
1067 different from the Arg.\r
1068 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the\r
1069 Arg, and the token is cancelled.\r
1070\r
1071**/\r
1072EFI_STATUS\r
1073EFIAPI\r
1074MnpCancelTokens (\r
1075 IN OUT NET_MAP *Map,\r
1076 IN OUT NET_MAP_ITEM *Item,\r
1077 IN VOID *Arg\r
1078 )\r
1079{\r
1080 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;\r
1081\r
1082 if ((Arg != NULL) && (Item->Key != Arg)) {\r
1083 //\r
1084 // The token in Item is not the token specified by Arg.\r
1085 //\r
1086 return EFI_SUCCESS;\r
1087 }\r
1088\r
1089 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
1090\r
1091 //\r
1092 // Remove the item from the map.\r
1093 //\r
1094 NetMapRemoveItem (Map, Item, NULL);\r
1095\r
1096 //\r
1097 // Cancel this token with status set to EFI_ABORTED.\r
1098 //\r
1099 TokenToCancel->Status = EFI_ABORTED;\r
1100 gBS->SignalEvent (TokenToCancel->Event);\r
1101\r
1102 if (Arg != NULL) {\r
1103 //\r
1104 // Only abort the token specified by Arg if Arg isn't NULL.\r
1105 //\r
1106 return EFI_ABORTED;\r
1107 }\r
1108\r
1109 return EFI_SUCCESS;\r
1110}\r
1111\r
1112\r
1113/**\r
1114 Start and initialize the simple network.\r
1115\r
1116 @param[in] Snp Pointer to the simple network protocol.\r
1117\r
1118 @retval EFI_SUCCESS The simple network protocol is started.\r
1119 @retval Others Other errors as indicated.\r
1120\r
1121**/\r
1122EFI_STATUS\r
1123MnpStartSnp (\r
1124 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
1125 )\r
1126{\r
1127 EFI_STATUS Status;\r
1128\r
1129 ASSERT (Snp != NULL);\r
1130\r
1131 //\r
1132 // Start the simple network.\r
1133 //\r
1134 Status = Snp->Start (Snp);\r
1135\r
1136 if (!EFI_ERROR (Status)) {\r
1137 //\r
1138 // Initialize the simple network.\r
1139 //\r
1140 Status = Snp->Initialize (Snp, 0, 0);\r
1141 }\r
1142\r
1143 return Status;\r
1144}\r
1145\r
1146\r
1147/**\r
1148 Stop the simple network.\r
1149\r
1150 @param[in] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
1151\r
1152 @retval EFI_SUCCESS The simple network is stopped.\r
1153 @retval Others Other errors as indicated.\r
1154\r
1155**/\r
1156EFI_STATUS\r
1157MnpStopSnp (\r
1158 IN MNP_DEVICE_DATA *MnpDeviceData\r
1159 )\r
1160{\r
1161 EFI_STATUS Status;\r
1162 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
1163\r
1164 Snp = MnpDeviceData->Snp;\r
1165 ASSERT (Snp != NULL);\r
1166\r
1167 //\r
1168 // Recycle all the transmit buffer from SNP.\r
1169 //\r
1170 Status = MnpRecycleTxBuf (MnpDeviceData);\r
1171 if (EFI_ERROR (Status)) {\r
1172 return Status;\r
1173 }\r
1174\r
1175 //\r
1176 // Shut down the simple network.\r
1177 //\r
1178 Status = Snp->Shutdown (Snp);\r
1179 if (!EFI_ERROR (Status)) {\r
1180 //\r
1181 // Stop the simple network.\r
1182 //\r
1183 Status = Snp->Stop (Snp);\r
1184 }\r
1185\r
1186 return Status;\r
1187}\r
1188\r
1189\r
1190/**\r
1191 Start the managed network, this function is called when one instance is configured\r
1192 or reconfigured.\r
1193\r
1194 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
1195 @param[in] IsConfigUpdate The instance is reconfigured or it's the first\r
1196 time the instanced is configured.\r
1197 @param[in] EnableSystemPoll Enable the system polling or not.\r
1198\r
1199 @retval EFI_SUCCESS The managed network is started and some\r
1200 configuration is updated.\r
1201 @retval Others Other errors as indicated.\r
1202\r
1203**/\r
1204EFI_STATUS\r
1205MnpStart (\r
1206 IN OUT MNP_SERVICE_DATA *MnpServiceData,\r
1207 IN BOOLEAN IsConfigUpdate,\r
1208 IN BOOLEAN EnableSystemPoll\r
1209 )\r
1210{\r
1211 EFI_STATUS Status;\r
1212 EFI_TIMER_DELAY TimerOpType;\r
1213 MNP_DEVICE_DATA *MnpDeviceData;\r
1214\r
1215 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
1216\r
1217 Status = EFI_SUCCESS;\r
1218 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1219\r
1220 if (!IsConfigUpdate) {\r
1221 //\r
1222 // If it's not a configuration update, increase the configured children number.\r
1223 //\r
1224 MnpDeviceData->ConfiguredChildrenNumber++;\r
1225\r
1226 if (MnpDeviceData->ConfiguredChildrenNumber == 1) {\r
1227 //\r
1228 // It's the first configured child, start the simple network.\r
1229 //\r
1230 Status = MnpStartSnp (MnpDeviceData->Snp);\r
1231 if (EFI_ERROR (Status)) {\r
1232 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));\r
1233\r
1234 goto ErrorExit;\r
1235 }\r
1236\r
1237 //\r
1238 // Start the timeout timer.\r
1239 //\r
1240 Status = gBS->SetTimer (\r
1241 MnpDeviceData->TimeoutCheckTimer,\r
1242 TimerPeriodic,\r
1243 MNP_TIMEOUT_CHECK_INTERVAL\r
1244 );\r
1245 if (EFI_ERROR (Status)) {\r
1246 DEBUG (\r
1247 (EFI_D_ERROR,\r
1248 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",\r
1249 Status)\r
1250 );\r
1251\r
1252 goto ErrorExit;\r
1253 }\r
1254\r
1255 //\r
1256 // Start the media detection timer.\r
1257 //\r
1258 Status = gBS->SetTimer (\r
1259 MnpDeviceData->MediaDetectTimer,\r
1260 TimerPeriodic,\r
1261 MNP_MEDIA_DETECT_INTERVAL\r
1262 );\r
1263 if (EFI_ERROR (Status)) {\r
1264 DEBUG (\r
1265 (EFI_D_ERROR,\r
1266 "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n",\r
1267 Status)\r
1268 );\r
1269\r
1270 goto ErrorExit;\r
1271 }\r
1272 }\r
1273 }\r
1274\r
1275 if (MnpDeviceData->EnableSystemPoll ^ EnableSystemPoll) {\r
1276 //\r
1277 // The EnableSystemPoll differs with the current state, disable or enable\r
1278 // the system poll.\r
1279 //\r
1280 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;\r
1281\r
1282 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);\r
1283 if (EFI_ERROR (Status)) {\r
1284 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));\r
1285\r
1286 goto ErrorExit;\r
1287 }\r
1288\r
1289 MnpDeviceData->EnableSystemPoll = EnableSystemPoll;\r
1290 }\r
1291\r
1292 //\r
1293 // Change the receive filters if need.\r
1294 //\r
1295 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
1296\r
1297ErrorExit:\r
1298 return Status;\r
1299}\r
1300\r
1301\r
1302/**\r
1303 Stop the managed network.\r
1304\r
1305 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
1306\r
1307 @retval EFI_SUCCESS The managed network is stopped.\r
1308 @retval Others Other errors as indicated.\r
1309\r
1310**/\r
1311EFI_STATUS\r
1312MnpStop (\r
1313 IN OUT MNP_SERVICE_DATA *MnpServiceData\r
1314 )\r
1315{\r
1316 EFI_STATUS Status;\r
1317 MNP_DEVICE_DATA *MnpDeviceData;\r
1318\r
1319 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
1320 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1321 ASSERT (MnpDeviceData->ConfiguredChildrenNumber > 0);\r
1322\r
1323 //\r
1324 // Configure the receive filters.\r
1325 //\r
1326 MnpConfigReceiveFilters (MnpDeviceData);\r
1327\r
1328 //\r
1329 // Decrease the children number.\r
1330 //\r
1331 MnpDeviceData->ConfiguredChildrenNumber--;\r
1332\r
1333 if (MnpDeviceData->ConfiguredChildrenNumber > 0) {\r
1334 //\r
1335 // If there are other configured chilren, return and keep the timers and\r
1336 // simple network unchanged.\r
1337 //\r
1338 return EFI_SUCCESS;\r
1339 }\r
1340\r
1341 //\r
1342 // No configured children now.\r
1343 //\r
1344 if (MnpDeviceData->EnableSystemPoll) {\r
1345 //\r
1346 // The system poll in on, cancel the poll timer.\r
1347 //\r
1348 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerCancel, 0);\r
1349 MnpDeviceData->EnableSystemPoll = FALSE;\r
1350 }\r
1351\r
1352 //\r
1353 // Cancel the timeout timer.\r
1354 //\r
1355 Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0);\r
1356\r
1357 //\r
1358 // Cancel the media detect timer.\r
1359 //\r
1360 Status = gBS->SetTimer (MnpDeviceData->MediaDetectTimer, TimerCancel, 0);\r
1361\r
1362 //\r
1363 // Stop the simple network.\r
1364 //\r
1365 Status = MnpStopSnp (MnpDeviceData);\r
1366 return Status;\r
1367}\r
1368\r
1369\r
1370/**\r
1371 Flush the instance's received data.\r
1372\r
1373 @param[in, out] Instance Pointer to the mnp instance context data.\r
1374\r
1375**/\r
1376VOID\r
1377MnpFlushRcvdDataQueue (\r
1378 IN OUT MNP_INSTANCE_DATA *Instance\r
1379 )\r
1380{\r
1381 EFI_TPL OldTpl;\r
1382 MNP_RXDATA_WRAP *RxDataWrap;\r
1383\r
1384 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1385\r
1386 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1387\r
1388 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {\r
1389 //\r
1390 // Remove all the Wraps.\r
1391 //\r
1392 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);\r
1393\r
1394 //\r
1395 // Recycle the RxDataWrap.\r
1396 //\r
1397 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);\r
1398 Instance->RcvdPacketQueueSize--;\r
1399 }\r
1400\r
1401 ASSERT (Instance->RcvdPacketQueueSize == 0);\r
1402\r
1403 gBS->RestoreTPL (OldTpl);\r
1404}\r
1405\r
1406\r
1407/**\r
1408 Configure the Instance using ConfigData.\r
1409\r
1410 @param[in, out] Instance Pointer to the mnp instance context data.\r
1411 @param[in] ConfigData Pointer to the configuration data used to configure\r
1412 the isntance.\r
1413\r
1414 @retval EFI_SUCCESS The Instance is configured.\r
1415 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the\r
1416 implementation doesn't support it.\r
1417 @retval Others Other errors as indicated.\r
1418\r
1419**/\r
1420EFI_STATUS\r
1421MnpConfigureInstance (\r
1422 IN OUT MNP_INSTANCE_DATA *Instance,\r
1423 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL\r
1424 )\r
1425{\r
1426 EFI_STATUS Status;\r
1427 MNP_SERVICE_DATA *MnpServiceData;\r
1428 MNP_DEVICE_DATA *MnpDeviceData;\r
1429 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;\r
1430 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;\r
1431 BOOLEAN IsConfigUpdate;\r
1432\r
1433 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1434\r
1435 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {\r
1436 //\r
1437 // Don't support timestamp.\r
1438 //\r
1439 return EFI_UNSUPPORTED;\r
1440 }\r
1441\r
1442 Status = EFI_SUCCESS;\r
1443\r
1444 MnpServiceData = Instance->MnpServiceData;\r
1445 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1446 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
1447\r
1448 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));\r
1449\r
1450 OldConfigData = &Instance->ConfigData;\r
1451 NewConfigData = ConfigData;\r
1452 if (NewConfigData == NULL) {\r
1453 //\r
1454 // Restore back the default config data if a reset of this instance\r
1455 // is required.\r
1456 //\r
1457 NewConfigData = &mMnpDefaultConfigData;\r
1458 }\r
1459\r
1460 //\r
1461 // Reset the instance's receive filter.\r
1462 //\r
1463 Instance->ReceiveFilter = 0;\r
1464\r
1465 //\r
1466 // Clear the receive counters according to the old ConfigData.\r
1467 //\r
1468 if (OldConfigData->EnableUnicastReceive) {\r
1469 MnpDeviceData->UnicastCount--;\r
1470 }\r
1471\r
1472 if (OldConfigData->EnableMulticastReceive) {\r
1473 MnpDeviceData->MulticastCount--;\r
1474 }\r
1475\r
1476 if (OldConfigData->EnableBroadcastReceive) {\r
1477 MnpDeviceData->BroadcastCount--;\r
1478 }\r
1479\r
1480 if (OldConfigData->EnablePromiscuousReceive) {\r
1481 MnpDeviceData->PromiscuousCount--;\r
1482 }\r
1483\r
1484 //\r
1485 // Set the receive filter counters and the receive filter of the\r
1486 // instance according to the new ConfigData.\r
1487 //\r
1488 if (NewConfigData->EnableUnicastReceive) {\r
1489 MnpDeviceData->UnicastCount++;\r
1490 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;\r
1491 }\r
1492\r
1493 if (NewConfigData->EnableMulticastReceive) {\r
1494 MnpDeviceData->MulticastCount++;\r
1495 }\r
1496\r
1497 if (NewConfigData->EnableBroadcastReceive) {\r
1498 MnpDeviceData->BroadcastCount++;\r
1499 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;\r
1500 }\r
1501\r
1502 if (NewConfigData->EnablePromiscuousReceive) {\r
1503 MnpDeviceData->PromiscuousCount++;\r
1504 }\r
1505\r
1506 if (OldConfigData->FlushQueuesOnReset) {\r
1507 MnpFlushRcvdDataQueue (Instance);\r
1508 }\r
1509\r
1510 if (ConfigData == NULL) {\r
1511 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);\r
1512 }\r
1513\r
1514 if (!NewConfigData->EnableMulticastReceive) {\r
1515 MnpGroupOp (Instance, FALSE, NULL, NULL);\r
1516 }\r
1517\r
1518 //\r
1519 // Save the new configuration data.\r
1520 //\r
1521 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));\r
1522\r
1523 Instance->Configured = (BOOLEAN) (ConfigData != NULL);\r
1524 if (Instance->Configured) {\r
1525 //\r
1526 // The instance is configured, start the Mnp.\r
1527 //\r
1528 Status = MnpStart (\r
1529 MnpServiceData,\r
1530 IsConfigUpdate,\r
1531 (BOOLEAN) !NewConfigData->DisableBackgroundPolling\r
1532 );\r
1533 } else {\r
1534 //\r
1535 // The instance is changed to the unconfigured state, stop the Mnp.\r
1536 //\r
1537 Status = MnpStop (MnpServiceData);\r
1538 }\r
1539\r
1540 return Status;\r
1541}\r
1542\r
1543/**\r
1544 Configure the Snp receive filters according to the instances' receive filter\r
1545 settings.\r
1546\r
1547 @param[in] MnpDeviceData Pointer to the mnp device context data.\r
1548\r
1549 @retval EFI_SUCCESS The receive filters is configured.\r
1550 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due\r
1551 to lack of memory resource.\r
1552\r
1553**/\r
1554EFI_STATUS\r
1555MnpConfigReceiveFilters (\r
1556 IN MNP_DEVICE_DATA *MnpDeviceData\r
1557 )\r
1558{\r
1559 EFI_STATUS Status;\r
1560 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
1561 EFI_MAC_ADDRESS *MCastFilter;\r
1562 UINT32 MCastFilterCnt;\r
1563 UINT32 EnableFilterBits;\r
1564 UINT32 DisableFilterBits;\r
1565 BOOLEAN ResetMCastFilters;\r
1566 LIST_ENTRY *Entry;\r
1567 UINT32 Index;\r
1568 MNP_GROUP_ADDRESS *GroupAddress;\r
1569\r
1570 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
1571\r
1572 Snp = MnpDeviceData->Snp;\r
1573\r
1574 //\r
1575 // Initialize the enable filter and disable filter.\r
1576 //\r
1577 EnableFilterBits = 0;\r
1578 DisableFilterBits = Snp->Mode->ReceiveFilterMask;\r
1579\r
1580 if (MnpDeviceData->UnicastCount != 0) {\r
1581 //\r
1582 // Enable unicast if any instance wants to receive unicast.\r
1583 //\r
1584 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
1585 }\r
1586\r
1587 if (MnpDeviceData->BroadcastCount != 0) {\r
1588 //\r
1589 // Enable broadcast if any instance wants to receive broadcast.\r
1590 //\r
1591 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
1592 }\r
1593\r
1594 MCastFilter = NULL;\r
1595 MCastFilterCnt = 0;\r
1596 ResetMCastFilters = TRUE;\r
1597\r
1598 if ((MnpDeviceData->MulticastCount != 0) && (MnpDeviceData->GroupAddressCount != 0)) {\r
1599 //\r
1600 // There are instances configured to receive multicast and already some group\r
1601 // addresses are joined.\r
1602 //\r
1603\r
1604 ResetMCastFilters = FALSE;\r
1605\r
1606 if (MnpDeviceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {\r
1607 //\r
1608 // The joind group address is less than simple network's maximum count.\r
1609 // Just configure the snp to do the multicast filtering.\r
1610 //\r
1611\r
1612 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
1613\r
1614 //\r
1615 // Allocate pool for the mulicast addresses.\r
1616 //\r
1617 MCastFilterCnt = MnpDeviceData->GroupAddressCount;\r
1618 MCastFilter = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);\r
1619 if (MCastFilter == NULL) {\r
1620 DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));\r
1621\r
1622 return EFI_OUT_OF_RESOURCES;\r
1623 }\r
1624\r
1625 //\r
1626 // Fill the multicast HW address buffer.\r
1627 //\r
1628 Index = 0;\r
1629 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
1630\r
1631 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
1632 CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));\r
1633 Index++;\r
1634\r
1635 ASSERT (Index <= MCastFilterCnt);\r
1636 }\r
1637 } else {\r
1638 //\r
1639 // The maximum multicast is reached, set the filter to be promiscuous\r
1640 // multicast.\r
1641 //\r
1642\r
1643 if ((Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {\r
1644 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
1645 } else {\r
1646 //\r
1647 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,\r
1648 // set the NIC to be promiscuous although this will tremendously degrade\r
1649 // the performance.\r
1650 //\r
1651 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
1652 }\r
1653 }\r
1654 }\r
1655\r
1656 if (MnpDeviceData->PromiscuousCount != 0) {\r
1657 //\r
1658 // Enable promiscuous if any instance wants to receive promiscuous.\r
1659 //\r
1660 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
1661 }\r
1662\r
1663 //\r
1664 // Set the disable filter.\r
1665 //\r
1666 DisableFilterBits ^= EnableFilterBits;\r
1667\r
1668 //\r
1669 // Configure the receive filters of SNP.\r
1670 //\r
1671 Status = Snp->ReceiveFilters (\r
1672 Snp,\r
1673 EnableFilterBits,\r
1674 DisableFilterBits,\r
1675 ResetMCastFilters,\r
1676 MCastFilterCnt,\r
1677 MCastFilter\r
1678 );\r
1679 DEBUG_CODE (\r
1680 if (EFI_ERROR (Status)) {\r
1681 DEBUG (\r
1682 (EFI_D_ERROR,\r
1683 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",\r
1684 Status)\r
1685 );\r
1686 }\r
1687 );\r
1688\r
1689 if (MCastFilter != NULL) {\r
1690 //\r
1691 // Free the buffer used to hold the group addresses.\r
1692 //\r
1693 FreePool (MCastFilter);\r
1694 }\r
1695\r
1696 return Status;\r
1697}\r
1698\r
1699\r
1700/**\r
1701 Add a group address control block which controls the MacAddress for\r
1702 this instance.\r
1703\r
1704 @param[in, out] Instance Pointer to the mnp instance context data.\r
1705 @param[in, out] CtrlBlk Pointer to the group address control block.\r
1706 @param[in, out] GroupAddress Pointer to the group adress.\r
1707 @param[in] MacAddress Pointer to the mac address.\r
1708 @param[in] HwAddressSize The hardware address size.\r
1709\r
1710 @retval EFI_SUCCESS The group address control block is added.\r
1711 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.\r
1712\r
1713**/\r
1714EFI_STATUS\r
1715MnpGroupOpAddCtrlBlk (\r
1716 IN OUT MNP_INSTANCE_DATA *Instance,\r
1717 IN OUT MNP_GROUP_CONTROL_BLOCK *CtrlBlk,\r
1718 IN OUT MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,\r
1719 IN EFI_MAC_ADDRESS *MacAddress,\r
1720 IN UINT32 HwAddressSize\r
1721 )\r
1722{\r
1723 MNP_DEVICE_DATA *MnpDeviceData;\r
1724\r
1725 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1726\r
1727 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1728 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
1729\r
1730 if (GroupAddress == NULL) {\r
1731 ASSERT (MacAddress != NULL);\r
1732\r
1733 //\r
1734 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.\r
1735 //\r
1736 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));\r
1737 if (GroupAddress == NULL) {\r
1738\r
1739 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));\r
1740\r
1741 return EFI_OUT_OF_RESOURCES;\r
1742 }\r
1743\r
1744 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));\r
1745 GroupAddress->RefCnt = 0;\r
1746 InsertTailList (\r
1747 &MnpDeviceData->GroupAddressList,\r
1748 &GroupAddress->AddrEntry\r
1749 );\r
1750 MnpDeviceData->GroupAddressCount++;\r
1751 }\r
1752\r
1753 //\r
1754 // Increase the RefCnt.\r
1755 //\r
1756 GroupAddress->RefCnt++;\r
1757\r
1758 //\r
1759 // Add the CtrlBlk into the instance's GroupCtrlBlkList.\r
1760 //\r
1761 CtrlBlk->GroupAddress = GroupAddress;\r
1762 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);\r
1763\r
1764 return EFI_SUCCESS;\r
1765}\r
1766\r
1767\r
1768/**\r
1769 Delete a group control block from the instance. If the controlled group address's\r
1770 reference count reaches zero, the group address is removed too.\r
1771\r
1772 @param[in] Instance Pointer to the instance context data.\r
1773 @param[in] CtrlBlk Pointer to the group control block to delete.\r
1774\r
1775 @return The group address controlled by the control block is no longer used or not.\r
1776\r
1777**/\r
1778BOOLEAN\r
1779MnpGroupOpDelCtrlBlk (\r
1780 IN MNP_INSTANCE_DATA *Instance,\r
1781 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk\r
1782 )\r
1783{\r
1784 MNP_DEVICE_DATA *MnpDeviceData;\r
1785 MNP_GROUP_ADDRESS *GroupAddress;\r
1786\r
1787 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1788\r
1789 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1790 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
1791\r
1792 //\r
1793 // Remove and free the CtrlBlk.\r
1794 //\r
1795 GroupAddress = CtrlBlk->GroupAddress;\r
1796 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);\r
1797 FreePool (CtrlBlk);\r
1798\r
1799 ASSERT (GroupAddress->RefCnt > 0);\r
1800\r
1801 //\r
1802 // Count down the RefCnt.\r
1803 //\r
1804 GroupAddress->RefCnt--;\r
1805\r
1806 if (GroupAddress->RefCnt == 0) {\r
1807 //\r
1808 // Free this GroupAddress entry if no instance uses it.\r
1809 //\r
1810 MnpDeviceData->GroupAddressCount--;\r
1811 RemoveEntryList (&GroupAddress->AddrEntry);\r
1812 FreePool (GroupAddress);\r
1813\r
1814 return TRUE;\r
1815 }\r
1816\r
1817 return FALSE;\r
1818}\r
1819\r
1820\r
1821/**\r
1822 Do the group operations for this instance.\r
1823\r
1824 @param[in, out] Instance Pointer to the instance context data.\r
1825 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to\r
1826 leave a group/groups.\r
1827 @param[in] MacAddress Pointer to the group address to join or leave.\r
1828 @param[in] CtrlBlk Pointer to the group control block if JoinFlag\r
1829 is FALSE.\r
1830\r
1831 @retval EFI_SUCCESS The group operation finished.\r
1832 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.\r
1833 @retval Others Other errors as indicated.\r
1834\r
1835**/\r
1836EFI_STATUS\r
1837MnpGroupOp (\r
1838 IN OUT MNP_INSTANCE_DATA *Instance,\r
1839 IN BOOLEAN JoinFlag,\r
1840 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,\r
1841 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL\r
1842 )\r
1843{\r
1844 MNP_DEVICE_DATA *MnpDeviceData;\r
1845 LIST_ENTRY *Entry;\r
1846 LIST_ENTRY *NextEntry;\r
1847 MNP_GROUP_ADDRESS *GroupAddress;\r
1848 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
1849 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;\r
1850 EFI_STATUS Status;\r
1851 BOOLEAN AddressExist;\r
1852 BOOLEAN NeedUpdate;\r
1853\r
1854 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1855\r
1856 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1857 SnpMode = MnpDeviceData->Snp->Mode;\r
1858\r
1859 if (JoinFlag) {\r
1860 //\r
1861 // A new gropu address is to be added.\r
1862 //\r
1863 GroupAddress = NULL;\r
1864 AddressExist = FALSE;\r
1865\r
1866 //\r
1867 // Allocate memory for the control block.\r
1868 //\r
1869 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));\r
1870 if (NewCtrlBlk == NULL) {\r
1871 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));\r
1872\r
1873 return EFI_OUT_OF_RESOURCES;\r
1874 }\r
1875\r
1876 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
1877 //\r
1878 // Check whether the MacAddress is already joined by other instances.\r
1879 //\r
1880 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
1881 if (CompareMem (MacAddress, &GroupAddress->Address, SnpMode->HwAddressSize) == 0) {\r
1882 AddressExist = TRUE;\r
1883 break;\r
1884 }\r
1885 }\r
1886\r
1887 if (!AddressExist) {\r
1888 GroupAddress = NULL;\r
1889 }\r
1890\r
1891 //\r
1892 // Add the GroupAddress for this instance.\r
1893 //\r
1894 Status = MnpGroupOpAddCtrlBlk (\r
1895 Instance,\r
1896 NewCtrlBlk,\r
1897 GroupAddress,\r
1898 MacAddress,\r
1899 SnpMode->HwAddressSize\r
1900 );\r
1901 if (EFI_ERROR (Status)) {\r
1902 return Status;\r
1903 }\r
1904\r
1905 NeedUpdate = TRUE;\r
1906 } else {\r
1907 if (MacAddress != NULL) {\r
1908 ASSERT (CtrlBlk != NULL);\r
1909\r
1910 //\r
1911 // Leave the specific multicast mac address.\r
1912 //\r
1913 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);\r
1914 } else {\r
1915 //\r
1916 // Leave all multicast mac addresses.\r
1917 //\r
1918 NeedUpdate = FALSE;\r
1919\r
1920 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {\r
1921\r
1922 NewCtrlBlk = NET_LIST_USER_STRUCT (\r
1923 Entry,\r
1924 MNP_GROUP_CONTROL_BLOCK,\r
1925 CtrlBlkEntry\r
1926 );\r
1927 //\r
1928 // Update is required if the group address left is no longer used\r
1929 // by other instances.\r
1930 //\r
1931 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);\r
1932 }\r
1933 }\r
1934 }\r
1935\r
1936 Status = EFI_SUCCESS;\r
1937\r
1938 if (NeedUpdate) {\r
1939 //\r
1940 // Reconfigure the receive filters if necessary.\r
1941 //\r
1942 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
1943 }\r
1944\r
1945 return Status;\r
1946}\r