]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
For network dynamic media detect support: invoke Snp->GetStatus() before use Snp...
[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 - 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
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 tx timeout check.\r
360 //\r
361 Status = gBS->CreateEvent (\r
362 EVT_TIMER,\r
363 TPL_CALLBACK,\r
364 NULL,\r
365 NULL,\r
366 &MnpDeviceData->TxTimeoutEvent\r
367 );\r
368 if (EFI_ERROR (Status)) {\r
369 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for tx timeout event failed.\n"));\r
370 }\r
371\r
372ERROR:\r
373 if (EFI_ERROR (Status)) {\r
374 //\r
375 // Free the dynamic allocated resources if necessary.\r
376 //\r
377 if (MnpDeviceData->MacString != NULL) {\r
378 FreePool (MnpDeviceData->MacString);\r
379 }\r
380\r
381 if (MnpDeviceData->TimeoutCheckTimer != NULL) {\r
382 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
383 }\r
384\r
385 if (MnpDeviceData->PollTimer != NULL) {\r
386 gBS->CloseEvent (MnpDeviceData->PollTimer);\r
387 }\r
388\r
389 if (MnpDeviceData->TxBuf != NULL) {\r
390 FreePool (MnpDeviceData->TxBuf);\r
391 }\r
392\r
393 if (MnpDeviceData->RxNbufCache != NULL) {\r
394 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
395 }\r
396\r
397 if (MnpDeviceData->FreeNbufQue.BufNum != 0) {\r
398 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
399 }\r
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
410 }\r
411\r
412 return Status;\r
413}\r
414\r
415\r
416/**\r
417 Destroy the MNP device context data.\r
418\r
419 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
420 @param[in] ImageHandle The driver image handle.\r
421\r
422**/\r
423VOID\r
424MnpDestroyDeviceData (\r
425 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
426 IN EFI_HANDLE ImageHandle\r
427 )\r
428{\r
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
437\r
438 //\r
439 // The GroupAddressList must be empty.\r
440 //\r
441 ASSERT (IsListEmpty (&MnpDeviceData->GroupAddressList));\r
442\r
443 //\r
444 // Close the event.\r
445 //\r
446 gBS->CloseEvent (&MnpDeviceData->TxTimeoutEvent);\r
447 gBS->CloseEvent (&MnpDeviceData->TimeoutCheckTimer);\r
448 gBS->CloseEvent (&MnpDeviceData->PollTimer);\r
449\r
450 //\r
451 // Free the tx buffer.\r
452 //\r
453 FreePool (MnpDeviceData->TxBuf);\r
454\r
455 //\r
456 // Free the RxNbufCache.\r
457 //\r
458 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
459\r
460 //\r
461 // Flush the FreeNbufQue.\r
462 //\r
463 MnpDeviceData->NbufCnt -= MnpDeviceData->FreeNbufQue.BufNum;\r
464 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);\r
465\r
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
487\r
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
501\r
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
510 }\r
511\r
512 //\r
513 // Add to MNP service list\r
514 //\r
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
666}\r
667\r
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
737\r
738/**\r
739 Initialize the mnp instance context data.\r
740\r
741 @param[in] MnpServiceData Pointer to the mnp service context data.\r
742 @param[in, out] Instance Pointer to the mnp instance context data\r
743 to initialize.\r
744\r
745**/\r
746VOID\r
747MnpInitializeInstanceData (\r
748 IN MNP_SERVICE_DATA *MnpServiceData,\r
749 IN OUT MNP_INSTANCE_DATA *Instance\r
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
763 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));\r
764\r
765 //\r
766 // Copy the default config data.\r
767 //\r
768 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));\r
769\r
770 //\r
771 // Initialize the lists.\r
772 //\r
773 InitializeListHead (&Instance->GroupCtrlBlkList);\r
774 InitializeListHead (&Instance->RcvdPacketQueue);\r
775 InitializeListHead (&Instance->RxDeliveredPacketQueue);\r
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
790 Check whether the token specified by Arg matches the token in Item.\r
791\r
792 @param[in] Map Pointer to the NET_MAP.\r
793 @param[in] Item Pointer to the NET_MAP_ITEM.\r
794 @param[in] Arg Pointer to the Arg, it's a pointer to the token to\r
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
805 IN NET_MAP *Map,\r
806 IN NET_MAP_ITEM *Item,\r
807 IN VOID *Arg\r
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
827/**\r
828 Cancel the token specified by Arg if it matches the token in Item.\r
829\r
830 @param[in, out] Map Pointer to the NET_MAP.\r
831 @param[in, out] Item Pointer to the NET_MAP_ITEM.\r
832 @param[in] Arg Pointer to the Arg, it's a pointer to the\r
833 token to cancel.\r
834\r
835 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,\r
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
840\r
841**/\r
842EFI_STATUS\r
843MnpCancelTokens (\r
844 IN OUT NET_MAP *Map,\r
845 IN OUT NET_MAP_ITEM *Item,\r
846 IN VOID *Arg\r
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
858 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
859\r
860 //\r
861 // Remove the item from the map.\r
862 //\r
863 NetMapRemoveItem (Map, Item, NULL);\r
864\r
865 //\r
866 // Cancel this token with status set to EFI_ABORTED.\r
867 //\r
868 TokenToCancel->Status = EFI_ABORTED;\r
869 gBS->SignalEvent (TokenToCancel->Event);\r
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
885 @param[in] Snp Pointer to the simple network protocol.\r
886\r
887 @retval EFI_SUCCESS The simple network protocol is started.\r
888 @retval Others Other errors as indicated.\r
889\r
890**/\r
891EFI_STATUS\r
892MnpStartSnp (\r
893 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
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
909 Status = Snp->Initialize (Snp, 0, 0);\r
910 }\r
911\r
912 return Status;\r
913}\r
914\r
915\r
916/**\r
917 Stop the simple network.\r
918\r
919 @param[in] Snp Pointer to the simple network protocol.\r
920\r
921 @retval EFI_SUCCESS The simple network is stopped.\r
922 @retval Others Other errors as indicated.\r
923\r
924**/\r
925EFI_STATUS\r
926MnpStopSnp (\r
927 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
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
937 Status = Snp->Shutdown (Snp);\r
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
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
957\r
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
961\r
962**/\r
963EFI_STATUS\r
964MnpStart (\r
965 IN OUT MNP_SERVICE_DATA *MnpServiceData,\r
966 IN BOOLEAN IsConfigUpdate,\r
967 IN BOOLEAN EnableSystemPoll\r
968 )\r
969{\r
970 EFI_STATUS Status;\r
971 EFI_TIMER_DELAY TimerOpType;\r
972 MNP_DEVICE_DATA *MnpDeviceData;\r
973\r
974 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
975\r
976 Status = EFI_SUCCESS;\r
977 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
978\r
979 if (!IsConfigUpdate) {\r
980 //\r
981 // If it's not a configuration update, increase the configured children number.\r
982 //\r
983 MnpDeviceData->ConfiguredChildrenNumber++;\r
984\r
985 if (MnpDeviceData->ConfiguredChildrenNumber == 1) {\r
986 //\r
987 // It's the first configured child, start the simple network.\r
988 //\r
989 Status = MnpStartSnp (MnpDeviceData->Snp);\r
990 if (EFI_ERROR (Status)) {\r
991 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));\r
992\r
993 goto ErrorExit;\r
994 }\r
995\r
996 //\r
997 // Start the timeout timer.\r
998 //\r
999 Status = gBS->SetTimer (\r
1000 MnpDeviceData->TimeoutCheckTimer,\r
1001 TimerPeriodic,\r
1002 MNP_TIMEOUT_CHECK_INTERVAL\r
1003 );\r
1004 if (EFI_ERROR (Status)) {\r
1005 DEBUG (\r
1006 (EFI_D_ERROR,\r
1007 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",\r
1008 Status)\r
1009 );\r
1010\r
1011 goto ErrorExit;\r
1012 }\r
1013 }\r
1014 }\r
1015\r
1016 if (MnpDeviceData->EnableSystemPoll ^ EnableSystemPoll) {\r
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
1023 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);\r
1024 if (EFI_ERROR (Status)) {\r
1025 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));\r
1026\r
1027 goto ErrorExit;\r
1028 }\r
1029\r
1030 MnpDeviceData->EnableSystemPoll = EnableSystemPoll;\r
1031 }\r
1032\r
1033 //\r
1034 // Change the receive filters if need.\r
1035 //\r
1036 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
1037\r
1038ErrorExit:\r
1039 return Status;\r
1040}\r
1041\r
1042\r
1043/**\r
1044 Stop the managed network.\r
1045\r
1046 @param[in, out] MnpServiceData Pointer to the mnp service context data.\r
1047\r
1048 @retval EFI_SUCCESS The managed network is stopped.\r
1049 @retval Others Other errors as indicated.\r
1050\r
1051**/\r
1052EFI_STATUS\r
1053MnpStop (\r
1054 IN OUT MNP_SERVICE_DATA *MnpServiceData\r
1055 )\r
1056{\r
1057 EFI_STATUS Status;\r
1058 MNP_DEVICE_DATA *MnpDeviceData;\r
1059\r
1060 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
1061 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1062 ASSERT (MnpDeviceData->ConfiguredChildrenNumber > 0);\r
1063\r
1064 //\r
1065 // Configure the receive filters.\r
1066 //\r
1067 MnpConfigReceiveFilters (MnpDeviceData);\r
1068\r
1069 //\r
1070 // Decrease the children number.\r
1071 //\r
1072 MnpDeviceData->ConfiguredChildrenNumber--;\r
1073\r
1074 if (MnpDeviceData->ConfiguredChildrenNumber > 0) {\r
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
1085 if (MnpDeviceData->EnableSystemPoll) {\r
1086 //\r
1087 // The system poll in on, cancel the poll timer.\r
1088 //\r
1089 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerCancel, 0);\r
1090 MnpDeviceData->EnableSystemPoll = FALSE;\r
1091 }\r
1092\r
1093 //\r
1094 // Cancel the timeout timer.\r
1095 //\r
1096 Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0);\r
1097\r
1098 //\r
1099 // Stop the simple network.\r
1100 //\r
1101 Status = MnpStopSnp (MnpDeviceData->Snp);\r
1102 return Status;\r
1103}\r
1104\r
1105\r
1106/**\r
1107 Flush the instance's received data.\r
1108\r
1109 @param[in, out] Instance Pointer to the mnp instance context data.\r
1110\r
1111**/\r
1112VOID\r
1113MnpFlushRcvdDataQueue (\r
1114 IN OUT MNP_INSTANCE_DATA *Instance\r
1115 )\r
1116{\r
1117 EFI_TPL OldTpl;\r
1118 MNP_RXDATA_WRAP *RxDataWrap;\r
1119\r
1120 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1121\r
1122 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1123\r
1124 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {\r
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
1139 gBS->RestoreTPL (OldTpl);\r
1140}\r
1141\r
1142\r
1143/**\r
1144 Configure the Instance using ConfigData.\r
1145\r
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
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
1153 @retval Others Other errors as indicated.\r
1154\r
1155**/\r
1156EFI_STATUS\r
1157MnpConfigureInstance (\r
1158 IN OUT MNP_INSTANCE_DATA *Instance,\r
1159 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL\r
1160 )\r
1161{\r
1162 EFI_STATUS Status;\r
1163 MNP_SERVICE_DATA *MnpServiceData;\r
1164 MNP_DEVICE_DATA *MnpDeviceData;\r
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
1181 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
1182 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
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
1205 MnpDeviceData->UnicastCount--;\r
1206 }\r
1207\r
1208 if (OldConfigData->EnableMulticastReceive) {\r
1209 MnpDeviceData->MulticastCount--;\r
1210 }\r
1211\r
1212 if (OldConfigData->EnableBroadcastReceive) {\r
1213 MnpDeviceData->BroadcastCount--;\r
1214 }\r
1215\r
1216 if (OldConfigData->EnablePromiscuousReceive) {\r
1217 MnpDeviceData->PromiscuousCount--;\r
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
1225 MnpDeviceData->UnicastCount++;\r
1226 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;\r
1227 }\r
1228\r
1229 if (NewConfigData->EnableMulticastReceive) {\r
1230 MnpDeviceData->MulticastCount++;\r
1231 }\r
1232\r
1233 if (NewConfigData->EnableBroadcastReceive) {\r
1234 MnpDeviceData->BroadcastCount++;\r
1235 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;\r
1236 }\r
1237\r
1238 if (NewConfigData->EnablePromiscuousReceive) {\r
1239 MnpDeviceData->PromiscuousCount++;\r
1240 }\r
1241\r
1242 if (OldConfigData->FlushQueuesOnReset) {\r
1243 MnpFlushRcvdDataQueue (Instance);\r
1244 }\r
1245\r
1246 if (ConfigData == NULL) {\r
1247 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);\r
1248 }\r
1249\r
1250 if (!NewConfigData->EnableMulticastReceive) {\r
1251 MnpGroupOp (Instance, FALSE, NULL, NULL);\r
1252 }\r
1253\r
1254 //\r
1255 // Save the new configuration data.\r
1256 //\r
1257 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));\r
1258\r
1259 Instance->Configured = (BOOLEAN) (ConfigData != NULL);\r
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
1267 (BOOLEAN) !NewConfigData->DisableBackgroundPolling\r
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
1279/**\r
1280 Configure the Snp receive filters according to the instances' receive filter\r
1281 settings.\r
1282\r
1283 @param[in] MnpDeviceData Pointer to the mnp device context data.\r
1284\r
1285 @retval EFI_SUCCESS The receive filters is configured.\r
1286 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due\r
1287 to lack of memory resource.\r
1288\r
1289**/\r
1290EFI_STATUS\r
1291MnpConfigReceiveFilters (\r
1292 IN MNP_DEVICE_DATA *MnpDeviceData\r
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
1306 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
1307\r
1308 Snp = MnpDeviceData->Snp;\r
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
1316 if (MnpDeviceData->UnicastCount != 0) {\r
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
1323 if (MnpDeviceData->BroadcastCount != 0) {\r
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
1334 if ((MnpDeviceData->MulticastCount != 0) && (MnpDeviceData->GroupAddressCount != 0)) {\r
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
1342 if (MnpDeviceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {\r
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
1353 MCastFilterCnt = MnpDeviceData->GroupAddressCount;\r
1354 MCastFilter = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);\r
1355 if (MCastFilter == NULL) {\r
1356 DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));\r
1357\r
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
1365 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
1366\r
1367 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
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
1392 if (MnpDeviceData->PromiscuousCount != 0) {\r
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
1417 DEBUG (\r
1418 (EFI_D_ERROR,\r
1419 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",\r
1420 Status)\r
1421 );\r
1422 }\r
1423 );\r
1424\r
1425 if (MCastFilter != NULL) {\r
1426 //\r
1427 // Free the buffer used to hold the group addresses.\r
1428 //\r
1429 FreePool (MCastFilter);\r
1430 }\r
1431\r
1432 return Status;\r
1433}\r
1434\r
1435\r
1436/**\r
1437 Add a group address control block which controls the MacAddress for\r
1438 this instance.\r
1439\r
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
1445\r
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
1448\r
1449**/\r
1450EFI_STATUS\r
1451MnpGroupOpAddCtrlBlk (\r
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
1457 )\r
1458{\r
1459 MNP_DEVICE_DATA *MnpDeviceData;\r
1460\r
1461 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1462\r
1463 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1464 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
1465\r
1466 if (GroupAddress == NULL) {\r
1467 ASSERT (MacAddress != NULL);\r
1468\r
1469 //\r
1470 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.\r
1471 //\r
1472 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));\r
1473 if (GroupAddress == NULL) {\r
1474\r
1475 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));\r
1476\r
1477 return EFI_OUT_OF_RESOURCES;\r
1478 }\r
1479\r
1480 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));\r
1481 GroupAddress->RefCnt = 0;\r
1482 InsertTailList (\r
1483 &MnpDeviceData->GroupAddressList,\r
1484 &GroupAddress->AddrEntry\r
1485 );\r
1486 MnpDeviceData->GroupAddressCount++;\r
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
1498 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);\r
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
1508 @param[in] Instance Pointer to the instance context data.\r
1509 @param[in] CtrlBlk Pointer to the group control block to delete.\r
1510\r
1511 @return The group address controlled by the control block is no longer used or not.\r
1512\r
1513**/\r
1514BOOLEAN\r
1515MnpGroupOpDelCtrlBlk (\r
1516 IN MNP_INSTANCE_DATA *Instance,\r
1517 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk\r
1518 )\r
1519{\r
1520 MNP_DEVICE_DATA *MnpDeviceData;\r
1521 MNP_GROUP_ADDRESS *GroupAddress;\r
1522\r
1523 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1524\r
1525 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1526 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
1527\r
1528 //\r
1529 // Remove and free the CtrlBlk.\r
1530 //\r
1531 GroupAddress = CtrlBlk->GroupAddress;\r
1532 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);\r
1533 FreePool (CtrlBlk);\r
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
1546 MnpDeviceData->GroupAddressCount--;\r
1547 RemoveEntryList (&GroupAddress->AddrEntry);\r
1548 FreePool (GroupAddress);\r
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
1560 @param[in, out] Instance Pointer to the instance context data.\r
1561 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to\r
1562 leave a group/groups.\r
1563 @param[in] MacAddress Pointer to the group address to join or leave.\r
1564 @param[in] CtrlBlk Pointer to the group control block if JoinFlag\r
1565 is FALSE.\r
1566\r
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
1570\r
1571**/\r
1572EFI_STATUS\r
1573MnpGroupOp (\r
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
1578 )\r
1579{\r
1580 MNP_DEVICE_DATA *MnpDeviceData;\r
1581 LIST_ENTRY *Entry;\r
1582 LIST_ENTRY *NextEntry;\r
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
1592 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
1593 SnpMode = MnpDeviceData->Snp->Mode;\r
1594\r
1595 if (JoinFlag) {\r
1596 //\r
1597 // A new gropu address is to be added.\r
1598 //\r
1599 GroupAddress = NULL;\r
1600 AddressExist = FALSE;\r
1601\r
1602 //\r
1603 // Allocate memory for the control block.\r
1604 //\r
1605 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));\r
1606 if (NewCtrlBlk == NULL) {\r
1607 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));\r
1608\r
1609 return EFI_OUT_OF_RESOURCES;\r
1610 }\r
1611\r
1612 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
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
1617 if (CompareMem (MacAddress, &GroupAddress->Address, SnpMode->HwAddressSize) == 0) {\r
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
1638 return Status;\r
1639 }\r
1640\r
1641 NeedUpdate = TRUE;\r
1642 } else {\r
1643 if (MacAddress != NULL) {\r
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
1678 Status = MnpConfigReceiveFilters (MnpDeviceData);\r
1679 }\r
1680\r
1681 return Status;\r
1682}\r