X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FSnpDxe%2FSnp.c;h=a23af05078bc8939c7ea42dc83f2d26ad9489888;hp=213b724e5f6da7691df0fc338e3d9ba955f4189d;hb=c0fd7f734e2d33e22215899b40a47b843129541d;hpb=894d038a8d0e99d456042e2b6d1554c4a406ea70 diff --git a/MdeModulePkg/Universal/Network/SnpDxe/Snp.c b/MdeModulePkg/Universal/Network/SnpDxe/Snp.c index 213b724e5f..a23af05078 100644 --- a/MdeModulePkg/Universal/Network/SnpDxe/Snp.c +++ b/MdeModulePkg/Universal/Network/SnpDxe/Snp.c @@ -1,32 +1,18 @@ /** @file Implementation of driver entry point and driver binding protocol. - -Copyright (c) 2004 - 2009, 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. +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Snp.h" -// -// Module global variables needed to support undi 3.0 interface -// -EFI_PCI_IO_PROTOCOL *mPciIo; -V2P *mV2p = NULL; // undi3.0 map_list head -// End Global variables -// - /** One notified function to stop UNDI device when gBS->ExitBootServices() called. @param Event Pointer to this event - @param Context Event hanlder private data + @param Context Event handler private data **/ VOID @@ -49,15 +35,16 @@ SnpNotifyExitBootServices ( /** Send command to UNDI. It does nothing currently. - + @param Cdb command to be sent to UNDI. - - @retval EFI_INVALID_PARAMETER The command is 0. - @retval EFI_UNSUPPORTED Default return status because it's not + + @retval EFI_INVALID_PARAMETER The command is 0. + @retval EFI_UNSUPPORTED Default return status because it's not supported currently. - + **/ EFI_STATUS +EFIAPI IssueHwUndiCommand ( UINT64 Cdb ) @@ -81,7 +68,7 @@ IssueHwUndiCommand ( @param Buffer Pointer to buffer. @param Length Length of buffer in bytes. - @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len + @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len is zero. **/ @@ -178,7 +165,7 @@ SimpleNetworkDriverSupported ( // // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required. // - if (NiiProtocol->Id & 0x0F) { + if ((NiiProtocol->Id & 0x0F) != 0) { DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n")); Status = EFI_UNSUPPORTED; goto Done; @@ -257,7 +244,7 @@ Done: device to start. @retval EFI_SUCCESS This driver is added to ControllerHandle - @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle + @retval EFI_DEVICE_ERROR This driver could not be started due to a device error @retval other This driver does not support this device **/ @@ -276,11 +263,12 @@ SimpleNetworkDriverStart ( SNP_DRIVER *Snp; VOID *Address; EFI_HANDLE Handle; - PXE_PCI_CONFIG_INFO ConfigInfo; - PCI_TYPE00 *ConfigHeader; - UINT32 *TempBar; UINT8 BarIndex; PXE_STATFLAGS InitStatFlags; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; + BOOLEAN FoundIoBar; + BOOLEAN FoundMemoryBar; DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() ")); @@ -310,7 +298,7 @@ SimpleNetworkDriverStart ( Status = gBS->OpenProtocol ( Handle, &gEfiPciIoProtocolGuid, - (VOID **) &mPciIo, + (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL @@ -366,14 +354,14 @@ SimpleNetworkDriverStart ( // OK, we like this UNDI, and we know snp is not already there on this handle // Allocate and initialize a new simple network protocol structure. // - Status = mPciIo->AllocateBuffer ( - mPciIo, - AllocateAnyPages, - EfiBootServicesData, - SNP_MEM_PAGES (sizeof (SNP_DRIVER)), - &Address, - 0 - ); + Status = PciIo->AllocateBuffer ( + PciIo, + AllocateAnyPages, + EfiBootServicesData, + SNP_MEM_PAGES (sizeof (SNP_DRIVER)), + &Address, + 0 + ); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n")); @@ -384,7 +372,7 @@ SimpleNetworkDriverStart ( ZeroMem (Snp, sizeof (SNP_DRIVER)); - Snp->PciIo = mPciIo; + Snp->PciIo = PciIo; Snp->Signature = SNP_DRIVER_SIGNATURE; EfiInitializeLock (&Snp->Lock, TPL_NOTIFY); @@ -410,7 +398,20 @@ SimpleNetworkDriverStart ( Snp->TxRxBufferSize = 0; Snp->TxRxBuffer = NULL; - Snp->IfNum = Nii->IfNum; + Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASEMENT); + if (Snp->RecycledTxBuf == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error_DeleteSNP; + } + Snp->MaxRecycledTxBuf = SNP_TX_BUFFER_INCREASEMENT; + Snp->RecycledTxBufCount = 0; + + if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) { + Snp->IfNum = Nii->IfNum; + + } else { + Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF); + } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) { Snp->IsSwUndi = FALSE; @@ -440,14 +441,14 @@ SimpleNetworkDriverStart ( // -it is OK to allocate one global set of CPB, DB pair for each UNDI // interface as EFI does not multi-task and so SNP will not be re-entered! // - Status = mPciIo->AllocateBuffer ( - mPciIo, - AllocateAnyPages, - EfiBootServicesData, - SNP_MEM_PAGES (4096), - &Address, - 0 - ); + Status = PciIo->AllocateBuffer ( + PciIo, + AllocateAnyPages, + EfiBootServicesData, + SNP_MEM_PAGES (4096), + &Address, + 0 + ); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n")); @@ -458,19 +459,44 @@ SimpleNetworkDriverStart ( Snp->Db = (VOID *) ((UINTN) Address + 2048); // - // PxeStart call is going to give the callback functions to UNDI, these callback - // functions use the BarIndex values from the snp structure, so these must be initialized - // with default values before doing a PxeStart. The correct values can be obtained after - // getting the config information from UNDI + // Find the correct BAR to do IO. + // + // Enumerate through the PCI BARs for the device to determine which one is + // the IO BAR. Save the index of the BAR into the adapter info structure. + // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped // Snp->MemoryBarIndex = 0; Snp->IoBarIndex = 1; + FoundMemoryBar = FALSE; + FoundIoBar = FALSE; + for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) { + Status = PciIo->GetBarAttributes ( + PciIo, + BarIndex, + NULL, + (VOID**) &BarDesc + ); + if (Status == EFI_UNSUPPORTED) { + continue; + } else if (EFI_ERROR (Status)) { + goto Error_DeleteSNP; + } + + if ((!FoundMemoryBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) { + Snp->MemoryBarIndex = BarIndex; + FoundMemoryBar = TRUE; + } else if ((!FoundIoBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) { + Snp->IoBarIndex = BarIndex; + FoundIoBar = TRUE; + } + + FreePool (BarDesc); + + if (FoundMemoryBar && FoundIoBar) { + break; + } + } - // - // we need the undi init information many times in this snp code, just get it - // once here and store it in the snp driver structure. to get Init Info - // from UNDI we have to start undi first. - // Status = PxeStart (Snp); if (Status != EFI_SUCCESS) { @@ -483,8 +509,8 @@ SimpleNetworkDriverStart ( Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED; Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED; - Snp->Cdb.DBsize = sizeof Snp->InitInfo; - Snp->Cdb.DBaddr = (UINT64)(UINTN) &Snp->InitInfo; + Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo); + Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo); Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE; Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; @@ -507,57 +533,6 @@ SimpleNetworkDriverStart ( goto Error_DeleteSNP; } - Snp->Cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO; - Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED; - - Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED; - Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED; - - Snp->Cdb.DBsize = sizeof ConfigInfo; - Snp->Cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo; - - Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE; - Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; - - Snp->Cdb.IFnum = Snp->IfNum; - Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; - - DEBUG ((EFI_D_NET, "\nSnp->undi.get_config_info() ")); - - (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb); - - if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) { - DEBUG ((EFI_D_NET, "\nSnp->undi.config_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode)); - PxeStop (Snp); - goto Error_DeleteSNP; - } - // - // Find the correct BAR to do IO. - // - // - // Enumerate through the PCI BARs for the device to determine which one is - // the IO BAR. Save the index of the BAR into the adapter info structure. - // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped - // - ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0]; - TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0]; - for (BarIndex = 0; BarIndex <= 5; BarIndex++) { - if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) { - // - // This is a 64-bit memory bar, skip this and the - // next bar as well. - // - TempBar++; - } - - if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) { - Snp->IoBarIndex = BarIndex; - break; - } - - TempBar++; - } - // // Initialize simple network protocol mode structure // @@ -573,12 +548,26 @@ SimpleNetworkDriverStart ( switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) { case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED: - Snp->Mode.MediaPresentSupported = TRUE; + Snp->CableDetectSupported = TRUE; break; case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED: default: - Snp->Mode.MediaPresentSupported = FALSE; + Snp->CableDetectSupported = FALSE; + } + + switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) { + case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED: + Snp->MediaStatusSupported = TRUE; + break; + + case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED: + default: + Snp->MediaStatusSupported = FALSE; + } + + if (Snp->CableDetectSupported || Snp->MediaStatusSupported) { + Snp->Mode.MediaPresentSupported = TRUE; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) { @@ -615,7 +604,7 @@ SimpleNetworkDriverStart ( } - if (Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) { + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; } @@ -687,19 +676,23 @@ SimpleNetworkDriverStart ( return Status; } - Status = mPciIo->FreeBuffer ( - mPciIo, - SNP_MEM_PAGES (4096), - Snp->Cpb - ); + PciIo->FreeBuffer ( + PciIo, + SNP_MEM_PAGES (4096), + Snp->Cpb + ); Error_DeleteSNP: - mPciIo->FreeBuffer ( - mPciIo, - SNP_MEM_PAGES (sizeof (SNP_DRIVER)), - Snp - ); + if (Snp->RecycledTxBuf != NULL) { + FreePool (Snp->RecycledTxBuf); + } + + PciIo->FreeBuffer ( + PciIo, + SNP_MEM_PAGES (sizeof (SNP_DRIVER)), + Snp + ); NiiError: gBS->CloseProtocol ( Controller, @@ -715,6 +708,13 @@ NiiError: Controller ); + // + // If we got here that means we are in error state. + // + if (!EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + return Status; } @@ -725,7 +725,7 @@ NiiError: restrictions for this service. DisconnectController() must follow these calling restrictions. If any other agent wishes to call Stop() it must also follow these calling restrictions. - + @param This Protocol instance pointer. @param ControllerHandle Handle of device to stop driver on @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of @@ -748,6 +748,7 @@ SimpleNetworkDriverStop ( EFI_STATUS Status; EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol; SNP_DRIVER *Snp; + EFI_PCI_IO_PROTOCOL *PciIo; // // Get our context back. @@ -799,17 +800,20 @@ SimpleNetworkDriverStop ( PxeShutdown (Snp); PxeStop (Snp); - mPciIo->FreeBuffer ( - mPciIo, - SNP_MEM_PAGES (4096), - Snp->Cpb - ); + FreePool (Snp->RecycledTxBuf); - mPciIo->FreeBuffer ( - mPciIo, - SNP_MEM_PAGES (sizeof (SNP_DRIVER)), - Snp - ); + PciIo = Snp->PciIo; + PciIo->FreeBuffer ( + PciIo, + SNP_MEM_PAGES (4096), + Snp->Cpb + ); + + PciIo->FreeBuffer ( + PciIo, + SNP_MEM_PAGES (sizeof (SNP_DRIVER)), + Snp + ); return Status; } @@ -817,7 +821,7 @@ SimpleNetworkDriverStop ( // // Simple Network Protocol Driver Global Variables // -EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = { +EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = { SimpleNetworkDriverSupported, SimpleNetworkDriverStart, SimpleNetworkDriverStop, @@ -826,159 +830,6 @@ EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = { NULL }; - -/** - This routine maps the given CPU address to a Device address. It creates a - an entry in the map list with the virtual and physical addresses and the - un map cookie. - - @param V2p pointer to return a map list node pointer. - @param Type the direction in which the data flows from the given - virtual address device->cpu or cpu->device or both - ways. - @param VirtualAddress virtual address (or CPU address) to be mapped. - @param BufferSize size of the buffer to be mapped. - - @retval EFI_SUCEESS routine has completed the mapping. - @retval EFI_INVALID_PARAMETER invalid parameter. - @retval EFI_OUT_OF_RESOURCES out of resource. - @retval other error as indicated. - -**/ -EFI_STATUS -AddV2P ( - IN OUT V2P **V2p, - EFI_PCI_IO_PROTOCOL_OPERATION Type, - VOID *VirtualAddress, - UINTN BufferSize - ) -{ - EFI_STATUS Status; - - if ((V2p == NULL) || (VirtualAddress == NULL) || (BufferSize == 0)) { - return EFI_INVALID_PARAMETER; - } - - *V2p = AllocatePool (sizeof (V2P)); - if (*V2p == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Status = mPciIo->Map ( - mPciIo, - Type, - VirtualAddress, - &BufferSize, - &(*V2p)->PhysicalAddress, - &(*V2p)->Unmap - ); - if (Status != EFI_SUCCESS) { - FreePool (*V2p); - return Status; - } - (*V2p)->VirtualAddress = VirtualAddress; - (*V2p)->BufferSize = BufferSize; - (*V2p)->Next = mV2p; - mV2p = *V2p; - - return EFI_SUCCESS; -} - - -/** - This routine searches the linked list of mapped address nodes (for undi3.0 - interface) to find the node that corresponds to the given virtual address and - returns a pointer to that node. - - @param V2p pointer to return a map list node pointer. - @param VirtualAddr virtual address (or CPU address) to be searched in - the map list - - @retval EFI_SUCEESS A match was found. - @retval Other A match cannot be found. - -**/ -EFI_STATUS -FindV2p ( - V2P **V2p, - VOID *VirtualAddr - ) -{ - V2P *Ptr; - - if (V2p == NULL || VirtualAddr == NULL) { - return EFI_INVALID_PARAMETER; - } - - for (Ptr = mV2p; Ptr != NULL; Ptr = Ptr->Next) { - if (Ptr->VirtualAddress == VirtualAddr) { - *V2p = Ptr; - return EFI_SUCCESS; - } - } - - return EFI_NOT_FOUND; -} - - -/** - Unmap the given virtual address and free the memory allocated for the map list - node corresponding to that address. - - @param VirtualAddress virtual address (or CPU address) to be unmapped. - - @retval EFI_SUCEESS Successfully unmapped. - @retval Other Other errors as indicated. - -**/ -EFI_STATUS -DelV2p ( - VOID *VirtualAddress - ) -{ - V2P *Current; - V2P *Next; - EFI_STATUS Status; - - if (VirtualAddress == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (mV2p == NULL) { - return EFI_NOT_FOUND; - } - // - // Is our node at the head of the list?? - // - if ((Current = mV2p)->VirtualAddress == VirtualAddress) { - mV2p = mV2p->Next; - - Status = mPciIo->Unmap (mPciIo, Current->Unmap); - - FreePool (Current); - - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status)); - } - return Status; - } - - for (; Current->Next != NULL; Current = Next) { - if ((Next = Current->Next)->VirtualAddress == VirtualAddress) { - Current->Next = Next->Next; - Status = mPciIo->Unmap (mPciIo, Next->Unmap); - FreePool (Next); - - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status)); - } - return Status; - } - } - - return EFI_NOT_FOUND; -} - /** The SNP driver entry point. @@ -1003,8 +854,8 @@ InitializeSnpNiiDriver ( return EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, - &mSimpleNetworkDriverBinding, - NULL, + &gSimpleNetworkDriverBinding, + ImageHandle, &gSimpleNetworkComponentName, &gSimpleNetworkComponentName2 );