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