In Supported(), try to test open SNP protocol BY_DRIVER instead of using TEST_PROTOCOL.
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Network / MnpDxe / MnpDriver.c
1 /** @file\r
2 \r
3 Copyright (c) 2005 - 2008, Intel Corporation\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution.  The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8 \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 Module Name:\r
13 \r
14   MnpDriver.c\r
15 \r
16 Abstract:\r
17 \r
18 \r
19 **/\r
20 \r
21 #include "MnpDriver.h"\r
22 #include "MnpImpl.h"\r
23 \r
24 \r
25 EFI_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
48 EFI_STATUS\r
49 EFIAPI\r
50 MnpDriverBindingSupported (\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
56   EFI_STATUS                   Status;\r
57   EFI_SIMPLE_NETWORK_PROTOCOL  *Snp;\r
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
71     return EFI_ALREADY_STARTED;\r
72   }\r
73 \r
74   //\r
75   // Test to open the Simple Network protocol BY_DRIVER.\r
76   //\r
77   Status = gBS->OpenProtocol (\r
78                   ControllerHandle,\r
79                   &gEfiSimpleNetworkProtocolGuid,\r
80                   (VOID **) &Snp,\r
81                   This->DriverBindingHandle,\r
82                   ControllerHandle,\r
83                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
84                   );\r
85 \r
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
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
118 EFI_STATUS\r
119 EFIAPI\r
120 MnpDriverBindingStart (\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
132   MnpServiceData  = AllocateZeroPool (sizeof (MNP_SERVICE_DATA));\r
133   if (MnpServiceData == NULL) {\r
134     DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart(): Failed to allocate the Mnp Service Data.\n"));\r
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
145     DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart: MnpInitializeServiceData failed, %r.\n",Status));\r
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
161 ErrorExit:\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
182     gBS->FreePool (MnpServiceData);\r
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
202 EFI_STATUS\r
203 EFIAPI\r
204 MnpDriverBindingStop (\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
229     DEBUG (\r
230       (EFI_D_ERROR,\r
231       "MnpDriverBindingStop: Locate MNP Service Binding Protocol failed, %r.\n",\r
232       Status)\r
233       );\r
234     return EFI_DEVICE_ERROR;\r
235   }\r
236 \r
237   MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (ServiceBinding);\r
238 \r
239   if (NumberOfChildren == 0) {\r
240     //\r
241     // Uninstall the MNP Service Binding Protocol.\r
242     //\r
243     gBS->UninstallMultipleProtocolInterfaces (\r
244            ControllerHandle,\r
245            &gEfiManagedNetworkServiceBindingProtocolGuid,\r
246            ServiceBinding,\r
247            NULL\r
248            );\r
249 \r
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
259 \r
260     //\r
261     // Flush the Mnp service data.\r
262     //\r
263     MnpFlushServiceData (MnpServiceData);\r
264 \r
265     gBS->FreePool (MnpServiceData);\r
266   } else {\r
267     while (!IsListEmpty (&MnpServiceData->ChildrenList)) {\r
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
277 \r
278       ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
279     }\r
280   }\r
281 \r
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
302 EFI_STATUS\r
303 EFIAPI\r
304 MnpServiceBindingCreateChild (\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
325   Instance = AllocateZeroPool (sizeof (MNP_INSTANCE_DATA));\r
326   if (Instance == NULL) {\r
327 \r
328     DEBUG ((EFI_D_ERROR, "MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));\r
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
345     DEBUG (\r
346       (EFI_D_ERROR,\r
347       "MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",\r
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
373   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
374 \r
375   InsertTailList (&MnpServiceData->ChildrenList, &Instance->InstEntry);\r
376   MnpServiceData->ChildrenNumber++;\r
377 \r
378   gBS->RestoreTPL (OldTpl);\r
379 \r
380 ErrorExit:\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
393     gBS->FreePool (Instance);\r
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
416 EFI_STATUS\r
417 EFIAPI\r
418 MnpServiceBindingDestroyChild (\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
488     DEBUG (\r
489       (EFI_D_ERROR,\r
490       "MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",\r
491       Status)\r
492       );\r
493 \r
494     Instance->Destroyed = FALSE;\r
495     return Status;\r
496   }\r
497 \r
498   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
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
518   RemoveEntryList (&Instance->InstEntry);\r
519   MnpServiceData->ChildrenNumber--;\r
520 \r
521   gBS->RestoreTPL (OldTpl);\r
522 \r
523   gBS->FreePool (Instance);\r
524 \r
525   return Status;\r
526 }\r
527 \r
528 \r
529 EFI_STATUS\r
530 EFIAPI\r
531 MnpDriverEntryPoint (\r
532   IN EFI_HANDLE        ImageHandle,\r
533   IN EFI_SYSTEM_TABLE  *SystemTable\r
534   )\r
535 /*++\r
536 \r
537 Routine 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
542 Arguments:\r
543 \r
544   ImageHandle - The image handle of the driver.\r
545   SystemTable - The system table.\r
546 \r
547 Returns:\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
554   return EfiLibInstallDriverBindingComponentName2 (\r
555            ImageHandle,\r
556            SystemTable,\r
557            &gMnpDriverBinding,\r
558            ImageHandle,\r
559            &gMnpComponentName,\r
560            &gMnpComponentName2\r
561            );\r
562 }\r