]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772/DriverBinding.c
SNP driver for ASIX Electronics AX88772 found in SMC Networks SMC2209 USB/Ethernet...
[mirror_edk2.git] / OptionRomPkg / Bus / Usb / UsbNetworking / Ax88772 / DriverBinding.c
diff --git a/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772/DriverBinding.c b/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772/DriverBinding.c
new file mode 100644 (file)
index 0000000..5f0f286
--- /dev/null
@@ -0,0 +1,526 @@
+/** @file\r
+  Implement the driver binding protocol for Asix AX88772 Ethernet driver.\r
+\r
+  Copyright (c) 2011, Intel Corporation\r
+  All rights reserved. This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Ax88772.h"\r
+\r
+/**\r
+  Verify the controller type\r
+\r
+  @param [in] pThis                Protocol instance pointer.\r
+  @param [in] Controller           Handle of device to test.\r
+  @param [in] pRemainingDevicePath Not used.\r
+\r
+  @retval EFI_SUCCESS          This driver supports this device.\r
+  @retval other                This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL * pThis,\r
+  IN EFI_HANDLE Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath\r
+  )\r
+{\r
+  EFI_USB_DEVICE_DESCRIPTOR Device;\r
+  EFI_USB_IO_PROTOCOL * pUsbIo;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Connect to the USB stack\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiUsbIoProtocolGuid,\r
+                  (VOID **) &pUsbIo,\r
+                  pThis->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (!EFI_ERROR ( Status )) {\r
+\r
+    //\r
+    //  Get the interface descriptor to check the USB class and find a transport\r
+    //  protocol handler.\r
+    //\r
+    Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );\r
+    if (!EFI_ERROR ( Status )) {\r
+\r
+      //\r
+      //  Validate the adapter\r
+      //\r
+      if (( VENDOR_ID != Device.IdVendor )\r
+        || ( PRODUCT_ID != Device.IdProduct )) {\r
+        Status = EFI_UNSUPPORTED;\r
+      }\r
+    }\r
+\r
+    //\r
+    //  Done with the USB stack\r
+    //\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiUsbIoProtocolGuid,\r
+           pThis->DriverBindingHandle,\r
+           Controller\r
+           );\r
+  }\r
+\r
+  //\r
+  //  Return the device supported status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Start this driver on Controller by opening UsbIo and DevicePath protocols.\r
+  Initialize PXE structures, create a copy of the Controller Device Path with the\r
+  NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol\r
+  on the newly created Device Path.\r
+\r
+  @param [in] pThis                Protocol instance pointer.\r
+  @param [in] Controller           Handle of device to work with.\r
+  @param [in] pRemainingDevicePath Not used, always produce all possible children.\r
+\r
+  @retval EFI_SUCCESS          This driver is added to Controller.\r
+  @retval other                This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL * pThis,\r
+  IN EFI_HANDLE Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  NIC_DEVICE * pNicDevice;\r
+  UINTN LengthInBytes;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Allocate the device structure\r
+  //\r
+  LengthInBytes = sizeof ( *pNicDevice );\r
+  Status = gBS->AllocatePool (\r
+                  EfiRuntimeServicesData,\r
+                  LengthInBytes,\r
+                  (VOID **) &pNicDevice\r
+                  );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
+              "0x%08x: Allocate pNicDevice, %d bytes\r\n",\r
+              pNicDevice,\r
+              sizeof ( *pNicDevice )));\r
+\r
+    //\r
+    //  Set the structure signature\r
+    //\r
+    ZeroMem ( pNicDevice, LengthInBytes );\r
+    pNicDevice->Signature = DEV_SIGNATURE;\r
+\r
+    //\r
+    //  Connect to the USB I/O protocol\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiUsbIoProtocolGuid,\r
+                    (VOID **) &pNicDevice->pUsbIo,\r
+                    pThis->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+\r
+    if ( !EFI_ERROR ( Status )) {\r
+      //\r
+      //  Allocate the necessary events\r
+      //\r
+      Status = gBS->CreateEvent ( EVT_TIMER,\r
+                                  TPL_AX88772,\r
+                                  (EFI_EVENT_NOTIFY)Ax88772Timer,\r
+                                  pNicDevice,\r
+                                  (VOID **)&pNicDevice->Timer );\r
+      if ( !EFI_ERROR ( Status )) {\r
+        DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+                  "0x%08x: Allocated timer\r\n",\r
+                  pNicDevice->Timer ));\r
+\r
+        //\r
+        //  Initialize the simple network protocol\r
+        //\r
+        pNicDevice->Controller = Controller;\r
+        SN_Setup ( pNicDevice );\r
+\r
+        //\r
+        //  Start the timer\r
+        //\r
+        Status = gBS->SetTimer ( pNicDevice->Timer,\r
+                                 TimerPeriodic,\r
+                                 TIMER_MSEC );\r
+        if ( !EFI_ERROR ( Status )) {\r
+          //\r
+          //  Install both the simple network and device path protocols.\r
+          //\r
+          Status = gBS->InstallMultipleProtocolInterfaces (\r
+                          &Controller,\r
+                          &gEfiCallerIdGuid,\r
+                          pNicDevice,\r
+                          &gEfiSimpleNetworkProtocolGuid,\r
+                          &pNicDevice->SimpleNetwork,\r
+                          NULL\r
+                          );\r
+\r
+          if ( !EFI_ERROR ( Status )) {\r
+            DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+                      "Installed: gEfiCallerIdGuid on   0x%08x\r\n",\r
+                      Controller ));\r
+            DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+                      "Installed: gEfiSimpleNetworkProtocolGuid on   0x%08x\r\n",\r
+                      Controller ));\r
+            DBG_EXIT_STATUS ( Status );\r
+            return Status;\r
+          }\r
+          DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,\r
+                    "ERROR - Failed to install gEfiSimpleNetworkProtocol on 0x%08x\r\n",\r
+                    Controller ));\r
+        }\r
+        else {\r
+          DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,\r
+                    "ERROR - Failed to start the timer, Status: %r\r\n",\r
+                    Status ));\r
+        }\r
+      }\r
+      else {\r
+        DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,\r
+                  "ERROR - Failed to create timer event, Status: %r\r\n",\r
+                  Status ));\r
+      }\r
+\r
+      //\r
+      //  Done with the USB stack\r
+      //\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiUsbIoProtocolGuid,\r
+             pThis->DriverBindingHandle,\r
+             Controller\r
+             );\r
+    }\r
+\r
+    //\r
+    //  Done with the device\r
+    //\r
+    gBS->FreePool ( pNicDevice );\r
+  }\r
+\r
+  //\r
+  //  Display the driver start status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and\r
+  closing the DevicePath and PciIo protocols on Controller.\r
+\r
+  @param [in] pThis                Protocol instance pointer.\r
+  @param [in] Controller           Handle of device to stop driver on.\r
+  @param [in] NumberOfChildren     How many children need to be stopped.\r
+  @param [in] pChildHandleBuffer   Not used.\r
+\r
+  @retval EFI_SUCCESS          This driver is removed Controller.\r
+  @retval EFI_DEVICE_ERROR     The device could not be stopped due to a device error.\r
+  @retval other                This driver was not removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL * pThis,\r
+  IN  EFI_HANDLE Controller,\r
+  IN  UINTN NumberOfChildren,\r
+  IN  EFI_HANDLE * pChildHandleBuffer\r
+  )\r
+{\r
+  NIC_DEVICE * pNicDevice;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Determine if this driver is already attached\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiCallerIdGuid,\r
+                  (VOID **) &pNicDevice,\r
+                  pThis->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    //\r
+    //  AX88772 driver is no longer running on this device\r
+    //\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+              Controller,\r
+              &gEfiSimpleNetworkProtocolGuid,\r
+              &pNicDevice->SimpleNetwork,\r
+              &gEfiCallerIdGuid,\r
+              pNicDevice,\r
+              NULL );\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
+                "Removed:   gEfiSimpleNetworkProtocolGuid from 0x%08x\r\n",\r
+                Controller ));\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
+                "Removed:   gEfiCallerIdGuid from 0x%08x\r\n",\r
+                Controller ));\r
+\r
+    //\r
+    //  Stop the timer\r
+    //\r
+    if ( NULL != pNicDevice->Timer ) {\r
+      gBS->SetTimer ( pNicDevice->Timer, TimerCancel, 0 );\r
+      gBS->CloseEvent ( pNicDevice->Timer );\r
+      DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+                "0x%08x: Released timer\r\n",\r
+                pNicDevice->Timer ));\r
+    }\r
+\r
+    //\r
+    //  Done with the device context\r
+    //\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
+              "0x%08x: Free pNicDevice, %d bytes\r\n",\r
+              pNicDevice,\r
+              sizeof ( *pNicDevice )));\r
+    gBS->FreePool ( pNicDevice );\r
+  }\r
+\r
+  //\r
+  //  Return the shutdown status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Driver binding protocol declaration\r
+**/\r
+EFI_DRIVER_BINDING_PROTOCOL  gDriverBinding = {\r
+  DriverSupported,\r
+  DriverStart,\r
+  DriverStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+\r
+/**\r
+  Ax88772 driver unload routine.\r
+\r
+  @param [in] ImageHandle       Handle for the image.\r
+\r
+  @retval EFI_SUCCESS           Image may be unloaded\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverUnload (\r
+  IN EFI_HANDLE ImageHandle\r
+  )\r
+{\r
+  UINTN BufferSize;\r
+  UINTN Index;\r
+  UINTN Max;\r
+  EFI_HANDLE * pHandle;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Determine which devices are using this driver\r
+  //\r
+  BufferSize = 0;\r
+  pHandle = NULL;\r
+  Status = gBS->LocateHandle (\r
+                  ByProtocol,\r
+                  &gEfiCallerIdGuid,\r
+                  NULL,\r
+                  &BufferSize,\r
+                  NULL );\r
+  if ( EFI_BUFFER_TOO_SMALL == Status ) {\r
+    for ( ; ; ) {\r
+      //\r
+      //  One or more block IO devices are present\r
+      //\r
+      Status = gBS->AllocatePool (\r
+                      EfiRuntimeServicesData,\r
+                      BufferSize,\r
+                      (VOID **) &pHandle\r
+                      );\r
+      if ( EFI_ERROR ( Status )) {\r
+        DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+                  "Insufficient memory, failed handle buffer allocation\r\n" ));\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Locate the block IO devices\r
+      //\r
+      Status = gBS->LocateHandle (\r
+                      ByProtocol,\r
+                      &gEfiCallerIdGuid,\r
+                      NULL,\r
+                      &BufferSize,\r
+                      pHandle );\r
+      if ( EFI_ERROR ( Status )) {\r
+        //\r
+        //  Error getting handles\r
+        //\r
+        DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,\r
+                "Failure getting Telnet handles\r\n" ));\r
+        break;\r
+      }\r
+      \r
+      //\r
+      //  Remove any use of the driver\r
+      //\r
+      Max = BufferSize / sizeof ( pHandle[ 0 ]);\r
+      for ( Index = 0; Max > Index; Index++ ) {\r
+        Status = DriverStop ( &gDriverBinding,\r
+                              pHandle[ Index ],\r
+                              0,\r
+                              NULL );\r
+        if ( EFI_ERROR ( Status )) {\r
+          DEBUG (( DEBUG_WARN | DEBUG_INIT | DEBUG_INFO,\r
+                    "WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ]));\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+    }\r
+  }\r
+  else {\r
+    if ( EFI_NOT_FOUND == Status ) {\r
+      //\r
+      //  No devices were found\r
+      //\r
+      Status = EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Free the handle array\r
+  //\r
+  if ( NULL != pHandle ) {\r
+    gBS->FreePool ( pHandle );\r
+  }\r
+\r
+  //\r
+  //  Remove the protocols installed by the EntryPoint routine.\r
+  //\r
+  if ( !EFI_ERROR ( Status )) {\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+            ImageHandle,\r
+            &gEfiDriverBindingProtocolGuid,\r
+            &gDriverBinding,\r
+            &gEfiComponentNameProtocolGuid,\r
+            &gComponentName,\r
+            &gEfiComponentName2ProtocolGuid,\r
+            &gComponentName2,\r
+            NULL\r
+            );\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+            "Removed:   gEfiComponentName2ProtocolGuid from 0x%08x\r\n",\r
+            ImageHandle ));\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+              "Removed:   gEfiComponentNameProtocolGuid from 0x%08x\r\n",\r
+              ImageHandle ));\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+              "Removed:   gEfiDriverBindingProtocolGuid from 0x%08x\r\n",\r
+              ImageHandle ));\r
+  }\r
+\r
+  //\r
+  //  Return the unload status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+Ax88772 driver entry point.\r
+\r
+@param [in] ImageHandle       Handle for the image.\r
+@param [in] pSystemTable      Address of the system table.\r
+\r
+@retval EFI_SUCCESS           Image successfully loaded.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EntryPoint (\r
+  IN EFI_HANDLE ImageHandle,\r
+  IN EFI_SYSTEM_TABLE * pSystemTable\r
+  )\r
+{\r
+  EFI_LOADED_IMAGE_PROTOCOL * pLoadedImage;\r
+  EFI_STATUS    Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Enable unload support\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  gImageHandle,\r
+                  &gEfiLoadedImageProtocolGuid,\r
+                  (VOID **)&pLoadedImage\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    pLoadedImage->Unload = DriverUnload;\r
+  }\r
+\r
+  //\r
+  //  Add the driver to the list of drivers\r
+  //\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             pSystemTable,\r
+             &gDriverBinding,\r
+             ImageHandle,\r
+             &gComponentName,\r
+             &gComponentName2\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+  if ( !EFI_ERROR ( Status )) {\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+              "Installed: gEfiDriverBindingProtocolGuid on   0x%08x\r\n",\r
+              ImageHandle ));\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+              "Installed: gEfiComponentNameProtocolGuid on   0x%08x\r\n",\r
+              ImageHandle ));\r
+    DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+              "Installed: gEfiComponentName2ProtocolGuid on   0x%08x\r\n",\r
+              ImageHandle ));\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r