biossnp16.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 2,446 行 · 第 1/5 页
C
2,446 行
/*++
Copyright (c) 1999 - 2003 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
BiosSnp16.c
Abstract:
ConsoleOut Routines that speak VGA.
Revision History
--*/
#include "BiosSnp16.h"
//
// The stack to maintain the PCI NICs managed by this driver
//
#define MANAGED_NIC_INFO_SIGNATURE EFI_SIGNATURE_32('m','n','i','c')
typedef struct {
UINTN Signature;
EFI_HANDLE Controller;
EFI_LIST_ENTRY Link;
} MANAGED_NIC_INFO;
EFI_LIST_ENTRY ManagedNicList;
//
// EFI Driver Binding Protocol Instance
//
// This driver has a version value of 0x00000000. This is the
// lowest possible priority for a driver. This is done on purpose to help
// the developers of native UNDI drivers. This driver can bind if no UNDI driver
// is present, so a network connection is available. Then, when a UNDI driver is
// loaded this driver can be disconnected, and the UNDI driver can be connected.
// As long as the UNDI driver has a version value greater than 0x00000000, it
// will be connected first and will block this driver from connecting.
//
EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = {
BiosSnp16DriverBindingSupported,
BiosSnp16DriverBindingStart,
BiosSnp16DriverBindingStop,
0x00000000,
NULL,
NULL
};
//
// Private worker functions;
//
static
EFI_STATUS
Undi16SimpleNetworkStartUndi (
EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
UINT16 AX
);
static
EFI_STATUS
Undi16SimpleNetworkStopUndi (
EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
);
static
EFI_STATUS
Undi16SimpleNetworkStartupUndi (
EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
);
static
EFI_STATUS
Undi16SimpleNetworkCleanupUndi (
EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
);
static
EFI_STATUS
Undi16SimpleNetworkGetInformation (
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
);
static
EFI_STATUS
Undi16SimpleNetworkGetNicType (
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
);
static
EFI_STATUS
Undi16SimpleNetworkGetNdisInfo (
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
);
//
// Driver Entry Point
//
EFI_DRIVER_ENTRY_POINT(BiosSnp16DriverEntryPoint)
EFI_STATUS
BiosSnp16DriverEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Driver Entry Point.
Arguments:
(Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
Returns:
EFI_STATUS
--*/
{
InitializeListHead (&ManagedNicList);
return EfiLibInstallAllDriverProtocols (
ImageHandle,
SystemTable,
&gBiosSnp16DriverBinding,
ImageHandle,
&gBiosSnp16ComponentName,
NULL,
NULL
);
}
//
// EFI Driver Binding Protocol Functions
//
EFI_STATUS
BiosSnp16DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Supported.
Arguments:
(Standard DriverBinding Protocol Supported() function)
Returns:
EFI_STATUS
--*/
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_PCI_IO_PROTOCOL *PciIo;
PCI_TYPE00 Pci;
//
// 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;
}
EFI_STATUS
BiosSnp16DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Install VGA Mini Port Protocol onto VGA device handles
Arguments:
(Standard DriverBinding Protocol Start() function)
Returns:
EFI_STATUS
--*/
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
EFI_DEV_PATH Node;
MANAGED_NIC_INFO *NicInfo;
UINTN Index;
UINTN j;
UINTN Segment;
UINTN Bus;
UINTN Device;
UINTN Function;
SimpleNetworkDevice = NULL;
PciIo = NULL;
//
// 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,
EfiPciIoAttributeOperationEnable,
EFI_PCI_DEVICE_ENABLE,
NULL
);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Allocate memory for this SimpleNetwork device instance
//
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof(EFI_SIMPLE_NETWORK_DEV),
&SimpleNetworkDevice
);
if (EFI_ERROR(Status)) {
goto Done;
}
EfiZeroMem (SimpleNetworkDevice, sizeof(EFI_SIMPLE_NETWORK_DEV));
//
// Initialize the SimpleNetwork device instance
//
SimpleNetworkDevice->Signature = EFI_SIMPLE_NETWORK_DEV_SIGNATURE;
SimpleNetworkDevice->BaseDevicePath = DevicePath;
SimpleNetworkDevice->PciIo = PciIo;
//
// Initialize the NII Protocol
//
SimpleNetworkDevice->NII.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
SimpleNetworkDevice->NII.Type = EfiNetworkInterfaceUndi;
EfiCopyMem (&SimpleNetworkDevice->NII.StringId, "UNDI", 4);
//
// Load 16 bit UNDI Option ROM into Memory
//
Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice);
if (EFI_ERROR(Status)) {
DEBUG ((EFI_D_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 ((EFI_D_NET,"ERROR : Could not StartUndi. Status = %r\n",Status));
goto Done;
}
//
// Initialize the Simple Network Protocol
//
DEBUG ((EFI_D_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(
EFI_EVENT_NOTIFY_WAIT,
EFI_TPL_NOTIFY,
Undi16SimpleNetworkWaitForPacket,
&SimpleNetworkDevice->SimpleNetwork,
&SimpleNetworkDevice->SimpleNetwork.WaitForPacket
);
if (EFI_ERROR(Status)) {
DEBUG ((EFI_D_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->CreateEvent(
EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
EFI_TPL_NOTIFY,
Undi16SimpleNetworkEvent,
NULL,
&SimpleNetworkDevice->Event
);
if (EFI_ERROR(Status)) {
DEBUG ((EFI_D_ERROR,"ERROR : Could not create event. Status = %r\n",Status));
goto Done;
}
//
// Initialize the SimpleNetwork Mode Information
//
DEBUG ((EFI_D_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 ((EFI_D_NET,"Initialize Private Information\n"));
Status = BiosSnp16AllocatePagesBelowOneMb (
sizeof (PXENV_UNDI_TBD_t)/ EFI_PAGE_SIZE + 1,
&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)SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f);
SimpleNetworkDevice->Xmit->XmitSegment =
(UINT16)(((UINT32)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)SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f);
SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment =
(UINT16)(((UINT32)SimpleNetworkDevice->TxRealModeDataBuffer) >> 4);
SimpleNetworkDevice->TxBufferFifo.First = 0;
SimpleNetworkDevice->TxBufferFifo.Last = 0;
//
// Call PXENV_UNDI_STARTUP - Initilizes the contents of the UNDI code & data
// segment for proper operation.
//
Status = Undi16SimpleNetworkStartupUndi (SimpleNetworkDevice);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_NET,"ERROR : Could not UndiStartup. Status = %r\n",Status));
goto Done;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?