--- /dev/null
+/** @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