/** @file\r
Implementation of driver entry point and driver binding protocol.\r
\r
-Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials are licensed\r
-and made available under the terms and conditions of the BSD License which\r
-accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "Snp.h"\r
\r
-//\r
-// Module global variables needed to support undi 3.0 interface\r
-//\r
-EFI_PCI_IO_PROTOCOL *mPciIo;\r
-V2P *mV2p = NULL; // undi3.0 map_list head\r
-// End Global variables\r
-//\r
-\r
/**\r
One notified function to stop UNDI device when gBS->ExitBootServices() called.\r
\r
@param Event Pointer to this event\r
- @param Context Event hanlder private data\r
+ @param Context Event handler private data\r
\r
**/\r
VOID\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
IssueHwUndiCommand (\r
UINT64 Cdb\r
)\r
device to start.\r
\r
@retval EFI_SUCCESS This driver is added to ControllerHandle\r
- @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
+ @retval EFI_DEVICE_ERROR This driver could not be started due to a device error\r
@retval other This driver does not support this device\r
\r
**/\r
SNP_DRIVER *Snp;\r
VOID *Address;\r
EFI_HANDLE Handle;\r
- PXE_PCI_CONFIG_INFO ConfigInfo;\r
- PCI_TYPE00 *ConfigHeader;\r
- UINT32 *TempBar;\r
UINT8 BarIndex;\r
PXE_STATFLAGS InitStatFlags;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;\r
+ BOOLEAN FoundIoBar;\r
+ BOOLEAN FoundMemoryBar;\r
\r
DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));\r
\r
Status = gBS->OpenProtocol (\r
Handle,\r
&gEfiPciIoProtocolGuid,\r
- (VOID **) &mPciIo,\r
+ (VOID **) &PciIo,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
// OK, we like this UNDI, and we know snp is not already there on this handle\r
// Allocate and initialize a new simple network protocol structure.\r
//\r
- Status = mPciIo->AllocateBuffer (\r
- mPciIo,\r
- AllocateAnyPages,\r
- EfiBootServicesData,\r
- SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
- &Address,\r
- 0\r
- );\r
+ Status = PciIo->AllocateBuffer (\r
+ PciIo,\r
+ AllocateAnyPages,\r
+ EfiBootServicesData,\r
+ SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
+ &Address,\r
+ 0\r
+ );\r
\r
if (Status != EFI_SUCCESS) {\r
DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));\r
\r
ZeroMem (Snp, sizeof (SNP_DRIVER));\r
\r
- Snp->PciIo = mPciIo;\r
+ Snp->PciIo = PciIo;\r
Snp->Signature = SNP_DRIVER_SIGNATURE;\r
\r
EfiInitializeLock (&Snp->Lock, TPL_NOTIFY);\r
Snp->TxRxBufferSize = 0;\r
Snp->TxRxBuffer = NULL;\r
\r
- Snp->IfNum = Nii->IfNum;\r
+ Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASEMENT);\r
+ if (Snp->RecycledTxBuf == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error_DeleteSNP;\r
+ }\r
+ Snp->MaxRecycledTxBuf = SNP_TX_BUFFER_INCREASEMENT;\r
+ Snp->RecycledTxBufCount = 0;\r
+\r
+ if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) {\r
+ Snp->IfNum = Nii->IfNum;\r
+\r
+ } else {\r
+ Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF);\r
+ }\r
\r
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {\r
Snp->IsSwUndi = FALSE;\r
// -it is OK to allocate one global set of CPB, DB pair for each UNDI\r
// interface as EFI does not multi-task and so SNP will not be re-entered!\r
//\r
- Status = mPciIo->AllocateBuffer (\r
- mPciIo,\r
- AllocateAnyPages,\r
- EfiBootServicesData,\r
- SNP_MEM_PAGES (4096),\r
- &Address,\r
- 0\r
- );\r
+ Status = PciIo->AllocateBuffer (\r
+ PciIo,\r
+ AllocateAnyPages,\r
+ EfiBootServicesData,\r
+ SNP_MEM_PAGES (4096),\r
+ &Address,\r
+ 0\r
+ );\r
\r
if (Status != EFI_SUCCESS) {\r
DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));\r
Snp->Db = (VOID *) ((UINTN) Address + 2048);\r
\r
//\r
- // PxeStart call is going to give the callback functions to UNDI, these callback\r
- // functions use the BarIndex values from the snp structure, so these must be initialized\r
- // with default values before doing a PxeStart. The correct values can be obtained after\r
- // getting the config information from UNDI\r
+ // Find the correct BAR to do IO.\r
+ //\r
+ // Enumerate through the PCI BARs for the device to determine which one is\r
+ // the IO BAR. Save the index of the BAR into the adapter info structure.\r
+ // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped\r
//\r
Snp->MemoryBarIndex = 0;\r
Snp->IoBarIndex = 1;\r
+ FoundMemoryBar = FALSE;\r
+ FoundIoBar = FALSE;\r
+ for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {\r
+ Status = PciIo->GetBarAttributes (\r
+ PciIo,\r
+ BarIndex,\r
+ NULL,\r
+ (VOID**) &BarDesc\r
+ );\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ continue;\r
+ } else if (EFI_ERROR (Status)) {\r
+ goto Error_DeleteSNP;\r
+ }\r
+\r
+ if ((!FoundMemoryBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) {\r
+ Snp->MemoryBarIndex = BarIndex;\r
+ FoundMemoryBar = TRUE;\r
+ } else if ((!FoundIoBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) {\r
+ Snp->IoBarIndex = BarIndex;\r
+ FoundIoBar = TRUE;\r
+ }\r
+\r
+ FreePool (BarDesc);\r
+\r
+ if (FoundMemoryBar && FoundIoBar) {\r
+ break;\r
+ }\r
+ }\r
\r
- //\r
- // we need the undi init information many times in this snp code, just get it\r
- // once here and store it in the snp driver structure. to get Init Info\r
- // from UNDI we have to start undi first.\r
- //\r
Status = PxeStart (Snp);\r
\r
if (Status != EFI_SUCCESS) {\r
goto Error_DeleteSNP;\r
}\r
\r
- Snp->Cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO;\r
- Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
-\r
- Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
- Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
-\r
- Snp->Cdb.DBsize = (UINT16) sizeof (ConfigInfo);\r
- Snp->Cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo;\r
-\r
- Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
- Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
-\r
- Snp->Cdb.IFnum = Snp->IfNum;\r
- Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
-\r
- DEBUG ((EFI_D_NET, "\nSnp->undi.get_config_info() "));\r
-\r
- (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
-\r
- if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
- DEBUG ((EFI_D_NET, "\nSnp->undi.config_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
- PxeStop (Snp);\r
- goto Error_DeleteSNP;\r
- }\r
- //\r
- // Find the correct BAR to do IO.\r
- //\r
- //\r
- // Enumerate through the PCI BARs for the device to determine which one is\r
- // the IO BAR. Save the index of the BAR into the adapter info structure.\r
- // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped\r
- //\r
- ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0];\r
- TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0];\r
- for (BarIndex = 0; BarIndex <= 5; BarIndex++) {\r
- if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) {\r
- //\r
- // This is a 64-bit memory bar, skip this and the\r
- // next bar as well.\r
- //\r
- TempBar++;\r
- }\r
-\r
- if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) {\r
- Snp->IoBarIndex = BarIndex;\r
- break;\r
- }\r
-\r
- TempBar++;\r
- }\r
-\r
//\r
// Initialize simple network protocol mode structure\r
//\r
\r
switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {\r
case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:\r
- Snp->Mode.MediaPresentSupported = TRUE;\r
+ Snp->CableDetectSupported = TRUE;\r
break;\r
\r
case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:\r
default:\r
- Snp->Mode.MediaPresentSupported = FALSE;\r
+ Snp->CableDetectSupported = FALSE;\r
}\r
\r
switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) {\r
Snp->MediaStatusSupported = FALSE;\r
}\r
\r
+ if (Snp->CableDetectSupported || Snp->MediaStatusSupported) {\r
+ Snp->Mode.MediaPresentSupported = TRUE;\r
+ }\r
+\r
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {\r
Snp->Mode.MacAddressChangeable = TRUE;\r
} else {\r
return Status;\r
}\r
\r
- Status = mPciIo->FreeBuffer (\r
- mPciIo,\r
- SNP_MEM_PAGES (4096),\r
- Snp->Cpb\r
- );\r
+ PciIo->FreeBuffer (\r
+ PciIo,\r
+ SNP_MEM_PAGES (4096),\r
+ Snp->Cpb\r
+ );\r
\r
Error_DeleteSNP:\r
\r
- mPciIo->FreeBuffer (\r
- mPciIo,\r
- SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
- Snp\r
- );\r
+ if (Snp->RecycledTxBuf != NULL) {\r
+ FreePool (Snp->RecycledTxBuf);\r
+ }\r
+\r
+ PciIo->FreeBuffer (\r
+ PciIo,\r
+ SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
+ Snp\r
+ );\r
NiiError:\r
gBS->CloseProtocol (\r
Controller,\r
Controller\r
);\r
\r
+ //\r
+ // If we got here that means we are in error state.\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+\r
return Status;\r
}\r
\r
EFI_STATUS Status;\r
EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;\r
SNP_DRIVER *Snp;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
\r
//\r
// Get our context back.\r
PxeShutdown (Snp);\r
PxeStop (Snp);\r
\r
- mPciIo->FreeBuffer (\r
- mPciIo,\r
- SNP_MEM_PAGES (4096),\r
- Snp->Cpb\r
- );\r
+ FreePool (Snp->RecycledTxBuf);\r
\r
- mPciIo->FreeBuffer (\r
- mPciIo,\r
- SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
- Snp\r
- );\r
+ PciIo = Snp->PciIo;\r
+ PciIo->FreeBuffer (\r
+ PciIo,\r
+ SNP_MEM_PAGES (4096),\r
+ Snp->Cpb\r
+ );\r
+\r
+ PciIo->FreeBuffer (\r
+ PciIo,\r
+ SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
+ Snp\r
+ );\r
\r
return Status;\r
}\r
//\r
// Simple Network Protocol Driver Global Variables\r
//\r
-EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = {\r
+EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {\r
SimpleNetworkDriverSupported,\r
SimpleNetworkDriverStart,\r
SimpleNetworkDriverStop,\r
NULL\r
};\r
\r
-\r
-/**\r
- This routine maps the given CPU address to a Device address. It creates a\r
- an entry in the map list with the virtual and physical addresses and the\r
- un map cookie.\r
-\r
- @param V2p pointer to return a map list node pointer.\r
- @param Type the direction in which the data flows from the given\r
- virtual address device->cpu or cpu->device or both\r
- ways.\r
- @param VirtualAddress virtual address (or CPU address) to be mapped.\r
- @param BufferSize size of the buffer to be mapped.\r
-\r
- @retval EFI_SUCEESS routine has completed the mapping.\r
- @retval EFI_INVALID_PARAMETER invalid parameter.\r
- @retval EFI_OUT_OF_RESOURCES out of resource.\r
- @retval other error as indicated.\r
-\r
-**/\r
-EFI_STATUS\r
-AddV2P (\r
- IN OUT V2P **V2p,\r
- EFI_PCI_IO_PROTOCOL_OPERATION Type,\r
- VOID *VirtualAddress,\r
- UINTN BufferSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- if ((V2p == NULL) || (VirtualAddress == NULL) || (BufferSize == 0)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *V2p = AllocatePool (sizeof (V2P));\r
- if (*V2p == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Status = mPciIo->Map (\r
- mPciIo,\r
- Type,\r
- VirtualAddress,\r
- &BufferSize,\r
- &(*V2p)->PhysicalAddress,\r
- &(*V2p)->Unmap\r
- );\r
- if (Status != EFI_SUCCESS) {\r
- FreePool (*V2p);\r
- return Status;\r
- }\r
- (*V2p)->VirtualAddress = VirtualAddress;\r
- (*V2p)->BufferSize = BufferSize;\r
- (*V2p)->Next = mV2p;\r
- mV2p = *V2p;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- This routine searches the linked list of mapped address nodes (for undi3.0\r
- interface) to find the node that corresponds to the given virtual address and\r
- returns a pointer to that node.\r
-\r
- @param V2p pointer to return a map list node pointer.\r
- @param VirtualAddr virtual address (or CPU address) to be searched in\r
- the map list\r
-\r
- @retval EFI_SUCEESS A match was found.\r
- @retval Other A match cannot be found.\r
-\r
-**/\r
-EFI_STATUS\r
-FindV2p (\r
- V2P **V2p,\r
- VOID *VirtualAddr\r
- )\r
-{\r
- V2P *Ptr;\r
-\r
- if (V2p == NULL || VirtualAddr == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- for (Ptr = mV2p; Ptr != NULL; Ptr = Ptr->Next) {\r
- if (Ptr->VirtualAddress == VirtualAddr) {\r
- *V2p = Ptr;\r
- return EFI_SUCCESS;\r
- }\r
- }\r
-\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
-\r
-/**\r
- Unmap the given virtual address and free the memory allocated for the map list\r
- node corresponding to that address.\r
-\r
- @param VirtualAddress virtual address (or CPU address) to be unmapped.\r
-\r
- @retval EFI_SUCEESS Successfully unmapped.\r
- @retval Other Other errors as indicated.\r
-\r
-**/\r
-EFI_STATUS\r
-DelV2p (\r
- VOID *VirtualAddress\r
- )\r
-{\r
- V2P *Current;\r
- V2P *Next;\r
- EFI_STATUS Status;\r
-\r
- if (VirtualAddress == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (mV2p == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
- //\r
- // Is our node at the head of the list??\r
- //\r
- if ((Current = mV2p)->VirtualAddress == VirtualAddress) {\r
- mV2p = mV2p->Next;\r
-\r
- Status = mPciIo->Unmap (mPciIo, Current->Unmap);\r
-\r
- FreePool (Current);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
- }\r
- return Status;\r
- }\r
-\r
- for (; Current->Next != NULL; Current = Next) {\r
- if ((Next = Current->Next)->VirtualAddress == VirtualAddress) {\r
- Current->Next = Next->Next;\r
- Status = mPciIo->Unmap (mPciIo, Next->Unmap);\r
- FreePool (Next);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
- }\r
- return Status;\r
- }\r
- }\r
-\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
/**\r
The SNP driver entry point.\r
\r
return EfiLibInstallDriverBindingComponentName2 (\r
ImageHandle,\r
SystemTable,\r
- &mSimpleNetworkDriverBinding,\r
- NULL,\r
+ &gSimpleNetworkDriverBinding,\r
+ ImageHandle,\r
&gSimpleNetworkComponentName,\r
&gSimpleNetworkComponentName2\r
);\r