]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c
move protocol close process from MnpDriverBindingStart() to MnpFlushServiceData().
[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
e48e37fc 172 gBS->FreePool (MnpServiceData);\r
8a67d61d 173 }\r
174\r
175 return Status;\r
176}\r
177\r
178\r
179/**\r
180 Stop this driver on ControllerHandle.\r
181\r
182 @param This Protocol instance pointer.\r
183 @param ControllerHandle Handle of device to stop driver on.\r
184 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
185 of children is zero stop the entire bus driver.\r
186 @param ChildHandleBuffer List of Child Handles to Stop.\r
187\r
188 @retval EFI_SUCCES This driver is removed ControllerHandle.\r
189 @retval other This driver was not removed from this device.\r
190\r
191**/\r
192EFI_STATUS\r
193EFIAPI\r
194MnpDriverBindingStop (\r
195 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
196 IN EFI_HANDLE ControllerHandle,\r
197 IN UINTN NumberOfChildren,\r
198 IN EFI_HANDLE *ChildHandleBuffer\r
199 )\r
200{\r
201 EFI_STATUS Status;\r
202 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
203 MNP_SERVICE_DATA *MnpServiceData;\r
204 MNP_INSTANCE_DATA *Instance;\r
205\r
206 //\r
207 // Retrieve the MNP service binding protocol from the ControllerHandle.\r
208 //\r
209 Status = gBS->OpenProtocol (\r
210 ControllerHandle,\r
211 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
212 (VOID **) &ServiceBinding,\r
213 This->DriverBindingHandle,\r
214 ControllerHandle,\r
215 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
216 );\r
217 if (EFI_ERROR (Status)) {\r
218\r
e48e37fc 219 DEBUG (\r
220 (EFI_D_ERROR,\r
221 "MnpDriverBindingStop: Locate MNP Service Binding Protocol failed, %r.\n",\r
8a67d61d 222 Status)\r
223 );\r
c4a62a12 224 return EFI_DEVICE_ERROR;\r
8a67d61d 225 }\r
226\r
227 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (ServiceBinding);\r
228\r
c4a62a12 229 if (NumberOfChildren == 0) {\r
8a67d61d 230 //\r
c4a62a12 231 // Uninstall the MNP Service Binding Protocol.\r
8a67d61d 232 //\r
c4a62a12 233 gBS->UninstallMultipleProtocolInterfaces (\r
234 ControllerHandle,\r
235 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
236 ServiceBinding,\r
237 NULL\r
238 );\r
8a67d61d 239\r
c4a62a12 240 //\r
241 // Close the openned Snp protocol.\r
242 //\r
243 gBS->CloseProtocol (\r
244 ControllerHandle,\r
245 &gEfiSimpleNetworkProtocolGuid,\r
246 This->DriverBindingHandle,\r
247 ControllerHandle\r
248 );\r
8a67d61d 249\r
c4a62a12 250 //\r
251 // Flush the Mnp service data.\r
252 //\r
253 MnpFlushServiceData (MnpServiceData);\r
8a67d61d 254\r
e48e37fc 255 gBS->FreePool (MnpServiceData);\r
c4a62a12 256 } else {\r
e48e37fc 257 while (!IsListEmpty (&MnpServiceData->ChildrenList)) {\r
c4a62a12 258 //\r
259 // Don't use NetListRemoveHead here, the remove opreration will be done\r
260 // in ServiceBindingDestroyChild.\r
261 //\r
262 Instance = NET_LIST_HEAD (\r
263 &MnpServiceData->ChildrenList,\r
264 MNP_INSTANCE_DATA,\r
265 InstEntry\r
266 );\r
8a67d61d 267\r
c4a62a12 268 ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
269 }\r
8a67d61d 270 }\r
271\r
8a67d61d 272 return Status;\r
273}\r
274\r
275\r
276/**\r
277 Creates a child handle with a set of I/O services.\r
278\r
279 @param This Protocol instance pointer.\r
280 @param ChildHandle Pointer to the handle of the child to create. If\r
281 it is NULL, then a new handle is created. If it is\r
282 not NULL, then the I/O services are added to the\r
283 existing child handle.\r
284\r
285 @retval EFI_SUCCES The child handle was created with the I/O\r
286 services.\r
287 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
288 the child.\r
289 @retval other The child handle was not created.\r
290\r
291**/\r
292EFI_STATUS\r
293EFIAPI\r
294MnpServiceBindingCreateChild (\r
295 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
296 IN EFI_HANDLE *ChildHandle\r
297 )\r
298{\r
299 EFI_STATUS Status;\r
300 MNP_SERVICE_DATA *MnpServiceData;\r
301 MNP_INSTANCE_DATA *Instance;\r
302 VOID *Snp;\r
303 EFI_TPL OldTpl;\r
304\r
305 if ((This == NULL) || (ChildHandle == NULL)) {\r
306\r
307 return EFI_INVALID_PARAMETER;\r
308 }\r
309\r
310 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);\r
311\r
312 //\r
313 // Allocate buffer for the new instance.\r
314 //\r
e48e37fc 315 Instance = AllocateZeroPool (sizeof (MNP_INSTANCE_DATA));\r
8a67d61d 316 if (Instance == NULL) {\r
317\r
e48e37fc 318 DEBUG ((EFI_D_ERROR, "MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));\r
8a67d61d 319 return EFI_OUT_OF_RESOURCES;\r
320 }\r
321\r
322 //\r
323 // Init the instance data.\r
324 //\r
325 MnpInitializeInstanceData (MnpServiceData, Instance);\r
326\r
327 Status = gBS->InstallMultipleProtocolInterfaces (\r
328 ChildHandle,\r
329 &gEfiManagedNetworkProtocolGuid,\r
330 &Instance->ManagedNetwork,\r
331 NULL\r
332 );\r
333 if (EFI_ERROR (Status)) {\r
334\r
e48e37fc 335 DEBUG (\r
336 (EFI_D_ERROR,\r
337 "MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",\r
8a67d61d 338 Status)\r
339 );\r
340 goto ErrorExit;\r
341 }\r
342\r
343 //\r
344 // Save the instance's childhandle.\r
345 //\r
346 Instance->Handle = *ChildHandle;\r
347\r
348 Status = gBS->OpenProtocol (\r
349 MnpServiceData->ControllerHandle,\r
350 &gEfiSimpleNetworkProtocolGuid,\r
351 (VOID **) &Snp,\r
352 gMnpDriverBinding.DriverBindingHandle,\r
353 Instance->Handle,\r
354 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
355 );\r
356 if (EFI_ERROR (Status)) {\r
357 goto ErrorExit;\r
358 }\r
359\r
360 //\r
361 // Add the child instance into ChildrenList.\r
362 //\r
e48e37fc 363 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
8a67d61d 364\r
e48e37fc 365 InsertTailList (&MnpServiceData->ChildrenList, &Instance->InstEntry);\r
8a67d61d 366 MnpServiceData->ChildrenNumber++;\r
367\r
e48e37fc 368 gBS->RestoreTPL (OldTpl);\r
8a67d61d 369\r
370ErrorExit:\r
371\r
372 if (EFI_ERROR (Status)) {\r
373\r
374 if (Instance->Handle != NULL) {\r
375\r
376 gBS->UninstallMultipleProtocolInterfaces (\r
377 &gEfiManagedNetworkProtocolGuid,\r
378 &Instance->ManagedNetwork,\r
379 NULL\r
380 );\r
381 }\r
382\r
e48e37fc 383 gBS->FreePool (Instance);\r
8a67d61d 384 }\r
385\r
386 return Status;\r
387}\r
388\r
389\r
390/**\r
391 Destroys a child handle with a set of I/O services.\r
392\r
393 @param This Protocol instance pointer.\r
394 @param ChildHandle Handle of the child to destroy.\r
395\r
396 @retval EFI_SUCCES The I/O services were removed from the child\r
397 handle.\r
398 @retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
399 that are being removed.\r
400 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
401 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
402 its I/O services are being used.\r
403 @retval other The child handle was not destroyed.\r
404\r
405**/\r
406EFI_STATUS\r
407EFIAPI\r
408MnpServiceBindingDestroyChild (\r
409 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
410 IN EFI_HANDLE ChildHandle\r
411 )\r
412{\r
413 EFI_STATUS Status;\r
414 MNP_SERVICE_DATA *MnpServiceData;\r
415 EFI_MANAGED_NETWORK_PROTOCOL *ManagedNetwork;\r
416 MNP_INSTANCE_DATA *Instance;\r
417 EFI_TPL OldTpl;\r
418\r
419 if ((This == NULL) || (ChildHandle == NULL)) {\r
420\r
421 return EFI_INVALID_PARAMETER;\r
422 }\r
423\r
424 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);\r
425\r
426 //\r
427 // Try to retrieve ManagedNetwork Protocol from ChildHandle.\r
428 //\r
429 Status = gBS->OpenProtocol (\r
430 ChildHandle,\r
431 &gEfiManagedNetworkProtocolGuid,\r
432 (VOID **) &ManagedNetwork,\r
433 gMnpDriverBinding.DriverBindingHandle,\r
434 ChildHandle,\r
435 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
436 );\r
437 if (EFI_ERROR (Status)) {\r
438\r
439 return EFI_UNSUPPORTED;\r
440 }\r
441\r
442 Instance = MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork);\r
443\r
444 //\r
445 // MnpServiceBindingDestroyChild may be called twice: first called by\r
446 // MnpServiceBindingStop, second called by uninstalling the MNP protocol\r
447 // in this ChildHandle. Use destroyed to make sure the resource clean code\r
448 // will only excecute once.\r
449 //\r
450 if (Instance->Destroyed) {\r
451\r
452 return EFI_SUCCESS;\r
453 }\r
454\r
455 Instance->Destroyed = TRUE;\r
456\r
457 //\r
458 // Close the Simple Network protocol.\r
459 //\r
460 gBS->CloseProtocol (\r
461 MnpServiceData->ControllerHandle,\r
462 &gEfiSimpleNetworkProtocolGuid,\r
463 gMnpDriverBinding.DriverBindingHandle,\r
464 ChildHandle\r
465 );\r
466\r
467 //\r
468 // Uninstall the ManagedNetwork protocol.\r
469 //\r
470 Status = gBS->UninstallMultipleProtocolInterfaces (\r
471 ChildHandle,\r
472 &gEfiManagedNetworkProtocolGuid,\r
473 &Instance->ManagedNetwork,\r
474 NULL\r
475 );\r
476 if (EFI_ERROR (Status)) {\r
477\r
e48e37fc 478 DEBUG (\r
479 (EFI_D_ERROR,\r
480 "MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",\r
8a67d61d 481 Status)\r
482 );\r
483\r
484 Instance->Destroyed = FALSE;\r
485 return Status;\r
486 }\r
487\r
e48e37fc 488 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
8a67d61d 489\r
490 //\r
491 // Reset the configuration.\r
492 //\r
493 ManagedNetwork->Configure (ManagedNetwork, NULL);\r
494\r
495 //\r
496 // Try to flush the RcvdPacketQueue.\r
497 //\r
498 MnpFlushRcvdDataQueue (Instance);\r
499\r
500 //\r
501 // Clean the RxTokenMap.\r
502 //\r
503 NetMapClean (&Instance->RxTokenMap);\r
504\r
505 //\r
506 // Remove this instance from the ChildrenList.\r
507 //\r
e48e37fc 508 RemoveEntryList (&Instance->InstEntry);\r
8a67d61d 509 MnpServiceData->ChildrenNumber--;\r
510\r
e48e37fc 511 gBS->RestoreTPL (OldTpl);\r
8a67d61d 512\r
e48e37fc 513 gBS->FreePool (Instance);\r
8a67d61d 514\r
515 return Status;\r
516}\r
517\r
8a67d61d 518\r
519EFI_STATUS\r
520EFIAPI\r
521MnpDriverEntryPoint (\r
522 IN EFI_HANDLE ImageHandle,\r
523 IN EFI_SYSTEM_TABLE *SystemTable\r
524 )\r
525/*++\r
526\r
527Routine Description:\r
528\r
529 The entry point for Mnp driver which installs the driver binding and component name\r
530 protocol on its ImageHandle.\r
531\r
532Arguments:\r
533\r
534 ImageHandle - The image handle of the driver.\r
535 SystemTable - The system table.\r
536\r
537Returns:\r
538\r
539 EFI_SUCCESS - If the driver binding and component name protocols are successfully\r
540 installed, otherwise if failed.\r
541\r
542--*/\r
543{\r
83cbd279 544 return EfiLibInstallDriverBindingComponentName2 (\r
da1d0201 545 ImageHandle,\r
546 SystemTable,\r
547 &gMnpDriverBinding,\r
548 ImageHandle,\r
549 &gMnpComponentName,\r
83cbd279 550 &gMnpComponentName2\r
da1d0201 551 );\r
8a67d61d 552}\r