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