Import SnpDxe, Tcp4Dxe, Udp4Dxe and MnpDxe.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3416 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
vanjeff
2007-07-24 08:06:37 +00:00
parent f9bef4b3ac
commit 8a67d61da4
66 changed files with 25898 additions and 52 deletions

View File

@@ -0,0 +1,163 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module Name:
ComponentName.c
Abstract:
**/
#include "Snp.h"
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
EFI_COMPONENT_NAME_PROTOCOL gSimpleNetworkComponentName = {
SimpleNetworkComponentNameGetDriverName,
SimpleNetworkComponentNameGetControllerName,
"eng"
};
static EFI_UNICODE_STRING_TABLE mSimpleNetworkDriverNameTable[] = {
{
"eng",
L"Simple Network Protocol Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that that the caller
is requesting, and it must match one of the languages specified
in SupportedLanguages. The number of languages supported by a
driver is up to the driver writer.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCESS - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString (
Language,
gSimpleNetworkComponentName.SupportedLanguages,
mSimpleNetworkDriverNameTable,
DriverName
);
}
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that that the caller is requesting, and it must match one
of the languages specified in SupportedLanguages. The
number of languages supported by a driver is up to the
driver writer.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language specified
by Language from the point of view of the driver specified
by This.
Returns:
EFI_SUCCESS - The Unicode string for the user readable name in the
language specified by Language for the driver
specified by This was returned in DriverName.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently managing
the controller specified by ControllerHandle and
ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@@ -0,0 +1,75 @@
#/** @file
# Component name for module SNP
#
# FIX ME!
# Copyright (c) 2006, Intel Corporation. All right reserved.
#
# All rights reserved. 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.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SnpDxe
FILE_GUID = A2f436EA-A127-4EF8-957C-8048606FF670
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = InitializeSnpNiiDriver
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
receive.c
snp.h
nvdata.c
get_status.c
start.c
snp.c
stop.c
statistics.c
reset.c
shutdown.c
mcast_ip_to_mac.c
transmit.c
WaitForPacket.c
receive_filters.c
initialize.c
ComponentName.c
callback.c
station_address.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiLib
BaseLib
UefiBootServicesTableLib
UefiDriverEntryPoint
BaseMemoryLib
DebugLib
[Protocols]
gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiNetworkInterfaceIdentifierProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiNetworkInterfaceIdentifierProtocolGuid_31 # PROTOCOL ALWAYS_CONSUMED

View File

@@ -0,0 +1,90 @@
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MsaHeader>
<ModuleName>SnpDxe</ModuleName>
<ModuleType>DXE_DRIVER</ModuleType>
<GuidValue>A2f436EA-A127-4EF8-957C-8048606FF670</GuidValue>
<Version>1.0</Version>
<Abstract>Component name for module SNP</Abstract>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2006, Intel Corporation. All right reserved.</Copyright>
<License>All rights reserved. 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.</License>
<Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
</MsaHeader>
<ModuleDefinitions>
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
<BinaryModule>false</BinaryModule>
<OutputFileBasename>SnpDxe</OutputFileBasename>
</ModuleDefinitions>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>DebugLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>BaseMemoryLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiDriverEntryPoint</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiBootServicesTableLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>BaseLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiLib</Keyword>
</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>station_address.c</Filename>
<Filename>SNPEntry.c</Filename>
<Filename>callback.c</Filename>
<Filename>ComponentName.c</Filename>
<Filename>initialize.c</Filename>
<Filename>receive_filters.c</Filename>
<Filename>WaitForPacket.c</Filename>
<Filename>transmit.c</Filename>
<Filename>mcast_ip_to_mac.c</Filename>
<Filename>shutdown.c</Filename>
<Filename>reset.c</Filename>
<Filename>statistics.c</Filename>
<Filename>stop.c</Filename>
<Filename>snp.c</Filename>
<Filename>start.c</Filename>
<Filename>get_status.c</Filename>
<Filename>nvdata.c</Filename>
<Filename>snp.h</Filename>
<Filename>receive.c</Filename>
</SourceFiles>
<PackageDependencies>
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
</PackageDependencies>
<Protocols>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiNetworkInterfaceIdentifierProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiSimpleNetworkProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiPciIoProtocolGuid</ProtocolCName>
</Protocol>
</Protocols>
<Externs>
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
<Extern>
<ModuleEntryPoint>InitializeSnpNiiDriver</ModuleEntryPoint>
</Extern>
</Externs>
</ModuleSurfaceArea>

View File

@@ -0,0 +1,97 @@
/** @file
Copyright (c) 2004, Intel Corporation
All rights reserved. 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.
Module name:
WaitForPacket.c
Abstract:
Event handler to check for available packet.
**/
#include "Snp.h"
/**
**/
VOID
EFIAPI
SnpWaitForPacketNotify (
EFI_EVENT Event,
VOID *SnpPtr
)
{
PXE_DB_GET_STATUS PxeDbGetStatus;
//
// Do nothing if either parameter is a NULL pointer.
//
if (Event == NULL || SnpPtr == NULL) {
return ;
}
//
// Do nothing if the SNP interface is not initialized.
//
switch (((SNP_DRIVER *) SnpPtr)->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
case EfiSimpleNetworkStarted:
default:
return ;
}
//
// Fill in CDB for UNDI GetStatus().
//
((SNP_DRIVER *) SnpPtr)->cdb.OpCode = PXE_OPCODE_GET_STATUS;
((SNP_DRIVER *) SnpPtr)->cdb.OpFlags = 0;
((SNP_DRIVER *) SnpPtr)->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
((SNP_DRIVER *) SnpPtr)->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
((SNP_DRIVER *) SnpPtr)->cdb.DBsize = sizeof (UINT32) * 2;
((SNP_DRIVER *) SnpPtr)->cdb.DBaddr = (UINT64)(UINTN) (((SNP_DRIVER *) SnpPtr)->db);
((SNP_DRIVER *) SnpPtr)->cdb.StatCode = PXE_STATCODE_INITIALIZE;
((SNP_DRIVER *) SnpPtr)->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
((SNP_DRIVER *) SnpPtr)->cdb.IFnum = ((SNP_DRIVER *) SnpPtr)->if_num;
((SNP_DRIVER *) SnpPtr)->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Clear contents of DB buffer.
//
ZeroMem (((SNP_DRIVER *) SnpPtr)->db, sizeof (UINT32) * 2);
//
// Issue UNDI command and check result.
//
(*((SNP_DRIVER *) SnpPtr)->issue_undi32_command) ((UINT64)(UINTN) &((SNP_DRIVER *) SnpPtr)->cdb);
if (((SNP_DRIVER *) SnpPtr)->cdb.StatCode != EFI_SUCCESS) {
return ;
}
//
// We might have a packet. Check the receive length and signal
// the event if the length is not zero.
//
CopyMem (
&PxeDbGetStatus,
((SNP_DRIVER *) SnpPtr)->db,
sizeof (UINT32) * 2
);
if (PxeDbGetStatus.RxFrameLen != 0) {
gBS->SignalEvent (Event);
}
}
/* eof - WaitForPacket.c */

View File

@@ -0,0 +1,611 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. 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.
Module name:
callback.c
Abstract:
This file contains two sets of callback routines for undi3.0 and undi3.1.
the callback routines for Undi3.1 have an extra parameter UniqueId which
stores the interface context for the NIC that snp is trying to talk..
--*/
#include "Snp.h"
//
// Global variables
// these 2 global variables are used only for 3.0 undi. we could not place
// them in the snp structure because we will not know which snp structure
// in the callback context!
//
STATIC BOOLEAN mInitializeLock = TRUE;
STATIC EFI_LOCK mLock;
//
// End Global variables
//
extern EFI_PCI_IO_PROTOCOL *mPciIoFncs;
VOID
snp_undi32_callback_v2p_30 (
IN UINT64 CpuAddr,
IN OUT UINT64 DeviceAddrPtr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine with a virtual or CPU address that SNP provided
to convert it to a physical or device address. Since EFI uses the identical
mapping, this routine returns the physical address same as the virtual address
for most of the addresses. an address above 4GB cannot generally be used as a
device address, it needs to be mapped to a lower physical address. This routine
does not call the map routine itself, but it assumes that the mapping was done
at the time of providing the address to UNDI. This routine just looks up the
address in a map table (which is the v2p structure chain)
Arguments:
CpuAddr - virtual address of a buffer
DeviceAddrPtr - pointer to the physical address
Returns:
void - The DeviceAddrPtr will contain 0 in case of any error
--*/
{
struct s_v2p *v2p;
//
// Do nothing if virtual address is zero or physical pointer is NULL.
// No need to map if the virtual address is within 4GB limit since
// EFI uses identical mapping
//
if ((CpuAddr == 0) || (DeviceAddrPtr == 0)) {
DEBUG ((EFI_D_ERROR, "\nv2p: Null virtual address or physical pointer.\n"));
return ;
}
if (CpuAddr < FOUR_GIGABYTES) {
*(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;
return ;
}
//
// SNP creates a vaddr tp paddr mapping at the time of calling undi with any
// big address, this callback routine just looks up in the v2p list and
// returns the physical address for any given virtual address.
//
if (find_v2p (&v2p, (VOID *) (UINTN) CpuAddr) != EFI_SUCCESS) {
*(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;
} else {
*(UINT64 *) (UINTN) DeviceAddrPtr = v2p->paddr;
}
}
VOID
snp_undi32_callback_block_30 (
IN UINT32 Enable
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it wants to have exclusive access to a critical
section of the code/data
Arguments:
Enable - non-zero indicates acquire
zero indicates release
Returns:
void
--*/
{
//
// tcpip was calling snp at tpl_notify and if we acquire a lock that was
// created at a lower level (TPL_CALLBACK) it gives an assert!
//
if (mInitializeLock) {
EfiInitializeLock (&mLock, TPL_NOTIFY);
mInitializeLock = FALSE;
}
if (Enable != 0) {
EfiAcquireLock (&mLock);
} else {
EfiReleaseLock (&mLock);
}
}
VOID
snp_undi32_callback_delay_30 (
IN UINT64 MicroSeconds
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine with the number of micro seconds when it wants to
pause.
Arguments:
MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
Returns:
void
--*/
{
if (MicroSeconds != 0) {
gBS->Stall ((UINTN) MicroSeconds);
}
}
VOID
snp_undi32_callback_memio_30 (
IN UINT8 ReadOrWrite,
IN UINT8 NumBytes,
IN UINT64 Address,
IN OUT UINT64 BufferAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
This is the IO routine for UNDI. This is not currently being used by UNDI3.0
because Undi3.0 uses io/mem offsets relative to the beginning of the device
io/mem address and so it needs to use the PCI_IO_FUNCTION that abstracts the
start of the device's io/mem addresses. Since SNP cannot retrive the context
of the undi3.0 interface it cannot use the PCI_IO_FUNCTION that specific for
that NIC and uses one global IO functions structure, this does not work.
This however works fine for EFI1.0 Undis because they use absolute addresses
for io/mem access.
Arguments:
ReadOrWrite - indicates read or write, IO or Memory
NumBytes - number of bytes to read or write
Address - IO or memory address to read from or write to
BufferAddr - memory location to read into or that contains the bytes
to write
Returns:
--*/
{
EFI_PCI_IO_PROTOCOL_WIDTH Width;
switch (NumBytes) {
case 2:
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;
break;
case 4:
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;
break;
case 8:
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;
break;
default:
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;
}
switch (ReadOrWrite) {
case PXE_IO_READ:
mPciIoFncs->Io.Read (
mPciIoFncs,
Width,
1, // BAR 1, IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_IO_WRITE:
mPciIoFncs->Io.Write (
mPciIoFncs,
Width,
1, // BAR 1, IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_READ:
mPciIoFncs->Mem.Read (
mPciIoFncs,
Width,
0, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_WRITE:
mPciIoFncs->Mem.Write (
mPciIoFncs,
Width,
0, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
}
return ;
}
//
// New callbacks for 3.1:
// there won't be a virtual2physical callback for UNDI 3.1 because undi3.1 uses
// the MemMap call to map the required address by itself!
//
VOID
snp_undi32_callback_block (
IN UINT64 UniqueId,
IN UINT32 Enable
)
/*++
Routine Description:
This is a callback routine supplied to UNDI3.1 at undi_start time.
UNDI call this routine when it wants to have exclusive access to a critical
section of the code/data
Arguments:
UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
Undi interface context (Undi does not read or write this variable)
Enable - non-zero indicates acquire
zero indicates release
Returns:
void
--*/
{
SNP_DRIVER *snp;
snp = (SNP_DRIVER *) (UINTN) UniqueId;
//
// tcpip was calling snp at tpl_notify and when we acquire a lock that was
// created at a lower level (TPL_CALLBACK) it gives an assert!
//
if (Enable != 0) {
EfiAcquireLock (&snp->lock);
} else {
EfiReleaseLock (&snp->lock);
}
}
VOID
snp_undi32_callback_delay (
IN UINT64 UniqueId,
IN UINT64 MicroSeconds
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine with the number of micro seconds when it wants to
pause.
Arguments:
MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
Returns:
void
--*/
{
if (MicroSeconds != 0) {
gBS->Stall ((UINTN) MicroSeconds);
}
}
/*
* IO routine for UNDI start CPB.
*/
VOID
snp_undi32_callback_memio (
UINT64 UniqueId,
UINT8 ReadOrWrite,
UINT8 NumBytes,
UINT64 Address,
UINT64 BufferAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
This is the IO routine for UNDI3.1.
Arguments:
ReadOrWrite - indicates read or write, IO or Memory
NumBytes - number of bytes to read or write
Address - IO or memory address to read from or write to
BufferAddr - memory location to read into or that contains the bytes
to write
Returns:
--*/
{
SNP_DRIVER *snp;
EFI_PCI_IO_PROTOCOL_WIDTH Width;
snp = (SNP_DRIVER *) (UINTN) UniqueId;
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;
switch (NumBytes) {
case 2:
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;
break;
case 4:
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;
break;
case 8:
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;
break;
}
switch (ReadOrWrite) {
case PXE_IO_READ:
snp->IoFncs->Io.Read (
snp->IoFncs,
Width,
snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_IO_WRITE:
snp->IoFncs->Io.Write (
snp->IoFncs,
Width,
snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_READ:
snp->IoFncs->Mem.Read (
snp->IoFncs,
Width,
snp->MemoryBarIndex, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_WRITE:
snp->IoFncs->Mem.Write (
snp->IoFncs,
Width,
snp->MemoryBarIndex, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
}
return ;
}
VOID
snp_undi32_callback_map (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN OUT UINT64 DeviceAddrPtr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it has to map a CPU address to a device
address.
Arguments:
UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
Undi interface context (Undi does not read or write this variable)
CpuAddr - Virtual address to be mapped!
NumBytes - size of memory to be mapped
Direction - direction of data flow for this memory's usage:
cpu->device, device->cpu or both ways
DeviceAddrPtr - pointer to return the mapped device address
Returns:
None
--*/
{
EFI_PHYSICAL_ADDRESS *DevAddrPtr;
EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag;
UINTN BuffSize;
SNP_DRIVER *snp;
UINTN Index;
EFI_STATUS Status;
BuffSize = (UINTN) NumBytes;
snp = (SNP_DRIVER *) (UINTN) UniqueId;
DevAddrPtr = (EFI_PHYSICAL_ADDRESS *) (UINTN) DeviceAddrPtr;
if (CpuAddr == 0) {
*DevAddrPtr = 0;
return ;
}
switch (Direction) {
case TO_AND_FROM_DEVICE:
DirectionFlag = EfiPciIoOperationBusMasterCommonBuffer;
break;
case FROM_DEVICE:
DirectionFlag = EfiPciIoOperationBusMasterWrite;
break;
case TO_DEVICE:
DirectionFlag = EfiPciIoOperationBusMasterRead;
break;
default:
*DevAddrPtr = 0;
//
// any non zero indicates error!
//
return ;
}
//
// find an unused map_list entry
//
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
if (snp->map_list[Index].virt == 0) {
break;
}
}
if (Index >= MAX_MAP_LENGTH) {
DEBUG ((EFI_D_INFO, "SNP maplist is FULL\n"));
*DevAddrPtr = 0;
return ;
}
snp->map_list[Index].virt = (EFI_PHYSICAL_ADDRESS) CpuAddr;
Status = snp->IoFncs->Map (
snp->IoFncs,
DirectionFlag,
(VOID *) (UINTN) CpuAddr,
&BuffSize,
DevAddrPtr,
&(snp->map_list[Index].map_cookie)
);
if (Status != EFI_SUCCESS) {
*DevAddrPtr = 0;
snp->map_list[Index].virt = 0;
}
return ;
}
VOID
snp_undi32_callback_unmap (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN UINT64 DeviceAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it wants to unmap an address that was previously
mapped using map callback
Arguments:
UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
Undi interface context (Undi does not read or write this variable)
CpuAddr - Virtual address that was mapped!
NumBytes - size of memory mapped
Direction- direction of data flow for this memory's usage:
cpu->device, device->cpu or both ways
DeviceAddr - the mapped device address
Returns:
--*/
{
SNP_DRIVER *snp;
UINT16 Index;
snp = (SNP_DRIVER *) (UINTN) UniqueId;
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
if (snp->map_list[Index].virt == CpuAddr) {
break;
}
}
if (Index >= MAX_MAP_LENGTH)
{
DEBUG ((EFI_D_ERROR, "SNP could not find a mapping, failed to unmap.\n"));
return ;
}
snp->IoFncs->Unmap (snp->IoFncs, snp->map_list[Index].map_cookie);
snp->map_list[Index].virt = 0;
snp->map_list[Index].map_cookie = NULL;
return ;
}
VOID
snp_undi32_callback_sync (
UINT64 UniqueId,
UINT64 CpuAddr,
UINT32 NumBytes,
UINT32 Direction,
UINT64 DeviceAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it wants synchronize the virtual buffer contents
with the mapped buffer contents. The virtual and mapped buffers need not
correspond to the same physical memory (especially if the virtual address is
> 4GB). Depending on the direction for which the buffer is mapped, undi will
need to synchronize their contents whenever it writes to/reads from the buffer
using either the cpu address or the device address.
EFI does not provide a sync call, since virt=physical, we sould just do
the synchronization ourself here!
Arguments:
UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
Undi interface context (Undi does not read or write this variable)
CpuAddr - Virtual address that was mapped!
NumBytes - size of memory mapped
Direction- direction of data flow for this memory's usage:
cpu->device, device->cpu or both ways
DeviceAddr - the mapped device address
Returns:
--*/
{
if ((CpuAddr == 0) || (DeviceAddr == 0) || (NumBytes == 0)) {
return ;
}
switch (Direction) {
case FROM_DEVICE:
CopyMem ((UINT8 *) (UINTN) CpuAddr, (UINT8 *) (UINTN) DeviceAddr, NumBytes);
break;
case TO_DEVICE:
CopyMem ((UINT8 *) (UINTN) DeviceAddr, (UINT8 *) (UINTN) CpuAddr, NumBytes);
break;
}
return ;
}

View File

@@ -0,0 +1,195 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
get_status.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
**/
#include "Snp.h"
STATIC
/**
this routine calls undi to get the status of the interrupts, get the list of
transmit buffers that completed transmitting!
@param snp pointer to snp driver structure
@param InterruptStatusPtr a non null pointer gets the interrupt status
@param TransmitBufferListPtrs a non null ointer gets the list of pointers of
previously transmitted buffers whose
transmission was completed asynchrnously.
**/
EFI_STATUS
pxe_getstatus (
SNP_DRIVER *snp,
UINT32 *InterruptStatusPtr,
VOID **TransmitBufferListPtr
)
{
PXE_DB_GET_STATUS *db;
UINT16 InterruptFlags;
UINT64 TempData;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_GET_STATUS;
snp->cdb.OpFlags = 0;
if (TransmitBufferListPtr != NULL) {
snp->cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS;
}
if (InterruptStatusPtr != NULL) {
snp->cdb.OpFlags |= PXE_OPFLAGS_GET_INTERRUPT_STATUS;
}
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
//
// size DB for return of one buffer
//
snp->cdb.DBsize = (UINT16) (((UINT16) (sizeof (PXE_DB_GET_STATUS)) - (UINT16) (sizeof db->TxBuffer)) + (UINT16) (sizeof db->TxBuffer[0]));
snp->cdb.DBaddr = (UINT64)(UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.get_status() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_SUCCESS) {
DEBUG (
(EFI_D_NET,
"\nsnp->undi.get_status() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatFlags)
);
return EFI_DEVICE_ERROR;
}
//
// report the values back..
//
if (InterruptStatusPtr != NULL) {
InterruptFlags = (UINT16) (snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK);
*InterruptStatusPtr = 0;
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_RECEIVE) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
}
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_TRANSMIT) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
}
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_COMMAND) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
}
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_SOFTWARE) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
}
}
if (TransmitBufferListPtr != NULL) {
*TransmitBufferListPtr =
(
(snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) ||
(snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY)
) ? 0 : (VOID *) (UINTN) db->TxBuffer[0];
TempData = (UINT64) (UINTN) (*TransmitBufferListPtr);
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
del_v2p ((VOID *) (UINTN) (db->TxBuffer[0]));
}
}
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for getting the status
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_getstatus routine to actually get the undi status
@param this context pointer
@param InterruptStatusPtr a non null pointer gets the interrupt status
@param TransmitBufferListPtrs a non null ointer gets the list of pointers of
previously transmitted buffers whose
transmission was completed asynchrnously.
**/
EFI_STATUS
EFIAPI
snp_undi32_get_status (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINT32 *InterruptStatusPtr OPTIONAL,
OUT VOID **TransmitBufferListPtr OPTIONAL
)
{
SNP_DRIVER *snp;
EFI_TPL OldTpl;
EFI_STATUS Status;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
if (InterruptStatusPtr == NULL && TransmitBufferListPtr == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
Status = pxe_getstatus (snp, InterruptStatusPtr, TransmitBufferListPtr);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,245 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
initialize.c
Abstract:
Revision history:
2000-Feb-09 M(f)J Genesis.
**/
#include "Snp.h"
VOID
EFIAPI
SnpWaitForPacketNotify (
IN EFI_EVENT Event,
IN VOID *SnpPtr
);
/**
this routine calls undi to initialize the interface.
@param snp pointer to snp driver structure
@param CableDetectFlag Do/don't detect the cable (depending on what undi
supports)
**/
EFI_STATUS
pxe_init (
SNP_DRIVER *snp,
UINT16 CableDetectFlag
)
{
PXE_CPB_INITIALIZE *cpb;
VOID *addr;
EFI_STATUS Status;
cpb = snp->cpb;
if (snp->tx_rx_bufsize != 0) {
Status = snp->IoFncs->AllocateBuffer (
snp->IoFncs,
AllocateAnyPages,
EfiBootServicesData,
SNP_MEM_PAGES (snp->tx_rx_bufsize),
&addr,
0
);
if (Status != EFI_SUCCESS) {
DEBUG (
(EFI_D_ERROR,
"\nsnp->pxe_init() AllocateBuffer %xh (%r)\n",
Status,
Status)
);
return Status;
}
ASSERT (addr);
snp->tx_rx_buffer = addr;
}
cpb->MemoryAddr = (UINT64)(UINTN) snp->tx_rx_buffer;
cpb->MemoryLength = snp->tx_rx_bufsize;
//
// let UNDI decide/detect these values
//
cpb->LinkSpeed = 0;
cpb->TxBufCnt = 0;
cpb->TxBufSize = 0;
cpb->RxBufCnt = 0;
cpb->RxBufSize = 0;
cpb->DuplexMode = PXE_DUPLEX_DEFAULT;
cpb->LoopBackMode = LOOPBACK_NORMAL;
snp->cdb.OpCode = PXE_OPCODE_INITIALIZE;
snp->cdb.OpFlags = CableDetectFlag;
snp->cdb.CPBsize = sizeof (PXE_CPB_INITIALIZE);
snp->cdb.DBsize = sizeof (PXE_DB_INITIALIZE);
snp->cdb.CPBaddr = (UINT64)(UINTN) snp->cpb;
snp->cdb.DBaddr = (UINT64)(UINTN) snp->db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
DEBUG ((EFI_D_NET, "\nsnp->undi.initialize() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode == PXE_STATCODE_SUCCESS) {
snp->mode.State = EfiSimpleNetworkInitialized;
Status = EFI_SUCCESS;
} else {
DEBUG (
(EFI_D_WARN,
"\nsnp->undi.initialize() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
if (snp->tx_rx_buffer != NULL) {
snp->IoFncs->FreeBuffer (
snp->IoFncs,
SNP_MEM_PAGES (snp->tx_rx_bufsize),
(VOID *) snp->tx_rx_buffer
);
}
snp->tx_rx_buffer = NULL;
Status = EFI_DEVICE_ERROR;
}
return Status;
}
/**
This is the SNP interface routine for initializing the interface
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_initialize routine to actually do the undi initialization
@param this context pointer
@param extra_rx_buffer_size optional parameter, indicates extra space for
rx_buffers
@param extra_tx_buffer_size optional parameter, indicates extra space for
tx_buffers
**/
EFI_STATUS
EFIAPI
snp_undi32_initialize (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN UINTN extra_rx_buffer_size OPTIONAL,
IN UINTN extra_tx_buffer_size OPTIONAL
)
{
EFI_STATUS EfiStatus;
SNP_DRIVER *snp;
EFI_TPL OldTpl;
//
//
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
if (snp == NULL) {
EfiStatus = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
switch (snp->mode.State) {
case EfiSimpleNetworkStarted:
break;
case EfiSimpleNetworkStopped:
EfiStatus = EFI_NOT_STARTED;
goto ON_EXIT;
default:
EfiStatus = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
EfiStatus = gBS->CreateEvent (
EVT_NOTIFY_WAIT,
TPL_NOTIFY,
&SnpWaitForPacketNotify,
snp,
&snp->snp.WaitForPacket
);
if (EFI_ERROR (EfiStatus)) {
snp->snp.WaitForPacket = NULL;
EfiStatus = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
//
//
//
snp->mode.MCastFilterCount = 0;
snp->mode.ReceiveFilterSetting = 0;
ZeroMem (snp->mode.MCastFilter, sizeof snp->mode.MCastFilter);
CopyMem (
&snp->mode.CurrentAddress,
&snp->mode.PermanentAddress,
sizeof (EFI_MAC_ADDRESS)
);
//
// Compute tx/rx buffer sizes based on UNDI init info and parameters.
//
snp->tx_rx_bufsize = (UINT32) (snp->init_info.MemoryRequired + extra_rx_buffer_size + extra_tx_buffer_size);
if (snp->mode.MediaPresentSupported) {
if (pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) == EFI_SUCCESS) {
snp->mode.MediaPresent = TRUE;
goto ON_EXIT;
}
}
snp->mode.MediaPresent = FALSE;
EfiStatus = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
if (EFI_ERROR (EfiStatus)) {
gBS->CloseEvent (snp->snp.WaitForPacket);
}
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return EfiStatus;
}

View File

@@ -0,0 +1,165 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
mcast_ip_to_mac.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to convert an multicast IP address to a MAC address
@param snp pointer to snp driver structure
@param IPv6 flag to indicate if this is an ipv6 address
@param IP multicast IP address
@param MAC pointer to hold the return MAC address
**/
STATIC
EFI_STATUS
pxe_ip2mac (
IN SNP_DRIVER *snp,
IN BOOLEAN IPv6,
IN EFI_IP_ADDRESS *IP,
IN OUT EFI_MAC_ADDRESS *MAC
)
{
PXE_CPB_MCAST_IP_TO_MAC *cpb;
PXE_DB_MCAST_IP_TO_MAC *db;
cpb = snp->cpb;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_MCAST_IP_TO_MAC;
snp->cdb.OpFlags = (UINT16) (IPv6 ? PXE_OPFLAGS_MCAST_IPV6_TO_MAC : PXE_OPFLAGS_MCAST_IPV4_TO_MAC);
snp->cdb.CPBsize = sizeof (PXE_CPB_MCAST_IP_TO_MAC);
snp->cdb.DBsize = sizeof (PXE_DB_MCAST_IP_TO_MAC);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;
snp->cdb.DBaddr = (UINT64)(UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
CopyMem (&cpb->IP, IP, sizeof (PXE_IP_ADDR));
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.mcast_ip_to_mac() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
break;
case PXE_STATCODE_INVALID_CPB:
return EFI_INVALID_PARAMETER;
case PXE_STATCODE_UNSUPPORTED:
DEBUG (
(EFI_D_NET,
"\nsnp->undi.mcast_ip_to_mac() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_UNSUPPORTED;
default:
//
// UNDI command failed. Return EFI_DEVICE_ERROR
// to caller.
//
DEBUG (
(EFI_D_NET,
"\nsnp->undi.mcast_ip_to_mac() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
CopyMem (MAC, &db->MAC, sizeof (PXE_MAC_ADDR));
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for converting a multicast IP address to
a MAC address.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_ip2mac routine to actually do the conversion
@param this context pointer
@param IPv6 flag to indicate if this is an ipv6 address
@param IP multicast IP address
@param MAC pointer to hold the return MAC address
**/
EFI_STATUS
EFIAPI
snp_undi32_mcast_ip_to_mac (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN IPv6,
IN EFI_IP_ADDRESS *IP,
OUT EFI_MAC_ADDRESS *MAC
)
{
SNP_DRIVER *snp;
EFI_TPL OldTpl;
EFI_STATUS Status;
//
// Get pointer to SNP driver instance for *this.
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
if (IP == NULL || MAC == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
Status = pxe_ip2mac (snp, IPv6, IP, MAC);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,185 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
nvdata.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
**/
#include "snp.h"
/**
This routine calls Undi to read the desired number of eeprom bytes.
@param snp pointer to the snp driver structure
@param RegOffset eeprom register value relative to the base address
@param NumBytes number of bytes to read
@param BufferPtr pointer where to read into
**/
STATIC
EFI_STATUS
pxe_nvdata_read (
IN SNP_DRIVER *snp,
IN UINTN RegOffset,
IN UINTN NumBytes,
IN OUT VOID *BufferPtr
)
{
PXE_DB_NVDATA *db;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_NVDATA;
snp->cdb.OpFlags = PXE_OPFLAGS_NVDATA_READ;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBsize = sizeof (PXE_DB_NVDATA);
snp->cdb.DBaddr = (UINT64)(UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.nvdata () "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
break;
case PXE_STATCODE_UNSUPPORTED:
DEBUG (
(EFI_D_NET,
"\nsnp->undi.nvdata() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_UNSUPPORTED;
default:
DEBUG (
(EFI_D_NET,
"\nsnp->undi.nvdata() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
CopyMem (BufferPtr, db->Data.Byte + RegOffset, NumBytes);
return EFI_SUCCESS;
}
/**
This is an interface call provided by SNP.
It does the basic checking on the input parameters and retrieves snp structure
and then calls the read_nvdata() call which does the actual reading
@param this context pointer
@param ReadOrWrite true for reading and false for writing
@param RegOffset eeprom register relative to the base
@param NumBytes how many bytes to read
@param BufferPtr address of memory to read into
**/
EFI_STATUS
EFIAPI
snp_undi32_nvdata (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN ReadOrWrite,
IN UINTN RegOffset,
IN UINTN NumBytes,
IN OUT VOID *BufferPtr
)
{
SNP_DRIVER *snp;
EFI_TPL OldTpl;
EFI_STATUS Status;
//
// Get pointer to SNP driver instance for *this.
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
//
// Return error if the SNP is not initialized.
//
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
//
// Return error if non-volatile memory variables are not valid.
//
if (snp->mode.NvRamSize == 0 || snp->mode.NvRamAccessSize == 0) {
Status = EFI_UNSUPPORTED;
goto ON_EXIT;
}
//
// Check for invalid parameter combinations.
//
if ((NumBytes == 0) ||
(BufferPtr == NULL) ||
(RegOffset >= snp->mode.NvRamSize) ||
(RegOffset + NumBytes > snp->mode.NvRamSize) ||
(NumBytes % snp->mode.NvRamAccessSize != 0) ||
(RegOffset % snp->mode.NvRamAccessSize != 0)
) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
//
// check the implementation flags of undi if we can write the nvdata!
//
if (!ReadOrWrite) {
Status = EFI_UNSUPPORTED;
} else {
Status = pxe_nvdata_read (snp, RegOffset, NumBytes, BufferPtr);
}
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,255 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
receive.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to receive a packet and fills in the data in the
input pointers!
@param snp pointer to snp driver structure
@param BufferPtr pointer to the memory for the received data
@param BuffSizePtr is a pointer to the length of the buffer on entry and
contains the length of the received data on return
@param HeaderSizePtr pointer to the header portion of the data received.
@param SourceAddrPtr optional parameter, is a pointer to contain the
source ethernet address on return
@param DestinationAddrPtr optional parameter, is a pointer to contain the
destination ethernet address on return
@param ProtocolPtr optional parameter, is a pointer to contain the
protocol type from the ethernet header on return
**/
STATIC
EFI_STATUS
pxe_receive (
SNP_DRIVER *snp,
VOID *BufferPtr,
UINTN *BuffSizePtr,
UINTN *HeaderSizePtr,
EFI_MAC_ADDRESS *SourceAddrPtr,
EFI_MAC_ADDRESS *DestinationAddrPtr,
UINT16 *ProtocolPtr
)
{
PXE_CPB_RECEIVE *cpb;
PXE_DB_RECEIVE *db;
UINTN buf_size;
UINT64 TempData;
cpb = snp->cpb;
db = snp->db;
buf_size = *BuffSizePtr;
//
// IMPORTANT NOTE:
// In case of the older 3.0 UNDI, if the input buffer address is beyond 4GB,
// DO NOT call the map function on the given buffer, instead use
// a global buffer. The reason is that UNDI3.0 has some unnecessary check of
// making sure that all the addresses (whether or not they will be given
// to the NIC ) supplied to it are below 4GB. It may or may not use
// the mapped address after all (like in case of CPB and DB)!
// Instead of using the global buffer whose address is allocated within the
// 2GB limit if I start mapping the given buffer we lose the data, here is
// why!!!
// if our address is > 4GB, the map call creates another buffer below 2GB and
// copies data to/from the original buffer to the mapped buffer either at
// map time or unmap time depending on the map direction.
// UNDI will not complain since we already mapped the buffer to be
// within the 2GB limit but will not use (I know undi) the mapped address
// since it does not give the user buffers to the NIC's receive unit,
// It just copies the received packet into the user buffer using the virtual
// (CPU) address rather than the mapped (device or physical) address.
// When the UNDI call returns, if we then unmap the buffer, we will lose
// the contents because unmap copies the contents of the mapped buffer into
// the original buffer (since the direction is FROM_DEVICE) !!!
//
// this is not a problem in Undi 3.1 because this undi uses it's map callback
// routine to map a cpu address to device address and it does it only if
// it is giving the address to the device and unmaps it before using the cpu
// address!
//
TempData = (UINT64) (UINTN) BufferPtr;
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
cpb->BufferAddr = (UINT64)(UINTN) snp->receive_buf;
cpb->BufferLen = (UINT32) (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
} else {
cpb->BufferAddr = (UINT64)(UINTN) BufferPtr;
cpb->BufferLen = (UINT32) *BuffSizePtr;
}
cpb->reserved = 0;
snp->cdb.OpCode = PXE_OPCODE_RECEIVE;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = sizeof (PXE_CPB_RECEIVE);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;
snp->cdb.DBsize = sizeof (PXE_DB_RECEIVE);
snp->cdb.DBaddr = (UINT64)(UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_INFO, "\nsnp->undi.receive () "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
break;
case PXE_STATCODE_NO_DATA:
DEBUG (
(EFI_D_INFO,
"\nsnp->undi.receive () %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_NOT_READY;
default:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.receive() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
*BuffSizePtr = db->FrameLen;
if (HeaderSizePtr != NULL) {
*HeaderSizePtr = db->MediaHeaderLen;
}
if (SourceAddrPtr != NULL) {
CopyMem (SourceAddrPtr, &db->SrcAddr, snp->mode.HwAddressSize);
}
if (DestinationAddrPtr != NULL) {
CopyMem (DestinationAddrPtr, &db->DestAddr, snp->mode.HwAddressSize);
}
if (ProtocolPtr != NULL) {
*ProtocolPtr = (UINT16) PXE_SWAP_UINT16 (db->Protocol); /* we need to do the byte swapping */
}
TempData = (UINT64) (UINTN) BufferPtr;
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
CopyMem (BufferPtr, snp->receive_buf, snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
}
return (*BuffSizePtr <= buf_size) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
}
/**
This is the SNP interface routine for receiving network data.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_receive routine to actually do the receive!
@param this context pointer
@param HeaderSizePtr optional parameter and is a pointer to the header
portion of the data received.
@param BuffSizePtr is a pointer to the length of the buffer on entry and
contains the length of the received data on return
@param BufferPtr pointer to the memory for the received data
@param SourceAddrPtr optional parameter, is a pointer to contain the
source ethernet address on return
@param DestinationAddrPtr optional parameter, is a pointer to contain the
destination ethernet address on return
@param ProtocolPtr optional parameter, is a pointer to contain the
protocol type from the ethernet header on return
**/
EFI_STATUS
EFIAPI
snp_undi32_receive (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINTN *HeaderSizePtr OPTIONAL,
IN OUT UINTN *BuffSizePtr,
OUT VOID *BufferPtr,
OUT EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL,
OUT EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL,
OUT UINT16 *ProtocolPtr OPTIONAL
)
{
SNP_DRIVER *snp;
EFI_TPL OldTpl;
EFI_STATUS Status;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
if ((BuffSizePtr == NULL) || (BufferPtr == NULL)) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if (!snp->mode.ReceiveFilterSetting) {
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
Status = pxe_receive (
snp,
BufferPtr,
BuffSizePtr,
HeaderSizePtr,
SourceAddrPtr,
DestinationAddrPtr,
ProtocolPtr
);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,406 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
receive_filters.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to enable the receive filters.
@param snp pointer to snp driver structure
@param EnableFlags bit mask for enabling the receive filters
@param MCastAddressCount multicast address count for a new multicast address
list
@param MCastAddressList list of new multicast addresses
**/
STATIC
EFI_STATUS
pxe_rcvfilter_enable (
SNP_DRIVER *snp,
UINT32 EnableFlags,
UINTN MCastAddressCount,
EFI_MAC_ADDRESS *MCastAddressList
)
{
snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
snp->cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_ENABLE;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
}
if (MCastAddressCount != 0) {
snp->cdb.CPBsize = (UINT16) (MCastAddressCount * sizeof (EFI_MAC_ADDRESS));
snp->cdb.CPBaddr = (UINT64)(UINTN) snp->cpb;
CopyMem (snp->cpb, MCastAddressList, snp->cdb.CPBsize);
}
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_SUCCESS) {
//
// UNDI command failed. Return UNDI status to caller.
//
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.receive_filters() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_INVALID_CDB:
case PXE_STATCODE_INVALID_CPB:
case PXE_STATCODE_INVALID_PARAMETER:
return EFI_INVALID_PARAMETER;
case PXE_STATCODE_UNSUPPORTED:
return EFI_UNSUPPORTED;
}
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
/**
this routine calls undi to disable the receive filters.
@param snp pointer to snp driver structure
@param DisableFlags bit mask for disabling the receive filters
@param ResetMCastList boolean flag to reset/delete the multicast filter list
**/
STATIC
EFI_STATUS
pxe_rcvfilter_disable (
SNP_DRIVER *snp,
UINT32 DisableFlags,
BOOLEAN ResetMCastList
)
{
snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
snp->cdb.OpFlags = (UINT16) (DisableFlags ? PXE_OPFLAGS_RECEIVE_FILTER_DISABLE : PXE_OPFLAGS_NOT_USED);
if (ResetMCastList) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
}
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
}
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_SUCCESS) {
//
// UNDI command failed. Return UNDI status to caller.
//
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.receive_filters() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
/**
this routine calls undi to read the receive filters.
@param snp pointer to snp driver structure
**/
STATIC
EFI_STATUS
pxe_rcvfilter_read (
SNP_DRIVER *snp
)
{
snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
snp->cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_READ;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = (UINT16) (snp->mode.MaxMCastFilterCount * sizeof (EFI_MAC_ADDRESS));
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
if (snp->cdb.DBsize == 0) {
snp->cdb.DBaddr = (UINT64)(UINTN) NULL;
} else {
snp->cdb.DBaddr = (UINT64)(UINTN) snp->db;
ZeroMem (snp->db, snp->cdb.DBsize);
}
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_SUCCESS) {
//
// UNDI command failed. Return UNDI status to caller.
//
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.receive_filters() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
//
// Convert UNDI32 StatFlags to EFI SNP filter flags.
//
snp->mode.ReceiveFilterSetting = 0;
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_UNICAST) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
}
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
}
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
}
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
}
if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {
snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
}
CopyMem (snp->mode.MCastFilter, snp->db, snp->cdb.DBsize);
//
// Count number of active entries in multicast filter list.
//
{
EFI_MAC_ADDRESS ZeroMacAddr;
SetMem (&ZeroMacAddr, sizeof ZeroMacAddr, 0);
for (snp->mode.MCastFilterCount = 0;
snp->mode.MCastFilterCount < snp->mode.MaxMCastFilterCount;
snp->mode.MCastFilterCount++
) {
if (CompareMem (
&snp->mode.MCastFilter[snp->mode.MCastFilterCount],
&ZeroMacAddr,
sizeof ZeroMacAddr
) == 0) {
break;
}
}
}
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for reading/enabling/disabling the
receive filters.
This routine basically retrieves snp structure, checks the SNP state and
checks the parameter validity, calls one of the above routines to actually
do the work
@param this context pointer
@param EnableFlags bit mask for enabling the receive filters
@param DisableFlags bit mask for disabling the receive filters
@param ResetMCastList boolean flag to reset/delete the multicast filter list
@param MCastAddressCount multicast address count for a new multicast address
list
@param MCastAddressList list of new multicast addresses
**/
EFI_STATUS
EFIAPI
snp_undi32_receive_filters (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINT32 EnableFlags,
IN UINT32 DisableFlags,
IN BOOLEAN ResetMCastList,
IN UINTN MCastAddressCount OPTIONAL,
IN EFI_MAC_ADDRESS * MCastAddressList OPTIONAL
)
{
SNP_DRIVER *snp;
EFI_STATUS Status;
EFI_TPL OldTpl;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
//
// check if we are asked to enable or disable something that the UNDI
// does not even support!
//
if (((EnableFlags &~snp->mode.ReceiveFilterMask) != 0) ||
((DisableFlags &~snp->mode.ReceiveFilterMask) != 0)) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if (ResetMCastList) {
DisableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & snp->mode.ReceiveFilterMask;
MCastAddressCount = 0;
MCastAddressList = NULL;
} else {
if (MCastAddressCount != 0) {
if ((MCastAddressCount > snp->mode.MaxMCastFilterCount) ||
(MCastAddressList == NULL)) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
}
}
if (EnableFlags == 0 && DisableFlags == 0 && !ResetMCastList && MCastAddressCount == 0) {
Status = EFI_SUCCESS;
goto ON_EXIT;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastAddressCount == 0) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if ((EnableFlags != 0) || (MCastAddressCount != 0)) {
Status = pxe_rcvfilter_enable (
snp,
EnableFlags,
MCastAddressCount,
MCastAddressList
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
if ((DisableFlags != 0) || ResetMCastList) {
Status = pxe_rcvfilter_disable (snp, DisableFlags, ResetMCastList);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
Status = pxe_rcvfilter_read (snp);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,128 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
reset.c
Abstract:
Revision history:
2000-Feb-09 M(f)J Genesis.
**/
#include "Snp.h"
/**
This routine calls undi to reset the nic.
@param snp pointer to the snp driver structure
@return EFI_SUCCESSFUL for a successful completion
@return other for failed calls
**/
STATIC
EFI_STATUS
pxe_reset (
SNP_DRIVER *snp
)
{
snp->cdb.OpCode = PXE_OPCODE_RESET;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.reset() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
DEBUG (
(EFI_D_WARN,
"\nsnp->undi32.reset() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
//
// UNDI could not be reset. Return UNDI error.
//
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for resetting the NIC
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_reset routine to actually do the reset!
@param this context pointer
@param ExtendedVerification not implemented
**/
EFI_STATUS
EFIAPI
snp_undi32_reset (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN ExtendedVerification
)
{
SNP_DRIVER *snp;
EFI_TPL OldTpl;
EFI_STATUS Status;
//
// Resolve Warning 4 unreferenced parameter problem
//
ExtendedVerification = 0;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
Status = pxe_reset (snp);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,148 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
shutdown.c
Abstract:
Revision history:
2000-Feb-14 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to shut down the interface.
@param snp pointer to snp driver structure
**/
EFI_STATUS
pxe_shutdown (
IN SNP_DRIVER *snp
)
{
snp->cdb.OpCode = PXE_OPCODE_SHUTDOWN;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.shutdown() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
//
// UNDI could not be shutdown. Return UNDI error.
//
DEBUG ((EFI_D_WARN, "\nsnp->undi.shutdown() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
return EFI_DEVICE_ERROR;
}
//
// Free allocated memory.
//
if (snp->tx_rx_buffer != NULL) {
snp->IoFncs->FreeBuffer (
snp->IoFncs,
SNP_MEM_PAGES (snp->tx_rx_bufsize),
(VOID *) snp->tx_rx_buffer
);
}
snp->tx_rx_buffer = NULL;
snp->tx_rx_bufsize = 0;
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for shutting down the interface
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_shutdown routine to actually do the undi shutdown
@param this context pointer
**/
EFI_STATUS
EFIAPI
snp_undi32_shutdown (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
{
SNP_DRIVER *snp;
EFI_STATUS Status;
EFI_TPL OldTpl;
//
//
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
//
//
//
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
//
//
//
Status = pxe_shutdown (snp);
snp->mode.State = EfiSimpleNetworkStarted;
snp->mode.ReceiveFilterSetting = 0;
snp->mode.MCastFilterCount = 0;
snp->mode.ReceiveFilterSetting = 0;
ZeroMem (snp->mode.MCastFilter, sizeof snp->mode.MCastFilter);
CopyMem (
&snp->mode.CurrentAddress,
&snp->mode.PermanentAddress,
sizeof (EFI_MAC_ADDRESS)
);
gBS->CloseEvent (snp->snp.WaitForPacket);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,454 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
snp.h
Abstract:
Revision history:
**/
#ifndef _SNP_H
#define _SNP_H
#include <PiDxe.h>
#include <Protocol/SimpleNetwork.h>
#include <Protocol/PciIo.h>
#include <Protocol/NetworkInterfaceIdentifier.h>
#include <Protocol/DevicePath.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <IndustryStandard/Pci22.h>
#define FOUR_GIGABYTES (UINT64) 0x100000000ULL
//
// Driver Consumed Protocol Prototypes
//
//@MT:#include EFI_PROTOCOL_DEFINITION (DevicePath)
//@MT:#include EFI_PROTOCOL_DEFINITION (PciIo)
//@MT:#include EFI_PROTOCOL_DEFINITION (EfiNetworkInterfaceIdentifier)
//
// Driver Produced Protocol Prototypes
//
//@MT:#include EFI_PROTOCOL_DEFINITION (DriverBinding)
//@MT:#include EFI_PROTOCOL_DEFINITION (ComponentName)
//@MT:#include EFI_PROTOCOL_DEFINITION (ComponentName2)
//@MT:#include EFI_PROTOCOL_DEFINITION (SimpleNetwork)
#define SNP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('s', 'n', 'd', 's')
#define MAX_MAP_LENGTH 100
#define PCI_BAR_IO_MASK 0x00000003
#define PCI_BAR_IO_MODE 0x00000001
#define PCI_BAR_MEM_MASK 0x0000000F
#define PCI_BAR_MEM_MODE 0x00000000
#define PCI_BAR_MEM_64BIT 0x00000004
typedef struct {
UINT32 Signature;
EFI_LOCK lock;
EFI_SIMPLE_NETWORK_PROTOCOL snp;
EFI_SIMPLE_NETWORK_MODE mode;
EFI_HANDLE device_handle;
EFI_DEVICE_PATH_PROTOCOL *device_path;
//
// Local instance data needed by SNP driver
//
// Pointer to S/W UNDI API entry point
// This will be NULL for H/W UNDI
//
EFI_STATUS (*issue_undi32_command) (UINT64 cdb);
BOOLEAN is_swundi;
//
// undi interface number, if one undi manages more nics
//
PXE_IFNUM if_num;
//
// Allocated tx/rx buffer that was passed to UNDI Initialize.
//
UINT32 tx_rx_bufsize;
VOID *tx_rx_buffer;
//
// mappable buffers for receive and fill header for undi3.0
// these will be used if the user buffers are above 4GB limit (instead of
// mapping the user buffers)
//
UINT8 *receive_buf;
VOID *ReceiveBufUnmap;
UINT8 *fill_hdr_buf;
VOID *FillHdrBufUnmap;
EFI_PCI_IO_PROTOCOL *IoFncs;
UINT8 IoBarIndex;
UINT8 MemoryBarIndex;
BOOLEAN IsOldUndi; // true for EFI1.0 UNDI (3.0) drivers
//
// Buffers for command descriptor block, command parameter block
// and data block.
//
PXE_CDB cdb;
VOID *cpb;
VOID *CpbUnmap;
VOID *db;
//
// UNDI structure, we need to remember the init info for a long time!
//
PXE_DB_GET_INIT_INFO init_info;
VOID *SnpDriverUnmap;
//
// when ever we map an address, we must remember it's address and the un-map
// cookie so that we can unmap later
//
struct s_map_list {
EFI_PHYSICAL_ADDRESS virt;
VOID *map_cookie;
} map_list[MAX_MAP_LENGTH];
}
SNP_DRIVER;
#define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) CR (a, SNP_DRIVER, snp, SNP_DRIVER_SIGNATURE)
//
// Global Variables
//
extern EFI_COMPONENT_NAME_PROTOCOL gSimpleNetworkComponentName;
//
// Virtual to physical mapping for all UNDI 3.0s.
//
extern struct s_v2p {
struct s_v2p *next;
VOID *vaddr;
UINTN bsize;
EFI_PHYSICAL_ADDRESS paddr;
VOID *unmap;
}
*_v2p;
EFI_STATUS
add_v2p (
struct s_v2p **v2p,
EFI_PCI_IO_PROTOCOL_OPERATION type,
VOID *vaddr,
UINTN bsize
)
;
EFI_STATUS
find_v2p (
struct s_v2p **v2p,
VOID *vaddr
)
;
EFI_STATUS
del_v2p (
VOID *vaddr
)
;
extern
VOID
snp_undi32_callback_block_30 (
IN UINT32 Enable
)
;
extern
VOID
snp_undi32_callback_delay_30 (
IN UINT64 MicroSeconds
)
;
extern
VOID
snp_undi32_callback_memio_30 (
IN UINT8 ReadOrWrite,
IN UINT8 NumBytes,
IN UINT64 MemOrPortAddress,
IN OUT UINT64 BufferPtr
)
;
extern
VOID
snp_undi32_callback_v2p_30 (
IN UINT64 CpuAddr,
IN OUT UINT64 DeviceAddrPtr
)
;
extern
VOID
snp_undi32_callback_block (
IN UINT64 UniqueId,
IN UINT32 Enable
)
;
extern
VOID
snp_undi32_callback_delay (
IN UINT64 UniqueId,
IN UINT64 MicroSeconds
)
;
extern
VOID
snp_undi32_callback_memio (
IN UINT64 UniqueId,
IN UINT8 ReadOrWrite,
IN UINT8 NumBytes,
IN UINT64 MemOrPortAddr,
IN OUT UINT64 BufferPtr
)
;
extern
VOID
snp_undi32_callback_map (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN OUT UINT64 DeviceAddrPtr
)
;
extern
VOID
snp_undi32_callback_unmap (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN UINT64 DeviceAddr // not a pointer to device address
)
;
extern
VOID
snp_undi32_callback_sync (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN UINT64 DeviceAddr // not a pointer to device address
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_start (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_stop (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_initialize (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN UINTN extra_rx_buffer_size OPTIONAL,
IN UINTN extra_tx_buffer_size OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_reset (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN ExtendedVerification
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_shutdown (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_receive_filters (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINT32 enable,
IN UINT32 disable,
IN BOOLEAN reset_mcast_filter,
IN UINTN mcast_filter_count OPTIONAL,
IN EFI_MAC_ADDRESS * mcast_filter OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_station_address (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN reset,
IN EFI_MAC_ADDRESS *new OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_statistics (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN reset,
IN OUT UINTN *statistics_size OPTIONAL,
IN OUT EFI_NETWORK_STATISTICS * statistics_table OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_mcast_ip_to_mac (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN IPv6,
IN EFI_IP_ADDRESS *IP,
OUT EFI_MAC_ADDRESS *MAC
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_nvdata (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN read_write,
IN UINTN offset,
IN UINTN buffer_size,
IN OUT VOID *buffer
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_get_status (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINT32 *interrupt_status OPTIONAL,
OUT VOID **tx_buffer OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_transmit (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINTN header_size,
IN UINTN buffer_size,
IN VOID *buffer,
IN EFI_MAC_ADDRESS * src_addr OPTIONAL,
IN EFI_MAC_ADDRESS * dest_addr OPTIONAL,
IN UINT16 *protocol OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_receive (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINTN *header_size OPTIONAL,
IN OUT UINTN *buffer_size,
OUT VOID *buffer,
OUT EFI_MAC_ADDRESS * src_addr OPTIONAL,
OUT EFI_MAC_ADDRESS * dest_addr OPTIONAL,
OUT UINT16 *protocol OPTIONAL
)
;
typedef
EFI_STATUS
(*issue_undi32_command) (
UINT64 cdb
);
typedef
VOID
(*ptr) (
VOID
);
/**
Install all the driver protocol
@param ImageHandle Driver image handle
@param SystemTable System services table
@retval EFI_SUCEESS Initialization routine has found UNDI hardware, loaded it's
ROM, and installed a notify event for the Network
Indentifier Interface Protocol successfully.
@retval Other Return value from HandleProtocol for DeviceIoProtocol or
LoadedImageProtocol
**/
EFI_STATUS
EFIAPI
InitializeSnpNiiDriver (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
;
#ifdef EFI_SIZE_REDUCTION_APPLIED
#define COMPONENT_NAME_CODE(code)
#define COMPONENT_NAME NULL
#else
#define COMPONENT_NAME_CODE(code) code
#define COMPONENT_NAME &gSimpleNetworkComponentName
#endif
#define SNP_MEM_PAGES(x) (((x) - 1) / 4096 + 1)
#endif /* _SNP_H */

View File

@@ -0,0 +1,191 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
start.c
Abstract:
Revision history:
2000-Feb-07 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to start the interface and changes the snp state!
@param snp pointer to snp driver structure
**/
EFI_STATUS
pxe_start (
SNP_DRIVER *snp
)
{
PXE_CPB_START_30 *cpb;
PXE_CPB_START_31 *cpb_31;
cpb = snp->cpb;
cpb_31 = snp->cpb;
//
// Initialize UNDI Start CDB for H/W UNDI
//
snp->cdb.OpCode = PXE_OPCODE_START;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Make changes to H/W UNDI Start CDB if this is
// a S/W UNDI.
//
if (snp->is_swundi) {
if (snp->IsOldUndi) {
snp->cdb.CPBsize = sizeof (PXE_CPB_START_30);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;
cpb->Delay = (UINT64)(UINTN) &snp_undi32_callback_delay_30;
cpb->Block = (UINT64)(UINTN) &snp_undi32_callback_block_30;
//
// Virtual == Physical. This can be set to zero.
//
cpb->Virt2Phys = (UINT64)(UINTN) &snp_undi32_callback_v2p_30;
cpb->Mem_IO = (UINT64)(UINTN) &snp_undi32_callback_memio_30;
} else {
snp->cdb.CPBsize = sizeof (PXE_CPB_START_31);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb_31;
cpb_31->Delay = (UINT64)(UINTN) &snp_undi32_callback_delay;
cpb_31->Block = (UINT64)(UINTN) &snp_undi32_callback_block;
//
// Virtual == Physical. This can be set to zero.
//
cpb_31->Virt2Phys = (UINT64)(UINTN) 0;
cpb_31->Mem_IO = (UINT64)(UINTN) &snp_undi32_callback_memio;
cpb_31->Map_Mem = (UINT64)(UINTN) &snp_undi32_callback_map;
cpb_31->UnMap_Mem = (UINT64)(UINTN) &snp_undi32_callback_unmap;
cpb_31->Sync_Mem = (UINT64)(UINTN) &snp_undi32_callback_sync;
cpb_31->Unique_ID = (UINT64)(UINTN) snp;
}
}
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.start() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
//
// UNDI could not be started. Return UNDI error.
//
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.start() %xh:%xh\n",
snp->cdb.StatCode,
snp->cdb.StatFlags)
);
return EFI_DEVICE_ERROR;
}
//
// Set simple network state to Started and return success.
//
snp->mode.State = EfiSimpleNetworkStarted;
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for starting the interface
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_start routine to actually do start undi interface
@param This context pointer
@retval EFI_INVALID_PARAMETER "This" is Null
@retval No SNP driver can be extracted from "This"
@retval EFI_ALREADY_STARTED The state of SNP is EfiSimpleNetworkStarted or
EfiSimpleNetworkInitialized
@retval EFI_DEVICE_ERROR The state of SNP is other than
EfiSimpleNetworkStarted,
EfiSimpleNetworkInitialized, and
EfiSimpleNetworkStopped
@retval EFI_SUCCESS UNDI interface is succesfully started
@retval Other Error occurs while calling pxe_start function.
**/
EFI_STATUS
EFIAPI
snp_undi32_start (
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
)
{
SNP_DRIVER *Snp;
EFI_STATUS Status;
UINTN Index;
EFI_TPL OldTpl;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
switch (Snp->mode.State) {
case EfiSimpleNetworkStopped:
break;
case EfiSimpleNetworkStarted:
case EfiSimpleNetworkInitialized:
Status = EFI_ALREADY_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
Status = pxe_start (Snp);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// clear the map_list in SNP structure
//
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
Snp->map_list[Index].virt = 0;
Snp->map_list[Index].map_cookie = 0;
}
Snp->mode.MCastFilterCount = 0;
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,237 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
station_address.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to read the MAC address of the NIC and updates the
mode structure with the address.
@param snp pointer to snp driver structure
**/
EFI_STATUS
pxe_get_stn_addr (
SNP_DRIVER *snp
)
{
PXE_DB_STATION_ADDRESS *db;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_STATION_ADDRESS;
snp->cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_READ;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = sizeof (PXE_DB_STATION_ADDRESS);
snp->cdb.DBaddr = (UINT64)(UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.station_addr() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
//
// Set new station address in SNP->Mode structure and return success.
//
CopyMem (
&(snp->mode.CurrentAddress),
&db->StationAddr,
snp->mode.HwAddressSize
);
CopyMem (
&snp->mode.BroadcastAddress,
&db->BroadcastAddr,
snp->mode.HwAddressSize
);
CopyMem (
&snp->mode.PermanentAddress,
&db->PermanentAddr,
snp->mode.HwAddressSize
);
return EFI_SUCCESS;
}
/**
this routine calls undi to set a new MAC address for the NIC,
@param snp pointer to snp driver structure
@param NewMacAddr pointer to a mac address to be set for the nic, if this is
NULL then this routine resets the mac address to the NIC's
original address.
**/
STATIC
EFI_STATUS
pxe_set_stn_addr (
SNP_DRIVER *snp,
EFI_MAC_ADDRESS *NewMacAddr
)
{
PXE_CPB_STATION_ADDRESS *cpb;
PXE_DB_STATION_ADDRESS *db;
cpb = snp->cpb;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_STATION_ADDRESS;
if (NewMacAddr == NULL) {
snp->cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_RESET;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
} else {
snp->cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_READ;
//
// even though the OPFLAGS are set to READ, supplying a new address
// in the CPB will make undi change the mac address to the new one.
//
CopyMem (&cpb->StationAddr, NewMacAddr, snp->mode.HwAddressSize);
snp->cdb.CPBsize = sizeof (PXE_CPB_STATION_ADDRESS);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;
}
snp->cdb.DBsize = sizeof (PXE_DB_STATION_ADDRESS);
snp->cdb.DBaddr = (UINT64)(UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.station_addr() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
//
// UNDI command failed. Return UNDI status to caller.
//
return EFI_DEVICE_ERROR;
}
//
// read the changed address and save it in SNP->Mode structure
//
pxe_get_stn_addr (snp);
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for changing the NIC's mac address.
This routine basically retrieves snp structure, checks the SNP state and
calls the above routines to actually do the work
@param this context pointer
@param NewMacAddr pointer to a mac address to be set for the nic, if this is
NULL then this routine resets the mac address to the NIC's
original address.
@param ResetFlag If true, the mac address will change to NIC's original
address
**/
EFI_STATUS
EFIAPI
snp_undi32_station_address (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN ResetFlag,
IN EFI_MAC_ADDRESS * NewMacAddr OPTIONAL
)
{
SNP_DRIVER *snp;
EFI_STATUS Status;
EFI_TPL OldTpl;
//
// Check for invalid parameter combinations.
//
if ((this == NULL) ||
(!ResetFlag && (NewMacAddr == NULL))) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
//
// Return error if the SNP is not initialized.
//
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
if (ResetFlag) {
Status = pxe_set_stn_addr (snp, NULL);
} else {
Status = pxe_set_stn_addr (snp, NewMacAddr);
}
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,201 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
statistics.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
**/
#include "Snp.h"
/**
This is the SNP interface routine for getting the NIC's statistics.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_ routine to actually do the
@param this context pointer
@param ResetFlag true to reset the NIC's statistics counters to zero.
@param StatTableSizePtr pointer to the statistics table size
@param StatTablePtr pointer to the statistics table
**/
EFI_STATUS
EFIAPI
snp_undi32_statistics (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN ResetFlag,
IN OUT UINTN *StatTableSizePtr OPTIONAL,
IN OUT EFI_NETWORK_STATISTICS * StatTablePtr OPTIONAL
)
{
SNP_DRIVER *snp;
PXE_DB_STATISTICS *db;
UINT64 *stp;
UINT64 mask;
UINTN size;
UINTN n;
EFI_TPL OldTpl;
EFI_STATUS Status;
//
// Get pointer to SNP driver instance for *this.
//
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
//
// Return error if the SNP is not initialized.
//
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
//
// if we are not resetting the counters, we have to have a valid stat table
// with >0 size. if no reset, no table and no size, return success.
//
if (!ResetFlag && StatTableSizePtr == NULL) {
Status = StatTablePtr ? EFI_INVALID_PARAMETER : EFI_SUCCESS;
goto ON_EXIT;
}
//
// Initialize UNDI Statistics CDB
//
snp->cdb.OpCode = PXE_OPCODE_STATISTICS;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
if (ResetFlag) {
snp->cdb.OpFlags = PXE_OPFLAGS_STATISTICS_RESET;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
db = snp->db;
} else {
snp->cdb.OpFlags = PXE_OPFLAGS_STATISTICS_READ;
snp->cdb.DBsize = sizeof (PXE_DB_STATISTICS);
snp->cdb.DBaddr = (UINT64)(UINTN) (db = snp->db);
}
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.statistics() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
break;
case PXE_STATCODE_UNSUPPORTED:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.statistics() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
Status = EFI_UNSUPPORTED;
goto ON_EXIT;
default:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.statistics() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
if (ResetFlag) {
Status = EFI_SUCCESS;
goto ON_EXIT;
}
if (StatTablePtr == NULL) {
*StatTableSizePtr = sizeof (EFI_NETWORK_STATISTICS);
Status = EFI_BUFFER_TOO_SMALL;
goto ON_EXIT;
}
//
// Convert the UNDI statistics information to SNP statistics
// information.
//
ZeroMem (StatTablePtr, *StatTableSizePtr);
stp = (UINT64 *) StatTablePtr;
size = 0;
for (n = 0, mask = 1; n < 64; n++, mask = LShiftU64 (mask, 1), stp++) {
//
// There must be room for a full UINT64. Partial
// numbers will not be stored.
//
if ((n + 1) * sizeof (UINT64) > *StatTableSizePtr) {
break;
}
if (db->Supported & mask) {
*stp = db->Data[n];
size = n + 1;
} else {
SetMem (stp, sizeof (UINT64), 0xFF);
}
}
//
// Compute size up to last supported statistic.
//
while (++n < 64) {
if (db->Supported & (mask = LShiftU64 (mask, 1))) {
size = n;
}
}
size *= sizeof (UINT64);
if (*StatTableSizePtr >= size) {
*StatTableSizePtr = size;
Status = EFI_SUCCESS;
} else {
*StatTableSizePtr = size;
Status = EFI_BUFFER_TOO_SMALL;
}
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,118 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
stop.c
Abstract:
Revision history:
2000-Feb-09 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to stop the interface and changes the snp state
@param snp pointer to snp driver structure
**/
EFI_STATUS
pxe_stop (
SNP_DRIVER *snp
)
{
snp->cdb.OpCode = PXE_OPCODE_STOP;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command
//
DEBUG ((EFI_D_NET, "\nsnp->undi.stop() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
DEBUG (
(EFI_D_WARN,
"\nsnp->undi.stop() %xh:%xh\n",
snp->cdb.StatCode,
snp->cdb.StatFlags)
);
return EFI_DEVICE_ERROR;
}
//
// Set simple network state to Started and return success.
//
snp->mode.State = EfiSimpleNetworkStopped;
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for stopping the interface.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_stop routine to actually stop the undi interface
@param this context pointer
**/
EFI_STATUS
EFIAPI
snp_undi32_stop (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
{
SNP_DRIVER *snp;
EFI_TPL OldTpl;
EFI_STATUS Status;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
switch (snp->mode.State) {
case EfiSimpleNetworkStarted:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
Status = pxe_stop (snp);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@@ -0,0 +1,399 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. 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.
Module name:
transmit.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
**/
#include "Snp.h"
/**
This routine calls undi to create the meadia header for the given data buffer.
@param snp pointer to SNP driver structure
@param MacHeaderPtr address where the media header will be filled in.
@param MacHeaderSize size of the memory at MacHeaderPtr
@param BufferPtr data buffer pointer
@param BufferLength Size of data in the BufferPtr
@param DestinationAddrPtr address of the destination mac address buffer
@param SourceAddrPtr address of the source mac address buffer
@param ProtocolPtr address of the protocol type
@retval EFI_SUCCESS if successfully completed the undi call
@retval Other error return from undi call.
**/
STATIC
EFI_STATUS
pxe_fillheader (
SNP_DRIVER *snp,
VOID *MacHeaderPtr,
UINTN MacHeaderSize,
VOID *BufferPtr,
UINTN BufferLength,
EFI_MAC_ADDRESS *DestinationAddrPtr,
EFI_MAC_ADDRESS *SourceAddrPtr,
UINT16 *ProtocolPtr
)
{
PXE_CPB_FILL_HEADER_FRAGMENTED *cpb;
EFI_STATUS Status;
struct s_v2p *pkt_v2p;
UINT64 TempData;
cpb = snp->cpb;
if (SourceAddrPtr) {
CopyMem (
(VOID *) cpb->SrcAddr,
(VOID *) SourceAddrPtr,
snp->mode.HwAddressSize
);
} else {
CopyMem (
(VOID *) cpb->SrcAddr,
(VOID *) &(snp->mode.CurrentAddress),
snp->mode.HwAddressSize
);
}
CopyMem (
(VOID *) cpb->DestAddr,
(VOID *) DestinationAddrPtr,
snp->mode.HwAddressSize
);
//
// we need to do the byte swapping
//
cpb->Protocol = (UINT16) PXE_SWAP_UINT16 (*ProtocolPtr);
cpb->PacketLen = (UINT32) (BufferLength);
cpb->MediaHeaderLen = (UINT16) MacHeaderSize;
cpb->FragCnt = 2;
cpb->reserved = 0;
cpb->FragDesc[0].FragAddr = (UINT64)(UINTN) MacHeaderPtr;
cpb->FragDesc[0].FragLen = (UINT32) MacHeaderSize;
cpb->FragDesc[1].FragAddr = (UINT64)(UINTN) BufferPtr;
cpb->FragDesc[1].FragLen = (UINT32) BufferLength;
cpb->FragDesc[0].reserved = cpb->FragDesc[1].reserved = 0;
if (snp->IsOldUndi) {
TempData = (UINT64) (UINTN) MacHeaderPtr;
if (TempData >= FOUR_GIGABYTES) {
cpb->FragDesc[0].FragAddr = (UINT64) (UINTN) snp->fill_hdr_buf;
cpb->FragDesc[0].FragLen = (UINT32) snp->init_info.MediaHeaderLen;
}
TempData = (UINT64) (UINTN) (BufferPtr);
if (TempData >= FOUR_GIGABYTES) {
//
// Let the device just read this buffer
//
Status = add_v2p (
&pkt_v2p,
EfiPciIoOperationBusMasterRead,
BufferPtr,
BufferLength
);
if (Status != EFI_SUCCESS) {
return Status;
}
//
// give the virtual address to UNDI and it will call back on Virt2Phys
// to get the mapped address, if it needs it
//
cpb->FragDesc[1].FragLen = (UINT32) pkt_v2p->bsize;
}
}
snp->cdb.OpCode = PXE_OPCODE_FILL_HEADER;
snp->cdb.OpFlags = PXE_OPFLAGS_FILL_HEADER_FRAGMENTED;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.CPBsize = sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.fill_header() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->IsOldUndi) {
TempData = (UINT64) (UINTN) (BufferPtr);
if (TempData >= FOUR_GIGABYTES) {
del_v2p (BufferPtr);
}
//
// if we used the global buffer for header, copy the contents
//
TempData = (UINT64) (UINTN) MacHeaderPtr;
if (TempData >= FOUR_GIGABYTES) {
CopyMem (
MacHeaderPtr,
snp->fill_hdr_buf,
snp->init_info.MediaHeaderLen
);
}
}
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
return EFI_SUCCESS;
case PXE_STATCODE_INVALID_PARAMETER:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.fill_header() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_INVALID_PARAMETER;
default:
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.fill_header() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return EFI_DEVICE_ERROR;
}
}
/**
This routine calls undi to transmit the given data buffer
@param snp pointer to SNP driver structure
@param BufferPtr data buffer pointer
@param BufferLength Size of data in the BufferPtr
@retval EFI_SUCCESS if successfully completed the undi call
@retval Other error return from undi call.
**/
STATIC
EFI_STATUS
pxe_transmit (
SNP_DRIVER *snp,
VOID *BufferPtr,
UINTN BufferLength
)
{
PXE_CPB_TRANSMIT *cpb;
EFI_STATUS Status;
struct s_v2p *v2p;
UINT64 TempData;
cpb = snp->cpb;
cpb->FrameAddr = (UINT64) (UINTN) BufferPtr;
cpb->DataLen = (UINT32) BufferLength;
TempData = (UINT64) (UINTN) BufferPtr;
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
//
// we need to create a mapping now and give it to the undi when it calls
// the Virt2Phys on this address.
// this is a transmit, just map it for the device to READ
//
Status = add_v2p (
&v2p,
EfiPciIoOperationBusMasterRead,
BufferPtr,
BufferLength
);
if (Status != EFI_SUCCESS) {
return Status;
}
cpb->DataLen = (UINT32) v2p->bsize;
}
cpb->MediaheaderLen = 0;
cpb->reserved = 0;
snp->cdb.OpFlags = PXE_OPFLAGS_TRANSMIT_WHOLE;
snp->cdb.CPBsize = sizeof (PXE_CPB_TRANSMIT);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;
snp->cdb.OpCode = PXE_OPCODE_TRANSMIT;
snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.transmit() "));
DEBUG ((EFI_D_NET, "\nsnp->cdb.OpCode == %x", snp->cdb.OpCode));
DEBUG ((EFI_D_NET, "\nsnp->cdb.CPBaddr == %X", snp->cdb.CPBaddr));
DEBUG ((EFI_D_NET, "\nsnp->cdb.DBaddr == %X", snp->cdb.DBaddr));
DEBUG ((EFI_D_NET, "\ncpb->FrameAddr == %X\n", cpb->FrameAddr));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
DEBUG ((EFI_D_NET, "\nexit snp->undi.transmit() "));
DEBUG ((EFI_D_NET, "\nsnp->cdb.StatCode == %r", snp->cdb.StatCode));
//
// we will unmap the buffers in get_status call, not here
//
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
return EFI_SUCCESS;
case PXE_STATCODE_QUEUE_FULL:
case PXE_STATCODE_BUSY:
Status = EFI_NOT_READY;
break;
default:
Status = EFI_DEVICE_ERROR;
}
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.transmit() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return Status;
}
/**
This is the snp interface routine for transmitting a packet. this routine
basically retrieves the snp structure, checks the snp state and calls
pxe_fill_header and pxe_transmit calls to complete the transmission.
@param this pointer to SNP driver context
@param MacHeaderSize size of the memory at MacHeaderPtr
@param BufferLength Size of data in the BufferPtr
@param BufferPtr data buffer pointer
@param SourceAddrPtr address of the source mac address buffer
@param DestinationAddrPtr address of the destination mac address buffer
@param ProtocolPtr address of the protocol type
@retval EFI_SUCCESS if successfully completed the undi call
@retval Other error return from undi call.
**/
EFI_STATUS
EFIAPI
snp_undi32_transmit (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINTN MacHeaderSize,
IN UINTN BufferLength,
IN VOID *BufferPtr,
IN EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL,
IN EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL,
IN UINT16 *ProtocolPtr OPTIONAL
)
{
SNP_DRIVER *snp;
EFI_STATUS Status;
EFI_TPL OldTpl;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
if (snp == NULL) {
return EFI_DEVICE_ERROR;
}
switch (snp->mode.State) {
case EfiSimpleNetworkInitialized:
break;
case EfiSimpleNetworkStopped:
Status = EFI_NOT_STARTED;
goto ON_EXIT;
default:
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
if (BufferPtr == NULL) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if (BufferLength < snp->mode.MediaHeaderSize) {
Status = EFI_BUFFER_TOO_SMALL;
goto ON_EXIT;
}
//
// if the MacHeaderSize is non-zero, we need to fill up the header and for that
// we need the destination address and the protocol
//
if (MacHeaderSize != 0) {
if (MacHeaderSize != snp->mode.MediaHeaderSize || DestinationAddrPtr == 0 || ProtocolPtr == 0) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
Status = pxe_fillheader (
snp,
BufferPtr,
MacHeaderSize,
(UINT8 *) BufferPtr + MacHeaderSize,
BufferLength - MacHeaderSize,
DestinationAddrPtr,
SourceAddrPtr,
ProtocolPtr
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
Status = pxe_transmit (snp, BufferPtr, BufferLength);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}