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