• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Implement the driver binding protocol for Asix AX88772 Ethernet driver.
3 
4   Copyright (c) 2011-2013, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "Ax88772.h"
16 
17 /**
18   Verify the controller type
19 
20   @param [in] pThis                Protocol instance pointer.
21   @param [in] Controller           Handle of device to test.
22   @param [in] pRemainingDevicePath Not used.
23 
24   @retval EFI_SUCCESS          This driver supports this device.
25   @retval other                This driver does not support this device.
26 
27 **/
28 EFI_STATUS
29 EFIAPI
DriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * pThis,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath)30 DriverSupported (
31   IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
32   IN EFI_HANDLE Controller,
33   IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
34   )
35 {
36   EFI_USB_DEVICE_DESCRIPTOR Device;
37   EFI_USB_IO_PROTOCOL * pUsbIo;
38   EFI_STATUS Status;
39 
40   //
41   //  Connect to the USB stack
42   //
43   Status = gBS->OpenProtocol (
44                   Controller,
45                   &gEfiUsbIoProtocolGuid,
46                   (VOID **) &pUsbIo,
47                   pThis->DriverBindingHandle,
48                   Controller,
49                   EFI_OPEN_PROTOCOL_BY_DRIVER
50                   );
51   if (!EFI_ERROR ( Status )) {
52 
53     //
54     //  Get the interface descriptor to check the USB class and find a transport
55     //  protocol handler.
56     //
57     Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );
58     if (!EFI_ERROR ( Status )) {
59 
60       //
61       //  Validate the adapter
62       //
63       if (( VENDOR_ID != Device.IdVendor )
64         || ( PRODUCT_ID != Device.IdProduct )) {
65         Status = EFI_UNSUPPORTED;
66       }
67     }
68 
69     //
70     //  Done with the USB stack
71     //
72     gBS->CloseProtocol (
73            Controller,
74            &gEfiUsbIoProtocolGuid,
75            pThis->DriverBindingHandle,
76            Controller
77            );
78   }
79 
80   //
81   //  Return the device supported status
82   //
83   return Status;
84 }
85 
86 
87 /**
88   Start this driver on Controller by opening UsbIo and DevicePath protocols.
89   Initialize PXE structures, create a copy of the Controller Device Path with the
90   NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol
91   on the newly created Device Path.
92 
93   @param [in] pThis                Protocol instance pointer.
94   @param [in] Controller           Handle of device to work with.
95   @param [in] pRemainingDevicePath Not used, always produce all possible children.
96 
97   @retval EFI_SUCCESS          This driver is added to Controller.
98   @retval other                This driver does not support this device.
99 
100 **/
101 EFI_STATUS
102 EFIAPI
DriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * pThis,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath)103 DriverStart (
104   IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
105   IN EFI_HANDLE Controller,
106   IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
107   )
108 {
109   EFI_STATUS Status;
110   NIC_DEVICE * pNicDevice;
111   UINTN LengthInBytes;
112 
113   DBG_ENTER ( );
114 
115   //
116   //  Allocate the device structure
117   //
118   LengthInBytes = sizeof ( *pNicDevice );
119   Status = gBS->AllocatePool (
120                   EfiRuntimeServicesData,
121                   LengthInBytes,
122                   (VOID **) &pNicDevice
123                   );
124   if ( !EFI_ERROR ( Status )) {
125     DEBUG (( DEBUG_POOL | DEBUG_INIT,
126               "0x%08x: Allocate pNicDevice, %d bytes\r\n",
127               pNicDevice,
128               sizeof ( *pNicDevice )));
129 
130     //
131     //  Set the structure signature
132     //
133     ZeroMem ( pNicDevice, LengthInBytes );
134     pNicDevice->Signature = DEV_SIGNATURE;
135 
136     //
137     //  Connect to the USB I/O protocol
138     //
139     Status = gBS->OpenProtocol (
140                     Controller,
141                     &gEfiUsbIoProtocolGuid,
142                     (VOID **) &pNicDevice->pUsbIo,
143                     pThis->DriverBindingHandle,
144                     Controller,
145                     EFI_OPEN_PROTOCOL_BY_DRIVER
146                     );
147 
148     if ( !EFI_ERROR ( Status )) {
149       //
150       //  Allocate the necessary events
151       //
152       Status = gBS->CreateEvent ( EVT_TIMER,
153                                   TPL_AX88772,
154                                   (EFI_EVENT_NOTIFY)Ax88772Timer,
155                                   pNicDevice,
156                                   (VOID **)&pNicDevice->Timer );
157       if ( !EFI_ERROR ( Status )) {
158         DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
159                   "0x%08x: Allocated timer\r\n",
160                   pNicDevice->Timer ));
161 
162         //
163         //  Initialize the simple network protocol
164         //
165         pNicDevice->Controller = Controller;
166         SN_Setup ( pNicDevice );
167 
168         //
169         //  Start the timer
170         //
171         Status = gBS->SetTimer ( pNicDevice->Timer,
172                                  TimerPeriodic,
173                                  TIMER_MSEC );
174         if ( !EFI_ERROR ( Status )) {
175           //
176           //  Install both the simple network and device path protocols.
177           //
178           Status = gBS->InstallMultipleProtocolInterfaces (
179                           &Controller,
180                           &gEfiCallerIdGuid,
181                           pNicDevice,
182                           &gEfiSimpleNetworkProtocolGuid,
183                           &pNicDevice->SimpleNetwork,
184                           NULL
185                           );
186 
187           if ( !EFI_ERROR ( Status )) {
188             DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
189                       "Installed: gEfiCallerIdGuid on   0x%08x\r\n",
190                       Controller ));
191             DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
192                       "Installed: gEfiSimpleNetworkProtocolGuid on   0x%08x\r\n",
193                       Controller ));
194             DBG_EXIT_STATUS ( Status );
195             return Status;
196           }
197           DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,
198                     "ERROR - Failed to install gEfiSimpleNetworkProtocol on 0x%08x\r\n",
199                     Controller ));
200         }
201         else {
202           DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,
203                     "ERROR - Failed to start the timer, Status: %r\r\n",
204                     Status ));
205         }
206       }
207       else {
208         DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,
209                   "ERROR - Failed to create timer event, Status: %r\r\n",
210                   Status ));
211       }
212 
213       //
214       //  Done with the USB stack
215       //
216       gBS->CloseProtocol (
217              Controller,
218              &gEfiUsbIoProtocolGuid,
219              pThis->DriverBindingHandle,
220              Controller
221              );
222     }
223 
224     //
225     //  Done with the device
226     //
227     gBS->FreePool ( pNicDevice );
228   }
229 
230   //
231   //  Display the driver start status
232   //
233   DBG_EXIT_STATUS ( Status );
234   return Status;
235 }
236 
237 
238 /**
239   Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
240   closing the DevicePath and PciIo protocols on Controller.
241 
242   @param [in] pThis                Protocol instance pointer.
243   @param [in] Controller           Handle of device to stop driver on.
244   @param [in] NumberOfChildren     How many children need to be stopped.
245   @param [in] pChildHandleBuffer   Not used.
246 
247   @retval EFI_SUCCESS          This driver is removed Controller.
248   @retval EFI_DEVICE_ERROR     The device could not be stopped due to a device error.
249   @retval other                This driver was not removed from this device.
250 
251 **/
252 EFI_STATUS
253 EFIAPI
DriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * pThis,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * pChildHandleBuffer)254 DriverStop (
255   IN  EFI_DRIVER_BINDING_PROTOCOL * pThis,
256   IN  EFI_HANDLE Controller,
257   IN  UINTN NumberOfChildren,
258   IN  EFI_HANDLE * pChildHandleBuffer
259   )
260 {
261   NIC_DEVICE * pNicDevice;
262   EFI_STATUS Status;
263 
264   DBG_ENTER ( );
265 
266   //
267   //  Determine if this driver is already attached
268   //
269   Status = gBS->OpenProtocol (
270                   Controller,
271                   &gEfiCallerIdGuid,
272                   (VOID **) &pNicDevice,
273                   pThis->DriverBindingHandle,
274                   Controller,
275                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
276                   );
277   if ( !EFI_ERROR ( Status )) {
278     //
279     //  AX88772 driver is no longer running on this device
280     //
281     gBS->UninstallMultipleProtocolInterfaces (
282               Controller,
283               &gEfiSimpleNetworkProtocolGuid,
284               &pNicDevice->SimpleNetwork,
285               &gEfiCallerIdGuid,
286               pNicDevice,
287               NULL );
288     DEBUG (( DEBUG_POOL | DEBUG_INIT,
289                 "Removed:   gEfiSimpleNetworkProtocolGuid from 0x%08x\r\n",
290                 Controller ));
291     DEBUG (( DEBUG_POOL | DEBUG_INIT,
292                 "Removed:   gEfiCallerIdGuid from 0x%08x\r\n",
293                 Controller ));
294 
295     //
296     //  Stop the timer
297     //
298     if ( NULL != pNicDevice->Timer ) {
299       gBS->SetTimer ( pNicDevice->Timer, TimerCancel, 0 );
300       gBS->CloseEvent ( pNicDevice->Timer );
301       DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
302                 "0x%08x: Released timer\r\n",
303                 pNicDevice->Timer ));
304     }
305 
306     //
307     //  Done with the device context
308     //
309     DEBUG (( DEBUG_POOL | DEBUG_INIT,
310               "0x%08x: Free pNicDevice, %d bytes\r\n",
311               pNicDevice,
312               sizeof ( *pNicDevice )));
313     gBS->FreePool ( pNicDevice );
314   }
315 
316   //
317   //  Return the shutdown status
318   //
319   DBG_EXIT_STATUS ( Status );
320   return Status;
321 }
322 
323 
324 /**
325   Driver binding protocol declaration
326 **/
327 EFI_DRIVER_BINDING_PROTOCOL  gDriverBinding = {
328   DriverSupported,
329   DriverStart,
330   DriverStop,
331   0xa,
332   NULL,
333   NULL
334 };
335 
336 
337 /**
338   Ax88772 driver unload routine.
339 
340   @param [in] ImageHandle       Handle for the image.
341 
342   @retval EFI_SUCCESS           Image may be unloaded
343 
344 **/
345 EFI_STATUS
346 EFIAPI
DriverUnload(IN EFI_HANDLE ImageHandle)347 DriverUnload (
348   IN EFI_HANDLE ImageHandle
349   )
350 {
351   UINTN BufferSize;
352   UINTN Index;
353   UINTN Max;
354   EFI_HANDLE * pHandle;
355   EFI_STATUS Status;
356 
357   //
358   //  Determine which devices are using this driver
359   //
360   BufferSize = 0;
361   pHandle = NULL;
362   Status = gBS->LocateHandle (
363                   ByProtocol,
364                   &gEfiCallerIdGuid,
365                   NULL,
366                   &BufferSize,
367                   NULL );
368   if ( EFI_BUFFER_TOO_SMALL == Status ) {
369     for ( ; ; ) {
370       //
371       //  One or more block IO devices are present
372       //
373       Status = gBS->AllocatePool (
374                       EfiRuntimeServicesData,
375                       BufferSize,
376                       (VOID **) &pHandle
377                       );
378       if ( EFI_ERROR ( Status )) {
379         DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
380                   "Insufficient memory, failed handle buffer allocation\r\n" ));
381         break;
382       }
383 
384       //
385       //  Locate the block IO devices
386       //
387       Status = gBS->LocateHandle (
388                       ByProtocol,
389                       &gEfiCallerIdGuid,
390                       NULL,
391                       &BufferSize,
392                       pHandle );
393       if ( EFI_ERROR ( Status )) {
394         //
395         //  Error getting handles
396         //
397         DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,
398                 "Failure getting Telnet handles\r\n" ));
399         break;
400       }
401 
402       //
403       //  Remove any use of the driver
404       //
405       Max = BufferSize / sizeof ( pHandle[ 0 ]);
406       for ( Index = 0; Max > Index; Index++ ) {
407         Status = DriverStop ( &gDriverBinding,
408                               pHandle[ Index ],
409                               0,
410                               NULL );
411         if ( EFI_ERROR ( Status )) {
412           DEBUG (( DEBUG_WARN | DEBUG_INIT | DEBUG_INFO,
413                     "WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ]));
414           break;
415         }
416       }
417       break;
418     }
419   }
420   else {
421     if ( EFI_NOT_FOUND == Status ) {
422       //
423       //  No devices were found
424       //
425       Status = EFI_SUCCESS;
426     }
427   }
428 
429   //
430   //  Free the handle array
431   //
432   if ( NULL != pHandle ) {
433     gBS->FreePool ( pHandle );
434   }
435 
436   //
437   //  Remove the protocols installed by the EntryPoint routine.
438   //
439   if ( !EFI_ERROR ( Status )) {
440     gBS->UninstallMultipleProtocolInterfaces (
441             ImageHandle,
442             &gEfiDriverBindingProtocolGuid,
443             &gDriverBinding,
444             &gEfiComponentNameProtocolGuid,
445             &gComponentName,
446             &gEfiComponentName2ProtocolGuid,
447             &gComponentName2,
448             NULL
449             );
450     DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
451             "Removed:   gEfiComponentName2ProtocolGuid from 0x%08x\r\n",
452             ImageHandle ));
453     DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
454               "Removed:   gEfiComponentNameProtocolGuid from 0x%08x\r\n",
455               ImageHandle ));
456     DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
457               "Removed:   gEfiDriverBindingProtocolGuid from 0x%08x\r\n",
458               ImageHandle ));
459   }
460 
461   //
462   //  Return the unload status
463   //
464   return Status;
465 }
466 
467 
468 /**
469 Ax88772 driver entry point.
470 
471 @param [in] ImageHandle       Handle for the image.
472 @param [in] pSystemTable      Address of the system table.
473 
474 @retval EFI_SUCCESS           Image successfully loaded.
475 
476 **/
477 EFI_STATUS
478 EFIAPI
EntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * pSystemTable)479 EntryPoint (
480   IN EFI_HANDLE ImageHandle,
481   IN EFI_SYSTEM_TABLE * pSystemTable
482   )
483 {
484   EFI_STATUS    Status;
485 
486   DBG_ENTER ( );
487 
488   //
489   //  Add the driver to the list of drivers
490   //
491   Status = EfiLibInstallDriverBindingComponentName2 (
492              ImageHandle,
493              pSystemTable,
494              &gDriverBinding,
495              ImageHandle,
496              &gComponentName,
497              &gComponentName2
498              );
499   ASSERT_EFI_ERROR (Status);
500   if ( !EFI_ERROR ( Status )) {
501     DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
502               "Installed: gEfiDriverBindingProtocolGuid on   0x%08x\r\n",
503               ImageHandle ));
504     DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
505               "Installed: gEfiComponentNameProtocolGuid on   0x%08x\r\n",
506               ImageHandle ));
507     DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
508               "Installed: gEfiComponentName2ProtocolGuid on   0x%08x\r\n",
509               ImageHandle ));
510   }
511   DBG_EXIT_STATUS ( Status );
512   return Status;
513 }
514