biossnp16.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 2,446 行 · 第 1/5 页

C
2,446
字号
	//
	// Start() the SimpleNetwork device
	//
	DEBUG ((EFI_D_NET,"Start()\n"));

	Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork);
	if (EFI_ERROR (Status)) {
    goto Done;
	}

	//
	// GetInformation() the SimpleNetwork device
	//
	DEBUG ((EFI_D_NET,"GetInformation()\n"));

	Status = Undi16SimpleNetworkGetInformation(&SimpleNetworkDevice->SimpleNetwork);
	if (EFI_ERROR(Status)) {
    goto Done;
	}

  //
  // Build the device path for the child device
  //
  EfiZeroMem (&Node, sizeof(Node)) ;
  Node.DevPath.Type    = MESSAGING_DEVICE_PATH;
  Node.DevPath.SubType = MSG_MAC_ADDR_DP;
  SetDevicePathNodeLength (&Node.DevPath, sizeof(MAC_ADDR_DEVICE_PATH)) ;
	EfiCopyMem(
    &Node.MacAddr.MacAddress,
    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
    sizeof(EFI_MAC_ADDRESS)
    );
  SimpleNetworkDevice->DevicePath = EfiAppendDevicePathNode (
                                      SimpleNetworkDevice->BaseDevicePath, 
                                      &Node.DevPath
                                      );

  //
	// GetNicType()  the SimpleNetwork device
	//
	DEBUG ((EFI_D_NET,"GetNicType()\n"));

	Status = Undi16SimpleNetworkGetNicType(&SimpleNetworkDevice->SimpleNetwork);
	if (EFI_ERROR(Status)) {
//    goto Done;
	}

  //
	// GetNdisInfo() the SimpleNetwork device
  //
	DEBUG ((EFI_D_NET,"GetNdisInfo()\n"));

  Status = Undi16SimpleNetworkGetNdisInfo(&SimpleNetworkDevice->SimpleNetwork);
	if (EFI_ERROR(Status)) {
    goto Done;
  }

	//
	// Stop() the SimpleNetwork device
	//
	DEBUG ((EFI_D_NET,"Stop()\n"));

	Status = SimpleNetworkDevice->SimpleNetwork.Stop(&SimpleNetworkDevice->SimpleNetwork);
	if (EFI_ERROR(Status)) {
    goto Done;
	}

	//
	// Print Mode information
	//
	DEBUG((EFI_D_NET,"Mode->State                = %d\n",SimpleNetworkDevice->SimpleNetworkMode.State));
	DEBUG((EFI_D_NET,"Mode->HwAddressSize        = %d\n",SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize));
	DEBUG((EFI_D_NET,"Mode->MacAddressChangeable = %d\n",SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable));
	DEBUG((EFI_D_NET,"Mode->MultiplTxSupported   = %d\n",SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported));
	DEBUG((EFI_D_NET,"Mode->NvRamSize            = %d\n",SimpleNetworkDevice->SimpleNetworkMode.NvRamSize));
	DEBUG((EFI_D_NET,"Mode->NvRamAccessSize      = %d\n",SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize));
	DEBUG((EFI_D_NET,"Mode->ReceiveFilterSetting = %d\n",SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting));
	DEBUG((EFI_D_NET,"Mode->IfType               = %d\n",SimpleNetworkDevice->SimpleNetworkMode.IfType));
	DEBUG((EFI_D_NET,"Mode->MCastFilterCount     = %d\n",SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount));
	for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) {
		DEBUG((EFI_D_NET,"  Filter[%02d] = ",Index));
		for(j=0;j<16;j++) {
			DEBUG((EFI_D_NET,"%02x ",SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[j]));
		}
		DEBUG((EFI_D_NET,"\n"));
	}

	DEBUG((EFI_D_NET,"CurrentAddress = "));
	for(j=0;j<16;j++) {
		DEBUG((EFI_D_NET,"%02x ",SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[j]));
	}
	DEBUG((EFI_D_NET,"\n"));

	DEBUG((EFI_D_NET,"BroadcastAddress = "));
	for(j=0;j<16;j++) {
		DEBUG((EFI_D_NET,"%02x ",SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[j]));
	}
	DEBUG((EFI_D_NET,"\n"));

	DEBUG((EFI_D_NET,"PermanentAddress = "));
	for(j=0;j<16;j++) {
		DEBUG((EFI_D_NET,"%02x ",SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[j]));
	}
	DEBUG((EFI_D_NET,"\n"));

	//
	// The network device was started, information collected, and stopped.
	// Install protocol interfaces for the SimpleNetwork device.
	//
	DEBUG ((EFI_D_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 ((EFI_D_INIT,"UNDI16 Driver : EFI_SUCCESS\n"));

  //
  // Record the NIC controller to be managed onto the stack
  //
	if (!EFI_ERROR (Status)) {
    NicInfo = EfiLibAllocateZeroPool (sizeof (MANAGED_NIC_INFO));
    if (NicInfo == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto Done;
    }
    
    NicInfo->Signature = MANAGED_NIC_INFO_SIGNATURE;
    NicInfo->Controller = Controller;
    
    InsertHeadList (&ManagedNicList, &NicInfo->Link);
	}

Done:
  if (EFI_ERROR (Status)) {
    if (SimpleNetworkDevice) {

      if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket) {
        gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
      }

      if (SimpleNetworkDevice->Event) {
        gBS->CloseEvent (SimpleNetworkDevice->Event);
      }

      Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);  //CLOSE + SHUTDOWN

      Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);  //STOP

      Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);  //CLEANUP

      if (SimpleNetworkDevice->UndiLoaded) {
        Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
      }

      if (SimpleNetworkDevice->Xmit) {
        gBS->FreePages ( (EFI_PHYSICAL_ADDRESS)SimpleNetworkDevice->Xmit, sizeof (PXENV_UNDI_TBD_t)/ EFI_PAGE_SIZE + 1);
      }

      if (SimpleNetworkDevice->TxRealModeMediaHeader) {
        gBS->FreePages ( (EFI_PHYSICAL_ADDRESS)SimpleNetworkDevice->TxRealModeMediaHeader, 1);
      }

      if (SimpleNetworkDevice->TxRealModeDataBuffer) {
        gBS->FreePages ( (EFI_PHYSICAL_ADDRESS)SimpleNetworkDevice->TxRealModeDataBuffer, 1);
      }

      if (SimpleNetworkDevice->TxDestAddr) {
        gBS->FreePages ( (EFI_PHYSICAL_ADDRESS)SimpleNetworkDevice->TxDestAddr, 1);
      }

      gBS->FreePool (SimpleNetworkDevice);
    }

    if (PciIo) {
      PciIo->Attributes (
               PciIo,
               EfiPciIoAttributeOperationDisable,
               EFI_PCI_DEVICE_ENABLE, 
               NULL
               );
    }

    gBS->CloseProtocol (
           Controller,  
           &gEfiPciIoProtocolGuid, 
           This->DriverBindingHandle,   
           Controller   
           );

    gBS->CloseProtocol (
           Controller,  
           &gEfiDevicePathProtocolGuid, 
           This->DriverBindingHandle,   
           Controller   
           );
  }

  return Status;
}

EFI_STATUS
BiosSnp16DriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
  IN  EFI_HANDLE                      Controller,
  IN  UINTN                           NumberOfChildren,
  IN  EFI_HANDLE                      *ChildHandleBuffer
  )
/*++
  
  Routine Description:
    Stop.
  
  Arguments:
    (Standard DriverBinding Protocol Stop() function)
  
  Returns:
    EFI_STATUS
  
--*/                
{
  EFI_STATUS                   Status;
  UINTN                        Index;
  BOOLEAN                      AllChildrenStopped;
  EFI_SIMPLE_NETWORK_PROTOCOL  *SimpleNetwork;
	EFI_SIMPLE_NETWORK_DEV       *SimpleNetworkDevice;
  EFI_PCI_IO_PROTOCOL          *PciIo;
  MANAGED_NIC_INFO             *NicInfo;

  //
  // In order to unhook the interrupt chain set up by UNDI option ROM correctly,
  // the NIC controllers have to be stopped in the reverse order that they are 
  // produced. So if the passed-in controller does not match on the top of the 
  // stack, we will refuse to stop it.
  //
  if (IsListEmpty (&ManagedNicList)) {
    return EFI_DEVICE_ERROR;
  }
  
  NicInfo = CR(ManagedNicList.ForwardLink, MANAGED_NIC_INFO, Link, MANAGED_NIC_INFO_SIGNATURE);
  if (Controller != NicInfo->Controller) {
    return EFI_DEVICE_ERROR;
  }

  //
  // 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)) {
      PciIo->Attributes (
               PciIo,
               EfiPciIoAttributeOperationDisable,
               EFI_PCI_DEVICE_ENABLE, 
               NULL
               );
    }
    Status =  gBS->CloseProtocol (
                     Controller, 
                     &gEfiPciIoProtocolGuid, 
                     This->DriverBindingHandle, 
                     Controller
                     );

    Status =  gBS->CloseProtocol (
                     Controller, 
                     &gEfiDevicePathProtocolGuid, 
                     This->DriverBindingHandle, 
                     Controller
                     );
    
    //
    // Remove the NIC controller from the stack of the NICs managed by this driver
    //
    if (!EFI_ERROR (Status)) {
      RemoveEntryList (&NicInfo->Link);
      gBS->FreePool (NicInfo);
    }
    
    return Status;
  }

  AllChildrenStopped = TRUE;

  for (Index = NumberOfChildren; Index > 0; Index--) {

    Status = gBS->OpenProtocol (
                    ChildHandleBuffer[Index - 1], 
                    &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 - 1]
                       );

	    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 - 1],
               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
               );
      } else {
        if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket) {
          gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
        }

        if (SimpleNetworkDevice->Event) {
          gBS->CloseEvent (SimpleNetworkDevice->Event);
        }

        Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);  //CLOSE + SHUTDOWN

        Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);  //STOP

        Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);  //CLEANUP

        if (SimpleNetworkDevice->UndiLoaded) {
          Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
        }

        if (SimpleNetworkDevice->Xmit) {
          gBS->FreePages ( (EFI_PHYSICAL_ADDRESS)SimpleNetworkDevice->Xmit, sizeof (PXENV_UNDI_TBD_t)/ EFI_PAGE_SIZE + 1);
        }

        if (SimpleNetworkDevice->TxRealModeMediaHeader) {
          gBS->FreePages ( (EFI_PHYSICAL_ADDRESS)SimpleNetworkDevice->TxRealModeMediaHeader, 1);
        }

        if (SimpleNetworkDevice->TxRealModeDataBuffer) {
          gBS->FreePages ( (EFI_PHYSICAL_ADDRESS)SimpleNetworkDevice->TxRealModeDataBuffer, 1);
        }

        if (SimpleNetworkDevice->TxDestAddr) {
          gBS->FreePages ( (EFI_PHYSICAL_ADDRESS)SimpleNetworkDevice->TxDestAddr, 1);
        }

        gBS->FreePool (SimpleNetworkDevice);
      }

    }

    if (EFI_ERROR(Status)) {
      AllChildrenStopped = FALSE;
    }
  }

  if (AllChildrenStopped == FALSE) {
    return EFI_DEVICE_ERROR;
  }
  return EFI_SUCCESS;
}

//
// FIFO Support Functions
//

static
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;
}

//
//
//

static
BOOLEAN
SimpleNetworkTransmitFifoEmpty(
	EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
	)
{
	if (Fifo->Last == Fifo->First) {
		return TRUE;
	}
	return FALSE;
}


//
//
//

static
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;
}

//
//
//

static
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;
}

//
// Maps from EFI Receive Packet Filter Settings to UNDI 16 Receive Packet Filter Settings
//

static
UINT16
Undi16GetPacketFilterSetting(
	UINTN ReceiveFilterSetting
	)
{
	UINT16 PktFilter;

	PktFilter = 0;
	if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?