https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
		
			
				
	
	
		
			176 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
|   Implementation of the SNP.GetStatus() function and its private helpers if
 | |
|   any.
 | |
| 
 | |
|   Copyright (C) 2013, Red Hat, Inc.
 | |
|   Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| 
 | |
| #include "VirtioNet.h"
 | |
| 
 | |
| /**
 | |
|   Reads the current interrupt status and recycled transmit buffer status from
 | |
|   a network interface.
 | |
| 
 | |
|   @param  This            The protocol instance pointer.
 | |
|   @param  InterruptStatus A pointer to the bit mask of the currently active
 | |
|                           interrupts If this is NULL, the interrupt status will
 | |
|                           not be read from the device. If this is not NULL, the
 | |
|                           interrupt status will be read from the device. When
 | |
|                           the  interrupt status is read, it will also be
 | |
|                           cleared. Clearing the transmit  interrupt does not
 | |
|                           empty the recycled transmit buffer array.
 | |
|   @param  TxBuf           Recycled transmit buffer address. The network
 | |
|                           interface will not transmit if its internal recycled
 | |
|                           transmit buffer array is full. Reading the transmit
 | |
|                           buffer does not clear the transmit interrupt. If this
 | |
|                           is NULL, then the transmit buffer status will not be
 | |
|                           read. If there are no transmit buffers to recycle and
 | |
|                           TxBuf is not NULL, * TxBuf will be set to NULL.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The status of the network interface was
 | |
|                                 retrieved.
 | |
|   @retval EFI_NOT_STARTED       The network interface has not been started.
 | |
|   @retval EFI_INVALID_PARAMETER One or more of the parameters has an
 | |
|                                 unsupported value.
 | |
|   @retval EFI_DEVICE_ERROR      The command could not be sent to the network
 | |
|                                 interface.
 | |
|   @retval EFI_UNSUPPORTED       This function is not supported by the network
 | |
|                                 interface.
 | |
| 
 | |
| **/
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| VirtioNetGetStatus (
 | |
|   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
 | |
|   OUT UINT32                     *InterruptStatus OPTIONAL,
 | |
|   OUT VOID                       **TxBuf OPTIONAL
 | |
|   )
 | |
| {
 | |
|   VNET_DEV             *Dev;
 | |
|   EFI_TPL              OldTpl;
 | |
|   EFI_STATUS           Status;
 | |
|   UINT16               RxCurUsed;
 | |
|   UINT16               TxCurUsed;
 | |
|   EFI_PHYSICAL_ADDRESS DeviceAddress;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Dev = VIRTIO_NET_FROM_SNP (This);
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
|   switch (Dev->Snm.State) {
 | |
|   case EfiSimpleNetworkStopped:
 | |
|     Status = EFI_NOT_STARTED;
 | |
|     goto Exit;
 | |
|   case EfiSimpleNetworkStarted:
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto Exit;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // update link status
 | |
|   //
 | |
|   if (Dev->Snm.MediaPresentSupported) {
 | |
|     UINT16 LinkStatus;
 | |
| 
 | |
|     Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Exit;
 | |
|     }
 | |
|     Dev->Snm.MediaPresent =
 | |
|       (BOOLEAN) ((LinkStatus & VIRTIO_NET_S_LINK_UP) != 0);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
 | |
|   //
 | |
|   MemoryFence ();
 | |
|   RxCurUsed = *Dev->RxRing.Used.Idx;
 | |
|   TxCurUsed = *Dev->TxRing.Used.Idx;
 | |
|   MemoryFence ();
 | |
| 
 | |
|   if (InterruptStatus != NULL) {
 | |
|     //
 | |
|     // report the receive interrupt if there is data available for reception,
 | |
|     // report the transmit interrupt if we have transmitted at least one buffer
 | |
|     //
 | |
|     *InterruptStatus = 0;
 | |
|     if (Dev->RxLastUsed != RxCurUsed) {
 | |
|       *InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
 | |
|     }
 | |
|     if (Dev->TxLastUsed != TxCurUsed) {
 | |
|       ASSERT (Dev->TxCurPending > 0);
 | |
|       *InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (TxBuf != NULL) {
 | |
|     if (Dev->TxLastUsed == TxCurUsed) {
 | |
|       *TxBuf = NULL;
 | |
|     }
 | |
|     else {
 | |
|       UINT16 UsedElemIdx;
 | |
|       UINT32 DescIdx;
 | |
| 
 | |
|       //
 | |
|       // fetch the first descriptor among those that the hypervisor reports
 | |
|       // completed
 | |
|       //
 | |
|       ASSERT (Dev->TxCurPending > 0);
 | |
|       ASSERT (Dev->TxCurPending <= Dev->TxMaxPending);
 | |
| 
 | |
|       UsedElemIdx = Dev->TxLastUsed++ % Dev->TxRing.QueueSize;
 | |
|       DescIdx = Dev->TxRing.Used.UsedElem[UsedElemIdx].Id;
 | |
|       ASSERT (DescIdx < (UINT32) (2 * Dev->TxMaxPending - 1));
 | |
| 
 | |
|       //
 | |
|       // get the device address that has been enqueued for the caller's
 | |
|       // transmit buffer
 | |
|       //
 | |
|       DeviceAddress = Dev->TxRing.Desc[DescIdx + 1].Addr;
 | |
| 
 | |
|       //
 | |
|       // now this descriptor can be used again to enqueue a transmit buffer
 | |
|       //
 | |
|       Dev->TxFreeStack[--Dev->TxCurPending] = (UINT16) DescIdx;
 | |
| 
 | |
|       //
 | |
|       // Unmap the device address and perform the reverse mapping to find the
 | |
|       // caller buffer address.
 | |
|       //
 | |
|       Status = VirtioNetUnmapTxBuf (
 | |
|                  Dev,
 | |
|                  TxBuf,
 | |
|                  DeviceAddress
 | |
|                  );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         //
 | |
|         // VirtioNetUnmapTxBuf should never fail, if we have reached here
 | |
|         // that means our internal state has been corrupted
 | |
|         //
 | |
|         ASSERT (FALSE);
 | |
|         Status = EFI_DEVICE_ERROR;
 | |
|         goto Exit;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
| Exit:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return Status;
 | |
| }
 |