]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
CommitLineData
8a67d61d 1/** @file\r
c57273b0 2 Implementation of Managed Network Protocol private services.\r
6e4bac4d 3\r
d1102dba 4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
779ae357 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
8a67d61d 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
8a67d61d 14**/\r
15\r
8a67d61d 16#include "MnpImpl.h"\r
779ae357 17#include "MnpVlan.h"\r
8a67d61d 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
87f89c08 36 10000000,\r
37 10000000,\r
8a67d61d 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
8a67d61d 48/**\r
779ae357 49 Add Count of net buffers to MnpDeviceData->FreeNbufQue. The length of the net\r
50 buffer is specified by MnpDeviceData->BufferLength.\r
8a67d61d 51\r
779ae357 52 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
6e4bac4d 53 @param[in] Count Number of NET_BUFFERs to add.\r
8a67d61d 54\r
779ae357 55 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated\r
56 and added to MnpDeviceData->FreeNbufQue.\r
8a67d61d 57 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.\r
58\r
59**/\r
8a67d61d 60EFI_STATUS\r
61MnpAddFreeNbuf (\r
779ae357 62 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
63 IN UINTN Count\r
8a67d61d 64 )\r
65{\r
66 EFI_STATUS Status;\r
67 UINTN Index;\r
68 NET_BUF *Nbuf;\r
69\r
779ae357 70 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
71 ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));\r
8a67d61d 72\r
73 Status = EFI_SUCCESS;\r
8a67d61d 74 for (Index = 0; Index < Count; Index++) {\r
779ae357 75 Nbuf = NetbufAlloc (MnpDeviceData->BufferLength + MnpDeviceData->PaddingSize);\r
8a67d61d 76 if (Nbuf == NULL) {\r
e48e37fc 77 DEBUG ((EFI_D_ERROR, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));\r
779ae357 78\r
8a67d61d 79 Status = EFI_OUT_OF_RESOURCES;\r
80 break;\r
81 }\r
82\r
779ae357 83 if (MnpDeviceData->PaddingSize > 0) {\r
772db4bb 84 //\r
85 // Pad padding bytes before the media header\r
86 //\r
779ae357 87 NetbufAllocSpace (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_TAIL);\r
88 NetbufTrim (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_HEAD);\r
772db4bb 89 }\r
90\r
779ae357 91 NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);\r
8a67d61d 92 }\r
93\r
779ae357 94 MnpDeviceData->NbufCnt += Index;\r
8a67d61d 95 return Status;\r
96}\r
97\r
98\r
99/**\r
779ae357 100 Allocate a free NET_BUF from MnpDeviceData->FreeNbufQue. If there is none\r
8a67d61d 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
779ae357 104 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
8a67d61d 105\r
779ae357 106 @return Pointer to the allocated free NET_BUF structure, if NULL the\r
c57273b0 107 operation is failed.\r
8a67d61d 108\r
109**/\r
110NET_BUF *\r
111MnpAllocNbuf (\r
779ae357 112 IN OUT MNP_DEVICE_DATA *MnpDeviceData\r
8a67d61d 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
779ae357 120 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 121\r
779ae357 122 FreeNbufQue = &MnpDeviceData->FreeNbufQue;\r
123 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 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
779ae357 129 if ((MnpDeviceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {\r
e48e37fc 130 DEBUG (\r
131 (EFI_D_ERROR,\r
132 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",\r
779ae357 133 MnpDeviceData)\r
8a67d61d 134 );\r
135\r
136 Nbuf = NULL;\r
137 goto ON_EXIT;\r
138 }\r
139\r
779ae357 140 Status = MnpAddFreeNbuf (MnpDeviceData, MNP_NET_BUFFER_INCREASEMENT);\r
8a67d61d 141 if (EFI_ERROR (Status)) {\r
e48e37fc 142 DEBUG (\r
143 (EFI_D_ERROR,\r
144 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",\r
8a67d61d 145 Status)\r
146 );\r
779ae357 147\r
8a67d61d 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
e48e37fc 165 gBS->RestoreTPL (OldTpl);\r
8a67d61d 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
779ae357 174 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
5fe2f07f 175 @param[in, out] Nbuf Pointer to the NET_BUF to free.\r
6e4bac4d 176\r
8a67d61d 177**/\r
178VOID\r
179MnpFreeNbuf (\r
779ae357 180 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
6e4bac4d 181 IN OUT NET_BUF *Nbuf\r
8a67d61d 182 )\r
183{\r
184 EFI_TPL OldTpl;\r
185\r
779ae357 186 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 187 ASSERT (Nbuf->RefCnt > 1);\r
188\r
e48e37fc 189 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 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
779ae357 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
8a67d61d 207 }\r
208\r
e48e37fc 209 gBS->RestoreTPL (OldTpl);\r
8a67d61d 210}\r
211\r
05074499
FS
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
54d7177c 238 TxBufWrap = (MNP_TX_BUF_WRAP*) AllocatePool (OFFSET_OF (MNP_TX_BUF_WRAP, TxBuf) + MnpDeviceData->BufferLength );\r
05074499
FS
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
d1102dba 258 in the queue, first try to recycle some from SNP, then try to allocate some and add\r
05074499
FS
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
d1102dba 277\r
05074499
FS
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
d1102dba 372\r
05074499
FS
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
8a67d61d 414\r
415/**\r
779ae357 416 Initialize the mnp device context data.\r
8a67d61d 417\r
779ae357 418 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
6e4bac4d 419 @param[in] ImageHandle The driver image handle.\r
420 @param[in] ControllerHandle Handle of device to bind driver to.\r
8a67d61d 421\r
422 @retval EFI_SUCCESS The mnp service context is initialized.\r
6e4bac4d 423 @retval EFI_UNSUPPORTED ControllerHandle does not support Simple Network Protocol.\r
424 @retval Others Other errors as indicated.\r
8a67d61d 425\r
426**/\r
427EFI_STATUS\r
779ae357 428MnpInitializeDeviceData (\r
429 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
430 IN EFI_HANDLE ImageHandle,\r
431 IN EFI_HANDLE ControllerHandle\r
8a67d61d 432 )\r
433{\r
779ae357 434 EFI_STATUS Status;\r
435 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
436 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
8a67d61d 437\r
779ae357 438 MnpDeviceData->Signature = MNP_DEVICE_DATA_SIGNATURE;\r
439 MnpDeviceData->ImageHandle = ImageHandle;\r
440 MnpDeviceData->ControllerHandle = ControllerHandle;\r
8a67d61d 441\r
442 //\r
779ae357 443 // Copy the MNP Protocol interfaces from the template.\r
8a67d61d 444 //\r
779ae357 445 CopyMem (&MnpDeviceData->VlanConfig, &mVlanConfigProtocolTemplate, sizeof (EFI_VLAN_CONFIG_PROTOCOL));\r
8a67d61d 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
779ae357 465 SnpMode = Snp->Mode;\r
466 MnpDeviceData->Snp = Snp;\r
8a67d61d 467\r
468 //\r
469 // Initialize the lists.\r
470 //\r
779ae357 471 InitializeListHead (&MnpDeviceData->ServiceList);\r
472 InitializeListHead (&MnpDeviceData->GroupAddressList);\r
8a67d61d 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
779ae357 478 //\r
479 MnpDeviceData->BufferLength = SnpMode->MediaHeaderSize + NET_VLAN_TAG_LEN + SnpMode->MaxPacketSize + NET_ETHER_FCS_SIZE;\r
8a67d61d 480\r
772db4bb 481 //\r
e48e37fc 482 // Make sure the protocol headers immediately following the media header\r
779ae357 483 // 4-byte aligned, and also preserve additional space for VLAN tag\r
772db4bb 484 //\r
779ae357 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
772db4bb 494\r
8a67d61d 495 //\r
496 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.\r
497 //\r
779ae357 498 NetbufQueInit (&MnpDeviceData->FreeNbufQue);\r
499 Status = MnpAddFreeNbuf (MnpDeviceData, MNP_INIT_NET_BUFFER_NUM);\r
8a67d61d 500 if (EFI_ERROR (Status)) {\r
779ae357 501 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: MnpAddFreeNbuf failed, %r.\n", Status));\r
8a67d61d 502\r
8a67d61d 503 goto ERROR;\r
504 }\r
779ae357 505\r
8a67d61d 506 //\r
507 // Get one NET_BUF from the FreeNbufQue for rx cache.\r
508 //\r
779ae357 509 MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);\r
8a67d61d 510 NetbufAllocSpace (\r
779ae357 511 MnpDeviceData->RxNbufCache,\r
512 MnpDeviceData->BufferLength,\r
8a67d61d 513 NET_BUF_TAIL\r
514 );\r
515\r
516 //\r
517 // Allocate buffer pool for tx.\r
518 //\r
05074499
FS
519 InitializeListHead (&MnpDeviceData->FreeTxBufList);\r
520 InitializeListHead (&MnpDeviceData->AllTxBufList);\r
521 MnpDeviceData->TxBufCount = 0;\r
8a67d61d 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
e48e37fc 528 TPL_CALLBACK,\r
8a67d61d 529 MnpSystemPoll,\r
779ae357 530 MnpDeviceData,\r
531 &MnpDeviceData->PollTimer\r
8a67d61d 532 );\r
533 if (EFI_ERROR (Status)) {\r
779ae357 534 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for poll timer failed.\n"));\r
8a67d61d 535\r
8a67d61d 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
e48e37fc 544 TPL_CALLBACK,\r
8a67d61d 545 MnpCheckPacketTimeout,\r
779ae357 546 MnpDeviceData,\r
547 &MnpDeviceData->TimeoutCheckTimer\r
8a67d61d 548 );\r
549 if (EFI_ERROR (Status)) {\r
779ae357 550 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for packet timeout check failed.\n"));\r
8a67d61d 551\r
8a67d61d 552 goto ERROR;\r
553 }\r
554\r
dd29f3ed 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
8a67d61d 571ERROR:\r
8a67d61d 572 if (EFI_ERROR (Status)) {\r
573 //\r
574 // Free the dynamic allocated resources if necessary.\r
575 //\r
779ae357 576 if (MnpDeviceData->MacString != NULL) {\r
577 FreePool (MnpDeviceData->MacString);\r
8a67d61d 578 }\r
579\r
779ae357 580 if (MnpDeviceData->TimeoutCheckTimer != NULL) {\r
581 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
8a67d61d 582 }\r
583\r
dd29f3ed 584 if (MnpDeviceData->MediaDetectTimer != NULL) {\r
585 gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
586 }\r
587\r
779ae357 588 if (MnpDeviceData->PollTimer != NULL) {\r
589 gBS->CloseEvent (MnpDeviceData->PollTimer);\r
8a67d61d 590 }\r
591\r
779ae357 592 if (MnpDeviceData->RxNbufCache != NULL) {\r
593 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
594 }\r
8a67d61d 595\r
779ae357 596 if (MnpDeviceData->FreeNbufQue.BufNum != 0) {\r
597 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
8a67d61d 598 }\r
779ae357 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
8a67d61d 609 }\r
610\r
611 return Status;\r
612}\r
613\r
614\r
615/**\r
779ae357 616 Destroy the MNP device context data.\r
8a67d61d 617\r
779ae357 618 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
619 @param[in] ImageHandle The driver image handle.\r
6e4bac4d 620\r
8a67d61d 621**/\r
622VOID\r
779ae357 623MnpDestroyDeviceData (\r
624 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
625 IN EFI_HANDLE ImageHandle\r
8a67d61d 626 )\r
627{\r
05074499
FS
628 LIST_ENTRY *Entry;\r
629 LIST_ENTRY *NextEntry;\r
630 MNP_TX_BUF_WRAP *TxBufWrap;\r
631\r
779ae357 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
8a67d61d 640\r
641 //\r
642 // The GroupAddressList must be empty.\r
643 //\r
779ae357 644 ASSERT (IsListEmpty (&MnpDeviceData->GroupAddressList));\r
8a67d61d 645\r
646 //\r
647 // Close the event.\r
648 //\r
dd29f3ed 649 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
650 gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
651 gBS->CloseEvent (MnpDeviceData->PollTimer);\r
8a67d61d 652\r
653 //\r
05074499 654 // Free the Tx buffer pool.\r
8a67d61d 655 //\r
05074499
FS
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
8a67d61d 664\r
665 //\r
666 // Free the RxNbufCache.\r
667 //\r
779ae357 668 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
8a67d61d 669\r
670 //\r
671 // Flush the FreeNbufQue.\r
672 //\r
779ae357 673 MnpDeviceData->NbufCnt -= MnpDeviceData->FreeNbufQue.BufNum;\r
674 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
8a67d61d 675\r
779ae357 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
8a67d61d 697\r
779ae357 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
8a67d61d 711\r
779ae357 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
8a67d61d 720 }\r
e21ef3a2 721\r
722 //\r
779ae357 723 // Add to MNP service list\r
e21ef3a2 724 //\r
779ae357 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
8a67d61d 876}\r
877\r
216f7970 878/**\r
879 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
d1102dba 880\r
216f7970 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
1f7eb561 889EFIAPI\r
216f7970 890MnpDestoryChildEntry (\r
891 IN LIST_ENTRY *Entry,\r
892 IN VOID *Context\r
1f7eb561 893 )\r
216f7970 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
779ae357 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
216f7970 917 LIST_ENTRY *List;\r
918 EFI_STATUS Status;\r
919 UINTN ListLength;\r
d1102dba 920\r
216f7970 921 List = &MnpServiceData->ChildrenList;\r
d1102dba 922\r
216f7970 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
779ae357 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
8a67d61d 966\r
967/**\r
968 Initialize the mnp instance context data.\r
969\r
6e4bac4d 970 @param[in] MnpServiceData Pointer to the mnp service context data.\r
779ae357 971 @param[in, out] Instance Pointer to the mnp instance context data\r
6e4bac4d 972 to initialize.\r
8a67d61d 973\r
8a67d61d 974**/\r
975VOID\r
976MnpInitializeInstanceData (\r
779ae357 977 IN MNP_SERVICE_DATA *MnpServiceData,\r
978 IN OUT MNP_INSTANCE_DATA *Instance\r
8a67d61d 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
687a2e5f 992 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));\r
8a67d61d 993\r
994 //\r
995 // Copy the default config data.\r
996 //\r
687a2e5f 997 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));\r
8a67d61d 998\r
999 //\r
1000 // Initialize the lists.\r
1001 //\r
e48e37fc 1002 InitializeListHead (&Instance->GroupCtrlBlkList);\r
1003 InitializeListHead (&Instance->RcvdPacketQueue);\r
1004 InitializeListHead (&Instance->RxDeliveredPacketQueue);\r
8a67d61d 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
6e4bac4d 1019 Check whether the token specified by Arg matches the token in Item.\r
8a67d61d 1020\r
3e8c18da 1021 @param[in] Map Pointer to the NET_MAP.\r
6e4bac4d 1022 @param[in] Item Pointer to the NET_MAP_ITEM.\r
3e8c18da 1023 @param[in] Arg Pointer to the Arg, it's a pointer to the token to\r
8a67d61d 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
e798cd87 1033EFIAPI\r
8a67d61d 1034MnpTokenExist (\r
779ae357 1035 IN NET_MAP *Map,\r
1036 IN NET_MAP_ITEM *Item,\r
1037 IN VOID *Arg\r
8a67d61d 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
8a67d61d 1057/**\r
1058 Cancel the token specified by Arg if it matches the token in Item.\r
1059\r
6e4bac4d 1060 @param[in, out] Map Pointer to the NET_MAP.\r
1061 @param[in, out] Item Pointer to the NET_MAP_ITEM.\r
779ae357 1062 @param[in] Arg Pointer to the Arg, it's a pointer to the\r
6e4bac4d 1063 token to cancel.\r
8a67d61d 1064\r
779ae357 1065 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,\r
c57273b0 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
8a67d61d 1070\r
1071**/\r
1072EFI_STATUS\r
e798cd87 1073EFIAPI\r
8a67d61d 1074MnpCancelTokens (\r
779ae357 1075 IN OUT NET_MAP *Map,\r
1076 IN OUT NET_MAP_ITEM *Item,\r
1077 IN VOID *Arg\r
8a67d61d 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
779ae357 1089 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
8a67d61d 1090\r
1091 //\r
36ee91ca 1092 // Remove the item from the map.\r
8a67d61d 1093 //\r
36ee91ca 1094 NetMapRemoveItem (Map, Item, NULL);\r
8a67d61d 1095\r
1096 //\r
36ee91ca 1097 // Cancel this token with status set to EFI_ABORTED.\r
8a67d61d 1098 //\r
36ee91ca 1099 TokenToCancel->Status = EFI_ABORTED;\r
1100 gBS->SignalEvent (TokenToCancel->Event);\r
8a67d61d 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
3e8c18da 1116 @param[in] Snp Pointer to the simple network protocol.\r
8a67d61d 1117\r
1118 @retval EFI_SUCCESS The simple network protocol is started.\r
6e4bac4d 1119 @retval Others Other errors as indicated.\r
8a67d61d 1120\r
1121**/\r
8a67d61d 1122EFI_STATUS\r
1123MnpStartSnp (\r
779ae357 1124 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
8a67d61d 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
779ae357 1140 Status = Snp->Initialize (Snp, 0, 0);\r
8a67d61d 1141 }\r
1142\r
1143 return Status;\r
1144}\r
1145\r
1146\r
1147/**\r
1148 Stop the simple network.\r
1149\r
05074499 1150 @param[in] MnpDeviceData Pointer to the MNP_DEVICE_DATA.\r
8a67d61d 1151\r
1152 @retval EFI_SUCCESS The simple network is stopped.\r
6e4bac4d 1153 @retval Others Other errors as indicated.\r
8a67d61d 1154\r
1155**/\r
8a67d61d 1156EFI_STATUS\r
1157MnpStopSnp (\r
05074499 1158 IN MNP_DEVICE_DATA *MnpDeviceData\r
8a67d61d 1159 )\r
1160{\r
1161 EFI_STATUS Status;\r
05074499 1162 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
d1102dba 1163\r
05074499 1164 Snp = MnpDeviceData->Snp;\r
8a67d61d 1165 ASSERT (Snp != NULL);\r
1166\r
05074499
FS
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
8a67d61d 1175 //\r
1176 // Shut down the simple network.\r
1177 //\r
779ae357 1178 Status = Snp->Shutdown (Snp);\r
8a67d61d 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
6e4bac4d 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
8a67d61d 1198\r
6e4bac4d 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
8a67d61d 1202\r
1203**/\r
8a67d61d 1204EFI_STATUS\r
1205MnpStart (\r
779ae357 1206 IN OUT MNP_SERVICE_DATA *MnpServiceData,\r
1207 IN BOOLEAN IsConfigUpdate,\r
1208 IN BOOLEAN EnableSystemPoll\r
8a67d61d 1209 )\r
1210{\r
1211 EFI_STATUS Status;\r
1212 EFI_TIMER_DELAY TimerOpType;\r
779ae357 1213 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1214\r
1215 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
1216\r
779ae357 1217 Status = EFI_SUCCESS;\r
1218 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
8a67d61d 1219\r
1220 if (!IsConfigUpdate) {\r
1221 //\r
1222 // If it's not a configuration update, increase the configured children number.\r
1223 //\r
779ae357 1224 MnpDeviceData->ConfiguredChildrenNumber++;\r
8a67d61d 1225\r
779ae357 1226 if (MnpDeviceData->ConfiguredChildrenNumber == 1) {\r
8a67d61d 1227 //\r
1228 // It's the first configured child, start the simple network.\r
1229 //\r
779ae357 1230 Status = MnpStartSnp (MnpDeviceData->Snp);\r
8a67d61d 1231 if (EFI_ERROR (Status)) {\r
e48e37fc 1232 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));\r
779ae357 1233\r
8a67d61d 1234 goto ErrorExit;\r
1235 }\r
1236\r
1237 //\r
1238 // Start the timeout timer.\r
1239 //\r
1240 Status = gBS->SetTimer (\r
779ae357 1241 MnpDeviceData->TimeoutCheckTimer,\r
8a67d61d 1242 TimerPeriodic,\r
1243 MNP_TIMEOUT_CHECK_INTERVAL\r
1244 );\r
1245 if (EFI_ERROR (Status)) {\r
e48e37fc 1246 DEBUG (\r
1247 (EFI_D_ERROR,\r
1248 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",\r
8a67d61d 1249 Status)\r
1250 );\r
779ae357 1251\r
8a67d61d 1252 goto ErrorExit;\r
1253 }\r
dd29f3ed 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
8a67d61d 1272 }\r
1273 }\r
1274\r
779ae357 1275 if (MnpDeviceData->EnableSystemPoll ^ EnableSystemPoll) {\r
8a67d61d 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
779ae357 1282 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);\r
8a67d61d 1283 if (EFI_ERROR (Status)) {\r
e48e37fc 1284 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));\r
779ae357 1285\r
8a67d61d 1286 goto ErrorExit;\r
1287 }\r
1288\r
779ae357 1289 MnpDeviceData->EnableSystemPoll = EnableSystemPoll;\r
8a67d61d 1290 }\r
1291\r
1292 //\r
1293 // Change the receive filters if need.\r
1294 //\r
779ae357 1295 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
8a67d61d 1296\r
1297ErrorExit:\r
8a67d61d 1298 return Status;\r
1299}\r
1300\r
1301\r
1302/**\r
1303 Stop the managed network.\r
1304\r
6e4bac4d 1305 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
8a67d61d 1306\r
6e4bac4d 1307 @retval EFI_SUCCESS The managed network is stopped.\r
1308 @retval Others Other errors as indicated.\r
8a67d61d 1309\r
1310**/\r
8a67d61d 1311EFI_STATUS\r
1312MnpStop (\r
779ae357 1313 IN OUT MNP_SERVICE_DATA *MnpServiceData\r
8a67d61d 1314 )\r
1315{\r
779ae357 1316 EFI_STATUS Status;\r
1317 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1318\r
1319 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
779ae357 1320 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1321 ASSERT (MnpDeviceData->ConfiguredChildrenNumber > 0);\r
8a67d61d 1322\r
1323 //\r
1324 // Configure the receive filters.\r
1325 //\r
779ae357 1326 MnpConfigReceiveFilters (MnpDeviceData);\r
8a67d61d 1327\r
1328 //\r
1329 // Decrease the children number.\r
1330 //\r
779ae357 1331 MnpDeviceData->ConfiguredChildrenNumber--;\r
8a67d61d 1332\r
779ae357 1333 if (MnpDeviceData->ConfiguredChildrenNumber > 0) {\r
8a67d61d 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
779ae357 1344 if (MnpDeviceData->EnableSystemPoll) {\r
8a67d61d 1345 //\r
1346 // The system poll in on, cancel the poll timer.\r
1347 //\r
779ae357 1348 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerCancel, 0);\r
1349 MnpDeviceData->EnableSystemPoll = FALSE;\r
8a67d61d 1350 }\r
1351\r
1352 //\r
1353 // Cancel the timeout timer.\r
1354 //\r
779ae357 1355 Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0);\r
8a67d61d 1356\r
dd29f3ed 1357 //\r
1358 // Cancel the media detect timer.\r
1359 //\r
1360 Status = gBS->SetTimer (MnpDeviceData->MediaDetectTimer, TimerCancel, 0);\r
1361\r
8a67d61d 1362 //\r
1363 // Stop the simple network.\r
1364 //\r
05074499 1365 Status = MnpStopSnp (MnpDeviceData);\r
8a67d61d 1366 return Status;\r
1367}\r
1368\r
1369\r
1370/**\r
1371 Flush the instance's received data.\r
1372\r
6e4bac4d 1373 @param[in, out] Instance Pointer to the mnp instance context data.\r
8a67d61d 1374\r
8a67d61d 1375**/\r
1376VOID\r
1377MnpFlushRcvdDataQueue (\r
779ae357 1378 IN OUT MNP_INSTANCE_DATA *Instance\r
8a67d61d 1379 )\r
1380{\r
779ae357 1381 EFI_TPL OldTpl;\r
8a67d61d 1382 MNP_RXDATA_WRAP *RxDataWrap;\r
1383\r
1384 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1385\r
e48e37fc 1386 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 1387\r
e48e37fc 1388 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {\r
8a67d61d 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
e48e37fc 1403 gBS->RestoreTPL (OldTpl);\r
8a67d61d 1404}\r
1405\r
1406\r
1407/**\r
1408 Configure the Instance using ConfigData.\r
1409\r
6e4bac4d 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
8a67d61d 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
6e4bac4d 1417 @retval Others Other errors as indicated.\r
8a67d61d 1418\r
1419**/\r
1420EFI_STATUS\r
1421MnpConfigureInstance (\r
779ae357 1422 IN OUT MNP_INSTANCE_DATA *Instance,\r
1423 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL\r
8a67d61d 1424 )\r
1425{\r
1426 EFI_STATUS Status;\r
1427 MNP_SERVICE_DATA *MnpServiceData;\r
779ae357 1428 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 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
779ae357 1445 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1446 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 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
779ae357 1469 MnpDeviceData->UnicastCount--;\r
8a67d61d 1470 }\r
1471\r
1472 if (OldConfigData->EnableMulticastReceive) {\r
779ae357 1473 MnpDeviceData->MulticastCount--;\r
8a67d61d 1474 }\r
1475\r
1476 if (OldConfigData->EnableBroadcastReceive) {\r
779ae357 1477 MnpDeviceData->BroadcastCount--;\r
8a67d61d 1478 }\r
1479\r
1480 if (OldConfigData->EnablePromiscuousReceive) {\r
779ae357 1481 MnpDeviceData->PromiscuousCount--;\r
8a67d61d 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
779ae357 1489 MnpDeviceData->UnicastCount++;\r
8a67d61d 1490 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;\r
1491 }\r
1492\r
1493 if (NewConfigData->EnableMulticastReceive) {\r
779ae357 1494 MnpDeviceData->MulticastCount++;\r
8a67d61d 1495 }\r
1496\r
1497 if (NewConfigData->EnableBroadcastReceive) {\r
779ae357 1498 MnpDeviceData->BroadcastCount++;\r
8a67d61d 1499 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;\r
1500 }\r
1501\r
1502 if (NewConfigData->EnablePromiscuousReceive) {\r
779ae357 1503 MnpDeviceData->PromiscuousCount++;\r
8a67d61d 1504 }\r
1505\r
1506 if (OldConfigData->FlushQueuesOnReset) {\r
8a67d61d 1507 MnpFlushRcvdDataQueue (Instance);\r
1508 }\r
1509\r
1510 if (ConfigData == NULL) {\r
36ee91ca 1511 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);\r
8a67d61d 1512 }\r
1513\r
1514 if (!NewConfigData->EnableMulticastReceive) {\r
8a67d61d 1515 MnpGroupOp (Instance, FALSE, NULL, NULL);\r
1516 }\r
1517\r
1518 //\r
1519 // Save the new configuration data.\r
1520 //\r
687a2e5f 1521 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));\r
8a67d61d 1522\r
779ae357 1523 Instance->Configured = (BOOLEAN) (ConfigData != NULL);\r
8a67d61d 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
4eb65aff 1531 (BOOLEAN) !NewConfigData->DisableBackgroundPolling\r
8a67d61d 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
aeddd425 1543/**\r
1544 Configure the Snp receive filters according to the instances' receive filter\r
1545 settings.\r
1546\r
779ae357 1547 @param[in] MnpDeviceData Pointer to the mnp device context data.\r
aeddd425 1548\r
1549 @retval EFI_SUCCESS The receive filters is configured.\r
779ae357 1550 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due\r
aeddd425 1551 to lack of memory resource.\r
1552\r
1553**/\r
1554EFI_STATUS\r
1555MnpConfigReceiveFilters (\r
779ae357 1556 IN MNP_DEVICE_DATA *MnpDeviceData\r
aeddd425 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
779ae357 1570 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
aeddd425 1571\r
779ae357 1572 Snp = MnpDeviceData->Snp;\r
aeddd425 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
779ae357 1580 if (MnpDeviceData->UnicastCount != 0) {\r
aeddd425 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
779ae357 1587 if (MnpDeviceData->BroadcastCount != 0) {\r
aeddd425 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
779ae357 1598 if ((MnpDeviceData->MulticastCount != 0) && (MnpDeviceData->GroupAddressCount != 0)) {\r
aeddd425 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
779ae357 1606 if (MnpDeviceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {\r
aeddd425 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
779ae357 1617 MCastFilterCnt = MnpDeviceData->GroupAddressCount;\r
aeddd425 1618 MCastFilter = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);\r
1619 if (MCastFilter == NULL) {\r
aeddd425 1620 DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));\r
779ae357 1621\r
aeddd425 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
779ae357 1629 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
aeddd425 1630\r
779ae357 1631 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
aeddd425 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
779ae357 1656 if (MnpDeviceData->PromiscuousCount != 0) {\r
aeddd425 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
779ae357 1681 DEBUG (\r
1682 (EFI_D_ERROR,\r
1683 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",\r
1684 Status)\r
1685 );\r
1686 }\r
aeddd425 1687 );\r
1688\r
1689 if (MCastFilter != NULL) {\r
1690 //\r
1691 // Free the buffer used to hold the group addresses.\r
1692 //\r
766c7483 1693 FreePool (MCastFilter);\r
aeddd425 1694 }\r
1695\r
1696 return Status;\r
1697}\r
8a67d61d 1698\r
8a67d61d 1699\r
1700/**\r
1701 Add a group address control block which controls the MacAddress for\r
1702 this instance.\r
1703\r
6e4bac4d 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
8a67d61d 1709\r
6e4bac4d 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
8a67d61d 1712\r
1713**/\r
8a67d61d 1714EFI_STATUS\r
1715MnpGroupOpAddCtrlBlk (\r
779ae357 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
8a67d61d 1721 )\r
1722{\r
779ae357 1723 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1724\r
1725 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1726\r
779ae357 1727 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1728 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1729\r
1730 if (GroupAddress == NULL) {\r
8a67d61d 1731 ASSERT (MacAddress != NULL);\r
1732\r
1733 //\r
1734 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.\r
1735 //\r
e48e37fc 1736 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));\r
8a67d61d 1737 if (GroupAddress == NULL) {\r
1738\r
e48e37fc 1739 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));\r
8a67d61d 1740\r
1741 return EFI_OUT_OF_RESOURCES;\r
1742 }\r
1743\r
687a2e5f 1744 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));\r
779ae357 1745 GroupAddress->RefCnt = 0;\r
e48e37fc 1746 InsertTailList (\r
779ae357 1747 &MnpDeviceData->GroupAddressList,\r
8a67d61d 1748 &GroupAddress->AddrEntry\r
1749 );\r
779ae357 1750 MnpDeviceData->GroupAddressCount++;\r
8a67d61d 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
e48e37fc 1762 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);\r
8a67d61d 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
3e8c18da 1772 @param[in] Instance Pointer to the instance context data.\r
1773 @param[in] CtrlBlk Pointer to the group control block to delete.\r
8a67d61d 1774\r
1775 @return The group address controlled by the control block is no longer used or not.\r
1776\r
1777**/\r
8a67d61d 1778BOOLEAN\r
1779MnpGroupOpDelCtrlBlk (\r
779ae357 1780 IN MNP_INSTANCE_DATA *Instance,\r
1781 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk\r
8a67d61d 1782 )\r
1783{\r
779ae357 1784 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1785 MNP_GROUP_ADDRESS *GroupAddress;\r
1786\r
1787 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1788\r
779ae357 1789 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1790 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1791\r
1792 //\r
1793 // Remove and free the CtrlBlk.\r
1794 //\r
1795 GroupAddress = CtrlBlk->GroupAddress;\r
e48e37fc 1796 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);\r
766c7483 1797 FreePool (CtrlBlk);\r
8a67d61d 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
779ae357 1810 MnpDeviceData->GroupAddressCount--;\r
e48e37fc 1811 RemoveEntryList (&GroupAddress->AddrEntry);\r
766c7483 1812 FreePool (GroupAddress);\r
8a67d61d 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
6e4bac4d 1824 @param[in, out] Instance Pointer to the instance context data.\r
779ae357 1825 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to\r
6e4bac4d 1826 leave a group/groups.\r
1827 @param[in] MacAddress Pointer to the group address to join or leave.\r
779ae357 1828 @param[in] CtrlBlk Pointer to the group control block if JoinFlag\r
6e4bac4d 1829 is FALSE.\r
8a67d61d 1830\r
6e4bac4d 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
8a67d61d 1834\r
1835**/\r
1836EFI_STATUS\r
1837MnpGroupOp (\r
779ae357 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
8a67d61d 1842 )\r
1843{\r
779ae357 1844 MNP_DEVICE_DATA *MnpDeviceData;\r
e48e37fc 1845 LIST_ENTRY *Entry;\r
1846 LIST_ENTRY *NextEntry;\r
8a67d61d 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
779ae357 1856 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1857 SnpMode = MnpDeviceData->Snp->Mode;\r
8a67d61d 1858\r
1859 if (JoinFlag) {\r
1860 //\r
1861 // A new gropu address is to be added.\r
1862 //\r
8a67d61d 1863 GroupAddress = NULL;\r
1864 AddressExist = FALSE;\r
1865\r
1866 //\r
1867 // Allocate memory for the control block.\r
1868 //\r
779ae357 1869 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));\r
8a67d61d 1870 if (NewCtrlBlk == NULL) {\r
e48e37fc 1871 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));\r
779ae357 1872\r
8a67d61d 1873 return EFI_OUT_OF_RESOURCES;\r
1874 }\r
1875\r
779ae357 1876 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
8a67d61d 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
779ae357 1881 if (CompareMem (MacAddress, &GroupAddress->Address, SnpMode->HwAddressSize) == 0) {\r
8a67d61d 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
8a67d61d 1902 return Status;\r
1903 }\r
1904\r
1905 NeedUpdate = TRUE;\r
1906 } else {\r
8a67d61d 1907 if (MacAddress != NULL) {\r
8a67d61d 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
779ae357 1942 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
8a67d61d 1943 }\r
1944\r
1945 return Status;\r
1946}\r