Home | History | Annotate | Download | only in Ax88772
      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
     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
    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
    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
    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
    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