--- /dev/null
+/** @file\r
+ Provides the Simple Network functions.\r
+\r
+ Copyright (c) 2011, Intel Corporation\r
+ All rights reserved. This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which 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
+\r
+**/\r
+\r
+#include "Ax88772.h"\r
+\r
+/**\r
+ This function updates the filtering on the receiver.\r
+\r
+ This support routine calls ::Ax88772MacAddressSet to update\r
+ the MAC address. This routine then rebuilds the multicast\r
+ hash by calling ::Ax88772MulticastClear and ::Ax88772MulticastSet.\r
+ Finally this routine enables the receiver by calling\r
+ ::Ax88772RxControl.\r
+\r
+ @param [in] pSimpleNetwork Simple network mode pointer\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+ReceiveFilterUpdate (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork\r
+ )\r
+{\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ NIC_DEVICE * pNicDevice;\r
+ EFI_STATUS Status;\r
+ UINT32 Index;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Set the MAC address\r
+ //\r
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
+ pMode = pSimpleNetwork->Mode;\r
+ Status = Ax88772MacAddressSet ( pNicDevice,\r
+ &pMode->CurrentAddress.Addr[0]);\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Clear the multicast hash table\r
+ //\r
+ Ax88772MulticastClear ( pNicDevice );\r
+\r
+ //\r
+ // Load the multicast hash table\r
+ //\r
+ if ( 0 != ( pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {\r
+ for ( Index = 0;\r
+ ( !EFI_ERROR ( Status )) && ( Index < pMode->MCastFilterCount );\r
+ Index++ ) {\r
+ //\r
+ // Enable the next multicast address\r
+ //\r
+ Ax88772MulticastSet ( pNicDevice,\r
+ &pMode->MCastFilter[ Index ].Addr[0]);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Enable the receiver\r
+ //\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = Ax88772RxControl ( pNicDevice, pMode->ReceiveFilterSetting );\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function updates the SNP driver status.\r
+ \r
+ This function gets the current interrupt and recycled transmit\r
+ buffer status from the network interface. The interrupt status\r
+ and the media status are returned as a bit mask in InterruptStatus.\r
+ If InterruptStatus is NULL, the interrupt status will not be read.\r
+ Upon successful return of the media status, the MediaPresent field\r
+ of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change\r
+ of media status. If TxBuf is not NULL, a recycled transmit buffer\r
+ address will be retrived. If a recycled transmit buffer address\r
+ is returned in TxBuf, then the buffer has been successfully\r
+ transmitted, and the status for that buffer is cleared.\r
+\r
+ This function calls ::Ax88772Rx to update the media status and\r
+ queue any receive packets.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [in] pInterruptStatus A pointer to the bit mask of the current active interrupts.\r
+ If this is NULL, the interrupt status will not be read from\r
+ the device. If this is not NULL, the interrupt status will\r
+ be read from teh device. When the interrupt status is read,\r
+ it will also be cleared. Clearing the transmit interrupt\r
+ does not empty the recycled transmit buffer array.\r
+ @param [out] ppTxBuf Recycled transmit buffer address. The network interface will\r
+ not transmit if its internal recycled transmit buffer array is\r
+ full. Reading the transmit buffer does not clear the transmit\r
+ interrupt. If this is NULL, then the transmit buffer status\r
+ will not be read. If there are not transmit buffers to recycle\r
+ and TxBuf is not NULL, *TxBuf will be set to NULL.\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_GetStatus (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ OUT UINT32 * pInterruptStatus,\r
+ OUT VOID ** ppTxBuf\r
+ )\r
+{\r
+ BOOLEAN bLinkIdle;\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ NIC_DEVICE * pNicDevice;\r
+ EFI_STATUS Status;\r
+ EFI_TPL TplPrevious;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
+ //\r
+ // Return the transmit buffer\r
+ //\r
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
+ if (( NULL != ppTxBuf ) && ( NULL != pNicDevice->pTxBuffer )) {\r
+ *ppTxBuf = pNicDevice->pTxBuffer;\r
+ pNicDevice->pTxBuffer = NULL;\r
+ }\r
+\r
+ //\r
+ // Determine if interface is running\r
+ //\r
+ pMode = pSimpleNetwork->Mode;\r
+ if ( EfiSimpleNetworkStopped != pMode->State ) {\r
+ //\r
+ // Synchronize with Ax88772Timer\r
+ //\r
+ VERIFY_TPL ( TPL_AX88772 );\r
+ TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );\r
+\r
+ //\r
+ // Update the link status\r
+ //\r
+ bLinkIdle = pNicDevice->bLinkIdle;\r
+ pNicDevice->bLinkIdle = TRUE;\r
+ Ax88772Rx ( pNicDevice, bLinkIdle );\r
+ pMode->MediaPresent = pNicDevice->bLinkUp;\r
+\r
+ //\r
+ // Release the synchronization with Ax88772Timer\r
+ //\r
+ gBS->RestoreTPL ( TplPrevious );\r
+\r
+ //\r
+ // Return the interrupt status\r
+ //\r
+ if ( NULL != pInterruptStatus ) {\r
+ *pInterruptStatus = 0;\r
+ }\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ else {\r
+ Status = EFI_NOT_STARTED;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Resets the network adapter and allocates the transmit and receive buffers\r
+ required by the network interface; optionally, also requests allocation of\r
+ additional transmit and receive buffers. This routine must be called before\r
+ any other routine in the Simple Network protocol is called.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer allocation\r
+ @param [in] ExtraTxBufferSize Size in bytes to add to the transmit buffer allocation\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_OUT_OF_RESORUCES There was not enough memory for the transmit and receive buffers\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_Initialize (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ IN UINTN ExtraRxBufferSize,\r
+ IN UINTN ExtraTxBufferSize\r
+ )\r
+{\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+ \r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
+ //\r
+ // Determine if the interface is already started\r
+ //\r
+ pMode = pSimpleNetwork->Mode;\r
+ if ( EfiSimpleNetworkStarted == pMode->State ) {\r
+ if (( 0 == ExtraRxBufferSize ) && ( 0 == ExtraTxBufferSize )) {\r
+ //\r
+ // Start the adapter\r
+ //\r
+ Status = SN_Reset ( pSimpleNetwork, FALSE );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Update the network state\r
+ //\r
+ pMode->State = EfiSimpleNetworkInitialized;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_NOT_STARTED;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function converts a multicast IP address to a multicast HW MAC address\r
+ for all packet transactions.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [in] bIPv6 Set to TRUE if the multicast IP address is IPv6 [RFC2460].\r
+ Set to FALSE if the multicast IP address is IPv4 [RFC 791].\r
+ @param [in] pIP The multicast IP address that is to be converted to a\r
+ multicast HW MAC address.\r
+ @param [in] pMAC The multicast HW MAC address that is to be generated from IP.\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_MCastIPtoMAC (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ IN BOOLEAN bIPv6,\r
+ IN EFI_IP_ADDRESS * pIP,\r
+ IN EFI_MAC_ADDRESS * pMAC\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // This is not currently supported\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function performs read and write operations on the NVRAM device\r
+ attached to a network interface.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [in] ReadWrite TRUE for read operations, FALSE for write operations.\r
+ @param [in] Offset Byte offset in the NVRAM device at which to start the\r
+ read or write operation. This must be a multiple of\r
+ NvRamAccessSize and less than NvRamSize.\r
+ @param [in] BufferSize The number of bytes to read or write from the NVRAM device.\r
+ This must also be a multiple of NvramAccessSize.\r
+ @param [in, out] pBuffer A pointer to the data buffer.\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_NvData (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ IN BOOLEAN ReadWrite,\r
+ IN UINTN Offset,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID * pBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // This is not currently supported\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Attempt to receive a packet from the network adapter.\r
+\r
+ This function retrieves one packet from the receive queue of the network\r
+ interface. If there are no packets on the receive queue, then EFI_NOT_READY\r
+ will be returned. If there is a packet on the receive queue, and the size\r
+ of the packet is smaller than BufferSize, then the contents of the packet\r
+ will be placed in Buffer, and BufferSize will be udpated with the actual\r
+ size of the packet. In addition, if SrcAddr, DestAddr, and Protocol are\r
+ not NULL, then these values will be extracted from the media header and\r
+ returned. If BufferSize is smaller than the received packet, then the\r
+ size of the receive packet will be placed in BufferSize and\r
+ EFI_BUFFER_TOO_SMALL will be returned.\r
+\r
+ This routine calls ::Ax88772Rx to update the media status and\r
+ empty the network adapter of receive packets.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [out] pHeaderSize The size, in bytes, of the media header to be filled in by\r
+ the Transmit() function. If HeaderSize is non-zero, then\r
+ it must be equal to SimpleNetwork->Mode->MediaHeaderSize\r
+ and DestAddr and Protocol parameters must not be NULL.\r
+ @param [out] pBufferSize The size, in bytes, of the entire packet (media header and\r
+ data) to be transmitted through the network interface.\r
+ @param [out] pBuffer A pointer to the packet (media header followed by data) to\r
+ to be transmitted. This parameter can not be NULL. If\r
+ HeaderSize is zero, then the media header is Buffer must\r
+ already be filled in by the caller. If HeaderSize is nonzero,\r
+ then the media header will be filled in by the Transmit()\r
+ function.\r
+ @param [out] pSrcAddr The source HW MAC address. If HeaderSize is zero, then\r
+ this parameter is ignored. If HeaderSize is nonzero and\r
+ SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress\r
+ is used for the source HW MAC address.\r
+ @param [out] pDestAddr The destination HW MAC address. If HeaderSize is zero, then\r
+ this parameter is ignored.\r
+ @param [out] pProtocol The type of header to build. If HeaderSize is zero, then\r
+ this parameter is ignored.\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_NOT_READY No packets have been received on the network interface.\r
+ @retval EFI_BUFFER_TOO_SMALL The packet is larger than BufferSize bytes.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_Receive (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ OUT UINTN * pHeaderSize,\r
+ OUT UINTN * pBufferSize,\r
+ OUT VOID * pBuffer,\r
+ OUT EFI_MAC_ADDRESS * pSrcAddr,\r
+ OUT EFI_MAC_ADDRESS * pDestAddr,\r
+ OUT UINT16 * pProtocol\r
+ )\r
+{\r
+ ETHERNET_HEADER * pHeader;\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ NIC_DEVICE * pNicDevice;\r
+ RX_TX_PACKET * pRxPacket;\r
+ EFI_STATUS Status;\r
+ EFI_TPL TplPrevious;\r
+ UINT16 Type;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
+ //\r
+ // The interface must be running\r
+ //\r
+ pMode = pSimpleNetwork->Mode;\r
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {\r
+ //\r
+ // Synchronize with Ax88772Timer\r
+ //\r
+ VERIFY_TPL ( TPL_AX88772 );\r
+ TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );\r
+\r
+ //\r
+ // Update the link status\r
+ //\r
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
+ Ax88772Rx ( pNicDevice, FALSE );\r
+ pMode->MediaPresent = pNicDevice->bLinkUp;\r
+ if ( pMode->MediaPresent ) {\r
+ //\r
+ // Attempt to receive a packet\r
+ //\r
+ pRxPacket = pNicDevice->pRxHead;\r
+ if ( NULL != pRxPacket ) {\r
+ pNicDevice->pRxHead = pRxPacket->pNext;\r
+ if ( NULL == pNicDevice->pRxHead ) {\r
+ pNicDevice->pRxTail = NULL;\r
+ }\r
+\r
+ //\r
+ // Copy the received packet into the receive buffer\r
+ //\r
+ *pBufferSize = pRxPacket->Length;\r
+ CopyMem ( pBuffer, &pRxPacket->Data[0], pRxPacket->Length );\r
+ pHeader = (ETHERNET_HEADER *) &pRxPacket->Data[0];\r
+ if ( NULL != pHeaderSize ) {\r
+ *pHeaderSize = sizeof ( *pHeader );\r
+ }\r
+ if ( NULL != pDestAddr ) {\r
+ CopyMem ( pDestAddr, &pHeader->dest_addr, PXE_HWADDR_LEN_ETHER );\r
+ }\r
+ if ( NULL != pSrcAddr ) {\r
+ CopyMem ( pSrcAddr, &pHeader->src_addr, PXE_HWADDR_LEN_ETHER );\r
+ }\r
+ if ( NULL != pProtocol ) {\r
+ Type = pHeader->type;\r
+ Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));\r
+ *pProtocol = Type;\r
+ }\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ else {\r
+ //\r
+ // No receive packets available\r
+ //\r
+ Status = EFI_NOT_READY;\r
+ }\r
+ }\r
+ else {\r
+ //\r
+ // Link no up\r
+ //\r
+ Status = EFI_NOT_READY;\r
+ }\r
+\r
+ //\r
+ // Release the synchronization with Ax88772Timer\r
+ //\r
+ gBS->RestoreTPL ( TplPrevious );\r
+ }\r
+ else {\r
+ Status = EFI_NOT_STARTED;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function is used to enable and disable the hardware and software receive\r
+ filters for the underlying network device.\r
+\r
+ The receive filter change is broken down into three steps:\r
+\r
+ 1. The filter mask bits that are set (ON) in the Enable parameter\r
+ are added to the current receive filter settings.\r
+\r
+ 2. The filter mask bits that are set (ON) in the Disable parameter\r
+ are subtracted from the updated receive filter settins.\r
+\r
+ 3. If the resulting filter settigns is not supported by the hardware\r
+ a more liberal setting is selected.\r
+\r
+ If the same bits are set in the Enable and Disable parameters, then the bits\r
+ in the Disable parameter takes precedence.\r
+\r
+ If the ResetMCastFilter parameter is TRUE, then the multicast address list\r
+ filter is disabled (irregardless of what other multicast bits are set in\r
+ the enable and Disable parameters). The SNP->Mode->MCastFilterCount field\r
+ is set to zero. The SNP->Mode->MCastFilter contents are undefined.\r
+\r
+ After enableing or disabling receive filter settings, software should\r
+ verify the new settings by checking the SNP->Mode->ReceeiveFilterSettings,\r
+ SNP->Mode->MCastFilterCount and SNP->Mode->MCastFilter fields.\r
+\r
+ Note: Some network drivers and/or devices will automatically promote\r
+ receive filter settings if the requested setting can not be honored.\r
+ For example, if a request for four multicast addresses is made and\r
+ the underlying hardware only supports two multicast addresses the\r
+ driver might set the promiscuous or promiscuous multicast receive filters\r
+ instead. The receiving software is responsible for discarding any extra\r
+ packets that get through the hardware receive filters.\r
+\r
+ If ResetMCastFilter is TRUE, then the multicast receive filter list\r
+ on the network interface will be reset to the default multicast receive\r
+ filter list. If ResetMCastFilter is FALSE, and this network interface\r
+ allows the multicast receive filter list to be modified, then the\r
+ MCastFilterCnt and MCastFilter are used to update the current multicast\r
+ receive filter list. The modified receive filter list settings can be\r
+ found in the MCastFilter field of EFI_SIMPLE_NETWORK_MODE.\r
+\r
+ This routine calls ::ReceiveFilterUpdate to update the receive\r
+ state in the network adapter.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [in] Enable A bit mask of receive filters to enable on the network interface.\r
+ @param [in] Disable A bit mask of receive filters to disable on the network interface.\r
+ For backward compatibility with EFI 1.1 platforms, the\r
+ EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit must be set\r
+ when the ResetMCastFilter parameter is TRUE.\r
+ @param [in] bResetMCastFilter Set to TRUE to reset the contents of the multicast receive\r
+ filters on the network interface to their default values.\r
+ @param [in] MCastFilterCnt Number of multicast HW MAC address in the new MCastFilter list.\r
+ This value must be less than or equal to the MaxMCastFilterCnt\r
+ field of EFI_SIMPLE_NETWORK_MODE. This field is optional if\r
+ ResetMCastFilter is TRUE.\r
+ @param [in] pMCastFilter A pointer to a list of new multicast receive filter HW MAC\r
+ addresses. This list will replace any existing multicast\r
+ HW MAC address list. This field is optional if ResetMCastFilter\r
+ is TRUE.\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_ReceiveFilters (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ IN UINT32 Enable,\r
+ IN UINT32 Disable,\r
+ IN BOOLEAN bResetMCastFilter,\r
+ IN UINTN MCastFilterCnt,\r
+ IN EFI_MAC_ADDRESS * pMCastFilter\r
+ )\r
+{\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ EFI_MAC_ADDRESS * pMulticastAddress;\r
+ EFI_MAC_ADDRESS * pTableEnd;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Verify the parameters\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
+ pMode = pSimpleNetwork->Mode;\r
+\r
+ //\r
+ // Update the multicast list if necessary\r
+ //\r
+ if ( !bResetMCastFilter ) {\r
+ if ( 0 != MCastFilterCnt ) {\r
+ if (( MAX_MCAST_FILTER_CNT >= MCastFilterCnt )\r
+ && ( NULL != pMCastFilter )) {\r
+ //\r
+ // Verify the multicast addresses\r
+ //\r
+ pMulticastAddress = pMCastFilter;\r
+ pTableEnd = pMulticastAddress + MCastFilterCnt;\r
+ while ( pTableEnd > pMulticastAddress ) {\r
+ //\r
+ // The first digit of the multicast address must have the LSB set\r
+ //\r
+ if ( 0 == ( pMulticastAddress->Addr[0] & 1 )) {\r
+ //\r
+ // Invalid multicast address\r
+ //\r
+ break;\r
+ }\r
+ pMulticastAddress += 1;\r
+ }\r
+ if ( pTableEnd == pMulticastAddress ) {\r
+ //\r
+ // Update the multicast filter list.\r
+ //\r
+ CopyMem (&pMode->MCastFilter[0],\r
+ pMCastFilter,\r
+ MCastFilterCnt * sizeof ( *pMCastFilter ));\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+ else {\r
+ //\r
+ // No multicast address list is specified\r
+ //\r
+ MCastFilterCnt = 0;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // The parameters are valid!\r
+ //\r
+ pMode->ReceiveFilterSetting |= Enable;\r
+ pMode->ReceiveFilterSetting &= ~Disable;\r
+ pMode->MCastFilterCount = (UINT32)MCastFilterCnt;\r
+\r
+ //\r
+ // Update the receive filters in the adapter\r
+ //\r
+ Status = ReceiveFilterUpdate ( pSimpleNetwork );\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Reset the network adapter.\r
+\r
+ Resets a network adapter and reinitializes it with the parameters that\r
+ were provided in the previous call to Initialize (). The transmit and\r
+ receive queues are cleared. Receive filters, the station address, the\r
+ statistics, and the multicast-IP-to-HW MAC addresses are not reset by\r
+ this call.\r
+\r
+ This routine calls ::Ax88772Reset to perform the adapter specific\r
+ reset operation. This routine also starts the link negotiation\r
+ by calling ::Ax88772NegotiateLinkStart.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [in] bExtendedVerification Indicates that the driver may perform a more\r
+ exhaustive verification operation of the device\r
+ during reset.\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_Reset (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ IN BOOLEAN bExtendedVerification\r
+ )\r
+{\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ NIC_DEVICE * pNicDevice;\r
+ RX_TX_PACKET * pRxPacket;\r
+ EFI_STATUS Status;\r
+ EFI_TPL TplPrevious;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
+ //\r
+ // Synchronize with Ax88772Timer\r
+ //\r
+ VERIFY_TPL ( TPL_AX88772 );\r
+ TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );\r
+\r
+ //\r
+ // Update the device state\r
+ //\r
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
+ pNicDevice->bComplete = FALSE;\r
+ pNicDevice->bLinkUp = FALSE;\r
+\r
+ pMode = pSimpleNetwork->Mode;\r
+ pMode->MediaPresent = FALSE;\r
+\r
+ //\r
+ // Discard any received packets\r
+ //\r
+ while ( NULL != pNicDevice->pRxHead ) {\r
+ //\r
+ // Remove the packet from the received packet list\r
+ //\r
+ pRxPacket = pNicDevice->pRxHead;\r
+ pNicDevice->pRxHead = pRxPacket->pNext;\r
+\r
+ //\r
+ // Queue the packet to the free list\r
+ //\r
+ pRxPacket->pNext = pNicDevice->pRxFree;\r
+ pNicDevice->pRxFree = pRxPacket;\r
+ }\r
+ pNicDevice->pRxTail = NULL;\r
+\r
+ //\r
+ // Reset the device\r
+ //\r
+ Status = Ax88772Reset ( pNicDevice );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Update the receive filters in the adapter\r
+ //\r
+ Status = ReceiveFilterUpdate ( pSimpleNetwork );\r
+\r
+ //\r
+ // Try to get a connection to the network\r
+ //\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Start the autonegotiation\r
+ //\r
+ Status = Ax88772NegotiateLinkStart ( pNicDevice );\r
+ }\r
+ }\r
+\r
+ //\r
+ // Release the synchronization with Ax88772Timer\r
+ //\r
+ gBS->RestoreTPL ( TplPrevious );\r
+ }\r
+ else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Initialize the simple network protocol.\r
+\r
+ This routine calls ::Ax88772MacAddressGet to obtain the\r
+ MAC address.\r
+\r
+ @param [in] pNicDevice NIC_DEVICE_INSTANCE pointer\r
+\r
+ @retval EFI_SUCCESS Setup was successful\r
+\r
+**/\r
+EFI_STATUS\r
+SN_Setup (\r
+ IN NIC_DEVICE * pNicDevice\r
+ )\r
+{\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Initialize the simple network protocol\r
+ //\r
+ pSimpleNetwork = &pNicDevice->SimpleNetwork;\r
+ pSimpleNetwork->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
+ pSimpleNetwork->Start = (EFI_SIMPLE_NETWORK_START)SN_Start;\r
+ pSimpleNetwork->Stop = (EFI_SIMPLE_NETWORK_STOP)SN_Stop;\r
+ pSimpleNetwork->Initialize = (EFI_SIMPLE_NETWORK_INITIALIZE)SN_Initialize;\r
+ pSimpleNetwork->Reset = (EFI_SIMPLE_NETWORK_RESET)SN_Reset;\r
+ pSimpleNetwork->Shutdown = (EFI_SIMPLE_NETWORK_SHUTDOWN)SN_Shutdown;\r
+ pSimpleNetwork->ReceiveFilters = (EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)SN_ReceiveFilters;\r
+ pSimpleNetwork->StationAddress = (EFI_SIMPLE_NETWORK_STATION_ADDRESS)SN_StationAddress;\r
+ pSimpleNetwork->Statistics = (EFI_SIMPLE_NETWORK_STATISTICS)SN_Statistics;\r
+ pSimpleNetwork->MCastIpToMac = (EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)SN_MCastIPtoMAC;\r
+ pSimpleNetwork->NvData = (EFI_SIMPLE_NETWORK_NVDATA)SN_NvData;\r
+ pSimpleNetwork->GetStatus = (EFI_SIMPLE_NETWORK_GET_STATUS)SN_GetStatus;\r
+ pSimpleNetwork->Transmit = (EFI_SIMPLE_NETWORK_TRANSMIT)SN_Transmit;\r
+ pSimpleNetwork->Receive = (EFI_SIMPLE_NETWORK_RECEIVE)SN_Receive;\r
+ pSimpleNetwork->WaitForPacket = NULL;\r
+ pMode = &pNicDevice->SimpleNetworkData;\r
+ pSimpleNetwork->Mode = pMode;\r
+\r
+ pMode->State = EfiSimpleNetworkStopped;\r
+ pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;\r
+ pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );\r
+ pMode->MaxPacketSize = AX88772_MAX_PKT_SIZE;\r
+ pMode->NvRamSize = 0;\r
+ pMode->NvRamAccessSize = 0;\r
+ pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST\r
+ | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST\r
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST\r
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS\r
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
+ pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST\r
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
+ pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;\r
+ pMode->MCastFilterCount = 0;\r
+ SetMem ( &pMode->BroadcastAddress,\r
+ PXE_HWADDR_LEN_ETHER,\r
+ 0xff );\r
+ pMode->IfType = EfiNetworkInterfaceUndi;\r
+ pMode->MacAddressChangeable = TRUE;\r
+ pMode->MultipleTxSupported = TRUE;\r
+ pMode->MediaPresentSupported = TRUE;\r
+ pMode->MediaPresent = FALSE;\r
+\r
+ //\r
+ // Read the MAC address\r
+ //\r
+ pNicDevice->PhyId = PHY_ID_INTERNAL;\r
+ pNicDevice->b100Mbps = TRUE;\r
+ pNicDevice->bFullDuplex = TRUE;\r
+ Status = Ax88772MacAddressGet (\r
+ pNicDevice,\r
+ &pMode->PermanentAddress.Addr[0]);\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Display the MAC address\r
+ //\r
+ DEBUG (( DEBUG_MAC_ADDRESS | DEBUG_INFO,\r
+ "MAC: %02x-%02x-%02x-%02x-%02x-%02x\n",\r
+ pMode->PermanentAddress.Addr[0],\r
+ pMode->PermanentAddress.Addr[1],\r
+ pMode->PermanentAddress.Addr[2],\r
+ pMode->PermanentAddress.Addr[3],\r
+ pMode->PermanentAddress.Addr[4],\r
+ pMode->PermanentAddress.Addr[5]));\r
+\r
+ //\r
+ // Use the hardware address as the current address\r
+ //\r
+ CopyMem ( &pMode->CurrentAddress,\r
+ &pMode->PermanentAddress,\r
+ PXE_HWADDR_LEN_ETHER );\r
+ }\r
+\r
+ //\r
+ // Return the setup status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This routine starts the network interface.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_ALREADY_STARTED The network interface was already started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_Start (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork\r
+ )\r
+{\r
+ NIC_DEVICE * pNicDevice;\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ EFI_STATUS Status;\r
+ \r
+ DBG_ENTER ( );\r
+ \r
+ //\r
+ // Verify the parameters\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
+ pMode = pSimpleNetwork->Mode;\r
+ if ( EfiSimpleNetworkStopped == pMode->State ) {\r
+ //\r
+ // Initialize the mode structure\r
+ // NVRAM access is not supported\r
+ //\r
+ ZeroMem ( pMode, sizeof ( *pMode ));\r
+ \r
+ pMode->State = EfiSimpleNetworkStarted;\r
+ pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;\r
+ pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );\r
+ pMode->MaxPacketSize = AX88772_MAX_PKT_SIZE;\r
+ pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST\r
+ | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST\r
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST\r
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS\r
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
+ pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
+ pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;\r
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
+ Status = Ax88772MacAddressGet ( pNicDevice, &pMode->PermanentAddress.Addr[0]);\r
+ CopyMem ( &pMode->CurrentAddress,\r
+ &pMode->PermanentAddress,\r
+ sizeof ( pMode->CurrentAddress ));\r
+ pMode->BroadcastAddress.Addr[0] = 0xff;\r
+ pMode->BroadcastAddress.Addr[1] = 0xff;\r
+ pMode->BroadcastAddress.Addr[2] = 0xff;\r
+ pMode->BroadcastAddress.Addr[3] = 0xff;\r
+ pMode->BroadcastAddress.Addr[4] = 0xff;\r
+ pMode->BroadcastAddress.Addr[5] = 0xff;\r
+ pMode->IfType = 1;\r
+ pMode->MacAddressChangeable = TRUE;\r
+ pMode->MultipleTxSupported = TRUE;\r
+ pMode->MediaPresentSupported = TRUE;\r
+ pMode->MediaPresent = FALSE;\r
+ }\r
+ else {\r
+ Status = EFI_ALREADY_STARTED;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Set the MAC address.\r
+ \r
+ This function modifies or resets the current station address of a\r
+ network interface. If Reset is TRUE, then the current station address\r
+ is set ot the network interface's permanent address. If Reset if FALSE\r
+ then the current station address is changed to the address specified by\r
+ pNew.\r
+\r
+ This routine calls ::Ax88772MacAddressSet to update the MAC address\r
+ in the network adapter.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [in] bReset Flag used to reset the station address to the\r
+ network interface's permanent address.\r
+ @param [in] pNew New station address to be used for the network\r
+ interface.\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_StationAddress (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ IN BOOLEAN bReset,\r
+ IN EFI_MAC_ADDRESS * pNew\r
+ )\r
+{\r
+ NIC_DEVICE * pNicDevice;\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (( NULL != pSimpleNetwork )\r
+ && ( NULL != pSimpleNetwork->Mode )\r
+ && (( !bReset ) || ( bReset && ( NULL != pNew )))) {\r
+ //\r
+ // Verify that the adapter is already started\r
+ //\r
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
+ pMode = pSimpleNetwork->Mode;\r
+ if ( EfiSimpleNetworkStarted == pMode->State ) {\r
+ //\r
+ // Determine the adapter MAC address\r
+ //\r
+ if ( bReset ) {\r
+ //\r
+ // Use the permanent address\r
+ //\r
+ CopyMem ( &pMode->CurrentAddress,\r
+ &pMode->PermanentAddress,\r
+ sizeof ( pMode->CurrentAddress ));\r
+ }\r
+ else {\r
+ //\r
+ // Use the specified address\r
+ //\r
+ CopyMem ( &pMode->CurrentAddress,\r
+ pNew,\r
+ sizeof ( pMode->CurrentAddress ));\r
+ }\r
+\r
+ //\r
+ // Update the address on the adapter\r
+ //\r
+ Status = Ax88772MacAddressSet ( pNicDevice, &pMode->CurrentAddress.Addr[0]);\r
+ }\r
+ else {\r
+ Status = EFI_NOT_STARTED;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function resets or collects the statistics on a network interface.\r
+ If the size of the statistics table specified by StatisticsSize is not\r
+ big enough for all of the statistics that are collected by the network\r
+ interface, then a partial buffer of statistics is returned in\r
+ StatisticsTable.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [in] bReset Set to TRUE to reset the statistics for the network interface.\r
+ @param [in, out] pStatisticsSize On input the size, in bytes, of StatisticsTable. On output\r
+ the size, in bytes, of the resulting table of statistics.\r
+ @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that\r
+ conains the statistics.\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_BUFFER_TOO_SMALL The pStatisticsTable is NULL or the buffer is too small.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_Statistics (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ IN BOOLEAN bReset,\r
+ IN OUT UINTN * pStatisticsSize,\r
+ OUT EFI_NETWORK_STATISTICS * pStatisticsTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // This is not currently supported\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function stops a network interface. This call is only valid\r
+ if the network interface is in the started state.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_Stop (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork\r
+ )\r
+{\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ EFI_STATUS Status;\r
+ \r
+ DBG_ENTER ( );\r
+ \r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
+ //\r
+ // Determine if the interface is started\r
+ //\r
+ pMode = pSimpleNetwork->Mode;\r
+ if ( EfiSimpleNetworkStopped != pMode->State ) {\r
+ if ( EfiSimpleNetworkStarted == pMode->State ) {\r
+ //\r
+ // Release the resources acquired in SN_Start\r
+ //\r
+\r
+ //\r
+ // Mark the adapter as stopped\r
+ //\r
+ pMode->State = EfiSimpleNetworkStopped;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ else {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_NOT_STARTED;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function releases the memory buffers assigned in the Initialize() call.\r
+ Pending transmits and receives are lost, and interrupts are cleared and disabled.\r
+ After this call, only Initialize() and Stop() calls may be used.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_Shutdown (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork\r
+ )\r
+{\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ UINT32 RxFilter;\r
+ EFI_STATUS Status;\r
+ \r
+ DBG_ENTER ( );\r
+ \r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
+ //\r
+ // Determine if the interface is already started\r
+ //\r
+ pMode = pSimpleNetwork->Mode;\r
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {\r
+ //\r
+ // Stop the adapter\r
+ //\r
+ RxFilter = pMode->ReceiveFilterSetting;\r
+ pMode->ReceiveFilterSetting = 0;\r
+ Status = SN_Reset ( pSimpleNetwork, FALSE );\r
+ pMode->ReceiveFilterSetting = RxFilter;\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Release the resources acquired by SN_Initialize\r
+ //\r
+\r
+ //\r
+ // Update the network state\r
+ //\r
+ pMode->State = EfiSimpleNetworkStarted;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_NOT_STARTED;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Send a packet over the network.\r
+\r
+ This function places the packet specified by Header and Buffer on\r
+ the transmit queue. This function performs a non-blocking transmit\r
+ operation. When the transmit is complete, the buffer is returned\r
+ via the GetStatus() call.\r
+\r
+ This routine calls ::Ax88772Rx to empty the network adapter of\r
+ receive packets. The routine then passes the transmit packet\r
+ to the network adapter.\r
+\r
+ @param [in] pSimpleNetwork Protocol instance pointer\r
+ @param [in] HeaderSize The size, in bytes, of the media header to be filled in by\r
+ the Transmit() function. If HeaderSize is non-zero, then\r
+ it must be equal to SimpleNetwork->Mode->MediaHeaderSize\r
+ and DestAddr and Protocol parameters must not be NULL.\r
+ @param [in] BufferSize The size, in bytes, of the entire packet (media header and\r
+ data) to be transmitted through the network interface.\r
+ @param [in] pBuffer A pointer to the packet (media header followed by data) to\r
+ to be transmitted. This parameter can not be NULL. If\r
+ HeaderSize is zero, then the media header is Buffer must\r
+ already be filled in by the caller. If HeaderSize is nonzero,\r
+ then the media header will be filled in by the Transmit()\r
+ function.\r
+ @param [in] pSrcAddr The source HW MAC address. If HeaderSize is zero, then\r
+ this parameter is ignored. If HeaderSize is nonzero and\r
+ SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress\r
+ is used for the source HW MAC address.\r
+ @param [in] pDestAddr The destination HW MAC address. If HeaderSize is zero, then\r
+ this parameter is ignored.\r
+ @param [in] pProtocol The type of header to build. If HeaderSize is zero, then\r
+ this parameter is ignored.\r
+\r
+ @retval EFI_SUCCESS This operation was successful.\r
+ @retval EFI_NOT_STARTED The network interface was not started.\r
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SN_Transmit (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
+ IN UINTN HeaderSize,\r
+ IN UINTN BufferSize,\r
+ IN VOID * pBuffer,\r
+ IN EFI_MAC_ADDRESS * pSrcAddr,\r
+ IN EFI_MAC_ADDRESS * pDestAddr,\r
+ IN UINT16 * pProtocol\r
+ )\r
+{\r
+ RX_TX_PACKET Packet;\r
+ ETHERNET_HEADER * pHeader;\r
+ EFI_SIMPLE_NETWORK_MODE * pMode;\r
+ NIC_DEVICE * pNicDevice;\r
+ EFI_USB_IO_PROTOCOL * pUsbIo;\r
+ EFI_STATUS Status;\r
+ EFI_TPL TplPrevious;\r
+ UINTN TransferLength;\r
+ UINT32 TransferStatus;\r
+ UINT16 Type;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
+ //\r
+ // The interface must be running\r
+ //\r
+ pMode = pSimpleNetwork->Mode;\r
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {\r
+ //\r
+ // Synchronize with Ax88772Timer\r
+ //\r
+ VERIFY_TPL ( TPL_AX88772 );\r
+ TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );\r
+\r
+ //\r
+ // Update the link status\r
+ //\r
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
+ Ax88772Rx ( pNicDevice, FALSE );\r
+ pMode->MediaPresent = pNicDevice->bLinkUp;\r
+\r
+ //\r
+ // Release the synchronization with Ax88772Timer\r
+ //\r
+ gBS->RestoreTPL ( TplPrevious );\r
+ if ( pMode->MediaPresent ) {\r
+ //\r
+ // Copy the packet into the USB buffer\r
+ //\r
+ CopyMem ( &Packet.Data[0], pBuffer, BufferSize );\r
+ Packet.Length = (UINT16) BufferSize;\r
+\r
+ //\r
+ // Transmit the packet\r
+ //\r
+ pHeader = (ETHERNET_HEADER *) &Packet.Data[0];\r
+ if ( 0 != HeaderSize ) {\r
+ if ( NULL != pDestAddr ) {\r
+ CopyMem ( &pHeader->dest_addr, pDestAddr, PXE_HWADDR_LEN_ETHER );\r
+ }\r
+ if ( NULL != pSrcAddr ) {\r
+ CopyMem ( &pHeader->src_addr, pSrcAddr, PXE_HWADDR_LEN_ETHER );\r
+ }\r
+ else {\r
+ CopyMem ( &pHeader->src_addr, &pMode->CurrentAddress.Addr[0], PXE_HWADDR_LEN_ETHER );\r
+ }\r
+ if ( NULL != pProtocol ) {\r
+ Type = *pProtocol;\r
+ }\r
+ else {\r
+ Type = Packet.Length;\r
+ }\r
+ Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));\r
+ pHeader->type = Type;\r
+ }\r
+ if ( Packet.Length < MIN_ETHERNET_PKT_SIZE ) {\r
+ Packet.Length = MIN_ETHERNET_PKT_SIZE;\r
+ ZeroMem ( &Packet.Data[ BufferSize ],\r
+ Packet.Length - BufferSize );\r
+ }\r
+ DEBUG (( DEBUG_TX | DEBUG_INFO,\r
+ "TX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",\r
+ Packet.Data[0],\r
+ Packet.Data[1],\r
+ Packet.Data[2],\r
+ Packet.Data[3],\r
+ Packet.Data[4],\r
+ Packet.Data[5],\r
+ Packet.Data[6],\r
+ Packet.Data[7],\r
+ Packet.Data[8],\r
+ Packet.Data[9],\r
+ Packet.Data[10],\r
+ Packet.Data[11],\r
+ Packet.Data[12],\r
+ Packet.Data[13],\r
+ Packet.Length ));\r
+ Packet.LengthBar = ~Packet.Length;\r
+ TransferLength = sizeof ( Packet.Length )\r
+ + sizeof ( Packet.LengthBar )\r
+ + Packet.Length;\r
+\r
+ //\r
+ // Work around USB bus driver bug where a timeout set by receive\r
+ // succeeds but the timeout expires immediately after, causing the\r
+ // transmit operation to timeout.\r
+ //\r
+ pUsbIo = pNicDevice->pUsbIo;\r
+ Status = pUsbIo->UsbBulkTransfer ( pUsbIo,\r
+ BULK_OUT_ENDPOINT,\r
+ &Packet.Length,\r
+ &TransferLength,\r
+ 0xfffffffe,\r
+ &TransferStatus );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = TransferStatus;\r
+ }\r
+ if (( !EFI_ERROR ( Status ))\r
+ && ( TransferLength != (UINTN)( Packet.Length + 4 ))) {\r
+ Status = EFI_WARN_WRITE_FAILURE;\r
+ }\r
+ if ( EFI_SUCCESS == Status ) {\r
+ pNicDevice->pTxBuffer = pBuffer;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+ "Ax88772 USB transmit error, TransferLength: %d, Status: %r\r\n",\r
+ sizeof ( Packet.Length ) + Packet.Length,\r
+ Status ));\r
+ //\r
+ // Reset the controller to fix the error\r
+ //\r
+ if ( EFI_DEVICE_ERROR == Status ) {\r
+ SN_Reset ( pSimpleNetwork, FALSE );\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ //\r
+ // No packets available.\r
+ //\r
+ Status = EFI_NOT_READY;\r
+ }\r
+ }\r
+ else {\r
+ Status = EFI_NOT_STARTED;\r
+ }\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+ "Ax88772 invalid transmit parameter\r\n"\r
+ " 0x%08x: HeaderSize\r\n"\r
+ " 0x%08x: BufferSize\r\n"\r
+ " 0x%08x: Buffer\r\n"\r
+ " 0x%08x: SrcAddr\r\n"\r
+ " 0x%08x: DestAddr\r\n"\r
+ " 0x%04x: Protocol\r\n",\r
+ HeaderSize,\r
+ BufferSize,\r
+ pBuffer,\r
+ pSrcAddr,\r
+ pDestAddr,\r
+ pProtocol ));\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r