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