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