|
@@ -0,0 +1,1581 @@
|
|
|
+/** @file
|
|
|
+ Provides the Simple Network functions.
|
|
|
+
|
|
|
+ Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.
|
|
|
+ Copyright (c) 2020, ARM Limited. All rights reserved.
|
|
|
+
|
|
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
+
|
|
|
+**/
|
|
|
+
|
|
|
+#include "Ax88772.h"
|
|
|
+
|
|
|
+/**
|
|
|
+ This function updates the filtering on the receiver.
|
|
|
+
|
|
|
+ This support routine calls ::Ax88772MacAddressSet to update
|
|
|
+ the MAC address. This routine then rebuilds the multicast
|
|
|
+ hash by calling ::Ax88772MulticastClear and ::Ax88772MulticastSet.
|
|
|
+ Finally this routine enables the receiver by calling
|
|
|
+ ::Ax88772RxControl.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Simple network mode pointer
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+ReceiveFilterUpdate (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ NIC_DEVICE *NicDevice;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ UINT32 Index;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Set the MAC address
|
|
|
+ //
|
|
|
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ //
|
|
|
+ // Clear the multicast hash table
|
|
|
+ //
|
|
|
+ Ax88772MulticastClear (NicDevice);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Load the multicast hash table
|
|
|
+ //
|
|
|
+ if ((Mode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
|
|
|
+ for (Index = 0; Index < Mode->MCastFilterCount; Index++) {
|
|
|
+ //
|
|
|
+ // Enable the next multicast address
|
|
|
+ //
|
|
|
+ Ax88772MulticastSet (NicDevice,
|
|
|
+ &Mode->MCastFilter[Index].Addr[0]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = Ax88772RxControl (NicDevice, Mode->ReceiveFilterSetting);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Return the operation status
|
|
|
+ //
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ This function updates the SNP driver status.
|
|
|
+
|
|
|
+ This function gets the current interrupt and recycled transmit
|
|
|
+ buffer status from the network interface. The interrupt status
|
|
|
+ and the media status are returned as a bit mask in InterruptStatus.
|
|
|
+ If InterruptStatus is NULL, the interrupt status will not be read.
|
|
|
+ Upon successful return of the media status, the MediaPresent field
|
|
|
+ of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change
|
|
|
+ of media status. If TxBuf is not NULL, a recycled transmit buffer
|
|
|
+ address will be retrived. If a recycled transmit buffer address
|
|
|
+ is returned in TxBuf, then the buffer has been successfully
|
|
|
+ transmitted, and the status for that buffer is cleared.
|
|
|
+
|
|
|
+ This function calls ::Ax88772Rx to update the media status and
|
|
|
+ queue any receive packets.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [in] InterruptStatus A pointer to the bit mask of the current 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 teh 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 [out] 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 not transmit buffers to recycle
|
|
|
+ and TxBuf is not NULL, *TxBuf will be set to NULL.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+
|
|
|
+**/
|
|
|
+
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_GetStatus (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
|
|
|
+ OUT UINT32 *InterruptStatus,
|
|
|
+ OUT VOID **TxBuf
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ NIC_DEVICE *NicDevice = NULL;
|
|
|
+ EFI_STATUS Status = EFI_SUCCESS;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ //
|
|
|
+ // Verify the parameters
|
|
|
+ //
|
|
|
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
|
|
|
+ //
|
|
|
+ // Return the transmit buffer
|
|
|
+ //
|
|
|
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
|
|
|
+
|
|
|
+ if ((TxBuf != NULL) && (NicDevice->TxBuffer != NULL)) {
|
|
|
+ *TxBuf = NicDevice->TxBuffer;
|
|
|
+ NicDevice->TxBuffer = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ if (EfiSimpleNetworkInitialized == Mode->State) {
|
|
|
+ if ((TxBuf == NULL) && (InterruptStatus == NULL)) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+
|
|
|
+#if REPORTLINK
|
|
|
+#else
|
|
|
+ if (!NicDevice->LinkUp || !NicDevice->Complete) {
|
|
|
+#endif
|
|
|
+ Status = Ax88772NegotiateLinkComplete (NicDevice,
|
|
|
+ &NicDevice->PollCount,
|
|
|
+ &NicDevice->Complete,
|
|
|
+ &NicDevice->LinkUp,
|
|
|
+ &NicDevice->LinkSpeed100Mbps,
|
|
|
+ &NicDevice->FullDuplex);
|
|
|
+
|
|
|
+ if (EFI_ERROR(Status))
|
|
|
+ goto EXIT;
|
|
|
+#if REPORTLINK
|
|
|
+ if (NicDevice->LinkUp && NicDevice->Complete) {
|
|
|
+ Mode->MediaPresent = TRUE;
|
|
|
+ Status = ReceiveFilterUpdate (SimpleNetwork);
|
|
|
+ } else {
|
|
|
+ Mode->MediaPresent = FALSE;
|
|
|
+ }
|
|
|
+#else
|
|
|
+ if (NicDevice->LinkUp && NicDevice->Complete) {
|
|
|
+ Mode->MediaPresent = TRUE;
|
|
|
+ Mode->MediaPresentSupported = FALSE;
|
|
|
+ Status = ReceiveFilterUpdate (SimpleNetwork);
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ } else {
|
|
|
+ if (EfiSimpleNetworkStarted == Mode->State) {
|
|
|
+ Status = EFI_DEVICE_ERROR;
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED ;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+ if (InterruptStatus != NULL) {
|
|
|
+ *InterruptStatus = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+EXIT:
|
|
|
+ gBS->RestoreTPL(TplPrevious) ;
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ This function performs read and write operations on the NVRAM device
|
|
|
+ attached to a network interface.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [in] ReadWrite TRUE for read operations, FALSE for write operations.
|
|
|
+ @param [in] Offset Byte offset in the NVRAM device at which to start the
|
|
|
+ read or write operation. This must be a multiple of
|
|
|
+ NvRamAccessSize and less than NvRamSize.
|
|
|
+ @param [in] BufferSize The number of bytes to read or write from the NVRAM device.
|
|
|
+ This must also be a multiple of NvramAccessSize.
|
|
|
+ @param [in, out] Buffer A pointer to the data buffer.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_NvData (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
|
|
|
+ IN BOOLEAN ReadWrite,
|
|
|
+ IN UINTN Offset,
|
|
|
+ IN UINTN BufferSize,
|
|
|
+ IN OUT VOID *Buffer
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ NIC_DEVICE *NicDevice;
|
|
|
+ UINTN Index;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ if ((SimpleNetwork == NULL) || (SimpleNetwork->Mode == NULL)) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+
|
|
|
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+
|
|
|
+ if (EfiSimpleNetworkInitialized != Mode->State) {
|
|
|
+ Status = EFI_NOT_STARTED;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Offset != 0) {
|
|
|
+ if (((Offset % Mode->NvRamAccessSize) != 0) ||
|
|
|
+ (Offset >= Mode->NvRamSize)) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //
|
|
|
+ // Offset must be a multiple of NvRamAccessSize and less than NvRamSize.
|
|
|
+ //
|
|
|
+ if ((BufferSize % Mode->NvRamAccessSize) != 0) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (BufferSize + Offset > Mode->NvRamSize) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Buffer == NULL) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // ReadWrite: TRUE FOR READ FALSE FOR WRITE
|
|
|
+ //
|
|
|
+ if (ReadWrite) {
|
|
|
+ for (Index = 0; Index < BufferSize / 2; Index++) {
|
|
|
+ Status = Ax88772SromRead (NicDevice,
|
|
|
+ (UINT32)(Offset/2 + Index),
|
|
|
+ (((UINT16*)Buffer) + Index));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = Ax88772EnableSromWrite(NicDevice);
|
|
|
+ if (EFI_ERROR(Status))
|
|
|
+ goto EXIT;
|
|
|
+
|
|
|
+ for (Index = 0; Index < BufferSize / 2; Index++) {
|
|
|
+ Status = Ax88772SromWrite (NicDevice,
|
|
|
+ (UINT32)(Offset/2 + Index),
|
|
|
+ (((UINT16*)Buffer) + Index));
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = Ax88772DisableSromWrite(NicDevice);
|
|
|
+
|
|
|
+ if (BufferSize == 272)
|
|
|
+ Status = Ax88772ReloadSrom(NicDevice);
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Return the operation status
|
|
|
+ //
|
|
|
+EXIT:
|
|
|
+ gBS->RestoreTPL (TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Resets the network adapter and allocates the transmit and receive buffers
|
|
|
+ required by the network interface; optionally, also requests allocation of
|
|
|
+ additional transmit and receive buffers. This routine must be called before
|
|
|
+ any other routine in the Simple Network protocol is called.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer allocation
|
|
|
+ @param [in] ExtraTxBufferSize Size in bytes to add to the transmit buffer allocation
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and receive buffers
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_Initialize (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * SimpleNetwork,
|
|
|
+ IN UINTN ExtraRxBufferSize,
|
|
|
+ IN UINTN ExtraTxBufferSize
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ UINT32 TmpState;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+ NIC_DEVICE *NicDevice;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Verify the parameters
|
|
|
+ //
|
|
|
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
|
|
|
+ //
|
|
|
+ // Determine if the interface is already started
|
|
|
+ //
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ if (EfiSimpleNetworkStarted == Mode->State) {
|
|
|
+ if ((0 == ExtraRxBufferSize) && (0 == ExtraTxBufferSize)) {
|
|
|
+ //
|
|
|
+ // Start the adapter
|
|
|
+ //
|
|
|
+ TmpState = Mode->State;
|
|
|
+ Mode->State = EfiSimpleNetworkInitialized;
|
|
|
+ Status = SN_Reset (SimpleNetwork, FALSE);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ //
|
|
|
+ // Update the network state
|
|
|
+ //
|
|
|
+ Mode->State = TmpState; // EfiSimpleNetworkInitialized;
|
|
|
+ } else {
|
|
|
+ Mode->MediaPresentSupported = TRUE;
|
|
|
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
|
|
|
+ Mode->MediaPresent = Ax88772GetLinkStatus (NicDevice);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_UNSUPPORTED;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Return the operation status
|
|
|
+ //
|
|
|
+ gBS->RestoreTPL (TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ This function converts a multicast IP address to a multicast HW MAC address
|
|
|
+ for all packet transactions.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [in] IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC2460].
|
|
|
+ Set to FALSE if the multicast IP address is IPv4 [RFC 791].
|
|
|
+ @param [in] IP The multicast IP address that is to be converted to a
|
|
|
+ multicast HW MAC address.
|
|
|
+ @param [in] MAC The multicast HW MAC address that is to be generated from IP.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_MCastIPtoMAC (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
|
|
|
+ IN BOOLEAN IPv6,
|
|
|
+ IN EFI_IP_ADDRESS *IP,
|
|
|
+ IN EFI_MAC_ADDRESS *MAC
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
|
|
|
+ //
|
|
|
+ // The interface must be running
|
|
|
+ //
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ if (EfiSimpleNetworkInitialized == Mode->State) {
|
|
|
+ if (IP == NULL || MAC == NULL) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+ if (IPv6) {
|
|
|
+ Status = EFI_UNSUPPORTED;
|
|
|
+ goto EXIT;
|
|
|
+ } else {
|
|
|
+ //
|
|
|
+ // check if the ip given is a mcast IP
|
|
|
+ //
|
|
|
+ if ((IP->v4.Addr[0] & 0xF0) != 0xE0) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ } else {
|
|
|
+ MAC->Addr[0] = 0x01;
|
|
|
+ MAC->Addr[1] = 0x00;
|
|
|
+ MAC->Addr[2] = 0x5e;
|
|
|
+ MAC->Addr[3] = (UINT8) (IP->v4.Addr[1] & 0x7f);
|
|
|
+ MAC->Addr[4] = (UINT8) IP->v4.Addr[2];
|
|
|
+ MAC->Addr[5] = (UINT8) IP->v4.Addr[3];
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (EfiSimpleNetworkStarted == Mode->State) {
|
|
|
+ Status = EFI_DEVICE_ERROR;
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED ;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+EXIT:
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Attempt to receive a packet from the network adapter.
|
|
|
+
|
|
|
+ This function retrieves one packet from the receive queue of the network
|
|
|
+ interface. If there are no packets on the receive queue, then EFI_NOT_READY
|
|
|
+ will be returned. If there is a packet on the receive queue, and the size
|
|
|
+ of the packet is smaller than BufferSize, then the contents of the packet
|
|
|
+ will be placed in Buffer, and BufferSize will be udpated with the actual
|
|
|
+ size of the packet. In addition, if SrcAddr, DestAddr, and Protocol are
|
|
|
+ not NULL, then these values will be extracted from the media header and
|
|
|
+ returned. If BufferSize is smaller than the received packet, then the
|
|
|
+ size of the receive packet will be placed in BufferSize and
|
|
|
+ EFI_BUFFER_TOO_SMALL will be returned.
|
|
|
+
|
|
|
+ This routine calls ::Ax88179Rx to update the media status and
|
|
|
+ empty the network adapter of receive packets.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [out] HeaderSize The size, in bytes, of the media header to be filled in by
|
|
|
+ the Transmit() function. If HeaderSize is non-zero, then
|
|
|
+ it must be equal to SimpleNetwork->Mode->MediaHeaderSize
|
|
|
+ and DestAddr and Protocol parameters must not be NULL.
|
|
|
+ @param [out] BufferSize The size, in bytes, of the entire packet (media header and
|
|
|
+ data) to be transmitted through the network interface.
|
|
|
+ @param [out] Buffer A pointer to the packet (media header followed by data) to
|
|
|
+ to be transmitted. This parameter can not be NULL. If
|
|
|
+ HeaderSize is zero, then the media header is Buffer must
|
|
|
+ already be filled in by the caller. If HeaderSize is nonzero,
|
|
|
+ then the media header will be filled in by the Transmit()
|
|
|
+ function.
|
|
|
+ @param [out] SrcAddr The source HW MAC address. If HeaderSize is zero, then
|
|
|
+ this parameter is ignored. If HeaderSize is nonzero and
|
|
|
+ SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
|
|
|
+ is used for the source HW MAC address.
|
|
|
+ @param [out] DestAddr The destination HW MAC address. If HeaderSize is zero, then
|
|
|
+ this parameter is ignored.
|
|
|
+ @param [out] Protocol The type of header to build. If HeaderSize is zero, then
|
|
|
+ this parameter is ignored.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_NOT_READY No packets have been received on the network interface.
|
|
|
+ @retval EFI_BUFFER_TOO_SMALL The packet is larger than BufferSize bytes.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_Receive (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
|
|
|
+ OUT UINTN *HeaderSize,
|
|
|
+ OUT UINTN *BufferSize,
|
|
|
+ OUT VOID *Buffer,
|
|
|
+ OUT EFI_MAC_ADDRESS *SrcAddr,
|
|
|
+ OUT EFI_MAC_ADDRESS *DestAddr,
|
|
|
+ OUT UINT16 *Protocol
|
|
|
+ )
|
|
|
+{
|
|
|
+ ETHERNET_HEADER *Header;
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ NIC_DEVICE *NicDevice = NULL;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+ UINT16 Type;
|
|
|
+ UINT16 CurrentPktLen;
|
|
|
+
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
+ //
|
|
|
+ // Verify the parameters
|
|
|
+ //
|
|
|
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
|
|
|
+ //
|
|
|
+ // The interface must be running
|
|
|
+ //
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ if (EfiSimpleNetworkInitialized == Mode->State) {
|
|
|
+ if ((BufferSize == NULL) || (Buffer == NULL)) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ gBS->RestoreTPL (TplPrevious);
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Update the link status
|
|
|
+ //
|
|
|
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
|
|
|
+
|
|
|
+ if (NicDevice->LinkUp && NicDevice->Complete) {
|
|
|
+ if ((HeaderSize != NULL) && (*HeaderSize == 7720)) {
|
|
|
+ NicDevice->Grub_f = TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((NicDevice->Grub_f) && (*HeaderSize != 7720)) {
|
|
|
+ gBS->RestoreTPL (TplPrevious);
|
|
|
+ return EFI_NOT_READY;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Attempt to receive a packet
|
|
|
+ //
|
|
|
+ if (0 == NicDevice->PktCnt) {
|
|
|
+ Status = Ax88772BulkIn(NicDevice);
|
|
|
+ if (EFI_ERROR(Status)) {
|
|
|
+ goto no_pkt;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ CurrentPktLen = *((UINT16*) (NicDevice->CurPktHdrOff));
|
|
|
+ CurrentPktLen &= 0x7ff;
|
|
|
+
|
|
|
+ if ((60 <= CurrentPktLen) &&
|
|
|
+ (CurrentPktLen - 14 <= MAX_ETHERNET_PKT_SIZE)) {
|
|
|
+ if (*BufferSize < (UINTN)CurrentPktLen) {
|
|
|
+ gBS->RestoreTPL (TplPrevious);
|
|
|
+ return EFI_BUFFER_TOO_SMALL;
|
|
|
+ }
|
|
|
+
|
|
|
+ *BufferSize = CurrentPktLen;
|
|
|
+ CopyMem (Buffer, NicDevice->CurPktOff, CurrentPktLen);
|
|
|
+ Header = (ETHERNET_HEADER *) NicDevice->CurPktOff;
|
|
|
+
|
|
|
+ if ((HeaderSize != NULL) && (*HeaderSize != 7720)) {
|
|
|
+ *HeaderSize = sizeof (*Header);
|
|
|
+ }
|
|
|
+ if (DestAddr != NULL) {
|
|
|
+ CopyMem (DestAddr, &Header->DestAddr, PXE_HWADDR_LEN_ETHER);
|
|
|
+ }
|
|
|
+ if (SrcAddr != NULL) {
|
|
|
+ CopyMem (SrcAddr, &Header->SrcAddr, PXE_HWADDR_LEN_ETHER);
|
|
|
+ }
|
|
|
+ if (Protocol != NULL) {
|
|
|
+ Type = Header->Type;
|
|
|
+ Type = (UINT16)((Type >> 8) | (Type << 8));
|
|
|
+ *Protocol = Type;
|
|
|
+ }
|
|
|
+ NicDevice->PktCnt--;
|
|
|
+ NicDevice->CurPktHdrOff += (CurrentPktLen + 4 + 1) & 0xfffe;
|
|
|
+ NicDevice->CurPktOff = NicDevice->CurPktHdrOff + 4;
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ } else {
|
|
|
+ NicDevice->PktCnt = 0;
|
|
|
+ Status = EFI_DEVICE_ERROR;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //
|
|
|
+ // Link no up
|
|
|
+ //
|
|
|
+ Status = EFI_NOT_READY;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (EfiSimpleNetworkStarted == Mode->State) {
|
|
|
+ Status = EFI_DEVICE_ERROR;
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Return the operation status
|
|
|
+ //
|
|
|
+no_pkt:
|
|
|
+ gBS->RestoreTPL (TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ This function is used to enable and disable the hardware and software receive
|
|
|
+ filters for the underlying network device.
|
|
|
+
|
|
|
+ The receive filter change is broken down into three steps:
|
|
|
+
|
|
|
+ 1. The filter mask bits that are set (ON) in the Enable parameter
|
|
|
+ are added to the current receive filter settings.
|
|
|
+
|
|
|
+ 2. The filter mask bits that are set (ON) in the Disable parameter
|
|
|
+ are subtracted from the updated receive filter settins.
|
|
|
+
|
|
|
+ 3. If the resulting filter settigns is not supported by the hardware
|
|
|
+ a more liberal setting is selected.
|
|
|
+
|
|
|
+ If the same bits are set in the Enable and Disable parameters, then the bits
|
|
|
+ in the Disable parameter takes precedence.
|
|
|
+
|
|
|
+ If the ResetMCastFilter parameter is TRUE, then the multicast address list
|
|
|
+ filter is disabled (irregardless of what other multicast bits are set in
|
|
|
+ the enable and Disable parameters). The SNP->Mode->MCastFilterCount field
|
|
|
+ is set to zero. The SNP->Mode->MCastFilter contents are undefined.
|
|
|
+
|
|
|
+ After enableing or disabling receive filter settings, software should
|
|
|
+ verify the new settings by checking the SNP->Mode->ReceeiveFilterSettings,
|
|
|
+ SNP->Mode->MCastFilterCount and SNP->Mode->MCastFilter fields.
|
|
|
+
|
|
|
+ Note: Some network drivers and/or devices will automatically promote
|
|
|
+ receive filter settings if the requested setting can not be honored.
|
|
|
+ For example, if a request for four multicast addresses is made and
|
|
|
+ the underlying hardware only supports two multicast addresses the
|
|
|
+ driver might set the promiscuous or promiscuous multicast receive filters
|
|
|
+ instead. The receiving software is responsible for discarding any extra
|
|
|
+ packets that get through the hardware receive filters.
|
|
|
+
|
|
|
+ If ResetMCastFilter is TRUE, then the multicast receive filter list
|
|
|
+ on the network interface will be reset to the default multicast receive
|
|
|
+ filter list. If ResetMCastFilter is FALSE, and this network interface
|
|
|
+ allows the multicast receive filter list to be modified, then the
|
|
|
+ MCastFilterCnt and MCastFilter are used to update the current multicast
|
|
|
+ receive filter list. The modified receive filter list settings can be
|
|
|
+ found in the MCastFilter field of EFI_SIMPLE_NETWORK_MODE.
|
|
|
+
|
|
|
+ This routine calls ::ReceiveFilterUpdate to update the receive
|
|
|
+ state in the network adapter.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [in] Enable A bit mask of receive filters to enable on the network interface.
|
|
|
+ @param [in] Disable A bit mask of receive filters to disable on the network interface.
|
|
|
+ For backward compatibility with EFI 1.1 platforms, the
|
|
|
+ EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit must be set
|
|
|
+ when the ResetMCastFilter parameter is TRUE.
|
|
|
+ @param [in] ResetMCastFilter Set to TRUE to reset the contents of the multicast receive
|
|
|
+ filters on the network interface to their default values.
|
|
|
+ @param [in] MCastFilterCnt Number of multicast HW MAC address in the new MCastFilter list.
|
|
|
+ This value must be less than or equal to the MaxMCastFilterCnt
|
|
|
+ field of EFI_SIMPLE_NETWORK_MODE. This field is optional if
|
|
|
+ ResetMCastFilter is TRUE.
|
|
|
+ @param [in] MCastFilter A pointer to a list of new multicast receive filter HW MAC
|
|
|
+ addresses. This list will replace any existing multicast
|
|
|
+ HW MAC address list. This field is optional if ResetMCastFilter
|
|
|
+ is TRUE.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_ReceiveFilters (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
|
|
|
+ IN UINT32 Enable,
|
|
|
+ IN UINT32 Disable,
|
|
|
+ IN BOOLEAN ResetMCastFilter,
|
|
|
+ IN UINTN MCastFilterCnt,
|
|
|
+ IN EFI_MAC_ADDRESS *MCastFilter
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ EFI_STATUS Status = EFI_SUCCESS;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+ UINTN Index;
|
|
|
+ UINT8 Temp;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+
|
|
|
+ if (SimpleNetwork == NULL) {
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (Mode->State) {
|
|
|
+ case EfiSimpleNetworkInitialized:
|
|
|
+ break;
|
|
|
+
|
|
|
+ case EfiSimpleNetworkStopped:
|
|
|
+ Status = EFI_NOT_STARTED;
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+
|
|
|
+ default:
|
|
|
+ Status = EFI_DEVICE_ERROR;
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // check if we are asked to enable or disable something that the SNP
|
|
|
+ // does not even support!
|
|
|
+ //
|
|
|
+ if (((Enable &~Mode->ReceiveFilterMask) != 0) ||
|
|
|
+ ((Disable &~Mode->ReceiveFilterMask) != 0)) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ResetMCastFilter) {
|
|
|
+ if ((0 == (Mode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST)) &&
|
|
|
+ Enable == 0 &&
|
|
|
+ Disable == 2) {
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ }
|
|
|
+ Mode->MCastFilterCount = 0;
|
|
|
+ SetMem (&Mode->MCastFilter[0],
|
|
|
+ sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT,
|
|
|
+ 0);
|
|
|
+ } else {
|
|
|
+ if (MCastFilterCnt != 0) {
|
|
|
+ EFI_MAC_ADDRESS * MulticastAddress;
|
|
|
+ MulticastAddress = MCastFilter;
|
|
|
+
|
|
|
+ if ((MCastFilterCnt > Mode->MaxMCastFilterCount) ||
|
|
|
+ (MCastFilter == NULL)) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Index = 0 ; Index < MCastFilterCnt ; Index++) {
|
|
|
+ Temp = MulticastAddress->Addr[0];
|
|
|
+ if ((Temp & 0x01) != 0x01) {
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+ MulticastAddress++;
|
|
|
+ }
|
|
|
+
|
|
|
+ Mode->MCastFilterCount = (UINT32)MCastFilterCnt;
|
|
|
+ CopyMem (&Mode->MCastFilter[0],
|
|
|
+ MCastFilter,
|
|
|
+ MCastFilterCnt * sizeof (EFI_MAC_ADDRESS));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Enable == 0 && Disable == 0 && !ResetMCastFilter && MCastFilterCnt == 0) {
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastFilterCnt == 0) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ Mode->ReceiveFilterSetting |= Enable;
|
|
|
+ Mode->ReceiveFilterSetting &= ~Disable;
|
|
|
+
|
|
|
+ Status = ReceiveFilterUpdate (SimpleNetwork);
|
|
|
+
|
|
|
+ if (EFI_DEVICE_ERROR == Status || EFI_INVALID_PARAMETER == Status)
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Reset the network adapter.
|
|
|
+
|
|
|
+ Resets a network adapter and reinitializes it with the parameters that
|
|
|
+ were provided in the previous call to Initialize (). The transmit and
|
|
|
+ receive queues are cleared. Receive filters, the station address, the
|
|
|
+ statistics, and the multicast-IP-to-HW MAC addresses are not reset by
|
|
|
+ this call.
|
|
|
+
|
|
|
+ This routine calls ::Ax88772Reset to perform the adapter specific
|
|
|
+ reset operation. This routine also starts the link negotiation
|
|
|
+ by calling ::Ax88772NegotiateLinkStart.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [in] ExtendedVerification Indicates that the driver may perform a more
|
|
|
+ exhaustive verification operation of the device
|
|
|
+ during reset.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_Reset (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
|
|
|
+ IN BOOLEAN ExtendedVerification
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ NIC_DEVICE *NicDevice;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ //
|
|
|
+ // Verify the parameters
|
|
|
+ //
|
|
|
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ if (EfiSimpleNetworkInitialized == Mode->State) {
|
|
|
+ //
|
|
|
+ // Update the device state
|
|
|
+ //
|
|
|
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Reset the device
|
|
|
+ //
|
|
|
+ if (!NicDevice->FirstRst) {
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ } else {
|
|
|
+ Status = Ax88772Reset (NicDevice);
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ Status = ReceiveFilterUpdate (SimpleNetwork);
|
|
|
+ if (!EFI_ERROR (Status) && !NicDevice->LinkUp && NicDevice->FirstRst) {
|
|
|
+ Status = Ax88772NegotiateLinkStart (NicDevice);
|
|
|
+ NicDevice->FirstRst = FALSE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+ //
|
|
|
+ // Return the operation status
|
|
|
+ //
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Initialize the simple network protocol.
|
|
|
+
|
|
|
+ This routine calls ::Ax88772MacAddressGet to obtain the
|
|
|
+ MAC address.
|
|
|
+
|
|
|
+ @param [in] NicDevice NIC_DEVICE_INSTANCE pointer
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Setup was successful
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+SN_Setup (
|
|
|
+ IN NIC_DEVICE *NicDevice
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
|
|
|
+ EFI_STATUS Status;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Initialize the simple network protocol
|
|
|
+ //
|
|
|
+ SimpleNetwork = &NicDevice->SimpleNetwork;
|
|
|
+ SimpleNetwork->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
|
|
|
+ SimpleNetwork->Start = SN_Start;
|
|
|
+ SimpleNetwork->Stop = SN_Stop;
|
|
|
+ SimpleNetwork->Initialize = SN_Initialize;
|
|
|
+ SimpleNetwork->Reset = SN_Reset;
|
|
|
+ SimpleNetwork->Shutdown = SN_Shutdown;
|
|
|
+ SimpleNetwork->ReceiveFilters = SN_ReceiveFilters;
|
|
|
+ SimpleNetwork->StationAddress = SN_StationAddress;
|
|
|
+ SimpleNetwork->Statistics = SN_Statistics;
|
|
|
+ SimpleNetwork->MCastIpToMac = SN_MCastIPtoMAC;
|
|
|
+ SimpleNetwork->NvData = SN_NvData;
|
|
|
+ SimpleNetwork->GetStatus = SN_GetStatus;
|
|
|
+ SimpleNetwork->Transmit = SN_Transmit;
|
|
|
+ SimpleNetwork->Receive = SN_Receive;
|
|
|
+ SimpleNetwork->WaitForPacket = NULL;
|
|
|
+ Mode = &NicDevice->SimpleNetworkData;
|
|
|
+ SimpleNetwork->Mode = Mode;
|
|
|
+ Mode->State = EfiSimpleNetworkStopped;
|
|
|
+ Mode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
|
|
|
+ Mode->MediaHeaderSize = sizeof (ETHERNET_HEADER);
|
|
|
+ Mode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
|
|
|
+ Mode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
|
|
+ | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
|
|
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
|
|
|
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
|
|
|
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
|
|
|
+ Mode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
|
|
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
|
|
|
+ Mode->MaxMCastFilterCount = ASIX_MCAST_FILTER_CNT;
|
|
|
+ Mode->MCastFilterCount = 0;
|
|
|
+ Mode->NvRamSize = 512;
|
|
|
+ Mode->NvRamAccessSize = 2;
|
|
|
+ SetMem (&Mode->BroadcastAddress,
|
|
|
+ PXE_HWADDR_LEN_ETHER,
|
|
|
+ 0xff);
|
|
|
+
|
|
|
+ SetMem (&Mode->MCastFilter[0],
|
|
|
+ sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT,
|
|
|
+ 0);
|
|
|
+
|
|
|
+ Mode->IfType = NET_IFTYPE_ETHERNET;
|
|
|
+ Mode->MacAddressChangeable = TRUE;
|
|
|
+ Mode->MultipleTxSupported = FALSE;
|
|
|
+ Mode->MediaPresentSupported = TRUE;
|
|
|
+ Mode->MediaPresent = FALSE;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Read the MAC address
|
|
|
+ //
|
|
|
+ NicDevice->PhyId = PHY_ID_INTERNAL;
|
|
|
+ NicDevice->LinkSpeed100Mbps = TRUE;
|
|
|
+ NicDevice->FullDuplex = TRUE;
|
|
|
+ NicDevice->Complete = FALSE;
|
|
|
+ NicDevice->LinkUp = FALSE;
|
|
|
+ NicDevice->Grub_f = FALSE;
|
|
|
+ NicDevice->FirstRst = TRUE;
|
|
|
+ NicDevice->PktCnt = 0;
|
|
|
+
|
|
|
+ Status = Ax88772MacAddressGet (
|
|
|
+ NicDevice,
|
|
|
+ &Mode->PermanentAddress.Addr[0]);
|
|
|
+
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Use the hardware address as the current address
|
|
|
+ //
|
|
|
+ CopyMem (&Mode->CurrentAddress,
|
|
|
+ &Mode->PermanentAddress,
|
|
|
+ PXE_HWADDR_LEN_ETHER);
|
|
|
+
|
|
|
+ CopyMem (&NicDevice->MAC,
|
|
|
+ &Mode->PermanentAddress,
|
|
|
+ PXE_HWADDR_LEN_ETHER);
|
|
|
+
|
|
|
+ Status = gBS->AllocatePool (EfiBootServicesData,
|
|
|
+ AX88772_MAX_BULKIN_SIZE,
|
|
|
+ (VOID **) &NicDevice->BulkInbuf);
|
|
|
+
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = gBS->AllocatePool (EfiBootServicesData,
|
|
|
+ sizeof (RX_TX_PACKET),
|
|
|
+ (VOID **) &NicDevice->TxTest);
|
|
|
+
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ gBS->FreePool (NicDevice->BulkInbuf);
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Return the setup status
|
|
|
+ //
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ This routine starts the network interface.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_ALREADY_STARTED The network interface was already started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_Start (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
|
|
|
+ )
|
|
|
+{
|
|
|
+ NIC_DEVICE *NicDevice;
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ //
|
|
|
+ // Verify the parameters
|
|
|
+ //
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ if (EfiSimpleNetworkStopped == Mode->State) {
|
|
|
+ //
|
|
|
+ // Initialize the mode structure
|
|
|
+ // NVRAM access is not supported
|
|
|
+ //
|
|
|
+ ZeroMem (Mode, sizeof (*Mode));
|
|
|
+
|
|
|
+ Mode->State = EfiSimpleNetworkStarted;
|
|
|
+ Mode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
|
|
|
+ Mode->MediaHeaderSize = sizeof (ETHERNET_HEADER);
|
|
|
+ Mode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
|
|
|
+ Mode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
|
|
+ | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
|
|
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
|
|
|
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
|
|
|
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
|
|
|
+ Mode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
|
|
|
+ Mode->MaxMCastFilterCount = ASIX_MCAST_FILTER_CNT;
|
|
|
+ Mode->MCastFilterCount = 0;
|
|
|
+
|
|
|
+ SetMem (&Mode->MCastFilter[0],
|
|
|
+ sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT,
|
|
|
+ 0);
|
|
|
+
|
|
|
+ Mode->NvRamSize = 512;
|
|
|
+ Mode->NvRamAccessSize = 2;
|
|
|
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
|
|
|
+ Status = Ax88772MacAddressGet (NicDevice, &Mode->PermanentAddress.Addr[0]);
|
|
|
+ CopyMem (&Mode->CurrentAddress,
|
|
|
+ &Mode->PermanentAddress,
|
|
|
+ sizeof (Mode->CurrentAddress));
|
|
|
+ SetMem(&Mode->BroadcastAddress, PXE_HWADDR_LEN_ETHER, 0xff);
|
|
|
+ Mode->IfType = NET_IFTYPE_ETHERNET;
|
|
|
+ Mode->MacAddressChangeable = TRUE;
|
|
|
+ Mode->MultipleTxSupported = FALSE;
|
|
|
+ Mode->MediaPresentSupported = TRUE;
|
|
|
+ Mode->MediaPresent = FALSE;
|
|
|
+
|
|
|
+ } else {
|
|
|
+ Status = EFI_ALREADY_STARTED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Return the operation status
|
|
|
+ //
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Set the MAC address.
|
|
|
+
|
|
|
+ This function modifies or resets the current station address of a
|
|
|
+ network interface. If Reset is TRUE, then the current station address
|
|
|
+ is set ot the network interface's permanent address. If Reset if FALSE
|
|
|
+ then the current station address is changed to the address specified by
|
|
|
+ New.
|
|
|
+
|
|
|
+ This routine calls ::Ax88772MacAddressSet to update the MAC address
|
|
|
+ in the network adapter.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [in] Reset Flag used to reset the station address to the
|
|
|
+ network interface's permanent address.
|
|
|
+ @param [in] New New station address to be used for the network
|
|
|
+ interface.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_StationAddress (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
|
|
|
+ IN BOOLEAN Reset,
|
|
|
+ IN EFI_MAC_ADDRESS *New
|
|
|
+ )
|
|
|
+{
|
|
|
+ NIC_DEVICE *NicDevice;
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ EFI_STATUS Status;
|
|
|
+
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ //
|
|
|
+ // Verify the parameters
|
|
|
+ //
|
|
|
+ if ((SimpleNetwork != NULL) &&
|
|
|
+ (SimpleNetwork->Mode != NULL) &&
|
|
|
+ ((!Reset) || (Reset && (New != NULL)))) {
|
|
|
+ //
|
|
|
+ // Verify that the adapter is already started
|
|
|
+ //
|
|
|
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ if (EfiSimpleNetworkInitialized == Mode->State) {
|
|
|
+ //
|
|
|
+ // Determine the adapter MAC address
|
|
|
+ //
|
|
|
+ if (Reset) {
|
|
|
+ //
|
|
|
+ // Use the permanent address
|
|
|
+ //
|
|
|
+ CopyMem (&Mode->CurrentAddress,
|
|
|
+ &Mode->PermanentAddress,
|
|
|
+ sizeof (Mode->CurrentAddress));
|
|
|
+ } else {
|
|
|
+ //
|
|
|
+ // Use the specified address
|
|
|
+ //
|
|
|
+ CopyMem (&Mode->CurrentAddress,
|
|
|
+ New,
|
|
|
+ sizeof (Mode->CurrentAddress));
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Update the address on the adapter
|
|
|
+ //
|
|
|
+ Status = Ax88772MacAddressSet (NicDevice, &Mode->CurrentAddress.Addr[0]);
|
|
|
+ } else {
|
|
|
+ if (EfiSimpleNetworkStarted == Mode->State) {
|
|
|
+ Status = EFI_DEVICE_ERROR; ;
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED ;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Return the operation status
|
|
|
+ //
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ This function resets or collects the statistics on a network interface.
|
|
|
+ If the size of the statistics table specified by StatisticsSize is not
|
|
|
+ big enough for all of the statistics that are collected by the network
|
|
|
+ interface, then a partial buffer of statistics is returned in
|
|
|
+ StatisticsTable.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [in] Reset Set to TRUE to reset the statistics for the network interface.
|
|
|
+ @param [in, out] StatisticsSize On input the size, in bytes, of StatisticsTable. On output
|
|
|
+ the size, in bytes, of the resulting table of statistics.
|
|
|
+ @param [out] StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
|
|
|
+ conains the statistics.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_BUFFER_TOO_SMALL The StatisticsTable is NULL or the buffer is too small.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_Statistics (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
|
|
|
+ IN BOOLEAN Reset,
|
|
|
+ IN OUT UINTN *StatisticsSize,
|
|
|
+ OUT EFI_NETWORK_STATISTICS *StatisticsTable
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+
|
|
|
+ if (EfiSimpleNetworkInitialized == Mode->State) {
|
|
|
+ if ((StatisticsSize != NULL) && (*StatisticsSize == 0)) {
|
|
|
+ Status = EFI_BUFFER_TOO_SMALL;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(Reset) {
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ } else {
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (EfiSimpleNetworkStarted == Mode->State) {
|
|
|
+ Status = EFI_DEVICE_ERROR; ;
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED ;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //
|
|
|
+ // This is not currently supported
|
|
|
+ //
|
|
|
+
|
|
|
+EXIT:
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ This function stops a network interface. This call is only valid
|
|
|
+ if the network interface is in the started state.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_Stop (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ //
|
|
|
+ // Verify the parameters
|
|
|
+ //
|
|
|
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
|
|
|
+ //
|
|
|
+ // Determine if the interface is started
|
|
|
+ //
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+
|
|
|
+ if (EfiSimpleNetworkStarted == Mode->State) {
|
|
|
+ Mode->State = EfiSimpleNetworkStopped;
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Return the operation status
|
|
|
+ //
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ This function releases the memory buffers assigned in the Initialize() call.
|
|
|
+ Ending transmits and receives are lost, and interrupts are cleared and disabled.
|
|
|
+ After this call, only Initialize() and Stop() calls may be used.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_Shutdown (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ UINT32 RxFilter;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ //
|
|
|
+ // Verify the parameters
|
|
|
+ //
|
|
|
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
|
|
|
+ //
|
|
|
+ // Determine if the interface is already started
|
|
|
+ //
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ if (EfiSimpleNetworkInitialized == Mode->State) {
|
|
|
+ //
|
|
|
+ // Stop the adapter
|
|
|
+ //
|
|
|
+ RxFilter = Mode->ReceiveFilterSetting;
|
|
|
+ Mode->ReceiveFilterSetting = 0;
|
|
|
+ Status = SN_Reset (SimpleNetwork, FALSE);
|
|
|
+ Mode->ReceiveFilterSetting = RxFilter;
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ //
|
|
|
+ // Update the network state
|
|
|
+ //
|
|
|
+ Mode->State = EfiSimpleNetworkStarted;
|
|
|
+ } else if (EFI_DEVICE_ERROR == Status) {
|
|
|
+ Mode->State = EfiSimpleNetworkStopped;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Return the operation status
|
|
|
+ //
|
|
|
+ gBS->RestoreTPL(TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Send a packet over the network.
|
|
|
+
|
|
|
+ This function places the packet specified by Header and Buffer on
|
|
|
+ the transmit queue. This function performs a non-blocking transmit
|
|
|
+ operation. When the transmit is complete, the buffer is returned
|
|
|
+ via the GetStatus() call.
|
|
|
+
|
|
|
+ This routine calls ::Ax88772Rx to empty the network adapter of
|
|
|
+ receive packets. The routine then passes the transmit packet
|
|
|
+ to the network adapter.
|
|
|
+
|
|
|
+ @param [in] SimpleNetwork Protocol instance pointer
|
|
|
+ @param [in] HeaderSize The size, in bytes, of the media header to be filled in by
|
|
|
+ the Transmit() function. If HeaderSize is non-zero, then
|
|
|
+ it must be equal to SimpleNetwork->Mode->MediaHeaderSize
|
|
|
+ and DestAddr and Protocol parameters must not be NULL.
|
|
|
+ @param [in] BufferSize The size, in bytes, of the entire packet (media header and
|
|
|
+ data) to be transmitted through the network interface.
|
|
|
+ @param [in] Buffer A pointer to the packet (media header followed by data) to
|
|
|
+ to be transmitted. This parameter can not be NULL. If
|
|
|
+ HeaderSize is zero, then the media header is Buffer must
|
|
|
+ already be filled in by the caller. If HeaderSize is nonzero,
|
|
|
+ then the media header will be filled in by the Transmit()
|
|
|
+ function.
|
|
|
+ @param [in] SrcAddr The source HW MAC address. If HeaderSize is zero, then
|
|
|
+ this parameter is ignored. If HeaderSize is nonzero and
|
|
|
+ SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
|
|
|
+ is used for the source HW MAC address.
|
|
|
+ @param [in] DestAddr The destination HW MAC address. If HeaderSize is zero, then
|
|
|
+ this parameter is ignored.
|
|
|
+ @param [in] Protocol The type of header to build. If HeaderSize is zero, then
|
|
|
+ this parameter is ignored.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This operation was successful.
|
|
|
+ @retval EFI_NOT_STARTED The network interface was not started.
|
|
|
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
|
|
|
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
|
|
|
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
|
|
|
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
|
|
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SN_Transmit (
|
|
|
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
|
|
|
+ IN UINTN HeaderSize,
|
|
|
+ IN UINTN BufferSize,
|
|
|
+ IN VOID *Buffer,
|
|
|
+ IN EFI_MAC_ADDRESS *SrcAddr,
|
|
|
+ IN EFI_MAC_ADDRESS *DestAddr,
|
|
|
+ IN UINT16 *Protocol
|
|
|
+ )
|
|
|
+{
|
|
|
+ ETHERNET_HEADER *Header;
|
|
|
+ EFI_SIMPLE_NETWORK_MODE *Mode;
|
|
|
+ NIC_DEVICE *NicDevice;
|
|
|
+ EFI_USB_IO_PROTOCOL *UsbIo;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ UINTN TransferLength;
|
|
|
+ UINT32 TransferStatus;
|
|
|
+ UINT16 Type;
|
|
|
+ EFI_TPL TplPrevious;
|
|
|
+
|
|
|
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
|
|
|
+ //
|
|
|
+ // Verify the parameters
|
|
|
+ //
|
|
|
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
|
|
|
+ //
|
|
|
+ // The interface must be running
|
|
|
+ //
|
|
|
+ Mode = SimpleNetwork->Mode;
|
|
|
+ if (EfiSimpleNetworkInitialized == Mode->State) {
|
|
|
+ //
|
|
|
+ // Update the link status
|
|
|
+ //
|
|
|
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Release the synchronization with Ax88772Timer
|
|
|
+ //
|
|
|
+ if (NicDevice->LinkUp && NicDevice->Complete) {
|
|
|
+ //
|
|
|
+ // Copy the packet into the USB buffer
|
|
|
+ //
|
|
|
+
|
|
|
+ if ((HeaderSize != 0) && (Mode->MediaHeaderSize != HeaderSize)) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+ if (BufferSize < Mode->MediaHeaderSize) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+ if (Buffer == NULL) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+ if ((HeaderSize != 0) && (DestAddr == NULL)) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+ if ((HeaderSize != 0) && (Protocol == NULL)) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ goto EXIT;
|
|
|
+ }
|
|
|
+
|
|
|
+ CopyMem (&NicDevice->TxTest->Data[0], Buffer, BufferSize);
|
|
|
+ NicDevice->TxTest->Length = (UINT16) BufferSize;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Transmit the packet
|
|
|
+ //
|
|
|
+ Header = (ETHERNET_HEADER *) &NicDevice->TxTest->Data[0];
|
|
|
+ if (HeaderSize != 0) {
|
|
|
+ if (DestAddr != NULL) {
|
|
|
+ CopyMem (&Header->DestAddr, DestAddr, PXE_HWADDR_LEN_ETHER);
|
|
|
+ }
|
|
|
+ if (SrcAddr != NULL) {
|
|
|
+ CopyMem (&Header->SrcAddr, SrcAddr, PXE_HWADDR_LEN_ETHER);
|
|
|
+ } else {
|
|
|
+ CopyMem (&Header->SrcAddr, &Mode->CurrentAddress.Addr[0], PXE_HWADDR_LEN_ETHER);
|
|
|
+ }
|
|
|
+ if (Protocol != NULL) {
|
|
|
+ Type = *Protocol;
|
|
|
+ } else {
|
|
|
+ Type = NicDevice->TxTest->Length;
|
|
|
+ }
|
|
|
+ Type = (UINT16)((Type >> 8) | (Type << 8));
|
|
|
+ Header->Type = Type;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (NicDevice->TxTest->Length < MIN_ETHERNET_PKT_SIZE) {
|
|
|
+ NicDevice->TxTest->Length = MIN_ETHERNET_PKT_SIZE;
|
|
|
+ ZeroMem (&NicDevice->TxTest->Data[BufferSize],
|
|
|
+ NicDevice->TxTest->Length - BufferSize);
|
|
|
+ }
|
|
|
+
|
|
|
+ NicDevice->TxTest->LengthBar = ~(NicDevice->TxTest->Length);
|
|
|
+ TransferLength = sizeof (NicDevice->TxTest->Length)
|
|
|
+ + sizeof (NicDevice->TxTest->LengthBar)
|
|
|
+ + NicDevice->TxTest->Length;
|
|
|
+
|
|
|
+ if (TransferLength % 512 == 0 || TransferLength % 1024 == 0)
|
|
|
+ TransferLength +=4;
|
|
|
+#if RXTHOU
|
|
|
+ if (NicDevice->RxBurst == 1)
|
|
|
+ NicDevice->RxBurst--;
|
|
|
+#endif
|
|
|
+ //
|
|
|
+ // Work around USB bus driver bug where a timeout set by receive
|
|
|
+ // succeeds but the timeout expires immediately after, causing the
|
|
|
+ // transmit operation to timeout.
|
|
|
+ //
|
|
|
+ UsbIo = NicDevice->UsbIo;
|
|
|
+ Status = UsbIo->UsbBulkTransfer (UsbIo,
|
|
|
+ BULK_OUT_ENDPOINT,
|
|
|
+ &NicDevice->TxTest->Length,
|
|
|
+ &TransferLength,
|
|
|
+ 0xfffffffe,
|
|
|
+ &TransferStatus);
|
|
|
+ if (EFI_SUCCESS == Status) {
|
|
|
+ Status = TransferStatus;
|
|
|
+ }
|
|
|
+ if (EFI_SUCCESS == Status && EFI_SUCCESS == TransferStatus) {
|
|
|
+ NicDevice->TxBuffer = Buffer;
|
|
|
+ } else {
|
|
|
+ if (EFI_DEVICE_ERROR == Status) {
|
|
|
+ SN_Reset (SimpleNetwork, FALSE);
|
|
|
+ }
|
|
|
+ Status = EFI_NOT_READY;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //
|
|
|
+ // No packets available.
|
|
|
+ //
|
|
|
+ Status = EFI_NOT_READY;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (EfiSimpleNetworkStarted == Mode->State) {
|
|
|
+ Status = EFI_DEVICE_ERROR;
|
|
|
+ } else {
|
|
|
+ Status = EFI_NOT_STARTED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+EXIT:
|
|
|
+ gBS->RestoreTPL (TplPrevious);
|
|
|
+ return Status;
|
|
|
+}
|