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