]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c
In Supported(), try to test open SNP protocol BY_DRIVER instead of using TEST_PROTOCOL.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpDriver.c
CommitLineData
8a67d61d 1/** @file\r
2\r
b58baf6b 3Copyright (c) 2005 - 2008, Intel Corporation\r
8a67d61d 4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 MnpDriver.c\r
15\r
16Abstract:\r
17\r
18\r
19**/\r
20\r
21#include "MnpDriver.h"\r
8a67d61d 22#include "MnpImpl.h"\r
23\r
24\r
25EFI_DRIVER_BINDING_PROTOCOL gMnpDriverBinding = {\r
26 MnpDriverBindingSupported,\r
27 MnpDriverBindingStart,\r
28 MnpDriverBindingStop,\r
29 0xa,\r
30 NULL,\r
31 NULL\r
32};\r
33\r
34\r
35/**\r
36 Test to see if this driver supports ControllerHandle.\r
37\r
38 @param This Protocol instance pointer.\r
39 @param ControllerHandle Handle of device to test.\r
40 @param RemainingDevicePath Optional parameter use to pick a specific child\r
41 device to start.\r
42\r
43 @retval EFI_SUCCES This driver supports this device.\r
44 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
45 @retval other This driver does not support this device.\r
46\r
47**/\r
48EFI_STATUS\r
49EFIAPI\r
50MnpDriverBindingSupported (\r
51 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
52 IN EFI_HANDLE ControllerHandle,\r
53 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
54 )\r
55{\r
b58baf6b 56 EFI_STATUS Status;\r
57 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
8a67d61d 58\r
59 //\r
60 // Test to see if MNP is already installed.\r
61 //\r
62 Status = gBS->OpenProtocol (\r
63 ControllerHandle,\r
64 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
65 NULL,\r
66 This->DriverBindingHandle,\r
67 ControllerHandle,\r
68 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
69 );\r
70 if (!EFI_ERROR (Status)) {\r
8a67d61d 71 return EFI_ALREADY_STARTED;\r
72 }\r
73\r
74 //\r
b58baf6b 75 // Test to open the Simple Network protocol BY_DRIVER.\r
8a67d61d 76 //\r
77 Status = gBS->OpenProtocol (\r
78 ControllerHandle,\r
79 &gEfiSimpleNetworkProtocolGuid,\r
b58baf6b 80 (VOID **) &Snp,\r
8a67d61d 81 This->DriverBindingHandle,\r
82 ControllerHandle,\r
b58baf6b 83 EFI_OPEN_PROTOCOL_BY_DRIVER\r
8a67d61d 84 );\r
85\r
b58baf6b 86 if (EFI_ERROR (Status)) {\r
87 return Status;\r
88 }\r
89\r
90 //\r
91 // Close the openned SNP protocol.\r
92 //\r
93 gBS->CloseProtocol (\r
94 ControllerHandle,\r
95 &gEfiSimpleNetworkProtocolGuid,\r
96 This->DriverBindingHandle,\r
97 ControllerHandle\r
98 );\r
99\r
100 return EFI_SUCCESS;\r
8a67d61d 101}\r
102\r
103\r
104/**\r
105 Start this driver on ControllerHandle.\r
106\r
107 @param This Protocol instance pointer.\r
108 @param ControllerHandle Handle of device to bind driver to.\r
109 @param RemainingDevicePath Optional parameter use to pick a specific child\r
110 device to start.\r
111\r
112 @retval EFI_SUCCES This driver is added to ControllerHandle.\r
113 @retval EFI_ALREADY_STARTED This driver is already running on\r
114 ControllerHandle.\r
115 @retval other This driver does not support this device.\r
116\r
117**/\r
118EFI_STATUS\r
119EFIAPI\r
120MnpDriverBindingStart (\r
121 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
122 IN EFI_HANDLE ControllerHandle,\r
123 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
124 )\r
125{\r
126 EFI_STATUS Status;\r
127 MNP_SERVICE_DATA *MnpServiceData;\r
128 BOOLEAN MnpInitialized;\r
129\r
130 MnpInitialized = FALSE;\r
131\r
e48e37fc 132 MnpServiceData = AllocateZeroPool (sizeof (MNP_SERVICE_DATA));\r
8a67d61d 133 if (MnpServiceData == NULL) {\r
e48e37fc 134 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart(): Failed to allocate the Mnp Service Data.\n"));\r
8a67d61d 135\r
136 return EFI_OUT_OF_RESOURCES;\r
137 }\r
138\r
139 //\r
140 // Initialize the Mnp Service Data.\r
141 //\r
142 Status = MnpInitializeServiceData (MnpServiceData, This->DriverBindingHandle, ControllerHandle);\r
143 if (EFI_ERROR (Status)) {\r
144\r
e48e37fc 145 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart: MnpInitializeServiceData failed, %r.\n",Status));\r
8a67d61d 146 goto ErrorExit;\r
147 }\r
148\r
149 MnpInitialized = TRUE;\r
150\r
151 //\r
152 // Install the MNP Service Binding Protocol.\r
153 //\r
154 Status = gBS->InstallMultipleProtocolInterfaces (\r
155 &ControllerHandle,\r
156 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
157 &MnpServiceData->ServiceBinding,\r
158 NULL\r
159 );\r
160\r
161ErrorExit:\r
162\r
163 if (EFI_ERROR (Status)) {\r
164\r
165 if (MnpInitialized) {\r
166 //\r
167 // Flush the Mnp Service Data.\r
168 //\r
169 MnpFlushServiceData (MnpServiceData);\r
170 }\r
171\r
172 //\r
173 // Close the Simple Network Protocol.\r
174 //\r
175 gBS->CloseProtocol (\r
176 ControllerHandle,\r
177 &gEfiSimpleNetworkProtocolGuid,\r
178 This->DriverBindingHandle,\r
179 ControllerHandle\r
180 );\r
181\r
e48e37fc 182 gBS->FreePool (MnpServiceData);\r
8a67d61d 183 }\r
184\r
185 return Status;\r
186}\r
187\r
188\r
189/**\r
190 Stop this driver on ControllerHandle.\r
191\r
192 @param This Protocol instance pointer.\r
193 @param ControllerHandle Handle of device to stop driver on.\r
194 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
195 of children is zero stop the entire bus driver.\r
196 @param ChildHandleBuffer List of Child Handles to Stop.\r
197\r
198 @retval EFI_SUCCES This driver is removed ControllerHandle.\r
199 @retval other This driver was not removed from this device.\r
200\r
201**/\r
202EFI_STATUS\r
203EFIAPI\r
204MnpDriverBindingStop (\r
205 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
206 IN EFI_HANDLE ControllerHandle,\r
207 IN UINTN NumberOfChildren,\r
208 IN EFI_HANDLE *ChildHandleBuffer\r
209 )\r
210{\r
211 EFI_STATUS Status;\r
212 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
213 MNP_SERVICE_DATA *MnpServiceData;\r
214 MNP_INSTANCE_DATA *Instance;\r
215\r
216 //\r
217 // Retrieve the MNP service binding protocol from the ControllerHandle.\r
218 //\r
219 Status = gBS->OpenProtocol (\r
220 ControllerHandle,\r
221 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
222 (VOID **) &ServiceBinding,\r
223 This->DriverBindingHandle,\r
224 ControllerHandle,\r
225 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
226 );\r
227 if (EFI_ERROR (Status)) {\r
228\r
e48e37fc 229 DEBUG (\r
230 (EFI_D_ERROR,\r
231 "MnpDriverBindingStop: Locate MNP Service Binding Protocol failed, %r.\n",\r
8a67d61d 232 Status)\r
233 );\r
c4a62a12 234 return EFI_DEVICE_ERROR;\r
8a67d61d 235 }\r
236\r
237 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (ServiceBinding);\r
238\r
c4a62a12 239 if (NumberOfChildren == 0) {\r
8a67d61d 240 //\r
c4a62a12 241 // Uninstall the MNP Service Binding Protocol.\r
8a67d61d 242 //\r
c4a62a12 243 gBS->UninstallMultipleProtocolInterfaces (\r
244 ControllerHandle,\r
245 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
246 ServiceBinding,\r
247 NULL\r
248 );\r
8a67d61d 249\r
c4a62a12 250 //\r
251 // Close the openned Snp protocol.\r
252 //\r
253 gBS->CloseProtocol (\r
254 ControllerHandle,\r
255 &gEfiSimpleNetworkProtocolGuid,\r
256 This->DriverBindingHandle,\r
257 ControllerHandle\r
258 );\r
8a67d61d 259\r
c4a62a12 260 //\r
261 // Flush the Mnp service data.\r
262 //\r
263 MnpFlushServiceData (MnpServiceData);\r
8a67d61d 264\r
e48e37fc 265 gBS->FreePool (MnpServiceData);\r
c4a62a12 266 } else {\r
e48e37fc 267 while (!IsListEmpty (&MnpServiceData->ChildrenList)) {\r
c4a62a12 268 //\r
269 // Don't use NetListRemoveHead here, the remove opreration will be done\r
270 // in ServiceBindingDestroyChild.\r
271 //\r
272 Instance = NET_LIST_HEAD (\r
273 &MnpServiceData->ChildrenList,\r
274 MNP_INSTANCE_DATA,\r
275 InstEntry\r
276 );\r
8a67d61d 277\r
c4a62a12 278 ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
279 }\r
8a67d61d 280 }\r
281\r
8a67d61d 282 return Status;\r
283}\r
284\r
285\r
286/**\r
287 Creates a child handle with a set of I/O services.\r
288\r
289 @param This Protocol instance pointer.\r
290 @param ChildHandle Pointer to the handle of the child to create. If\r
291 it is NULL, then a new handle is created. If it is\r
292 not NULL, then the I/O services are added to the\r
293 existing child handle.\r
294\r
295 @retval EFI_SUCCES The child handle was created with the I/O\r
296 services.\r
297 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
298 the child.\r
299 @retval other The child handle was not created.\r
300\r
301**/\r
302EFI_STATUS\r
303EFIAPI\r
304MnpServiceBindingCreateChild (\r
305 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
306 IN EFI_HANDLE *ChildHandle\r
307 )\r
308{\r
309 EFI_STATUS Status;\r
310 MNP_SERVICE_DATA *MnpServiceData;\r
311 MNP_INSTANCE_DATA *Instance;\r
312 VOID *Snp;\r
313 EFI_TPL OldTpl;\r
314\r
315 if ((This == NULL) || (ChildHandle == NULL)) {\r
316\r
317 return EFI_INVALID_PARAMETER;\r
318 }\r
319\r
320 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);\r
321\r
322 //\r
323 // Allocate buffer for the new instance.\r
324 //\r
e48e37fc 325 Instance = AllocateZeroPool (sizeof (MNP_INSTANCE_DATA));\r
8a67d61d 326 if (Instance == NULL) {\r
327\r
e48e37fc 328 DEBUG ((EFI_D_ERROR, "MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));\r
8a67d61d 329 return EFI_OUT_OF_RESOURCES;\r
330 }\r
331\r
332 //\r
333 // Init the instance data.\r
334 //\r
335 MnpInitializeInstanceData (MnpServiceData, Instance);\r
336\r
337 Status = gBS->InstallMultipleProtocolInterfaces (\r
338 ChildHandle,\r
339 &gEfiManagedNetworkProtocolGuid,\r
340 &Instance->ManagedNetwork,\r
341 NULL\r
342 );\r
343 if (EFI_ERROR (Status)) {\r
344\r
e48e37fc 345 DEBUG (\r
346 (EFI_D_ERROR,\r
347 "MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",\r
8a67d61d 348 Status)\r
349 );\r
350 goto ErrorExit;\r
351 }\r
352\r
353 //\r
354 // Save the instance's childhandle.\r
355 //\r
356 Instance->Handle = *ChildHandle;\r
357\r
358 Status = gBS->OpenProtocol (\r
359 MnpServiceData->ControllerHandle,\r
360 &gEfiSimpleNetworkProtocolGuid,\r
361 (VOID **) &Snp,\r
362 gMnpDriverBinding.DriverBindingHandle,\r
363 Instance->Handle,\r
364 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
365 );\r
366 if (EFI_ERROR (Status)) {\r
367 goto ErrorExit;\r
368 }\r
369\r
370 //\r
371 // Add the child instance into ChildrenList.\r
372 //\r
e48e37fc 373 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
8a67d61d 374\r
e48e37fc 375 InsertTailList (&MnpServiceData->ChildrenList, &Instance->InstEntry);\r
8a67d61d 376 MnpServiceData->ChildrenNumber++;\r
377\r
e48e37fc 378 gBS->RestoreTPL (OldTpl);\r
8a67d61d 379\r
380ErrorExit:\r
381\r
382 if (EFI_ERROR (Status)) {\r
383\r
384 if (Instance->Handle != NULL) {\r
385\r
386 gBS->UninstallMultipleProtocolInterfaces (\r
387 &gEfiManagedNetworkProtocolGuid,\r
388 &Instance->ManagedNetwork,\r
389 NULL\r
390 );\r
391 }\r
392\r
e48e37fc 393 gBS->FreePool (Instance);\r
8a67d61d 394 }\r
395\r
396 return Status;\r
397}\r
398\r
399\r
400/**\r
401 Destroys a child handle with a set of I/O services.\r
402\r
403 @param This Protocol instance pointer.\r
404 @param ChildHandle Handle of the child to destroy.\r
405\r
406 @retval EFI_SUCCES The I/O services were removed from the child\r
407 handle.\r
408 @retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
409 that are being removed.\r
410 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
411 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
412 its I/O services are being used.\r
413 @retval other The child handle was not destroyed.\r
414\r
415**/\r
416EFI_STATUS\r
417EFIAPI\r
418MnpServiceBindingDestroyChild (\r
419 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
420 IN EFI_HANDLE ChildHandle\r
421 )\r
422{\r
423 EFI_STATUS Status;\r
424 MNP_SERVICE_DATA *MnpServiceData;\r
425 EFI_MANAGED_NETWORK_PROTOCOL *ManagedNetwork;\r
426 MNP_INSTANCE_DATA *Instance;\r
427 EFI_TPL OldTpl;\r
428\r
429 if ((This == NULL) || (ChildHandle == NULL)) {\r
430\r
431 return EFI_INVALID_PARAMETER;\r
432 }\r
433\r
434 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);\r
435\r
436 //\r
437 // Try to retrieve ManagedNetwork Protocol from ChildHandle.\r
438 //\r
439 Status = gBS->OpenProtocol (\r
440 ChildHandle,\r
441 &gEfiManagedNetworkProtocolGuid,\r
442 (VOID **) &ManagedNetwork,\r
443 gMnpDriverBinding.DriverBindingHandle,\r
444 ChildHandle,\r
445 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
446 );\r
447 if (EFI_ERROR (Status)) {\r
448\r
449 return EFI_UNSUPPORTED;\r
450 }\r
451\r
452 Instance = MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork);\r
453\r
454 //\r
455 // MnpServiceBindingDestroyChild may be called twice: first called by\r
456 // MnpServiceBindingStop, second called by uninstalling the MNP protocol\r
457 // in this ChildHandle. Use destroyed to make sure the resource clean code\r
458 // will only excecute once.\r
459 //\r
460 if (Instance->Destroyed) {\r
461\r
462 return EFI_SUCCESS;\r
463 }\r
464\r
465 Instance->Destroyed = TRUE;\r
466\r
467 //\r
468 // Close the Simple Network protocol.\r
469 //\r
470 gBS->CloseProtocol (\r
471 MnpServiceData->ControllerHandle,\r
472 &gEfiSimpleNetworkProtocolGuid,\r
473 gMnpDriverBinding.DriverBindingHandle,\r
474 ChildHandle\r
475 );\r
476\r
477 //\r
478 // Uninstall the ManagedNetwork protocol.\r
479 //\r
480 Status = gBS->UninstallMultipleProtocolInterfaces (\r
481 ChildHandle,\r
482 &gEfiManagedNetworkProtocolGuid,\r
483 &Instance->ManagedNetwork,\r
484 NULL\r
485 );\r
486 if (EFI_ERROR (Status)) {\r
487\r
e48e37fc 488 DEBUG (\r
489 (EFI_D_ERROR,\r
490 "MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",\r
8a67d61d 491 Status)\r
492 );\r
493\r
494 Instance->Destroyed = FALSE;\r
495 return Status;\r
496 }\r
497\r
e48e37fc 498 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
8a67d61d 499\r
500 //\r
501 // Reset the configuration.\r
502 //\r
503 ManagedNetwork->Configure (ManagedNetwork, NULL);\r
504\r
505 //\r
506 // Try to flush the RcvdPacketQueue.\r
507 //\r
508 MnpFlushRcvdDataQueue (Instance);\r
509\r
510 //\r
511 // Clean the RxTokenMap.\r
512 //\r
513 NetMapClean (&Instance->RxTokenMap);\r
514\r
515 //\r
516 // Remove this instance from the ChildrenList.\r
517 //\r
e48e37fc 518 RemoveEntryList (&Instance->InstEntry);\r
8a67d61d 519 MnpServiceData->ChildrenNumber--;\r
520\r
e48e37fc 521 gBS->RestoreTPL (OldTpl);\r
8a67d61d 522\r
e48e37fc 523 gBS->FreePool (Instance);\r
8a67d61d 524\r
525 return Status;\r
526}\r
527\r
8a67d61d 528\r
529EFI_STATUS\r
530EFIAPI\r
531MnpDriverEntryPoint (\r
532 IN EFI_HANDLE ImageHandle,\r
533 IN EFI_SYSTEM_TABLE *SystemTable\r
534 )\r
535/*++\r
536\r
537Routine Description:\r
538\r
539 The entry point for Mnp driver which installs the driver binding and component name\r
540 protocol on its ImageHandle.\r
541\r
542Arguments:\r
543\r
544 ImageHandle - The image handle of the driver.\r
545 SystemTable - The system table.\r
546\r
547Returns:\r
548\r
549 EFI_SUCCESS - If the driver binding and component name protocols are successfully\r
550 installed, otherwise if failed.\r
551\r
552--*/\r
553{\r
83cbd279 554 return EfiLibInstallDriverBindingComponentName2 (\r
da1d0201 555 ImageHandle,\r
556 SystemTable,\r
557 &gMnpDriverBinding,\r
558 ImageHandle,\r
559 &gMnpComponentName,\r
83cbd279 560 &gMnpComponentName2\r
da1d0201 561 );\r
8a67d61d 562}\r