1. Do not use tab characters 2. No trailing white space in one line 3. All files must end with CRLF Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			3523 lines
		
	
	
		
			107 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3523 lines
		
	
	
		
			107 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
Copyright (c) 1999 - 2018, 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 "BiosSnp16.h"
 | 
						|
 | 
						|
 | 
						|
///
 | 
						|
/// EFI Driver Binding Protocol Instance
 | 
						|
///
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = {
 | 
						|
  BiosSnp16DriverBindingSupported,
 | 
						|
  BiosSnp16DriverBindingStart,
 | 
						|
  BiosSnp16DriverBindingStop,
 | 
						|
  0x3,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
///
 | 
						|
///  This boolean is used to determine if we should release the cached vector during an error condition.
 | 
						|
///
 | 
						|
BOOLEAN     mCachedInt1A = FALSE;
 | 
						|
 | 
						|
//
 | 
						|
// Private worker functions;
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Start the UNDI interface.
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
  @param Ax                  PCI address of Undi device.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
 | 
						|
  @retval Others           Status of start 16 bit UNDI ROM.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkStartUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
 | 
						|
  UINT16                  Ax
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Start the UNDI interface
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
 | 
						|
  @retval Others           Status of start 16 bit UNDI ROM.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkStopUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Stop the UNDI interface
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM.
 | 
						|
  @retval Others           Status of stop 16 bit UNDI ROM.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkCleanupUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Get runtime information for Undi network interface
 | 
						|
 | 
						|
  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS Sucess operation.
 | 
						|
  @retval Others      Fail to get runtime information for Undi network interface.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkGetInformation (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Get NIC type
 | 
						|
 | 
						|
  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS Sucess operation.
 | 
						|
  @retval Others      Fail to get NIC type.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkGetNicType (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Get NDIS information
 | 
						|
 | 
						|
  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS Sucess operation.
 | 
						|
  @retval Others      Fail to get NDIS information.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkGetNdisInfo (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Signal handlers for ExitBootServices event.
 | 
						|
 | 
						|
  Clean up any Real-mode UNDI residue from the system
 | 
						|
 | 
						|
  @param Event      ExitBootServices event
 | 
						|
  @param Context
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkEvent (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Loads the undi driver.
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
 | 
						|
  @retval   EFI_SUCCESS   - Successfully loads undi driver.
 | 
						|
  @retval   EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkLoadUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Unload 16 bit UNDI Option ROM from memory
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
 | 
						|
  @return EFI_STATUS
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkUnloadUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Entry point for EFI drivers.
 | 
						|
 | 
						|
  @param ImageHandle Handle that identifies the loaded image.
 | 
						|
  @param SystemTable System Table for this image.
 | 
						|
 | 
						|
  @return EFI_STATUS Return status from EfiLibInstallAllDriverProtocols.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosSnp16DriverEntryPoint (
 | 
						|
  IN EFI_HANDLE         ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE   *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EfiLibInstallDriverBindingComponentName2 (
 | 
						|
           ImageHandle,
 | 
						|
           SystemTable,
 | 
						|
           &gBiosSnp16DriverBinding,
 | 
						|
           ImageHandle,
 | 
						|
           &gBiosSnp16ComponentName,
 | 
						|
           &gBiosSnp16ComponentName2
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// EFI Driver Binding Protocol Functions
 | 
						|
//
 | 
						|
/**
 | 
						|
  Tests to see if this driver supports a given controller.
 | 
						|
 | 
						|
  @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
 | 
						|
  @param Controller           The handle of the controller to test.
 | 
						|
  @param RemainingDevicePath  A pointer to the remaining portion of a device path.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    The driver supports given controller.
 | 
						|
  @retval EFI_UNSUPPORT  The driver doesn't support given controller.
 | 
						|
  @retval Other          Other errors prevent driver finishing to test
 | 
						|
                         if the driver supports given controller.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosSnp16DriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  EFI_PCI_IO_PROTOCOL       *PciIo;
 | 
						|
  PCI_TYPE00                Pci;
 | 
						|
 | 
						|
  //
 | 
						|
  // See if the Legacy BIOS Protocol is available
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Open the IO Abstraction(s) needed to perform the supported test
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  (VOID **) &DevicePath,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->CloseProtocol (
 | 
						|
        Controller,
 | 
						|
        &gEfiDevicePathProtocolGuid,
 | 
						|
        This->DriverBindingHandle,
 | 
						|
        Controller
 | 
						|
        );
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the IO Abstraction(s) needed to perform the supported test
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // See if this is a PCI Network Controller by looking at the Command register and
 | 
						|
  // Class Code Register
 | 
						|
  //
 | 
						|
  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_UNSUPPORTED;
 | 
						|
  if (Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
  gBS->CloseProtocol (
 | 
						|
        Controller,
 | 
						|
        &gEfiPciIoProtocolGuid,
 | 
						|
        This->DriverBindingHandle,
 | 
						|
        Controller
 | 
						|
        );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Starts the Snp device controller
 | 
						|
 | 
						|
  @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
 | 
						|
  @param Controller           The handle of the controller to test.
 | 
						|
  @param RemainingDevicePath  A pointer to the remaining portion of a device path.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS          - The device was started.
 | 
						|
  @retval  EFI_DEVICE_ERROR     - The device could not be started due to a device error.
 | 
						|
  @retval  EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosSnp16DriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  EFI_PCI_IO_PROTOCOL       *PciIo;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV    *SimpleNetworkDevice;
 | 
						|
  EFI_DEV_PATH              Node;
 | 
						|
  UINTN                     Index;
 | 
						|
  UINTN                     Index2;
 | 
						|
  UINTN                     Segment;
 | 
						|
  UINTN                     Bus;
 | 
						|
  UINTN                     Device;
 | 
						|
  UINTN                     Function;
 | 
						|
  UINTN                     Flags;
 | 
						|
  UINT64                    Supports;
 | 
						|
 | 
						|
  SimpleNetworkDevice = NULL;
 | 
						|
  PciIo               = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // See if the Legacy BIOS Protocol is available
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Open the IO Abstraction(s) needed
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  (VOID **) &DevicePath,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = PciIo->Attributes (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoAttributeOperationSupported,
 | 
						|
                    0,
 | 
						|
                    &Supports
 | 
						|
                    );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
 | 
						|
    Status = PciIo->Attributes (
 | 
						|
                      PciIo,
 | 
						|
                      EfiPciIoAttributeOperationEnable,
 | 
						|
                      Supports,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check to see if there is a legacy option ROM image associated with this PCI device
 | 
						|
  //
 | 
						|
  Status = LegacyBios->CheckPciRom (
 | 
						|
                         LegacyBios,
 | 
						|
                         Controller,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         &Flags
 | 
						|
                         );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Post the legacy option ROM if it is available.
 | 
						|
  //
 | 
						|
  Status = LegacyBios->InstallPciRom (
 | 
						|
                         LegacyBios,
 | 
						|
                         Controller,
 | 
						|
                         NULL,
 | 
						|
                         &Flags,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         NULL
 | 
						|
                         );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Allocate memory for this SimpleNetwork device instance
 | 
						|
  //
 | 
						|
  Status = gBS->AllocatePool (
 | 
						|
                  EfiBootServicesData,
 | 
						|
                  sizeof (EFI_SIMPLE_NETWORK_DEV),
 | 
						|
                  (VOID **) &SimpleNetworkDevice
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (SimpleNetworkDevice, sizeof (EFI_SIMPLE_NETWORK_DEV));
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the SimpleNetwork device instance
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->Signature      = EFI_SIMPLE_NETWORK_DEV_SIGNATURE;
 | 
						|
  SimpleNetworkDevice->LegacyBios     = LegacyBios;
 | 
						|
  SimpleNetworkDevice->BaseDevicePath = DevicePath;
 | 
						|
  SimpleNetworkDevice->PciIo          = PciIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the Nii Protocol
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->Nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
 | 
						|
  SimpleNetworkDevice->Nii.Type     = EfiNetworkInterfaceUndi;
 | 
						|
 | 
						|
  CopyMem (&SimpleNetworkDevice->Nii.StringId, "UNDI", 4);
 | 
						|
 | 
						|
  //
 | 
						|
  // Load 16 bit UNDI Option ROM into Memory
 | 
						|
  //
 | 
						|
  Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_NET, "ERROR : Could not load UNDI.  Status = %r\n", Status));
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  SimpleNetworkDevice->UndiLoaded = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Call PXENV_START_UNDI - Initilizes the UNID interface for use.
 | 
						|
  //
 | 
						|
  PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
 | 
						|
  Status = Undi16SimpleNetworkStartUndi (
 | 
						|
             SimpleNetworkDevice,
 | 
						|
             (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function))
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_NET, "ERROR : Could not StartUndi.  Status = %r\n", Status));
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Initialize the Simple Network Protocol
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "Initialize SimpleNetworkDevice instance\n"));
 | 
						|
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Revision       = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Start          = Undi16SimpleNetworkStart;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Stop           = Undi16SimpleNetworkStop;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Initialize     = Undi16SimpleNetworkInitialize;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Reset          = Undi16SimpleNetworkReset;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Shutdown       = Undi16SimpleNetworkShutdown;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.ReceiveFilters = Undi16SimpleNetworkReceiveFilters;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.StationAddress = Undi16SimpleNetworkStationAddress;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Statistics     = Undi16SimpleNetworkStatistics;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.MCastIpToMac   = Undi16SimpleNetworkMCastIpToMac;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.NvData         = Undi16SimpleNetworkNvData;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.GetStatus      = Undi16SimpleNetworkGetStatus;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Transmit       = Undi16SimpleNetworkTransmit;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Receive        = Undi16SimpleNetworkReceive;
 | 
						|
  SimpleNetworkDevice->SimpleNetwork.Mode           = &(SimpleNetworkDevice->SimpleNetworkMode);
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_WAIT,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  Undi16SimpleNetworkWaitForPacket,
 | 
						|
                  &SimpleNetworkDevice->SimpleNetwork,
 | 
						|
                  &SimpleNetworkDevice->SimpleNetwork.WaitForPacket
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Create an event to be signalled when ExitBootServices occurs in order
 | 
						|
  // to clean up nicely
 | 
						|
  //
 | 
						|
  Status = gBS->CreateEventEx (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  Undi16SimpleNetworkEvent,
 | 
						|
                  NULL,
 | 
						|
                  &gEfiEventExitBootServicesGuid,
 | 
						|
                  &SimpleNetworkDevice->EfiBootEvent
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create an event to be signalled when Legacy Boot occurs to clean up the IVT
 | 
						|
  //
 | 
						|
  Status = EfiCreateEventLegacyBootEx(
 | 
						|
             TPL_NOTIFY,
 | 
						|
             Undi16SimpleNetworkEvent,
 | 
						|
             NULL,
 | 
						|
             &SimpleNetworkDevice->LegacyBootEvent
 | 
						|
             );
 | 
						|
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR,"ERROR : Could not create event.  Status = %r\n",Status));
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the SimpleNetwork Mode Information
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "Initialize Mode Information\n"));
 | 
						|
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.State                = EfiSimpleNetworkStopped;
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize      = 14;
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable = TRUE;
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported  = TRUE;
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
 | 
						|
    EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
 | 
						|
    EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
 | 
						|
    EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
 | 
						|
    EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount = MAXNUM_MCADDR;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the SimpleNetwork Private Information
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "Initialize Private Information\n"));
 | 
						|
 | 
						|
  Status = BiosSnp16AllocatePagesBelowOneMb (
 | 
						|
             sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1,
 | 
						|
             (VOID **) &SimpleNetworkDevice->Xmit
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = BiosSnp16AllocatePagesBelowOneMb (
 | 
						|
             1,
 | 
						|
             &SimpleNetworkDevice->TxRealModeMediaHeader
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = BiosSnp16AllocatePagesBelowOneMb (
 | 
						|
             1,
 | 
						|
             &SimpleNetworkDevice->TxRealModeDataBuffer
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = BiosSnp16AllocatePagesBelowOneMb (
 | 
						|
             1,
 | 
						|
             &SimpleNetworkDevice->TxDestAddr
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  SimpleNetworkDevice->Xmit->XmitOffset               = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f);
 | 
						|
 | 
						|
  SimpleNetworkDevice->Xmit->XmitSegment              = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) >> 4);
 | 
						|
 | 
						|
  SimpleNetworkDevice->Xmit->DataBlkCount             = 1;
 | 
						|
 | 
						|
  SimpleNetworkDevice->Xmit->DataBlock[0].TDPtrType   = 1;
 | 
						|
  SimpleNetworkDevice->Xmit->DataBlock[0].TDRsvdByte  = 0;
 | 
						|
 | 
						|
  SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f);
 | 
						|
 | 
						|
  SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) >> 4);
 | 
						|
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.First = 0;
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Start() the SimpleNetwork device
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "Start()\n"));
 | 
						|
 | 
						|
  Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // GetInformation() the SimpleNetwork device
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "GetInformation()\n"));
 | 
						|
 | 
						|
  Status = Undi16SimpleNetworkGetInformation (&SimpleNetworkDevice->SimpleNetwork);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Build the device path for the child device
 | 
						|
  //
 | 
						|
  ZeroMem (&Node, sizeof (Node));
 | 
						|
  Node.DevPath.Type     = MESSAGING_DEVICE_PATH;
 | 
						|
  Node.DevPath.SubType  = MSG_MAC_ADDR_DP;
 | 
						|
  SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH));
 | 
						|
  CopyMem (
 | 
						|
    &Node.MacAddr.MacAddress,
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | 
						|
    sizeof (EFI_MAC_ADDRESS)
 | 
						|
    );
 | 
						|
  SimpleNetworkDevice->DevicePath = AppendDevicePathNode (
 | 
						|
                                      SimpleNetworkDevice->BaseDevicePath,
 | 
						|
                                      &Node.DevPath
 | 
						|
                                      );
 | 
						|
 | 
						|
  //
 | 
						|
  // GetNicType()  the SimpleNetwork device
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "GetNicType()\n"));
 | 
						|
 | 
						|
  Status = Undi16SimpleNetworkGetNicType (&SimpleNetworkDevice->SimpleNetwork);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // GetNdisInfo() the SimpleNetwork device
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "GetNdisInfo()\n"));
 | 
						|
 | 
						|
  Status = Undi16SimpleNetworkGetNdisInfo (&SimpleNetworkDevice->SimpleNetwork);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Stop() the SimpleNetwork device
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "Stop()\n"));
 | 
						|
 | 
						|
  Status = SimpleNetworkDevice->SimpleNetwork.Stop (&SimpleNetworkDevice->SimpleNetwork);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Print Mode information
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "Mode->State                = %d\n", SimpleNetworkDevice->SimpleNetworkMode.State));
 | 
						|
  DEBUG ((DEBUG_NET, "Mode->HwAddressSize        = %d\n", SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize));
 | 
						|
  DEBUG ((DEBUG_NET, "Mode->MacAddressChangeable = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable));
 | 
						|
  DEBUG ((DEBUG_NET, "Mode->MultiplTxSupported   = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported));
 | 
						|
  DEBUG ((DEBUG_NET, "Mode->NvRamSize            = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamSize));
 | 
						|
  DEBUG ((DEBUG_NET, "Mode->NvRamAccessSize      = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize));
 | 
						|
  DEBUG ((DEBUG_NET, "Mode->ReceiveFilterSetting = %d\n", SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting));
 | 
						|
  DEBUG ((DEBUG_NET, "Mode->IfType               = %d\n", SimpleNetworkDevice->SimpleNetworkMode.IfType));
 | 
						|
  DEBUG ((DEBUG_NET, "Mode->MCastFilterCount     = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount));
 | 
						|
  for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) {
 | 
						|
    DEBUG ((DEBUG_NET, "  Filter[%02d] = ", Index));
 | 
						|
    for (Index2 = 0; Index2 < 16; Index2++) {
 | 
						|
      DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[Index2]));
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((DEBUG_NET, "\n"));
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "CurrentAddress = "));
 | 
						|
  for (Index2 = 0; Index2 < 16; Index2++) {
 | 
						|
    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[Index2]));
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "\n"));
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "BroadcastAddress = "));
 | 
						|
  for (Index2 = 0; Index2 < 16; Index2++) {
 | 
						|
    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[Index2]));
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "\n"));
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "PermanentAddress = "));
 | 
						|
  for (Index2 = 0; Index2 < 16; Index2++) {
 | 
						|
    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[Index2]));
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "\n"));
 | 
						|
 | 
						|
  //
 | 
						|
  // The network device was started, information collected, and stopped.
 | 
						|
  // Install protocol interfaces for the SimpleNetwork device.
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "Install Protocol Interfaces on network interface\n"));
 | 
						|
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &SimpleNetworkDevice->Handle,
 | 
						|
                  &gEfiSimpleNetworkProtocolGuid,
 | 
						|
                  &SimpleNetworkDevice->SimpleNetwork,
 | 
						|
                  &gEfiNetworkInterfaceIdentifierProtocolGuid,
 | 
						|
                  &SimpleNetworkDevice->Nii,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  SimpleNetworkDevice->DevicePath,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Open PCI I/O from the newly created child handle
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  SimpleNetworkDevice->Handle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                  );
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INIT, "UNDI16 Driver : EFI_SUCCESS\n"));
 | 
						|
 | 
						|
Done:
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (SimpleNetworkDevice != NULL) {
 | 
						|
 | 
						|
      Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
 | 
						|
      //
 | 
						|
      // CLOSE + SHUTDOWN
 | 
						|
      //
 | 
						|
      Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
 | 
						|
      //
 | 
						|
      // CLEANUP
 | 
						|
      //
 | 
						|
      Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
 | 
						|
      //
 | 
						|
      // STOP
 | 
						|
      //
 | 
						|
      if (SimpleNetworkDevice->UndiLoaded) {
 | 
						|
        Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
 | 
						|
      }
 | 
						|
 | 
						|
      if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
 | 
						|
        gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
 | 
						|
      }
 | 
						|
 | 
						|
      if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
 | 
						|
        gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
 | 
						|
      }
 | 
						|
 | 
						|
      if (SimpleNetworkDevice->EfiBootEvent != NULL) {
 | 
						|
        gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
 | 
						|
      }
 | 
						|
 | 
						|
      if (SimpleNetworkDevice->Xmit != NULL) {
 | 
						|
        gBS->FreePages (
 | 
						|
               (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
 | 
						|
               sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
 | 
						|
               );
 | 
						|
      }
 | 
						|
 | 
						|
      if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
 | 
						|
        gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
 | 
						|
      }
 | 
						|
 | 
						|
      if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
 | 
						|
        gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
 | 
						|
      }
 | 
						|
 | 
						|
      if (SimpleNetworkDevice->TxDestAddr != NULL) {
 | 
						|
        gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
 | 
						|
      }
 | 
						|
 | 
						|
      gBS->FreePool (SimpleNetworkDevice);
 | 
						|
 | 
						|
      //
 | 
						|
      //  Only restore the vector if it was cached.
 | 
						|
      //
 | 
						|
      if (mCachedInt1A) {
 | 
						|
        RestoreCachedVectorAddress (0x1A);
 | 
						|
        mCachedInt1A = FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (PciIo != NULL) {
 | 
						|
      Status = PciIo->Attributes (
 | 
						|
                        PciIo,
 | 
						|
                        EfiPciIoAttributeOperationSupported,
 | 
						|
                        0,
 | 
						|
                        &Supports
 | 
						|
                        );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
 | 
						|
        Status = PciIo->Attributes (
 | 
						|
                          PciIo,
 | 
						|
                          EfiPciIoAttributeOperationDisable,
 | 
						|
                          Supports,
 | 
						|
                          NULL
 | 
						|
                          );
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Controller,
 | 
						|
           &gEfiPciIoProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Controller
 | 
						|
           );
 | 
						|
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Controller,
 | 
						|
           &gEfiDevicePathProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Controller
 | 
						|
           );
 | 
						|
    if (Status != EFI_OUT_OF_RESOURCES) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Stops the device by given device controller.
 | 
						|
 | 
						|
  @param This               A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
 | 
						|
  @param Controller         The handle of the controller to test.
 | 
						|
  @param NumberOfChildren   The number of child device handles in ChildHandleBuffer.
 | 
						|
  @param ChildHandleBuffer  An array of child handles to be freed. May be NULL if
 | 
						|
                            NumberOfChildren is 0.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS      - The device was stopped.
 | 
						|
  @retval  EFI_DEVICE_ERROR - The device could not be stopped due to a device error.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosSnp16DriverBindingStop (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | 
						|
  IN  EFI_HANDLE                      Controller,
 | 
						|
  IN  UINTN                           NumberOfChildren,
 | 
						|
  IN  EFI_HANDLE                      *ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  UINTN                       Index;
 | 
						|
  BOOLEAN                     AllChildrenStopped;
 | 
						|
  EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
 | 
						|
  EFI_PCI_IO_PROTOCOL         *PciIo;
 | 
						|
  UINT64                      Supports;
 | 
						|
 | 
						|
  //
 | 
						|
  // Complete all outstanding transactions to Controller.
 | 
						|
  // Don't allow any new transaction to Controller to be started.
 | 
						|
  //
 | 
						|
  if (NumberOfChildren == 0) {
 | 
						|
    //
 | 
						|
    // Close the bus driver
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &PciIo,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Controller,
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      Status = PciIo->Attributes (
 | 
						|
                        PciIo,
 | 
						|
                        EfiPciIoAttributeOperationSupported,
 | 
						|
                        0,
 | 
						|
                        &Supports
 | 
						|
                        );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
 | 
						|
        Status = PciIo->Attributes (
 | 
						|
                          PciIo,
 | 
						|
                          EfiPciIoAttributeOperationDisable,
 | 
						|
                          Supports,
 | 
						|
                          NULL
 | 
						|
                          );
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Status = gBS->CloseProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Controller
 | 
						|
                    );
 | 
						|
 | 
						|
    Status = gBS->CloseProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiDevicePathProtocolGuid,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Controller
 | 
						|
                    );
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  AllChildrenStopped = TRUE;
 | 
						|
 | 
						|
  for (Index = 0; Index < NumberOfChildren; Index++) {
 | 
						|
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    ChildHandleBuffer[Index],
 | 
						|
                    &gEfiSimpleNetworkProtocolGuid,
 | 
						|
                    (VOID **) &SimpleNetwork,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Controller,
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
 | 
						|
      SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SimpleNetwork);
 | 
						|
 | 
						|
      Status = gBS->CloseProtocol (
 | 
						|
                      Controller,
 | 
						|
                      &gEfiPciIoProtocolGuid,
 | 
						|
                      This->DriverBindingHandle,
 | 
						|
                      ChildHandleBuffer[Index]
 | 
						|
                      );
 | 
						|
 | 
						|
      Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                      SimpleNetworkDevice->Handle,
 | 
						|
                      &gEfiSimpleNetworkProtocolGuid,
 | 
						|
                      &SimpleNetworkDevice->SimpleNetwork,
 | 
						|
                      &gEfiNetworkInterfaceIdentifierProtocolGuid,
 | 
						|
                      &SimpleNetworkDevice->Nii,
 | 
						|
                      &gEfiDevicePathProtocolGuid,
 | 
						|
                      SimpleNetworkDevice->DevicePath,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        gBS->OpenProtocol (
 | 
						|
               Controller,
 | 
						|
               &gEfiPciIoProtocolGuid,
 | 
						|
               (VOID **) &PciIo,
 | 
						|
               This->DriverBindingHandle,
 | 
						|
               ChildHandleBuffer[Index],
 | 
						|
               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
               );
 | 
						|
      } else {
 | 
						|
 | 
						|
        Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
 | 
						|
        //
 | 
						|
        // CLOSE + SHUTDOWN
 | 
						|
        //
 | 
						|
        Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
 | 
						|
        //
 | 
						|
        // CLEANUP
 | 
						|
        //
 | 
						|
        Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
 | 
						|
        //
 | 
						|
        // STOP
 | 
						|
        //
 | 
						|
        if (SimpleNetworkDevice->UndiLoaded) {
 | 
						|
          Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
 | 
						|
        }
 | 
						|
 | 
						|
        if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
 | 
						|
          gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
 | 
						|
        }
 | 
						|
 | 
						|
        if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
 | 
						|
          gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
 | 
						|
        }
 | 
						|
 | 
						|
        if (SimpleNetworkDevice->EfiBootEvent != NULL) {
 | 
						|
          gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
 | 
						|
        }
 | 
						|
 | 
						|
        if (SimpleNetworkDevice->Xmit != NULL) {
 | 
						|
          gBS->FreePages (
 | 
						|
                 (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
 | 
						|
                 sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
 | 
						|
                 );
 | 
						|
        }
 | 
						|
 | 
						|
        if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
 | 
						|
          gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
 | 
						|
          gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        if (SimpleNetworkDevice->TxDestAddr != NULL) {
 | 
						|
          gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        gBS->FreePool (SimpleNetworkDevice);
 | 
						|
      }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      AllChildrenStopped = FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!AllChildrenStopped) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// FIFO Support Functions
 | 
						|
//
 | 
						|
/**
 | 
						|
  Judge whether transmit FIFO is full.
 | 
						|
 | 
						|
  @param Fifo Point to trasmit FIFO structure.
 | 
						|
 | 
						|
  @return BOOLEAN whether transmit FIFO is full.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
SimpleNetworkTransmitFifoFull (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (((Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE) == Fifo->First) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Judge whether transmit FIFO is empty.
 | 
						|
 | 
						|
  @param Fifo Point to trasmit FIFO structure.
 | 
						|
 | 
						|
  @return BOOLEAN whether transmit FIFO is empty.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
SimpleNetworkTransmitFifoEmpty (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Fifo->Last == Fifo->First) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Add data into transmit buffer.
 | 
						|
 | 
						|
  @param Fifo Point to trasmit FIFO structure.
 | 
						|
  @param Data The data point want to be added.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  FIFO is full
 | 
						|
  @retval EFI_SUCCESS           Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SimpleNetworkTransmitFifoAdd (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
 | 
						|
  VOID                        *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (SimpleNetworkTransmitFifoFull (Fifo)) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Fifo->Data[Fifo->Last]  = Data;
 | 
						|
  Fifo->Last              = (Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get a data and remove it from network transmit FIFO.
 | 
						|
 | 
						|
  @param Fifo Point to trasmit FIFO structure.
 | 
						|
  @param Data On return, point to the data point want to be got and removed.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES network transmit buffer is empty.
 | 
						|
  @retval EFI_SUCCESS           Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SimpleNetworkTransmitFifoRemove (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
 | 
						|
  VOID                        **Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (SimpleNetworkTransmitFifoEmpty (Fifo)) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  *Data       = Fifo->Data[Fifo->First];
 | 
						|
  Fifo->First = (Fifo->First + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get recive filter setting according to EFI mask value.
 | 
						|
 | 
						|
  @param ReceiveFilterSetting  filter setting EFI mask value.
 | 
						|
 | 
						|
  @return UINT16 Undi filter setting value.
 | 
						|
**/
 | 
						|
UINT16
 | 
						|
Undi16GetPacketFilterSetting (
 | 
						|
  UINTN ReceiveFilterSetting
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT16  PktFilter;
 | 
						|
 | 
						|
  PktFilter = 0;
 | 
						|
  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
 | 
						|
    PktFilter |= FLTR_DIRECTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
 | 
						|
    PktFilter |= FLTR_DIRECTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
 | 
						|
    PktFilter |= FLTR_BRDCST;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
 | 
						|
    PktFilter |= FLTR_PRMSCS;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
 | 
						|
    PktFilter |= FLTR_PRMSCS;
 | 
						|
    //
 | 
						|
    // @bug : Do not know if this is right????
 | 
						|
    //
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // @bug : What is FLTR_SRC_RTG?
 | 
						|
  //
 | 
						|
  return PktFilter;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get filter setting from multi cast buffer .
 | 
						|
 | 
						|
  @param Mode           Point to mode structure.
 | 
						|
  @param McastBuffer    The multi cast buffer
 | 
						|
  @param HwAddressSize  Size of filter value.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Undi16GetMCastFilters (
 | 
						|
  IN EFI_SIMPLE_NETWORK_MODE      *Mode,
 | 
						|
  IN OUT PXENV_UNDI_MCAST_ADDR_T  *McastBuffer,
 | 
						|
  IN UINTN                        HwAddressSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // @bug : What if Mode->MCastFilterCount > MAXNUM_MCADDR?
 | 
						|
  //
 | 
						|
  McastBuffer->MCastAddrCount = (UINT16) Mode->MCastFilterCount;
 | 
						|
  for (Index = 0; Index < MAXNUM_MCADDR; Index++) {
 | 
						|
    if (Index < McastBuffer->MCastAddrCount) {
 | 
						|
      CopyMem (&McastBuffer->MCastAddr[Index], &Mode->MCastFilter[Index], HwAddressSize);
 | 
						|
    } else {
 | 
						|
      ZeroMem (&McastBuffer->MCastAddr[Index], HwAddressSize);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
//
 | 
						|
// Load 16 bit UNDI Option ROM into memory
 | 
						|
//
 | 
						|
/**
 | 
						|
  Loads the undi driver.
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
 | 
						|
  @retval   EFI_SUCCESS   - Successfully loads undi driver.
 | 
						|
  @retval   EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkLoadUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL       *PciIo;
 | 
						|
  UINTN                     RomAddress;
 | 
						|
  PCI_EXPANSION_ROM_HEADER  *PciExpansionRomHeader;
 | 
						|
  PCI_DATA_STRUCTURE        *PciDataStructure;
 | 
						|
  PCI_TYPE00                Pci;
 | 
						|
 | 
						|
  if (!mCachedInt1A) {
 | 
						|
    Status = CacheVectorAddress (0x1A);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      mCachedInt1A = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  PciIo = SimpleNetworkDevice->PciIo;
 | 
						|
 | 
						|
  PciIo->Pci.Read (
 | 
						|
               PciIo,
 | 
						|
               EfiPciIoWidthUint32,
 | 
						|
               0,
 | 
						|
               sizeof (Pci) / sizeof (UINT32),
 | 
						|
               &Pci
 | 
						|
               );
 | 
						|
 | 
						|
  for (RomAddress = 0xc0000; RomAddress < 0xfffff; RomAddress += 0x800) {
 | 
						|
 | 
						|
    PciExpansionRomHeader = (PCI_EXPANSION_ROM_HEADER *) RomAddress;
 | 
						|
 | 
						|
    if (PciExpansionRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((DEBUG_INIT, "Option ROM found at %X\n", RomAddress));
 | 
						|
 | 
						|
    //
 | 
						|
    // If the pointer to the PCI Data Structure is invalid, no further images can be located.
 | 
						|
    // The PCI Data Structure must be DWORD aligned.
 | 
						|
    //
 | 
						|
    if (PciExpansionRomHeader->PcirOffset == 0 ||
 | 
						|
        (PciExpansionRomHeader->PcirOffset & 3) != 0 ||
 | 
						|
        RomAddress + PciExpansionRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > 0x100000) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    PciDataStructure = (PCI_DATA_STRUCTURE *) (RomAddress + PciExpansionRomHeader->PcirOffset);
 | 
						|
 | 
						|
    if (PciDataStructure->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((DEBUG_INIT, "PCI Data Structure found at %X\n", PciDataStructure));
 | 
						|
 | 
						|
    if (PciDataStructure->VendorId != Pci.Hdr.VendorId || PciDataStructure->DeviceId != Pci.Hdr.DeviceId) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG (
 | 
						|
        (DEBUG_INIT,
 | 
						|
         "PCI device with matchinng VendorId and DeviceId (%d,%d)\n",
 | 
						|
         (UINTN) PciDataStructure->VendorId,
 | 
						|
         (UINTN) PciDataStructure->DeviceId)
 | 
						|
        );
 | 
						|
 | 
						|
    Status = LaunchBaseCode (SimpleNetworkDevice, RomAddress);
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Free resources allocated in LaunchBaseCode
 | 
						|
    //
 | 
						|
    Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Unload 16 bit UNDI Option ROM from memory
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
 | 
						|
  @return EFI_STATUS
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkUnloadUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (SimpleNetworkDevice->UndiLoaderTable != NULL) {
 | 
						|
    ZeroMem (SimpleNetworkDevice->UndiLoaderTable, SimpleNetworkDevice->UndiLoaderTablePages << EFI_PAGE_SHIFT);
 | 
						|
    gBS->FreePages (
 | 
						|
          (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->UndiLoaderTable,
 | 
						|
          SimpleNetworkDevice->UndiLoaderTablePages
 | 
						|
          );
 | 
						|
  }
 | 
						|
 | 
						|
  if (SimpleNetworkDevice->DestinationDataSegment != NULL) {
 | 
						|
    ZeroMem (
 | 
						|
      SimpleNetworkDevice->DestinationDataSegment,
 | 
						|
      SimpleNetworkDevice->DestinationDataSegmentPages << EFI_PAGE_SHIFT
 | 
						|
      );
 | 
						|
    gBS->FreePages (
 | 
						|
          (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationDataSegment,
 | 
						|
          SimpleNetworkDevice->DestinationDataSegmentPages
 | 
						|
          );
 | 
						|
  }
 | 
						|
 | 
						|
  if (SimpleNetworkDevice->DestinationStackSegment != NULL) {
 | 
						|
    ZeroMem (
 | 
						|
      SimpleNetworkDevice->DestinationStackSegment,
 | 
						|
      SimpleNetworkDevice->DestinationStackSegmentPages << EFI_PAGE_SHIFT
 | 
						|
      );
 | 
						|
    gBS->FreePages (
 | 
						|
          (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationStackSegment,
 | 
						|
          SimpleNetworkDevice->DestinationStackSegmentPages
 | 
						|
          );
 | 
						|
  }
 | 
						|
 | 
						|
  if (SimpleNetworkDevice->DestinationCodeSegment != NULL) {
 | 
						|
    ZeroMem (
 | 
						|
      SimpleNetworkDevice->DestinationCodeSegment,
 | 
						|
      SimpleNetworkDevice->DestinationCodeSegmentPages << EFI_PAGE_SHIFT
 | 
						|
      );
 | 
						|
    gBS->FreePages (
 | 
						|
          (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationCodeSegment,
 | 
						|
          SimpleNetworkDevice->DestinationCodeSegmentPages
 | 
						|
          );
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Start the UNDI interface.
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
  @param Ax                  PCI address of Undi device.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
 | 
						|
  @retval Others           Status of start 16 bit UNDI ROM.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkStartUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
 | 
						|
  UINT16                  Ax
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  PXENV_START_UNDI_T  Start;
 | 
						|
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to start the network interface
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // @bug : What is this state supposed to be???
 | 
						|
  //
 | 
						|
  Start.Status  = INIT_PXE_STATUS;
 | 
						|
  Start.Ax      = Ax;
 | 
						|
  Start.Bx      = 0x0000;
 | 
						|
  Start.Dx      = 0x0000;
 | 
						|
  Start.Di      = 0x0000;
 | 
						|
  Start.Es      = 0x0000;
 | 
						|
 | 
						|
  Status        = PxeStartUndi (SimpleNetworkDevice, &Start);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Start.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Stop the UNDI interface
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM.
 | 
						|
  @retval Others           Status of stop 16 bit UNDI ROM.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkStopUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  PXENV_STOP_UNDI_T Stop;
 | 
						|
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to start the network interface
 | 
						|
  //
 | 
						|
  Stop.Status = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Status      = PxeUndiStop (SimpleNetworkDevice, &Stop);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Stop.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Cleanup Unid network interface
 | 
						|
 | 
						|
  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to cleanup 16 bit UNDI ROM.
 | 
						|
  @retval Others           Status of cleanup 16 bit UNDI ROM.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkCleanupUndi (
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  PXENV_UNDI_CLEANUP_T  Cleanup;
 | 
						|
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to cleanup the network interface
 | 
						|
  //
 | 
						|
  Cleanup.Status  = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Status          = PxeUndiCleanup (SimpleNetworkDevice, &Cleanup);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Cleanup.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get runtime information for Undi network interface
 | 
						|
 | 
						|
  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS Sucess operation.
 | 
						|
  @retval Others      Fail to get runtime information for Undi network interface.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkGetInformation (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  UINTN                   Index;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to start the network interface
 | 
						|
  //
 | 
						|
  ZeroMem (&SimpleNetworkDevice->GetInformation, sizeof (PXENV_UNDI_GET_INFORMATION_T));
 | 
						|
 | 
						|
  SimpleNetworkDevice->GetInformation.Status  = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Status = PxeUndiGetInformation (SimpleNetworkDevice, &SimpleNetworkDevice->GetInformation);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.Status      = %d\n", SimpleNetworkDevice->GetInformation.Status));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.BaseIo      = %d\n", SimpleNetworkDevice->GetInformation.BaseIo));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.IntNumber   = %d\n", SimpleNetworkDevice->GetInformation.IntNumber));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.MaxTranUnit = %d\n", SimpleNetworkDevice->GetInformation.MaxTranUnit));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.HwType      = %d\n", SimpleNetworkDevice->GetInformation.HwType));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.HwAddrLen   = %d\n", SimpleNetworkDevice->GetInformation.HwAddrLen));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.ROMAddress  = %d\n", SimpleNetworkDevice->GetInformation.ROMAddress));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.RxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.RxBufCt));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.TxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.TxBufCt));
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.CurNodeAddr ="));
 | 
						|
  for (Index = 0; Index < 16; Index++) {
 | 
						|
    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.CurrentNodeAddress[Index]));
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "\n"));
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "  GetInformation.PermNodeAddr ="));
 | 
						|
  for (Index = 0; Index < 16; Index++) {
 | 
						|
    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.PermNodeAddress[Index]));
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "\n"));
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (SimpleNetworkDevice->GetInformation.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // The information has been retrieved.  Fill in Mode data.
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize  = SimpleNetworkDevice->GetInformation.HwAddrLen;
 | 
						|
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.MaxPacketSize  = SimpleNetworkDevice->GetInformation.MaxTranUnit;
 | 
						|
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.IfType         = (UINT8) SimpleNetworkDevice->GetInformation.HwType;
 | 
						|
 | 
						|
  ZeroMem (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | 
						|
    sizeof SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
 | 
						|
    );
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | 
						|
    &SimpleNetworkDevice->GetInformation.CurrentNodeAddress,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
    );
 | 
						|
 | 
						|
  ZeroMem (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
 | 
						|
    sizeof SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress
 | 
						|
    );
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
 | 
						|
    &SimpleNetworkDevice->GetInformation.PermNodeAddress,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // hard code broadcast address - not avail in PXE2.1
 | 
						|
  //
 | 
						|
  ZeroMem (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
 | 
						|
    sizeof SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress
 | 
						|
    );
 | 
						|
 | 
						|
  SetMem (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
 | 
						|
    0xff
 | 
						|
    );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get NIC type
 | 
						|
 | 
						|
  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS Sucess operation.
 | 
						|
  @retval Others      Fail to get NIC type.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkGetNicType (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (&SimpleNetworkDevice->GetNicType, sizeof (PXENV_UNDI_GET_NIC_TYPE_T));
 | 
						|
 | 
						|
  SimpleNetworkDevice->GetNicType.Status  = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Status = PxeUndiGetNicType (SimpleNetworkDevice, &SimpleNetworkDevice->GetNicType);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "  GetNicType.Status      = %d\n", SimpleNetworkDevice->GetNicType.Status));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetNicType.NicType     = %d\n", SimpleNetworkDevice->GetNicType.NicType));
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (SimpleNetworkDevice->GetNicType.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // The information has been retrieved.  Fill in Mode data.
 | 
						|
  //
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get NDIS information
 | 
						|
 | 
						|
  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS Sucess operation.
 | 
						|
  @retval Others      Fail to get NDIS information.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkGetNdisInfo (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (&SimpleNetworkDevice->GetNdisInfo, sizeof (PXENV_UNDI_GET_NDIS_INFO_T));
 | 
						|
 | 
						|
  SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "  GetNdisInfo.Status       = %d\n", SimpleNetworkDevice->GetNdisInfo.Status));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetNdisInfo.IfaceType    = %a\n", SimpleNetworkDevice->GetNdisInfo.IfaceType));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetNdisInfo.LinkSpeed    = %d\n", SimpleNetworkDevice->GetNdisInfo.LinkSpeed));
 | 
						|
  DEBUG ((DEBUG_NET, "  GetNdisInfo.ServiceFlags = %08x\n", SimpleNetworkDevice->GetNdisInfo.ServiceFlags));
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // The information has been retrieved.  Fill in Mode data.
 | 
						|
  //
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Call Undi ROM 16bit ISR() to check interrupt cause.
 | 
						|
 | 
						|
  @param This               A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
  @param FrameLength        The length of frame buffer.
 | 
						|
  @param FrameHeaderLength  The length of frame buffer's header if has.
 | 
						|
  @param Frame              The frame buffer to process network interrupt.
 | 
						|
  @param ProtType           The type network transmit protocol
 | 
						|
  @param PktType            The type of package.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR  Fail to execute 16 bit ROM's ISR, or status is invalid.
 | 
						|
  @retval EFI_SUCCESS       Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkIsr (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
 | 
						|
  IN UINTN                       *FrameLength,
 | 
						|
  IN UINTN                       *FrameHeaderLength, OPTIONAL
 | 
						|
  IN UINT8                       *Frame, OPTIONAL
 | 
						|
  IN UINT8                       *ProtType, OPTIONAL
 | 
						|
  IN UINT8                       *PktType OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  BOOLEAN                 FrameReceived;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  FrameReceived = FALSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "Isr() IsrValid = %d\n", SimpleNetworkDevice->IsrValid));
 | 
						|
 | 
						|
  if (!SimpleNetworkDevice->IsrValid) {
 | 
						|
    //
 | 
						|
    // Call 16 bit UNDI ROM to open the network interface
 | 
						|
    //
 | 
						|
    ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
 | 
						|
    SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
 | 
						|
    SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
 | 
						|
 | 
						|
    DEBUG ((DEBUG_NET, "Isr() START\n"));
 | 
						|
 | 
						|
    Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check the status code from the 16 bit UNDI ROM
 | 
						|
    //
 | 
						|
    if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // There have been no events on this UNDI interface, so return EFI_NOT_READY
 | 
						|
    //
 | 
						|
    if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // There is data to process, so call until all events processed.
 | 
						|
    //
 | 
						|
    ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
 | 
						|
    SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
 | 
						|
    SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
 | 
						|
 | 
						|
    DEBUG ((DEBUG_NET, "Isr() PROCESS\n"));
 | 
						|
 | 
						|
    Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    SimpleNetworkDevice->IsrValid = TRUE;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call UNDI GET_NEXT until DONE
 | 
						|
  //
 | 
						|
  while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) {
 | 
						|
    //
 | 
						|
    // Check the status code from the 16 bit UNDI ROM
 | 
						|
    //
 | 
						|
    if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // UNDI is busy.  Caller will have to call again.
 | 
						|
    // This should never happen with a polled mode driver.
 | 
						|
    //
 | 
						|
    if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {
 | 
						|
      DEBUG ((DEBUG_NET, "  BUSY\n"));
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check for invalud UNDI FuncFlag
 | 
						|
    //
 | 
						|
    if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE &&
 | 
						|
        SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT
 | 
						|
        ) {
 | 
						|
      DEBUG ((DEBUG_NET, "  Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n", SimpleNetworkDevice->Isr.FuncFlag));
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check for Transmit Event
 | 
						|
    //
 | 
						|
    if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
 | 
						|
      DEBUG ((DEBUG_NET, "  TRANSMIT\n"));
 | 
						|
      SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check for Receive Event
 | 
						|
    //
 | 
						|
    else if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {
 | 
						|
      //
 | 
						|
      // note - this code will hang on a receive interrupt in a GetStatus loop
 | 
						|
      //
 | 
						|
      DEBUG ((DEBUG_NET, "  RECEIVE\n"));
 | 
						|
      SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
 | 
						|
 | 
						|
      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.BufferLength      = %d\n", SimpleNetworkDevice->Isr.BufferLength));
 | 
						|
      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameLength       = %d\n", SimpleNetworkDevice->Isr.FrameLength));
 | 
						|
      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n", SimpleNetworkDevice->Isr.FrameHeaderLength));
 | 
						|
      DEBUG (
 | 
						|
        (
 | 
						|
        DEBUG_NET, "SimpleNetworkDevice->Isr.Frame             = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel,
 | 
						|
        SimpleNetworkDevice->Isr.FrameOffset
 | 
						|
        )
 | 
						|
        );
 | 
						|
      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.ProtType          = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
 | 
						|
      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.PktType           = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
 | 
						|
 | 
						|
      if (FrameReceived) {
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
 | 
						|
      if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) {
 | 
						|
        DEBUG ((DEBUG_NET, "return EFI_BUFFER_TOO_SMALL   *FrameLength = %08x\n", *FrameLength));
 | 
						|
        *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
 | 
						|
        return EFI_BUFFER_TOO_SMALL;
 | 
						|
      }
 | 
						|
 | 
						|
      *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
 | 
						|
      if (FrameHeaderLength != NULL) {
 | 
						|
        *FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength;
 | 
						|
      }
 | 
						|
 | 
						|
      if (ProtType != NULL) {
 | 
						|
        *ProtType = SimpleNetworkDevice->Isr.ProtType;
 | 
						|
      }
 | 
						|
 | 
						|
      if (PktType != NULL) {
 | 
						|
        *PktType = SimpleNetworkDevice->Isr.PktType;
 | 
						|
      }
 | 
						|
 | 
						|
      CopyMem (
 | 
						|
        Frame,
 | 
						|
        (VOID *) (((UINTN) SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset),
 | 
						|
        SimpleNetworkDevice->Isr.BufferLength
 | 
						|
        );
 | 
						|
      Frame = Frame + SimpleNetworkDevice->Isr.BufferLength;
 | 
						|
      if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) {
 | 
						|
        FrameReceived = TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // There is data to process, so call until all events processed.
 | 
						|
    //
 | 
						|
    ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
 | 
						|
    SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
 | 
						|
    SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
 | 
						|
 | 
						|
    DEBUG ((DEBUG_NET, "Isr() GET NEXT\n"));
 | 
						|
 | 
						|
    Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check the status code from the 16 bit UNDI ROM
 | 
						|
    //
 | 
						|
    //        if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    //            return EFI_DEVICE_ERROR;
 | 
						|
    //        }
 | 
						|
    //
 | 
						|
  }
 | 
						|
 | 
						|
  SimpleNetworkDevice->IsrValid = FALSE;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
//
 | 
						|
// ///////////////////////////////////////////////////////////////////////////////////////
 | 
						|
// Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs
 | 
						|
/////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
//
 | 
						|
// Start()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Call 16 bit UNDI ROM to start the network interface
 | 
						|
 | 
						|
  @param This       A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Network interface has not be initialized.
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
 | 
						|
  @retval EFI_SUCESS       Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkStart (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  PXENV_UNDI_STARTUP_T    Startup;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    return EFI_ALREADY_STARTED;
 | 
						|
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to start the network interface
 | 
						|
  //
 | 
						|
  Startup.Status  = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Status          = PxeUndiStartup (SimpleNetworkDevice, &Startup);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Startup.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // The UNDI interface has been started, so update the State.
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
 | 
						|
 | 
						|
  //
 | 
						|
  //
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0;
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount     = 0;
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
//
 | 
						|
// Stop()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Call 16 bit UNDI ROM to stop the network interface
 | 
						|
 | 
						|
  @param This       A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Network interface has not be initialized.
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
 | 
						|
  @retval EFI_SUCESS       Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkStop (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Initialize()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Initialize network interface
 | 
						|
 | 
						|
  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
  @param ExtraRxBufferSize    The size of extra request receive buffer.
 | 
						|
  @param ExtraTxBufferSize    The size of extra request transmit buffer.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
 | 
						|
  @retval EFI_SUCESS       Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkInitialize (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
 | 
						|
  IN UINTN                                  ExtraRxBufferSize  OPTIONAL,
 | 
						|
  IN UINTN                                  ExtraTxBufferSize  OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  PXENV_UNDI_INITIALIZE_T Initialize;
 | 
						|
  PXENV_UNDI_OPEN_T       Open;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to start the network interface
 | 
						|
  //
 | 
						|
  Initialize.Status       = INIT_PXE_STATUS;
 | 
						|
  Initialize.ProtocolIni  = 0;
 | 
						|
 | 
						|
  Status                  = PxeUndiInitialize (SimpleNetworkDevice, &Initialize);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Status = %r\n", Status));
 | 
						|
    DEBUG ((DEBUG_ERROR, "Initialize.Status == %xh\n", Initialize.Status));
 | 
						|
 | 
						|
    if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) {
 | 
						|
      Status = EFI_NO_MEDIA;
 | 
						|
    }
 | 
						|
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Initialize.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n", Initialize.Status));
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to open the network interface
 | 
						|
  //
 | 
						|
  Open.Status     = INIT_PXE_STATUS;
 | 
						|
  Open.OpenFlag   = 0;
 | 
						|
  Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
 | 
						|
  Undi16GetMCastFilters (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode,
 | 
						|
    &Open.McastBuffer,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
    );
 | 
						|
 | 
						|
  Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Status = %r\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Open.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Open.Status = %04x\n", Open.Status));
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // The UNDI interface has been initialized, so update the State.
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized;
 | 
						|
 | 
						|
  //
 | 
						|
  // If initialize succeeds, then assume that media is present.
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Reset the recycled transmit buffer FIFO
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.First = 0;
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | 
						|
  SimpleNetworkDevice->IsrValid           = FALSE;
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
//
 | 
						|
// Reset()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Reset network interface.
 | 
						|
 | 
						|
  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
  @param ExtendedVerification Need extended verfication.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | 
						|
  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | 
						|
  @retval EFI_NOT_STARTED       Network device has been stopped.
 | 
						|
  @retval EFI_DEVICE_ERROR      Invalid status for network device
 | 
						|
  @retval EFI_SUCCESS           Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkReset (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL   *This,
 | 
						|
  IN BOOLEAN                       ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  PXENV_UNDI_RESET_T      Reset;
 | 
						|
  UINT16                  Rx_filter;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Reset.Status  = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Rx_filter     = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
 | 
						|
 | 
						|
  Undi16GetMCastFilters (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode,
 | 
						|
    &Reset.R_Mcast_Buf,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
    );
 | 
						|
 | 
						|
  Status = PxeUndiResetNic (SimpleNetworkDevice, &Reset, Rx_filter);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Reset.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Reset the recycled transmit buffer FIFO
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.First = 0;
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | 
						|
  SimpleNetworkDevice->IsrValid           = FALSE;
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
//
 | 
						|
// Shutdown()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Shutdown network interface.
 | 
						|
 | 
						|
  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | 
						|
  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | 
						|
  @retval EFI_NOT_STARTED       Network device has been stopped.
 | 
						|
  @retval EFI_DEVICE_ERROR      Invalid status for network device
 | 
						|
  @retval EFI_SUCCESS           Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkShutdown (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  PXENV_UNDI_CLOSE_T      Close;
 | 
						|
  PXENV_UNDI_SHUTDOWN_T   Shutdown;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  SimpleNetworkDevice->IsrValid = FALSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to start the network interface
 | 
						|
  //
 | 
						|
  Close.Status  = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Close.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to open the network interface
 | 
						|
  //
 | 
						|
  Shutdown.Status = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Status          = PxeUndiShutdown (SimpleNetworkDevice, &Shutdown);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Shutdown.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // The UNDI interface has been initialized, so update the State.
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
 | 
						|
 | 
						|
  //
 | 
						|
  // If shutdown succeeds, then assume that media is not present.
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = FALSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Reset the recycled transmit buffer FIFO
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.First = 0;
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // A short delay.  Without this an initialize immediately following
 | 
						|
  // a shutdown will cause some versions of UNDI-16 to stop operating.
 | 
						|
  //
 | 
						|
  gBS->Stall (250000);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
//
 | 
						|
// ReceiveFilters()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Reset network interface.
 | 
						|
 | 
						|
  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
  @param Enable               Enable mask value
 | 
						|
  @param Disable              Disable mask value
 | 
						|
  @param ResetMCastFilter     Whether reset multi cast filter or not
 | 
						|
  @param MCastFilterCnt       Count of mutli cast filter for different MAC address
 | 
						|
  @param MCastFilter          Buffer for mustli cast filter for different MAC address.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | 
						|
  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | 
						|
  @retval EFI_NOT_STARTED       Network device has been stopped.
 | 
						|
  @retval EFI_DEVICE_ERROR      Invalid status for network device
 | 
						|
  @retval EFI_SUCCESS           Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkReceiveFilters (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL                     * This,
 | 
						|
  IN UINT32                                          Enable,
 | 
						|
  IN UINT32                                          Disable,
 | 
						|
  IN BOOLEAN                                         ResetMCastFilter,
 | 
						|
  IN UINTN                                           MCastFilterCnt     OPTIONAL,
 | 
						|
  IN EFI_MAC_ADDRESS                                 * MCastFilter OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  UINTN                   Index;
 | 
						|
  UINT32                  NewFilter;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  PXENV_UNDI_CLOSE_T      Close;
 | 
						|
  PXENV_UNDI_OPEN_T       Open;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // First deal with possible filter setting changes
 | 
						|
  //
 | 
						|
  if ((Enable == 0) && (Disable == 0) && !ResetMCastFilter) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  NewFilter = (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting | Enable) &~Disable;
 | 
						|
 | 
						|
  if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
 | 
						|
    if ((MCastFilterCnt == 0) || (MCastFilter == 0) || MCastFilterCnt > SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to close the network interface
 | 
						|
  //
 | 
						|
  Close.Status  = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Close.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to open the network interface
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // Reset the recycled transmit buffer FIFO
 | 
						|
  //
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.First = 0;
 | 
						|
  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to open the network interface
 | 
						|
  //
 | 
						|
  ZeroMem (&Open, sizeof Open);
 | 
						|
 | 
						|
  Open.Status     = INIT_PXE_STATUS;
 | 
						|
  Open.PktFilter  = Undi16GetPacketFilterSetting (NewFilter);
 | 
						|
 | 
						|
  if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
 | 
						|
    //
 | 
						|
    // Copy the MAC addresses into the UNDI open parameter structure
 | 
						|
    //
 | 
						|
    Open.McastBuffer.MCastAddrCount = (UINT16) MCastFilterCnt;
 | 
						|
    for (Index = 0; Index < MCastFilterCnt; ++Index) {
 | 
						|
      CopyMem (
 | 
						|
        Open.McastBuffer.MCastAddr[Index],
 | 
						|
        &MCastFilter[Index],
 | 
						|
        sizeof Open.McastBuffer.MCastAddr[Index]
 | 
						|
        );
 | 
						|
    }
 | 
						|
  } else if (!ResetMCastFilter) {
 | 
						|
    for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; ++Index) {
 | 
						|
      CopyMem (
 | 
						|
        Open.McastBuffer.MCastAddr[Index],
 | 
						|
        &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
 | 
						|
        sizeof Open.McastBuffer.MCastAddr[Index]
 | 
						|
        );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (Open.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  SimpleNetworkDevice->IsrValid = FALSE;
 | 
						|
  SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = NewFilter;
 | 
						|
 | 
						|
  if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = (UINT32) MCastFilterCnt;
 | 
						|
    for (Index = 0; Index < MCastFilterCnt; ++Index) {
 | 
						|
      CopyMem (
 | 
						|
        &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
 | 
						|
        &MCastFilter[Index],
 | 
						|
        sizeof (EFI_MAC_ADDRESS)
 | 
						|
        );
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read back multicast addresses.
 | 
						|
  //
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
//
 | 
						|
// StationAddress()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Set new MAC address.
 | 
						|
 | 
						|
  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
  @param Reset                Whether reset station MAC address to permanent address
 | 
						|
  @param New                  A pointer to New address
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | 
						|
  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | 
						|
  @retval EFI_NOT_STARTED       Network device has been stopped.
 | 
						|
  @retval EFI_DEVICE_ERROR      Invalid status for network device
 | 
						|
  @retval EFI_SUCCESS           Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkStationAddress (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL           * This,
 | 
						|
  IN BOOLEAN                               Reset,
 | 
						|
  IN EFI_MAC_ADDRESS                       * New OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
 | 
						|
  PXENV_UNDI_SET_STATION_ADDR_T SetStationAddr;
 | 
						|
  //
 | 
						|
  // EFI_DEVICE_PATH_PROTOCOL     *OldDevicePath;
 | 
						|
  //
 | 
						|
  PXENV_UNDI_CLOSE_T            Close;
 | 
						|
  PXENV_UNDI_OPEN_T             Open;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to open the network interface
 | 
						|
  //
 | 
						|
  SetStationAddr.Status = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  if (Reset) {
 | 
						|
    //
 | 
						|
    // If we are resetting the Station Address to the permanent address, and the
 | 
						|
    // Station Address is not programmable, then just return EFI_SUCCESS.
 | 
						|
    //
 | 
						|
    if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // If the address is already the permanent address, then just return success.
 | 
						|
    //
 | 
						|
    if (CompareMem (
 | 
						|
          &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | 
						|
          &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
 | 
						|
          SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
          ) == 0) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Copy the adapters permanent address to the new station address
 | 
						|
    //
 | 
						|
    CopyMem (
 | 
						|
      &SetStationAddr.StationAddress,
 | 
						|
      &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
 | 
						|
      SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
      );
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // If we are setting the Station Address, and the
 | 
						|
    // Station Address is not programmable, return invalid parameter.
 | 
						|
    //
 | 
						|
    if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // If the address is already the new address, then just return success.
 | 
						|
    //
 | 
						|
    if (CompareMem (
 | 
						|
          &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | 
						|
          New,
 | 
						|
          SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
          ) == 0) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Copy New to the new station address
 | 
						|
    //
 | 
						|
    CopyMem (
 | 
						|
      &SetStationAddr.StationAddress,
 | 
						|
      New,
 | 
						|
      SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
      );
 | 
						|
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to stop the network interface
 | 
						|
  //
 | 
						|
  Close.Status = INIT_PXE_STATUS;
 | 
						|
 | 
						|
  PxeUndiClose (SimpleNetworkDevice, &Close);
 | 
						|
 | 
						|
  //
 | 
						|
  // Call 16-bit UNDI ROM to set the station address
 | 
						|
  //
 | 
						|
  SetStationAddr.Status = PXENV_STATUS_SUCCESS;
 | 
						|
 | 
						|
  Status                = PxeUndiSetStationAddr (SimpleNetworkDevice, &SetStationAddr);
 | 
						|
 | 
						|
  //
 | 
						|
  // Call 16-bit UNDI ROM to start the network interface
 | 
						|
  //
 | 
						|
  Open.Status     = PXENV_STATUS_SUCCESS;
 | 
						|
  Open.OpenFlag   = 0;
 | 
						|
  Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
 | 
						|
  Undi16GetMCastFilters (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode,
 | 
						|
    &Open.McastBuffer,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
    );
 | 
						|
 | 
						|
  PxeUndiOpen (SimpleNetworkDevice, &Open);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check status from station address change
 | 
						|
  //
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (SetStationAddr.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
 | 
						|
    &SetStationAddr.StationAddress,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
    );
 | 
						|
 | 
						|
#if 0 /* The device path is based on the permanent address not the current address. */
 | 
						|
  //
 | 
						|
  // The station address was changed, so update the device path with the new MAC address.
 | 
						|
  //
 | 
						|
  OldDevicePath                   = SimpleNetworkDevice->DevicePath;
 | 
						|
  SimpleNetworkDevice->DevicePath = DuplicateDevicePath (SimpleNetworkDevice->BaseDevicePath);
 | 
						|
  SimpleNetworkAppendMacAddressDevicePath (
 | 
						|
    &SimpleNetworkDevice->DevicePath,
 | 
						|
    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
 | 
						|
    );
 | 
						|
 | 
						|
  Status = LibReinstallProtocolInterfaces (
 | 
						|
            SimpleNetworkDevice->Handle,
 | 
						|
            &DevicePathProtocol,
 | 
						|
            OldDevicePath,
 | 
						|
            SimpleNetworkDevice->DevicePath,
 | 
						|
            NULL
 | 
						|
            );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "Failed to reinstall the DevicePath protocol for the Simple Network Device\n"));
 | 
						|
    DEBUG ((DEBUG_ERROR, "  Status = %r\n", Status));
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (OldDevicePath);
 | 
						|
#endif /* 0 */
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
//
 | 
						|
// Statistics()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Resets or collects the statistics on a network interface.
 | 
						|
 | 
						|
  @param  This            Protocol instance pointer.
 | 
						|
  @param  Reset           Set to TRUE to reset the statistics for the network interface.
 | 
						|
  @param  StatisticsSize  On input the size, in bytes, of StatisticsTable. On
 | 
						|
                          output the size, in bytes, of the resulting table of
 | 
						|
                          statistics.
 | 
						|
  @param  StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
 | 
						|
                          contains the statistics.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The statistics were collected from the network interface.
 | 
						|
  @retval EFI_NOT_STARTED       The network interface has not been started.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The Statistics buffer was too small. The current buffer
 | 
						|
                                size needed to hold the statistics is returned in
 | 
						|
                                StatisticsSize.
 | 
						|
  @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | 
						|
  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | 
						|
  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkStatistics (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL       * This,
 | 
						|
  IN BOOLEAN                           Reset,
 | 
						|
  IN OUT UINTN                         *StatisticsSize OPTIONAL,
 | 
						|
  OUT EFI_NETWORK_STATISTICS           * StatisticsTable OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
 | 
						|
  PXENV_UNDI_CLEAR_STATISTICS_T ClearStatistics;
 | 
						|
  PXENV_UNDI_GET_STATISTICS_T   GetStatistics;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((StatisticsSize != NULL) && (*StatisticsSize != 0) && (StatisticsTable == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If Reset is TRUE, then clear all the statistics.
 | 
						|
  //
 | 
						|
  if (Reset) {
 | 
						|
 | 
						|
    DEBUG ((DEBUG_NET, "  RESET Statistics\n"));
 | 
						|
 | 
						|
    //
 | 
						|
    // Call 16 bit UNDI ROM to open the network interface
 | 
						|
    //
 | 
						|
    ClearStatistics.Status  = INIT_PXE_STATUS;
 | 
						|
 | 
						|
    Status                  = PxeUndiClearStatistics (SimpleNetworkDevice, &ClearStatistics);
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check the status code from the 16 bit UNDI ROM
 | 
						|
    //
 | 
						|
    if (ClearStatistics.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((DEBUG_NET, "  RESET Statistics Complete"));
 | 
						|
  }
 | 
						|
 | 
						|
  if (StatisticsSize != NULL) {
 | 
						|
    EFI_NETWORK_STATISTICS  LocalStatisticsTable;
 | 
						|
 | 
						|
    DEBUG ((DEBUG_NET, "  GET Statistics\n"));
 | 
						|
 | 
						|
    //
 | 
						|
    // If the size if valid, then see if the table is valid
 | 
						|
    //
 | 
						|
    if (StatisticsTable == NULL) {
 | 
						|
      DEBUG ((DEBUG_NET, "  StatisticsTable is NULL\n"));
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Call 16 bit UNDI ROM to open the network interface
 | 
						|
    //
 | 
						|
    GetStatistics.Status            = INIT_PXE_STATUS;
 | 
						|
    GetStatistics.XmtGoodFrames     = 0;
 | 
						|
    GetStatistics.RcvGoodFrames     = 0;
 | 
						|
    GetStatistics.RcvCRCErrors      = 0;
 | 
						|
    GetStatistics.RcvResourceErrors = 0;
 | 
						|
 | 
						|
    Status                          = PxeUndiGetStatistics (SimpleNetworkDevice, &GetStatistics);
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check the status code from the 16 bit UNDI ROM
 | 
						|
    //
 | 
						|
    if (GetStatistics.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Fill in the Statistics Table with the collected values.
 | 
						|
    //
 | 
						|
    SetMem (&LocalStatisticsTable, sizeof LocalStatisticsTable, 0xff);
 | 
						|
 | 
						|
    LocalStatisticsTable.TxGoodFrames     = GetStatistics.XmtGoodFrames;
 | 
						|
    LocalStatisticsTable.RxGoodFrames     = GetStatistics.RcvGoodFrames;
 | 
						|
    LocalStatisticsTable.RxCrcErrorFrames = GetStatistics.RcvCRCErrors;
 | 
						|
    LocalStatisticsTable.RxDroppedFrames  = GetStatistics.RcvResourceErrors;
 | 
						|
 | 
						|
    CopyMem (StatisticsTable, &LocalStatisticsTable, *StatisticsSize);
 | 
						|
 | 
						|
    DEBUG (
 | 
						|
      (DEBUG_NET,
 | 
						|
      "  Statistics Collected : Size=%d  Buf=%08x\n",
 | 
						|
      *StatisticsSize,
 | 
						|
      StatisticsTable)
 | 
						|
      );
 | 
						|
 | 
						|
    DEBUG ((DEBUG_NET, "  GET Statistics Complete"));
 | 
						|
 | 
						|
    if (*StatisticsSize < sizeof LocalStatisticsTable) {
 | 
						|
      DEBUG ((DEBUG_NET, "  BUFFER TOO SMALL\n"));
 | 
						|
      Status = EFI_BUFFER_TOO_SMALL;
 | 
						|
    }
 | 
						|
 | 
						|
    *StatisticsSize = sizeof LocalStatisticsTable;
 | 
						|
 | 
						|
    return Status;
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
//
 | 
						|
// MCastIpToMac()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Translate IP address to MAC address.
 | 
						|
 | 
						|
  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
 | 
						|
  @param IPv6                 IPv6 or IPv4
 | 
						|
  @param IP                   A pointer to given Ip address.
 | 
						|
  @param MAC                  On return, translated MAC address.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER Invalid This parameter.
 | 
						|
  @retval EFI_INVALID_PARAMETER Invalid IP address.
 | 
						|
  @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address.
 | 
						|
  @retval EFI_UNSUPPORTED       Do not support IPv6
 | 
						|
  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
 | 
						|
  @retval EFI_NOT_STARTED       Network device has been stopped.
 | 
						|
  @retval EFI_DEVICE_ERROR      Invalid status for network device
 | 
						|
  @retval EFI_SUCCESS           Success operation.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkMCastIpToMac (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
 | 
						|
  IN BOOLEAN                                IPv6,
 | 
						|
  IN EFI_IP_ADDRESS                         *IP,
 | 
						|
  OUT EFI_MAC_ADDRESS                       *MAC
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
 | 
						|
  PXENV_UNDI_GET_MCAST_ADDR_T GetMcastAddr;
 | 
						|
 | 
						|
  if (This == NULL || IP == NULL || MAC == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // 16 bit UNDI Option ROMS do not support IPv6.  Check for IPv6 usage.
 | 
						|
  //
 | 
						|
  if (IPv6) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Call 16 bit UNDI ROM to open the network interface
 | 
						|
  //
 | 
						|
  GetMcastAddr.Status = INIT_PXE_STATUS;
 | 
						|
  CopyMem (&GetMcastAddr.InetAddr, IP, 4);
 | 
						|
 | 
						|
  Status = PxeUndiGetMcastAddr (SimpleNetworkDevice, &GetMcastAddr);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  if (GetMcastAddr.Status != PXENV_STATUS_SUCCESS) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Copy the MAC address from the returned data structure.
 | 
						|
  //
 | 
						|
  CopyMem (
 | 
						|
    MAC,
 | 
						|
    &GetMcastAddr.MediaAddr,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
    );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
//
 | 
						|
// NvData()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Performs read and write operations on the NVRAM device attached to a
 | 
						|
  network interface.
 | 
						|
 | 
						|
  @param  This       The protocol instance pointer.
 | 
						|
  @param  ReadWrite  TRUE for read operations, FALSE for write operations.
 | 
						|
  @param  Offset     Byte offset in the NVRAM device at which to start the read or
 | 
						|
                     write operation. This must be a multiple of NvRamAccessSize and
 | 
						|
                     less than NvRamSize.
 | 
						|
  @param  BufferSize The number of bytes to read or write from the NVRAM device.
 | 
						|
                     This must also be a multiple of NvramAccessSize.
 | 
						|
  @param  Buffer     A pointer to the data buffer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The NVRAM access was performed.
 | 
						|
  @retval EFI_NOT_STARTED       The network interface has not been started.
 | 
						|
  @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | 
						|
  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | 
						|
  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkNvData (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
 | 
						|
  IN BOOLEAN                      ReadWrite,
 | 
						|
  IN UINTN                        Offset,
 | 
						|
  IN UINTN                        BufferSize,
 | 
						|
  IN OUT VOID                     *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
//
 | 
						|
// GetStatus()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Reads the current interrupt status and recycled transmit buffer status from
 | 
						|
  a network interface.
 | 
						|
 | 
						|
  @param  This            The protocol instance pointer.
 | 
						|
  @param  InterruptStatus A pointer to the bit mask of the currently active interrupts
 | 
						|
                          If this is NULL, the interrupt status will not be read from
 | 
						|
                          the device. If this is not NULL, the interrupt status will
 | 
						|
                          be read from the device. When the  interrupt status is read,
 | 
						|
                          it will also be cleared. Clearing the transmit  interrupt
 | 
						|
                          does not empty the recycled transmit buffer array.
 | 
						|
  @param  TxBuf           Recycled transmit buffer address. The network interface will
 | 
						|
                          not transmit if its internal recycled transmit buffer array
 | 
						|
                          is full. Reading the transmit buffer does not clear the
 | 
						|
                          transmit interrupt. If this is NULL, then the transmit buffer
 | 
						|
                          status will not be read. If there are no transmit buffers to
 | 
						|
                          recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The status of the network interface was retrieved.
 | 
						|
  @retval EFI_NOT_STARTED       The network interface has not been started.
 | 
						|
  @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | 
						|
  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | 
						|
  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkGetStatus (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL  * This,
 | 
						|
  OUT UINT32                      *InterruptStatus OPTIONAL,
 | 
						|
  OUT VOID                        **TxBuf OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  UINTN                   FrameLength;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (InterruptStatus == NULL && TxBuf == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  FrameLength = 0;
 | 
						|
  Status      = Undi16SimpleNetworkIsr (This, &FrameLength, NULL, NULL, NULL, NULL);
 | 
						|
 | 
						|
  if (Status != EFI_BUFFER_TOO_SMALL) {
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // See if the caller wants interrupt info.
 | 
						|
  //
 | 
						|
  if (InterruptStatus != NULL) {
 | 
						|
    *InterruptStatus                      = SimpleNetworkDevice->InterruptStatus;
 | 
						|
    SimpleNetworkDevice->InterruptStatus  = 0;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // See if the caller wants transmit buffer status info.
 | 
						|
  //
 | 
						|
  if (TxBuf != NULL) {
 | 
						|
    *TxBuf = 0;
 | 
						|
    SimpleNetworkTransmitFifoRemove (&(SimpleNetworkDevice->TxBufferFifo), TxBuf);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Places a packet in the transmit queue of a network interface.
 | 
						|
 | 
						|
  @param  This       The protocol instance pointer.
 | 
						|
  @param  HeaderSize The size, in bytes, of the media header to be filled in by
 | 
						|
                     the Transmit() function. If HeaderSize is non-zero, then it
 | 
						|
                     must be equal to This->Mode->MediaHeaderSize and the DestAddr
 | 
						|
                     and Protocol parameters must not be NULL.
 | 
						|
  @param  BufferSize The size, in bytes, of the entire packet (media header and
 | 
						|
                     data) to be transmitted through the network interface.
 | 
						|
  @param  Buffer     A pointer to the packet (media header followed by data) to be
 | 
						|
                     transmitted. This parameter cannot be NULL. If HeaderSize is zero,
 | 
						|
                     then the media header in Buffer must already be filled in by the
 | 
						|
                     caller. If HeaderSize is non-zero, then the media header will be
 | 
						|
                     filled in by the Transmit() function.
 | 
						|
  @param  SrcAddr    The source HW MAC address. If HeaderSize is zero, then this parameter
 | 
						|
                     is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
 | 
						|
                     This->Mode->CurrentAddress is used for the source HW MAC address.
 | 
						|
  @param  DestAddr   The destination HW MAC address. If HeaderSize is zero, then this
 | 
						|
                     parameter is ignored.
 | 
						|
  @param  Protocol   The type of header to build. If HeaderSize is zero, then this
 | 
						|
                     parameter is ignored. See RFC 1700, section "Ether Types", for
 | 
						|
                     examples.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The packet was placed on the transmit queue.
 | 
						|
  @retval EFI_NOT_STARTED       The network interface has not been started.
 | 
						|
  @retval EFI_NOT_READY         The network interface is too busy to accept this transmit request.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
 | 
						|
  @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | 
						|
  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | 
						|
  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkTransmit (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL           *This,
 | 
						|
  IN UINTN                                 HeaderSize,
 | 
						|
  IN UINTN                                 BufferSize,
 | 
						|
  IN VOID                                  *Buffer,
 | 
						|
  IN EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
 | 
						|
  IN EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
 | 
						|
  IN UINT16                                *Protocol OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  PXENV_UNDI_TRANSMIT_T   XmitInfo;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Buffer == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (BufferSize < SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (HeaderSize != 0) {
 | 
						|
    if (HeaderSize != SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (DestAddr == NULL || Protocol == NULL) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (DestAddr != NULL) {
 | 
						|
      CopyMem (
 | 
						|
        Buffer,
 | 
						|
        DestAddr,
 | 
						|
        SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    if (SrcAddr == NULL) {
 | 
						|
      SrcAddr = &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (
 | 
						|
      (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
 | 
						|
      SrcAddr,
 | 
						|
      SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
      );
 | 
						|
 | 
						|
    if (Protocol != NULL) {
 | 
						|
      *(UINT16 *) ((UINT8 *) Buffer + 2 * SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize) = (UINT16) (((*Protocol & 0xFF) << 8) | ((*Protocol >> 8) & 0xFF));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // See if the recycled transmit buffer FIFO is full.
 | 
						|
  // If it is full, then we can not transmit until the caller calls GetStatus() to pull
 | 
						|
  // off recycled transmit buffers.
 | 
						|
  //
 | 
						|
  if (SimpleNetworkTransmitFifoFull (&(SimpleNetworkDevice->TxBufferFifo))) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  //  Output debug trace message.
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_NET, "Undi16SimpleNetworkTransmit\n\r "));
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize UNDI WRITE parameter structure.
 | 
						|
  //
 | 
						|
  XmitInfo.Status           = INIT_PXE_STATUS;
 | 
						|
  XmitInfo.Protocol         = P_UNKNOWN;
 | 
						|
  XmitInfo.XmitFlag         = XMT_DESTADDR;
 | 
						|
  XmitInfo.DestAddrOffset   = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr & 0x000f);
 | 
						|
  XmitInfo.DestAddrSegment  = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr >> 4);
 | 
						|
  XmitInfo.TBDOffset        = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit & 0x000f);
 | 
						|
  XmitInfo.TBDSegment       = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit >> 4);
 | 
						|
  XmitInfo.Reserved[0]      = 0;
 | 
						|
  XmitInfo.Reserved[1]      = 0;
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    SimpleNetworkDevice->TxDestAddr,
 | 
						|
    Buffer,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
 | 
						|
    );
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    SimpleNetworkDevice->TxRealModeMediaHeader,
 | 
						|
    Buffer,
 | 
						|
    SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize
 | 
						|
    );
 | 
						|
 | 
						|
  SimpleNetworkDevice->Xmit->ImmedLength            = (UINT16) SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize;
 | 
						|
 | 
						|
  SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen = (UINT16) (BufferSize - SimpleNetworkDevice->Xmit->ImmedLength);
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    SimpleNetworkDevice->TxRealModeDataBuffer,
 | 
						|
    (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize,
 | 
						|
    SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Make API call to UNDI TRANSMIT
 | 
						|
  //
 | 
						|
  XmitInfo.Status = 0;
 | 
						|
 | 
						|
  Status          = PxeUndiTransmit (SimpleNetworkDevice, &XmitInfo);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the status code from the 16 bit UNDI ROM
 | 
						|
  //
 | 
						|
  switch (XmitInfo.Status) {
 | 
						|
  case PXENV_STATUS_OUT_OF_RESOURCES:
 | 
						|
    return EFI_NOT_READY;
 | 
						|
 | 
						|
  case PXENV_STATUS_SUCCESS:
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Add address of Buffer to the recycled transmit buffer FIFO
 | 
						|
  //
 | 
						|
  SimpleNetworkTransmitFifoAdd (&(SimpleNetworkDevice->TxBufferFifo), Buffer);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Receives a packet from a network interface.
 | 
						|
 | 
						|
  @param  This       The protocol instance pointer.
 | 
						|
  @param  HeaderSize The size, in bytes, of the media header received on the network
 | 
						|
                     interface. If this parameter is NULL, then the media header size
 | 
						|
                     will not be returned.
 | 
						|
  @param  BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
 | 
						|
                     bytes, of the packet that was received on the network interface.
 | 
						|
  @param  Buffer     A pointer to the data buffer to receive both the media header and
 | 
						|
                     the data.
 | 
						|
  @param  SrcAddr    The source HW MAC address. If this parameter is NULL, the
 | 
						|
                     HW MAC source address will not be extracted from the media
 | 
						|
                     header.
 | 
						|
  @param  DestAddr   The destination HW MAC address. If this parameter is NULL,
 | 
						|
                     the HW MAC destination address will not be extracted from the
 | 
						|
                     media header.
 | 
						|
  @param  Protocol   The media header type. If this parameter is NULL, then the
 | 
						|
                     protocol will not be extracted from the media header. See
 | 
						|
                     RFC 1700 section "Ether Types" for examples.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS           The received data was stored in Buffer, and BufferSize has
 | 
						|
                                 been updated to the number of bytes received.
 | 
						|
  @retval  EFI_NOT_STARTED       The network interface has not been started.
 | 
						|
  @retval  EFI_NOT_READY         The network interface is too busy to accept this transmit
 | 
						|
                                 request.
 | 
						|
  @retval  EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
 | 
						|
  @retval  EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | 
						|
  @retval  EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | 
						|
  @retval  EFI_UNSUPPORTED       This function is not supported by the network interface.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkReceive (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
 | 
						|
  OUT UINTN                                 *HeaderSize OPTIONAL,
 | 
						|
  IN OUT UINTN                              *BufferSize,
 | 
						|
  OUT VOID                                  *Buffer,
 | 
						|
  OUT EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
 | 
						|
  OUT EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
 | 
						|
  OUT UINT16                                *Protocol OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  UINTN                   MediaAddrSize;
 | 
						|
  UINT8                   ProtType;
 | 
						|
 | 
						|
  if (This == NULL || BufferSize == NULL || Buffer == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Undi16SimpleNetworkIsr (
 | 
						|
            This,
 | 
						|
            BufferSize,
 | 
						|
            HeaderSize,
 | 
						|
            Buffer,
 | 
						|
            &ProtType,
 | 
						|
            NULL
 | 
						|
            );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) == 0) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  SimpleNetworkDevice->InterruptStatus &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
 | 
						|
 | 
						|
  MediaAddrSize = This->Mode->HwAddressSize;
 | 
						|
 | 
						|
  if (SrcAddr != NULL) {
 | 
						|
    CopyMem (SrcAddr, (UINT8 *) Buffer + MediaAddrSize, MediaAddrSize);
 | 
						|
  }
 | 
						|
 | 
						|
  if (DestAddr != NULL) {
 | 
						|
    CopyMem (DestAddr, Buffer, MediaAddrSize);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Protocol != NULL) {
 | 
						|
    *((UINT8 *) Protocol)     = *((UINT8 *) Buffer + (2 * MediaAddrSize) + 1);
 | 
						|
    *((UINT8 *) Protocol + 1) = *((UINT8 *) Buffer + (2 * MediaAddrSize));
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_NET, "Packet Received: BufferSize=%d  HeaderSize = %d\n", *BufferSize, *HeaderSize));
 | 
						|
 | 
						|
  return Status;
 | 
						|
 | 
						|
}
 | 
						|
//
 | 
						|
// WaitForPacket()
 | 
						|
//
 | 
						|
/**
 | 
						|
  wait for a packet to be received.
 | 
						|
 | 
						|
  @param Event      Event used with WaitForEvent() to wait for a packet to be received.
 | 
						|
  @param Context    Event Context
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkWaitForPacket (
 | 
						|
  IN EFI_EVENT               Event,
 | 
						|
  IN VOID                    *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Someone is waiting on the receive packet event, if there's
 | 
						|
  // a packet pending, signal the event
 | 
						|
  //
 | 
						|
  if (!EFI_ERROR (Undi16SimpleNetworkCheckForPacket (Context))) {
 | 
						|
    gBS->SignalEvent (Event);
 | 
						|
  }
 | 
						|
}
 | 
						|
//
 | 
						|
// CheckForPacket()
 | 
						|
//
 | 
						|
/**
 | 
						|
  Check whether packet is ready for receive.
 | 
						|
 | 
						|
  @param This The protocol instance pointer.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS           Receive data is ready.
 | 
						|
  @retval  EFI_NOT_STARTED       The network interface has not been started.
 | 
						|
  @retval  EFI_NOT_READY         The network interface is too busy to accept this transmit
 | 
						|
                                 request.
 | 
						|
  @retval  EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
 | 
						|
  @retval  EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
 | 
						|
  @retval  EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | 
						|
  @retval  EFI_UNSUPPORTED       This function is not supported by the network interface.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Undi16SimpleNetworkCheckForPacket (
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL *This
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
 | 
						|
  UINTN                   FrameLength;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  if (SimpleNetworkDevice == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify that the current state of the adapter is valid for this call.
 | 
						|
  //
 | 
						|
  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
 | 
						|
  case EfiSimpleNetworkInitialized:
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStopped:
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
 | 
						|
  case EfiSimpleNetworkStarted:
 | 
						|
  default:
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  FrameLength = 0;
 | 
						|
  Status = Undi16SimpleNetworkIsr (
 | 
						|
            This,
 | 
						|
            &FrameLength,
 | 
						|
            NULL,
 | 
						|
            NULL,
 | 
						|
            NULL,
 | 
						|
            NULL
 | 
						|
            );
 | 
						|
 | 
						|
  if (Status != EFI_BUFFER_TOO_SMALL) {
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) != 0) ? EFI_SUCCESS : EFI_NOT_READY;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Signal handlers for ExitBootServices event.
 | 
						|
 | 
						|
  Clean up any Real-mode UNDI residue from the system
 | 
						|
 | 
						|
  @param Event      ExitBootServices event
 | 
						|
  @param Context
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Undi16SimpleNetworkEvent (
 | 
						|
  IN EFI_EVENT        Event,
 | 
						|
  IN VOID             *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // NOTE:  This is not the only way to effect this cleanup.  The prescribed mechanism
 | 
						|
  //        would be to perform an UNDI STOP command.  This strategam has been attempted
 | 
						|
  //        but results in problems making some of the EFI core services from TPL_CALLBACK.
 | 
						|
  //        This issue needs to be resolved, but the other alternative has been to perform
 | 
						|
  //        the unchain logic explicitly, as done below.
 | 
						|
  //
 | 
						|
  RestoreCachedVectorAddress (0x1A);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocate buffer below 1M for real mode.
 | 
						|
 | 
						|
  @param NumPages     The number pages want to be allocated.
 | 
						|
  @param Buffer       On return, allocated buffer.
 | 
						|
 | 
						|
  @return Status of allocating pages.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BiosSnp16AllocatePagesBelowOneMb (
 | 
						|
  UINTN  NumPages,
 | 
						|
  VOID   **Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
 | 
						|
 | 
						|
  PhysicalAddress = 0x000fffff;
 | 
						|
  Status = gBS->AllocatePages (
 | 
						|
                  AllocateMaxAddress,
 | 
						|
                  EfiRuntimeServicesData,
 | 
						|
                  NumPages,
 | 
						|
                  &PhysicalAddress
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  *Buffer = (VOID *) (UINTN) PhysicalAddress;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |