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