--- /dev/null
+/** @file\r
+ Implement the interface to the AX88772 Ethernet controller.\r
+\r
+ This module implements the interface to the ASIX AX88772\r
+ USB to Ethernet MAC with integrated 10/100 PHY. Note that this implementation\r
+ only supports the integrated PHY since no other test cases were available.\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
+/**\r
+ Compute the CRC\r
+\r
+ @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.\r
+\r
+ @returns The CRC-32 value associated with this MAC address\r
+\r
+**/\r
+UINT32\r
+Ax88772Crc (\r
+ IN UINT8 * pMacAddress\r
+ )\r
+{\r
+ UINT32 BitNumber;\r
+ INT32 Carry;\r
+ INT32 Crc;\r
+ UINT32 Data;\r
+ UINT8 * pEnd;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Walk the MAC address\r
+ //\r
+ Crc = -1;\r
+ pEnd = &pMacAddress[ PXE_HWADDR_LEN_ETHER ];\r
+ while ( pEnd > pMacAddress ) {\r
+ Data = *pMacAddress++;\r
+ \r
+ \r
+ //\r
+ // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1\r
+ //\r
+ // 1 0000 0100 1100 0001 0001 1101 1011 0111\r
+ //\r
+ for ( BitNumber = 0; 8 > BitNumber; BitNumber++ ) {\r
+ Carry = (( Crc >> 31 ) & 1 ) ^ ( Data & 1 );\r
+ Crc <<= 1;\r
+ if ( 0 != Carry ) {\r
+ Crc ^= 0x04c11db7;\r
+ }\r
+ Data >>= 1;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the CRC value\r
+ //\r
+ DBG_EXIT_HEX ( Crc );\r
+ return (UINT32) Crc;\r
+}\r
+\r
+\r
+/**\r
+ Get the MAC address\r
+\r
+ This routine calls ::Ax88772UsbCommand to request the MAC\r
+ address from the network adapter.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [out] pMacAddress Address of a six byte buffer to receive the MAC address.\r
+\r
+ @retval EFI_SUCCESS The MAC address is available.\r
+ @retval other The MAC address is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772MacAddressGet (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ OUT UINT8 * pMacAddress\r
+ )\r
+{\r
+ USB_DEVICE_REQUEST SetupMsg;\r
+ EFI_STATUS Status;\r
+ \r
+ DBG_ENTER ( );\r
+ \r
+ //\r
+ // Set the register address.\r
+ //\r
+ SetupMsg.RequestType = USB_ENDPOINT_DIR_IN\r
+ | USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_MAC_ADDRESS_READ;\r
+ SetupMsg.Value = 0;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = PXE_HWADDR_LEN_ETHER;\r
+\r
+ //\r
+ // Read the PHY register\r
+ //\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ pMacAddress );\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 routine calls ::Ax88772UsbCommand to set the MAC address\r
+ in the network adapter.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address.\r
+\r
+ @retval EFI_SUCCESS The MAC address was set.\r
+ @retval other The MAC address was not set.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772MacAddressSet (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT8 * pMacAddress\r
+ )\r
+{\r
+ USB_DEVICE_REQUEST SetupMsg;\r
+ EFI_STATUS Status;\r
+ \r
+ DBG_ENTER ( );\r
+ \r
+ //\r
+ // Set the register address.\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_MAC_ADDRESS_WRITE;\r
+ SetupMsg.Value = 0;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = PXE_HWADDR_LEN_ETHER;\r
+ \r
+ //\r
+ // Read the PHY register\r
+ //\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ pMacAddress );\r
+ \r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Clear the multicast hash table\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+\r
+**/\r
+VOID\r
+Ax88772MulticastClear (\r
+ IN NIC_DEVICE * pNicDevice\r
+ )\r
+{\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Clear the multicast hash table\r
+ //\r
+ pNicDevice->MulticastHash[0] = 0;\r
+ pNicDevice->MulticastHash[1] = 0;\r
+\r
+ DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+ Enable a multicast address in the multicast hash table\r
+\r
+ This routine calls ::Ax88772Crc to compute the hash bit for\r
+ this MAC address.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.\r
+\r
+**/\r
+VOID\r
+Ax88772MulticastSet (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT8 * pMacAddress\r
+ )\r
+{\r
+ UINT32 BitNumber;\r
+ UINT32 Crc;\r
+ UINT32 Mask;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Compute the CRC on the destination address\r
+ //\r
+ Crc = Ax88772Crc ( pMacAddress );\r
+\r
+ //\r
+ // Set the bit corresponding to the destination address\r
+ //\r
+ BitNumber = Crc >> 26;\r
+ if ( 32 > BitNumber ) {\r
+ Mask = 1 << BitNumber;\r
+ pNicDevice->MulticastHash[0] |= Mask;\r
+ }\r
+ else {\r
+ Mask = 1 << ( BitNumber - 32 );\r
+ pNicDevice->MulticastHash[1] |= Mask;\r
+ }\r
+\r
+ //\r
+ // Display the multicast address\r
+ //\r
+ DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO,\r
+ "Enable multicast: 0x%02x-%02x-%02x-%02x-%02x-%02x, CRC: 0x%08x, Bit number: 0x%02x\r\n",\r
+ pMacAddress[0],\r
+ pMacAddress[1],\r
+ pMacAddress[2],\r
+ pMacAddress[3],\r
+ pMacAddress[4],\r
+ pMacAddress[5],\r
+ Crc,\r
+ BitNumber ));\r
+\r
+ DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+ Start the link negotiation\r
+\r
+ This routine calls ::Ax88772PhyWrite to start the PHY's link\r
+ negotiation.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+\r
+ @retval EFI_SUCCESS The link negotiation was started.\r
+ @retval other Failed to start the link negotiation.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772NegotiateLinkStart (\r
+ IN NIC_DEVICE * pNicDevice\r
+ )\r
+{\r
+ UINT16 Control;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Set the supported capabilities.\r
+ //\r
+ Status = Ax88772PhyWrite ( pNicDevice,\r
+ PHY_ANAR,\r
+ AN_CSMA_CD\r
+ | AN_TX_FDX | AN_TX_HDX\r
+ | AN_10_FDX | AN_10_HDX );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Set the link speed and duplex\r
+ //\r
+ Control = BMCR_AUTONEGOTIATION_ENABLE\r
+ | BMCR_RESTART_AUTONEGOTIATION;\r
+ if ( pNicDevice->b100Mbps ) {\r
+ Control |= BMCR_100MBPS;\r
+ }\r
+ if ( pNicDevice->bFullDuplex ) {\r
+ Control |= BMCR_FULL_DUPLEX;\r
+ }\r
+ Status = Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control );\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Complete the negotiation of the PHY link\r
+\r
+ This routine calls ::Ax88772PhyRead to determine if the\r
+ link negotiation is complete.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in, out] pPollCount Address of number of times this routine was polled\r
+ @param [out] pbComplete Address of boolean to receive complate status.\r
+ @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up.\r
+ @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps.\r
+ @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full.\r
+\r
+ @retval EFI_SUCCESS The MAC address is available.\r
+ @retval other The MAC address is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772NegotiateLinkComplete (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN OUT UINTN * pPollCount,\r
+ OUT BOOLEAN * pbComplete,\r
+ OUT BOOLEAN * pbLinkUp,\r
+ OUT BOOLEAN * pbHiSpeed,\r
+ OUT BOOLEAN * pbFullDuplex\r
+ )\r
+{\r
+ UINT16 Mask;\r
+ UINT16 PhyData;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+ \r
+ //\r
+ // Determine if the link is up.\r
+ //\r
+ *pbComplete = FALSE;\r
+\r
+ //\r
+ // Get the link status\r
+ //\r
+ Status = Ax88772PhyRead ( pNicDevice,\r
+ PHY_BMSR,\r
+ &PhyData );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Determine if the autonegotiation is complete.\r
+ //\r
+ *pbLinkUp = (BOOLEAN)( 0 != ( PhyData & BMSR_LINKST ));\r
+ *pbComplete = *pbLinkUp;\r
+ if ( 0 != *pbComplete ) {\r
+ //\r
+ // Get the partners capabilities.\r
+ //\r
+ Status = Ax88772PhyRead ( pNicDevice,\r
+ PHY_ANLPAR,\r
+ &PhyData );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Autonegotiation is complete\r
+ // Determine the link speed.\r
+ //\r
+ *pbHiSpeed = (BOOLEAN)( 0 != ( PhyData & ( AN_TX_FDX | AN_TX_HDX )));\r
+\r
+ //\r
+ // Determine the link duplex.\r
+ //\r
+ Mask = ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX;\r
+ *pbFullDuplex = (BOOLEAN)( 0 != ( PhyData & Mask ));\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Read a register from the PHY\r
+\r
+ This routine calls ::Ax88772UsbCommand to read a PHY register.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] RegisterAddress Number of the register to read.\r
+ @param [in, out] pPhyData Address of a buffer to receive the PHY register value\r
+\r
+ @retval EFI_SUCCESS The PHY data is available.\r
+ @retval other The PHY data is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772PhyRead (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT8 RegisterAddress,\r
+ IN OUT UINT16 * pPhyData\r
+ )\r
+{\r
+ USB_DEVICE_REQUEST SetupMsg;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Request access to the PHY\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;\r
+ SetupMsg.Value = 0;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = 0;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Read the PHY register address.\r
+ //\r
+ SetupMsg.RequestType = USB_ENDPOINT_DIR_IN\r
+ | USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_PHY_REG_READ;\r
+ SetupMsg.Value = pNicDevice->PhyId;\r
+ SetupMsg.Index = RegisterAddress;\r
+ SetupMsg.Length = sizeof ( *pPhyData );\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ pPhyData );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_PHY | DEBUG_INFO,\r
+ "PHY %d: 0x%02x --> 0x%04x\r\n",\r
+ pNicDevice->PhyId,\r
+ RegisterAddress,\r
+ *pPhyData ));\r
+\r
+ //\r
+ // Release the PHY to the hardware\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;\r
+ SetupMsg.Value = 0;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = 0;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status.\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Write to a PHY register\r
+\r
+ This routine calls ::Ax88772UsbCommand to write a PHY register.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] RegisterAddress Number of the register to read.\r
+ @param [in] PhyData Address of a buffer to receive the PHY register value\r
+\r
+ @retval EFI_SUCCESS The PHY data was written.\r
+ @retval other Failed to wwrite the PHY register.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772PhyWrite (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT8 RegisterAddress,\r
+ IN UINT16 PhyData\r
+ )\r
+{\r
+ USB_DEVICE_REQUEST SetupMsg;\r
+ EFI_STATUS Status;\r
+ \r
+ DBG_ENTER ( );\r
+ \r
+ //\r
+ // Request access to the PHY\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;\r
+ SetupMsg.Value = 0;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = 0;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Write the PHY register\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_PHY_REG_WRITE;\r
+ SetupMsg.Value = pNicDevice->PhyId;\r
+ SetupMsg.Index = RegisterAddress;\r
+ SetupMsg.Length = sizeof ( PhyData );\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ &PhyData );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_PHY | DEBUG_INFO,\r
+ "PHY %d: 0x%02x <-- 0x%04x\r\n",\r
+ pNicDevice->PhyId,\r
+ RegisterAddress,\r
+ PhyData ));\r
+\r
+ //\r
+ // Release the PHY to the hardware\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;\r
+ SetupMsg.Value = 0;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = 0;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\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 AX88772\r
+\r
+ This routine uses ::Ax88772UsbCommand to reset the network\r
+ adapter. This routine also uses ::Ax88772PhyWrite to reset\r
+ the PHY.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+\r
+ @retval EFI_SUCCESS The MAC address is available.\r
+ @retval other The MAC address is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772Reset (\r
+ IN NIC_DEVICE * pNicDevice\r
+ )\r
+{\r
+ USB_DEVICE_REQUEST SetupMsg;\r
+ EFI_STATUS Status;\r
+ \r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Turn off the MAC\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_RX_CONTROL_WRITE;\r
+ SetupMsg.Value = 0;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = 0;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_PHY | DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST\r
+ | DEBUG_RX_UNICAST | DEBUG_TX | DEBUG_INFO,\r
+ "MAC reset\r\n" ));\r
+\r
+ //\r
+ // The link is now idle\r
+ //\r
+ pNicDevice->bLinkIdle = TRUE;\r
+\r
+ //\r
+ // Delay for a bit\r
+ //\r
+ gBS->Stall ( RESET_MSEC );\r
+\r
+ //\r
+ // Select the internal PHY\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_PHY_SELECT;\r
+ SetupMsg.Value = SPHY_PSEL;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = 0;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Delay for a bit\r
+ //\r
+ gBS->Stall ( PHY_RESET_MSEC );\r
+\r
+ //\r
+ // Clear the internal PHY reset\r
+ //\r
+ SetupMsg.Request = CMD_RESET;\r
+ SetupMsg.Value = SRR_IPRL | SRR_PRL;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Reset the PHY\r
+ //\r
+ Status = Ax88772PhyWrite ( pNicDevice,\r
+ PHY_BMCR,\r
+ BMCR_RESET );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Set the gaps\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_GAPS_WRITE;\r
+ SetupMsg.Value = 0x0c15;\r
+ SetupMsg.Index = 0x0e;\r
+ SetupMsg.Length = 0;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status.\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Receive a frame from the network.\r
+\r
+ This routine polls the USB receive interface for a packet. If a packet\r
+ is available, this routine adds the receive packet to the list of\r
+ pending receive packets.\r
+\r
+ This routine calls ::Ax88772NegotiateLinkComplete to verify\r
+ that the link is up. This routine also calls ::SN_Reset to\r
+ reset the network adapter when necessary. Finally this\r
+ routine attempts to receive one or more packets from the\r
+ network adapter.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] bUpdateLink TRUE = Update link status\r
+\r
+**/\r
+VOID\r
+Ax88772Rx (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN BOOLEAN bUpdateLink\r
+ )\r
+{\r
+ BOOLEAN bFullDuplex;\r
+ BOOLEAN bLinkUp;\r
+ BOOLEAN bRxPacket;\r
+ BOOLEAN bSpeed100;\r
+ UINTN LengthInBytes;\r
+ RX_TX_PACKET Packet;\r
+ RX_TX_PACKET * pRxPacket;\r
+ EFI_USB_IO_PROTOCOL *pUsbIo;\r
+ EFI_STATUS Status;\r
+ EFI_TPL TplPrevious;\r
+ UINT32 TransferStatus;\r
+\r
+ //\r
+ // Synchronize with Ax88772Timer\r
+ //\r
+ VERIFY_TPL ( TPL_AX88772 );\r
+ TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );\r
+ DEBUG (( DEBUG_TPL | DEBUG_INFO,\r
+ "%d: TPL\r\n",\r
+ TPL_AX88772 ));\r
+\r
+ //\r
+ // Get the link status\r
+ //\r
+ if ( bUpdateLink ) {\r
+ bLinkUp = pNicDevice->bLinkUp;\r
+ bSpeed100 = pNicDevice->b100Mbps;\r
+ bFullDuplex = pNicDevice->bFullDuplex;\r
+ Status = Ax88772NegotiateLinkComplete ( pNicDevice,\r
+ &pNicDevice->PollCount,\r
+ &pNicDevice->bComplete,\r
+ &pNicDevice->bLinkUp,\r
+ &pNicDevice->b100Mbps,\r
+ &pNicDevice->bFullDuplex );\r
+\r
+ //\r
+ // Determine if the autonegotiation is complete\r
+ //\r
+ if ( pNicDevice->bComplete ) {\r
+ if ( pNicDevice->bLinkUp ) {\r
+ if (( bSpeed100 && ( !pNicDevice->b100Mbps ))\r
+ || (( !bSpeed100 ) && pNicDevice->b100Mbps )\r
+ || ( bFullDuplex && ( !pNicDevice->bFullDuplex ))\r
+ || (( !bFullDuplex ) && pNicDevice->bFullDuplex )) {\r
+ pNicDevice->PollCount = 0;\r
+ DEBUG (( DEBUG_LINK | DEBUG_INFO,\r
+ "Reset to establish proper link setup: %d Mbps, %s duplex\r\n",\r
+ pNicDevice->b100Mbps ? 100 : 10,\r
+ pNicDevice->bFullDuplex ? L"Full" : L"Half" ));\r
+ Status = SN_Reset ( &pNicDevice->SimpleNetwork, FALSE );\r
+ }\r
+ if (( !bLinkUp ) && pNicDevice->bLinkUp ) {\r
+ //\r
+ // Display the autonegotiation status\r
+ //\r
+ DEBUG (( DEBUG_LINK | DEBUG_INFO,\r
+ "Link: Up, %d Mbps, %s duplex\r\n",\r
+ pNicDevice->b100Mbps ? 100 : 10,\r
+ pNicDevice->bFullDuplex ? L"Full" : L"Half" ));\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Update the link status\r
+ //\r
+ if ( bLinkUp && ( !pNicDevice->bLinkUp )) {\r
+ DEBUG (( DEBUG_LINK | DEBUG_INFO, "Link: Down\r\n" ));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Loop until all the packets are emptied from the receiver\r
+ //\r
+ do {\r
+ bRxPacket = FALSE;\r
+\r
+ //\r
+ // Locate a packet for use\r
+ //\r
+ pRxPacket = pNicDevice->pRxFree;\r
+ LengthInBytes = sizeof ( *pRxPacket ) - sizeof ( pRxPacket->pNext );\r
+ if ( NULL == pRxPacket ) {\r
+ Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r
+ LengthInBytes,\r
+ (VOID **) &pRxPacket );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Add this packet to the free packet list\r
+ //\r
+ pNicDevice->pRxFree = pRxPacket;\r
+ pRxPacket->pNext = NULL;\r
+ }\r
+ else {\r
+ //\r
+ // Use the discard packet buffer\r
+ //\r
+ pRxPacket = &Packet;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Attempt to receive a packet\r
+ //\r
+ pUsbIo = pNicDevice->pUsbIo;\r
+ Status = pUsbIo->UsbBulkTransfer ( pUsbIo,\r
+ USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,\r
+ &pRxPacket->Length,\r
+ &LengthInBytes,\r
+ 2,\r
+ &TransferStatus );\r
+ if (( !EFI_ERROR ( Status ))\r
+ && ( 0 < pRxPacket->Length )\r
+ && ( pRxPacket->Length <= sizeof ( pRxPacket->Data ))) {\r
+\r
+ //\r
+ // Determine if the packet should be received\r
+ //\r
+ bRxPacket = TRUE;\r
+ LengthInBytes = pRxPacket->Length;\r
+ pNicDevice->bLinkIdle = FALSE;\r
+ if ( pNicDevice->pRxFree == pRxPacket ) {\r
+ //\r
+ // Display the received packet\r
+ //\r
+ if ( 0 != ( pRxPacket->Data[0] & 1 )) {\r
+ if (( 0xff == pRxPacket->Data[0])\r
+ && ( 0xff == pRxPacket->Data[1])\r
+ && ( 0xff == pRxPacket->Data[2])\r
+ && ( 0xff == pRxPacket->Data[3])\r
+ && ( 0xff == pRxPacket->Data[4])\r
+ && ( 0xff == pRxPacket->Data[5])) {\r
+ DEBUG (( DEBUG_RX_BROADCAST | DEBUG_INFO,\r
+ "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",\r
+ pRxPacket->Data[0],\r
+ pRxPacket->Data[1],\r
+ pRxPacket->Data[2],\r
+ pRxPacket->Data[3],\r
+ pRxPacket->Data[4],\r
+ pRxPacket->Data[5],\r
+ pRxPacket->Data[6],\r
+ pRxPacket->Data[7],\r
+ pRxPacket->Data[8],\r
+ pRxPacket->Data[9],\r
+ pRxPacket->Data[10],\r
+ pRxPacket->Data[11],\r
+ pRxPacket->Data[12],\r
+ pRxPacket->Data[13],\r
+ LengthInBytes ));\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO,\r
+ "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",\r
+ pRxPacket->Data[0],\r
+ pRxPacket->Data[1],\r
+ pRxPacket->Data[2],\r
+ pRxPacket->Data[3],\r
+ pRxPacket->Data[4],\r
+ pRxPacket->Data[5],\r
+ pRxPacket->Data[6],\r
+ pRxPacket->Data[7],\r
+ pRxPacket->Data[8],\r
+ pRxPacket->Data[9],\r
+ pRxPacket->Data[10],\r
+ pRxPacket->Data[11],\r
+ pRxPacket->Data[12],\r
+ pRxPacket->Data[13],\r
+ LengthInBytes ));\r
+ }\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_RX_UNICAST | DEBUG_INFO,\r
+ "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",\r
+ pRxPacket->Data[0],\r
+ pRxPacket->Data[1],\r
+ pRxPacket->Data[2],\r
+ pRxPacket->Data[3],\r
+ pRxPacket->Data[4],\r
+ pRxPacket->Data[5],\r
+ pRxPacket->Data[6],\r
+ pRxPacket->Data[7],\r
+ pRxPacket->Data[8],\r
+ pRxPacket->Data[9],\r
+ pRxPacket->Data[10],\r
+ pRxPacket->Data[11],\r
+ pRxPacket->Data[12],\r
+ pRxPacket->Data[13],\r
+ LengthInBytes ));\r
+ }\r
+ \r
+ //\r
+ // Remove this packet from the free packet list\r
+ //\r
+ pNicDevice->pRxFree = pRxPacket->pNext;\r
+ pRxPacket->pNext = NULL;\r
+\r
+ //\r
+ // Append this packet to the receive list\r
+ //\r
+ if ( NULL == pNicDevice->pRxTail ) {\r
+ pNicDevice->pRxHead = pRxPacket;\r
+ }\r
+ else {\r
+ pNicDevice->pRxTail->pNext = pRxPacket;\r
+ }\r
+ pNicDevice->pRxTail = pRxPacket;\r
+ }\r
+ else {\r
+ //\r
+ // Error, not enough buffers for this packet, discard packet\r
+ //\r
+ DEBUG (( DEBUG_WARN | DEBUG_INFO,\r
+ "WARNING - No buffer, discarding RX packet: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",\r
+ pRxPacket->Data[0],\r
+ pRxPacket->Data[1],\r
+ pRxPacket->Data[2],\r
+ pRxPacket->Data[3],\r
+ pRxPacket->Data[4],\r
+ pRxPacket->Data[5],\r
+ pRxPacket->Data[6],\r
+ pRxPacket->Data[7],\r
+ pRxPacket->Data[8],\r
+ pRxPacket->Data[9],\r
+ pRxPacket->Data[10],\r
+ pRxPacket->Data[11],\r
+ pRxPacket->Data[12],\r
+ pRxPacket->Data[13],\r
+ LengthInBytes ));\r
+ }\r
+ }\r
+ }while ( bRxPacket );\r
+\r
+ //\r
+ // Release the synchronization withhe Ax88772Timer\r
+ //\r
+ gBS->RestoreTPL ( TplPrevious );\r
+ DEBUG (( DEBUG_TPL | DEBUG_INFO,\r
+ "%d: TPL\r\n",\r
+ TplPrevious ));\r
+}\r
+\r
+\r
+/**\r
+ Enable or disable the receiver\r
+\r
+ This routine calls ::Ax88772UsbCommand to update the\r
+ receiver state. This routine also calls ::Ax88772MacAddressSet\r
+ to establish the MAC address for the network adapter.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] RxFilter Simple network RX filter mask value\r
+\r
+ @retval EFI_SUCCESS The MAC address was set.\r
+ @retval other The MAC address was not set.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772RxControl (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT32 RxFilter\r
+ )\r
+{\r
+ UINT16 MediumStatus;\r
+ INT32 MulticastHash[2];\r
+ UINT16 RxControl;\r
+ USB_DEVICE_REQUEST SetupMsg;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Disable all multicast\r
+ //\r
+ MulticastHash[0] = 0;\r
+ MulticastHash[1] = 0;\r
+\r
+ //\r
+ // Enable the receiver if something is to be received\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ RxControl = RXC_SO | RXC_MFB_16384;\r
+ if ( 0 != RxFilter ) {\r
+ //\r
+ // Enable the receiver\r
+ //\r
+ SetupMsg.RequestType = USB_ENDPOINT_DIR_IN\r
+ | USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_MEDIUM_STATUS_READ;\r
+ SetupMsg.Value = 0;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = sizeof ( MediumStatus );\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ &MediumStatus );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ if ( 0 == ( MediumStatus & MS_RE )) {\r
+ MediumStatus |= MS_RE | MS_ONE;\r
+ if ( pNicDevice->bFullDuplex ) {\r
+ MediumStatus |= MS_TFC | MS_RFC;\r
+ }\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE;\r
+ SetupMsg.Value = MediumStatus;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = 0;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+ "ERROR - Failed to enable receiver, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+ "ERROR - Failed to read receiver status, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+\r
+ //\r
+ // Enable multicast if requested\r
+ //\r
+ if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {\r
+ RxControl |= RXC_AM;\r
+ MulticastHash[0] = pNicDevice->MulticastHash[0];\r
+ MulticastHash[1] = pNicDevice->MulticastHash[1];\r
+ }\r
+\r
+ //\r
+ // Enable all multicast if requested\r
+ //\r
+ if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) {\r
+ RxControl |= RXC_AMALL;\r
+ MulticastHash[0] = -1;\r
+ MulticastHash[1] = -1;\r
+ }\r
+\r
+ //\r
+ // Enable broadcast if requested\r
+ //\r
+ if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) {\r
+ RxControl |= RXC_AB;\r
+ }\r
+\r
+ //\r
+ // Enable promiscuous mode if requested\r
+ //\r
+ if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) {\r
+ RxControl |= RXC_PRO;\r
+ MulticastHash[0] = -1;\r
+ MulticastHash[1] = -1;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Update the MAC address\r
+ //\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = Ax88772MacAddressSet ( pNicDevice, &pNicDevice->SimpleNetworkData.CurrentAddress.Addr[0]);\r
+ }\r
+\r
+ //\r
+ // Update the receiver control\r
+ //\r
+ if ( !EFI_ERROR ( Status )) {\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_RX_CONTROL_WRITE;\r
+ SetupMsg.Value = RxControl;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = 0;\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ NULL );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST | DEBUG_RX_UNICAST | DEBUG_INFO,\r
+ "RxControl: 0x%04x\r\n",\r
+ RxControl ));\r
+\r
+ //\r
+ // Update the multicast hash table\r
+ //\r
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_MULTICAST_HASH_WRITE;\r
+ SetupMsg.Value = 0;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash );\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ &pNicDevice->MulticastHash );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO,\r
+ "Multicast Hash: 0x%02x %02x %02x %02x %02x %02x %02x %02x\r\n",\r
+ (UINT8) MulticastHash[0],\r
+ (UINT8)( MulticastHash[0] >> 8 ),\r
+ (UINT8)( MulticastHash[0] >> 16 ),\r
+ (UINT8)( MulticastHash[0] >> 24 ),\r
+ (UINT8) MulticastHash[1],\r
+ (UINT8)( MulticastHash[1] >> 8 ),\r
+ (UINT8)( MulticastHash[1] >> 16 ),\r
+ (UINT8)( MulticastHash[1] >> 24 )));\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+ "ERROR - Failed to update multicast hash table, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+ "ERROR - Failed to set receiver control, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Read an SROM location\r
+\r
+ This routine calls ::Ax88772UsbCommand to read data from the\r
+ SROM.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] Address SROM address\r
+ @param [out] pData Buffer to receive the data\r
+\r
+ @retval EFI_SUCCESS The read was successful\r
+ @retval other The read failed\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772SromRead (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT32 Address,\r
+ OUT UINT16 * pData\r
+ )\r
+{\r
+ USB_DEVICE_REQUEST SetupMsg;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Read a value from the SROM\r
+ //\r
+ SetupMsg.RequestType = USB_ENDPOINT_DIR_IN\r
+ | USB_REQ_TYPE_VENDOR\r
+ | USB_TARGET_DEVICE;\r
+ SetupMsg.Request = CMD_SROM_READ;\r
+ SetupMsg.Value = (UINT16) Address;\r
+ SetupMsg.Index = 0;\r
+ SetupMsg.Length = sizeof ( *pData );\r
+ Status = Ax88772UsbCommand ( pNicDevice,\r
+ &SetupMsg,\r
+ pData );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This routine is called at a regular interval to poll for\r
+ receive packets.\r
+\r
+ This routine polls the link state and gets any receive packets\r
+ by calling ::Ax88772Rx.\r
+\r
+ @param [in] Event Timer event\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+\r
+**/\r
+VOID\r
+Ax88772Timer (\r
+ IN EFI_EVENT Event,\r
+ IN NIC_DEVICE * pNicDevice\r
+ )\r
+{\r
+ //\r
+ // Use explicit DEBUG messages since the output frequency is too\r
+ // high for DEBUG_INFO to keep up and have spare cycles for the\r
+ // shell\r
+ //\r
+ DEBUG (( DEBUG_TIMER, "Entering Ax88772Timer\r\n" ));\r
+\r
+ //\r
+ // Poll the link state and get any receive packets\r
+ //\r
+ Ax88772Rx ( pNicDevice, FALSE );\r
+\r
+ DEBUG (( DEBUG_TIMER, "Exiting Ax88772Timer\r\n" ));\r
+}\r
+\r
+\r
+/**\r
+ Send a command to the USB device.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] pRequest Pointer to the request structure\r
+ @param [in, out] pBuffer Data buffer address\r
+\r
+ @retval EFI_SUCCESS The USB transfer was successful\r
+ @retval other The USB transfer failed\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772UsbCommand (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN USB_DEVICE_REQUEST * pRequest,\r
+ IN OUT VOID * pBuffer\r
+ )\r
+{\r
+ UINT32 CmdStatus;\r
+ EFI_USB_DATA_DIRECTION Direction;\r
+ EFI_USB_IO_PROTOCOL * pUsbIo;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Determine the transfer direction\r
+ //\r
+ Direction = EfiUsbNoData;\r
+ if ( 0 != pRequest->Length ) {\r
+ Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN ))\r
+ ? EfiUsbDataIn : EfiUsbDataOut;\r
+ }\r
+\r
+ //\r
+ // Issue the command\r
+ //\r
+ pUsbIo = pNicDevice->pUsbIo;\r
+ Status = pUsbIo->UsbControlTransfer ( pUsbIo,\r
+ pRequest,\r
+ Direction,\r
+ USB_BUS_TIMEOUT,\r
+ pBuffer,\r
+ pRequest->Length,\r
+ &CmdStatus );\r
+\r
+ //\r
+ // Determine the operation status\r
+ //\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = CmdStatus;\r
+ }\r
+ else {\r
+ //\r
+ // Display any errors\r
+ //\r
+ DEBUG (( DEBUG_INFO,\r
+ "Ax88772UsbCommand - Status: %r\n",\r
+ Status ));\r
+\r
+ //\r
+ // Only use status values associated with the Simple Network protocol\r
+ //\r
+ if ( EFI_TIMEOUT == Status ) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ Definitions for ASIX AX88772 Ethernet adapter.\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
+#ifndef _AX88772_H_\r
+#define _AX88772_H_\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/NicIp4ConfigNvData.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/NetworkInterfaceIdentifier.h>\r
+#include <Protocol/SimpleNetwork.h>\r
+#include <Protocol/UsbIo.h>\r
+\r
+//------------------------------------------------------------------------------\r
+// Macros\r
+//------------------------------------------------------------------------------\r
+\r
+#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */\r
+#define DBG_ENTER() DEBUG (( DEBUG_INFO, "Entering " __FUNCTION__ "\n" )) ///< Display routine entry\r
+#define DBG_EXIT() DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ "\n" )) ///< Display routine exit\r
+#define DBG_EXIT_DEC(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %d\n", Status )) ///< Display routine exit with decimal value\r
+#define DBG_EXIT_HEX(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status )) ///< Display routine exit with hex value\r
+#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %r\n", Status )) ///< Display routine exit with status value\r
+#define DBG_EXIT_TF(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" )) ///< Display routine with TRUE/FALSE value\r
+#else // _MSC_VER\r
+#define DBG_ENTER() ///< Display routine entry\r
+#define DBG_EXIT() ///< Display routine exit\r
+#define DBG_EXIT_DEC(Status) ///< Display routine exit with decimal value\r
+#define DBG_EXIT_HEX(Status) ///< Display routine exit with hex value\r
+#define DBG_EXIT_STATUS(Status) ///< Display routine exit with status value\r
+#define DBG_EXIT_TF(Status) ///< Display routine with TRUE/FALSE value\r
+#endif // _MSC_VER\r
+\r
+#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) != 0) ///< Return TRUE/FALSE for IN direction\r
+#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) == 0) ///< Return TRUE/FALSE for OUT direction\r
+#define USB_IS_BULK_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_BULK) ///< Return TRUE/FALSE for BULK type\r
+#define USB_IS_INTERRUPT_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) ///< Return TRUE/FALSE for INTERRUPT type\r
+\r
+//------------------------------------------------------------------------------\r
+// Constants\r
+//------------------------------------------------------------------------------\r
+\r
+#define DEBUG_RX_BROADCAST 0x40000000 ///< Display RX broadcast messages\r
+#define DEBUG_RX_MULTICAST 0x20000000 ///< Display RX multicast messages\r
+#define DEBUG_RX_UNICAST 0x10000000 ///< Display RX unicast messages\r
+#define DEBUG_MAC_ADDRESS 0x08000000 ///< Display the MAC address\r
+#define DEBUG_LINK 0x04000000 ///< Display the link status\r
+#define DEBUG_TX 0x02000000 ///< Display the TX messages\r
+#define DEBUG_PHY 0x01000000 ///< Display the PHY register values\r
+#define DEBUG_SROM 0x00800000 ///< Display the SROM contents\r
+#define DEBUG_TIMER 0x00400000 ///< Display the timer routine entry/exit\r
+#define DEBUG_TPL 0x00200000 ///< Display the timer routine entry/exit\r
+\r
+#define AX88772_MAX_PKT_SIZE ( 2048 - 4 ) ///< Maximum packet size\r
+#define ETHERNET_HEADER_SIZE sizeof ( ETHERNET_HEADER ) ///< Size in bytes of the Ethernet header\r
+#define MIN_ETHERNET_PKT_SIZE 60 ///< Minimum packet size including Ethernet header\r
+#define MAX_ETHERNET_PKT_SIZE 1500 ///< Ethernet spec 3.1.1: Minimum packet size\r
+\r
+#define USB_NETWORK_CLASS 0x09 ///< USB Network class code\r
+#define USB_BUS_TIMEOUT 1000 ///< USB timeout in milliseconds\r
+\r
+#define TIMER_MSEC 20 ///< Polling interval for the NIC\r
+#define TPL_AX88772 TPL_CALLBACK ///< TPL for routine synchronization\r
+\r
+/**\r
+ Verify new TPL value\r
+\r
+ This macro which is enabled when debug is enabled verifies that\r
+ the new TPL value is >= the current TPL value.\r
+**/\r
+#ifdef VERIFY_TPL\r
+#undef VERIFY_TPL\r
+#endif // VERIFY_TPL\r
+\r
+#if !defined(MDEPKG_NDEBUG)\r
+\r
+#define VERIFY_TPL(tpl) \\r
+{ \\r
+ EFI_TPL PreviousTpl; \\r
+ \\r
+ PreviousTpl = gBS->RaiseTPL ( TPL_HIGH_LEVEL ); \\r
+ gBS->RestoreTPL ( PreviousTpl ); \\r
+ if ( PreviousTpl > tpl ) { \\r
+ DEBUG (( DEBUG_ERROR, "Current TPL: %d, New TPL: %d\r\n", PreviousTpl, tpl )); \\r
+ ASSERT ( PreviousTpl <= tpl ); \\r
+ } \\r
+}\r
+\r
+#else // MDEPKG_NDEBUG\r
+\r
+#define VERIFY_TPL(tpl)\r
+\r
+#endif // MDEPKG_NDEBUG\r
+\r
+//------------------------------------------------------------------------------\r
+// Hardware Definition\r
+//------------------------------------------------------------------------------\r
+\r
+#define DEV_SIGNATURE SIGNATURE_32 ('A','X','8','8') ///< Signature of data structures in memory\r
+\r
+#define VENDOR_ID 0x0b95 ///< Vendor ID for Asix\r
+#define PRODUCT_ID 0x7720 ///< Product ID for the AX88772 USB 10/100 Ethernet controller\r
+\r
+#define RESET_MSEC 1000 ///< Reset duration\r
+#define PHY_RESET_MSEC 500 ///< PHY reset duration\r
+\r
+//\r
+// RX Control register\r
+//\r
+\r
+#define RXC_PRO 0x0001 ///< Receive all packets\r
+#define RXC_AMALL 0x0002 ///< Receive all multicast packets\r
+#define RXC_SEP 0x0004 ///< Save error packets\r
+#define RXC_AB 0x0008 ///< Receive broadcast packets\r
+#define RXC_AM 0x0010 ///< Use multicast destination address hash table\r
+#define RXC_AP 0x0020 ///< Accept physical address from Multicast Filter\r
+#define RXC_SO 0x0080 ///< Start operation\r
+#define RXC_MFB 0x0300 ///< Maximum frame burst\r
+#define RXC_MFB_2048 0 ///< Maximum frame size: 2048 bytes\r
+#define RXC_MFB_4096 0x0100 ///< Maximum frame size: 4096 bytes\r
+#define RXC_MFB_8192 0x0200 ///< Maximum frame size: 8192 bytes\r
+#define RXC_MFB_16384 0x0300 ///< Maximum frame size: 16384 bytes\r
+\r
+//\r
+// Medium Status register\r
+//\r
+\r
+#define MS_FD 0x0002 ///< Full duplex\r
+#define MS_ONE 0x0004 ///< Must be one\r
+#define MS_RFC 0x0010 ///< RX flow control enable\r
+#define MS_TFC 0x0020 ///< TX flow control enable\r
+#define MS_PF 0x0080 ///< Pause frame enable\r
+#define MS_RE 0x0100 ///< Receive enable\r
+#define MS_PS 0x0200 ///< Port speed 1=100, 0=10 Mbps\r
+#define MS_SBP 0x0800 ///< Stop back pressure\r
+#define MS_SM 0x1000 ///< Super MAC support\r
+\r
+//\r
+// Software PHY Select register\r
+//\r
+\r
+#define SPHY_PSEL 0x01 ///< Select internal PHY\r
+#define SPHY_ASEL 0x02 ///< 1=Auto select, 0=Manual select\r
+\r
+//\r
+// Software Reset register\r
+//\r
+\r
+#define SRR_RR 0x01 ///< Clear receive frame length error\r
+#define SRR_RT 0x02 ///< Clear transmit frame length error\r
+#define SRR_PRTE 0x04 ///< External PHY reset pin tri-state enable\r
+#define SRR_PRL 0x08 ///< External PHY reset pin level\r
+#define SRR_BZ 0x10 ///< Force Bulk to return zero length packet\r
+#define SRR_IPRL 0x20 ///< Internal PHY reset control\r
+#define SRR_IPPD 0x40 ///< Internal PHY power down\r
+\r
+//\r
+// PHY ID values\r
+//\r
+\r
+#define PHY_ID_INTERNAL 0x0010 ///< Internal PHY\r
+\r
+//\r
+// USB Commands\r
+//\r
+\r
+#define CMD_PHY_ACCESS_SOFTWARE 0x06 ///< Software in control of PHY\r
+#define CMD_PHY_REG_READ 0x07 ///< Read PHY register, Value: PHY, Index: Register, Data: Register value\r
+#define CMD_PHY_REG_WRITE 0x08 ///< Write PHY register, Value: PHY, Index: Register, Data: New 16-bit value\r
+#define CMD_PHY_ACCESS_HARDWARE 0x0a ///< Hardware in control of PHY\r
+#define CMD_SROM_READ 0x0b ///< Read SROM register: Value: Address, Data: Value\r
+#define CMD_RX_CONTROL_WRITE 0x10 ///< Set the RX control register, Value: New value\r
+#define CMD_GAPS_WRITE 0x12 ///< Write the gaps register, Value: New value\r
+#define CMD_MAC_ADDRESS_READ 0x13 ///< Read the MAC address, Data: 6 byte MAC address\r
+#define CMD_MAC_ADDRESS_WRITE 0x14 ///< Set the MAC address, Data: New 6 byte MAC address\r
+#define CMD_MULTICAST_HASH_WRITE 0x16 ///< Write the multicast hash table, Data: New 8 byte value\r
+#define CMD_MEDIUM_STATUS_READ 0x1a ///< Read medium status register, Data: Register value\r
+#define CMD_MEDIUM_STATUS_WRITE 0x1b ///< Write medium status register, Value: New value\r
+#define CMD_RESET 0x20 ///< Reset register, Value: New value\r
+#define CMD_PHY_SELECT 0x22 ///< PHY select register, Value: New value\r
+\r
+//------------------------------\r
+// USB Endpoints\r
+//------------------------------\r
+\r
+#define CONTROL_ENDPOINT 0 ///< Control endpoint\r
+#define INTERRUPT_ENDPOINT 1 ///< Interrupt endpoint\r
+#define BULK_IN_ENDPOINT 2 ///< Receive endpoint\r
+#define BULK_OUT_ENDPOINT 3 ///< Transmit endpoint\r
+\r
+//------------------------------\r
+// PHY Registers\r
+//------------------------------\r
+\r
+#define PHY_BMCR 0 ///< Control register\r
+#define PHY_BMSR 1 ///< Status register\r
+#define PHY_ANAR 4 ///< Autonegotiation advertisement register\r
+#define PHY_ANLPAR 5 ///< Autonegotiation link parter ability register\r
+#define PHY_ANER 6 ///< Autonegotiation expansion register\r
+\r
+// BMCR - Register 0\r
+\r
+#define BMCR_RESET 0x8000 ///< 1 = Reset the PHY, bit clears after reset\r
+#define BMCR_LOOPBACK 0x4000 ///< 1 = Loopback enabled\r
+#define BMCR_100MBPS 0x2000 ///< 100 Mbits/Sec\r
+#define BMCR_10MBPS 0 ///< 10 Mbits/Sec\r
+#define BMCR_AUTONEGOTIATION_ENABLE 0x1000 ///< 1 = Enable autonegotiation\r
+#define BMCR_POWER_DOWN 0x0800 ///< 1 = Power down\r
+#define BMCR_ISOLATE 0x0400 ///< 0 = Isolate PHY\r
+#define BMCR_RESTART_AUTONEGOTIATION 0x0200 ///< 1 = Restart autonegotiation\r
+#define BMCR_FULL_DUPLEX 0x0100 ///< Full duplex operation\r
+#define BMCR_HALF_DUPLEX 0 ///< Half duplex operation\r
+#define BMCR_COLLISION_TEST 0x0080 ///< 1 = Collision test enabled\r
+\r
+// BSMR - Register 1\r
+\r
+#define BMSR_100BASET4 0x8000 ///< 1 = 100BASE-T4 mode\r
+#define BMSR_100BASETX_FDX 0x4000 ///< 1 = 100BASE-TX full duplex\r
+#define BMSR_100BASETX_HDX 0x2000 ///< 1 = 100BASE-TX half duplex\r
+#define BMSR_10BASET_FDX 0x1000 ///< 1 = 10BASE-T full duplex\r
+#define BMSR_10BASET_HDX 0x0800 ///< 1 = 10BASE-T half duplex\r
+#define BMSR_MF 0x0040 ///< 1 = PHY accepts frames with preamble suppressed\r
+#define BMSR_AUTONEG_CMPLT 0x0020 ///< 1 = Autonegotiation complete\r
+#define BMSR_RF 0x0010 ///< 1 = Remote fault\r
+#define BMSR_AUTONEG 0x0008 ///< 1 = Able to perform autonegotiation\r
+#define BMSR_LINKST 0x0004 ///< 1 = Link up\r
+#define BMSR_JABBER_DETECT 0x0002 ///< 1 = jabber condition detected\r
+#define BMSR_EXTENDED_CAPABILITY 0x0001 ///< 1 = Extended register capable\r
+\r
+// ANAR and ANLPAR Registers 4, 5\r
+\r
+#define AN_NP 0x8000 ///< 1 = Next page available\r
+#define AN_ACK 0x4000 ///< 1 = Link partner acknowledged\r
+#define AN_RF 0x2000 ///< 1 = Remote fault indicated by link partner\r
+#define AN_FCS 0x0400 ///< 1 = Flow control ability\r
+#define AN_T4 0x0200 ///< 1 = 100BASE-T4 support\r
+#define AN_TX_FDX 0x0100 ///< 1 = 100BASE-TX Full duplex\r
+#define AN_TX_HDX 0x0080 ///< 1 = 100BASE-TX support\r
+#define AN_10_FDX 0x0040 ///< 1 = 10BASE-T Full duplex\r
+#define AN_10_HDX 0x0020 ///< 1 = 10BASE-T support\r
+#define AN_CSMA_CD 0x0001 ///< 1 = IEEE 802.3 CSMA/CD support\r
+\r
+//------------------------------------------------------------------------------\r
+// Data Types\r
+//------------------------------------------------------------------------------\r
+\r
+/**\r
+ Ethernet header layout\r
+\r
+ IEEE 802.3-2002 Part 3 specification, section 3.1.1.\r
+**/\r
+#pragma pack(1)\r
+typedef struct {\r
+ UINT8 dest_addr[PXE_HWADDR_LEN_ETHER]; ///< Destination LAN address\r
+ UINT8 src_addr[PXE_HWADDR_LEN_ETHER]; ///< Source LAN address\r
+ UINT16 type; ///< Protocol or length\r
+} ETHERNET_HEADER;\r
+#pragma pack()\r
+\r
+/**\r
+ Receive and Transmit packet structure\r
+**/\r
+#pragma pack(1)\r
+typedef struct _RX_TX_PACKET {\r
+ struct _RX_TX_PACKET * pNext; ///< Next receive packet\r
+ UINT16 Length; ///< Packet length\r
+ UINT16 LengthBar; ///< Complement of the length\r
+ UINT8 Data[ AX88772_MAX_PKT_SIZE ]; ///< Received packet data\r
+} RX_TX_PACKET;\r
+#pragma pack()\r
+\r
+/**\r
+ AX88772 control structure\r
+\r
+ The driver uses this structure to manage the Asix AX88772 10/100\r
+ Ethernet controller.\r
+**/\r
+typedef struct {\r
+ UINTN Signature; ///< Structure identification\r
+\r
+ //\r
+ // USB data\r
+ //\r
+ EFI_HANDLE Controller; ///< Controller handle\r
+ EFI_USB_IO_PROTOCOL * pUsbIo; ///< USB driver interface\r
+\r
+ //\r
+ // Simple network protocol data\r
+ //\r
+ EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork; ///< Driver's network stack interface\r
+ EFI_SIMPLE_NETWORK_MODE SimpleNetworkData; ///< Data for simple network\r
+\r
+ //\r
+ // Ethernet controller data\r
+ //\r
+ BOOLEAN bInitialized; ///< Controller initialized\r
+ VOID * pTxBuffer; ///< Last transmit buffer\r
+ UINT16 PhyId; ///< PHY ID\r
+\r
+ //\r
+ // Link state\r
+ //\r
+ BOOLEAN b100Mbps; ///< Current link speed, FALSE = 10 Mbps\r
+ BOOLEAN bComplete; ///< Current state of auto-negotiation\r
+ BOOLEAN bFullDuplex; ///< Current duplex\r
+ BOOLEAN bLinkUp; ///< Current link state\r
+ BOOLEAN bLinkIdle; ///< TRUE = No received traffic\r
+ EFI_EVENT Timer; ///< Timer to monitor link state and receive packets\r
+ UINTN PollCount; ///< Number of times the autonegotiation status was polled\r
+\r
+ //\r
+ // Receive buffer list\r
+ //\r
+ RX_TX_PACKET * pRxHead; ///< Head of receive packet list\r
+ RX_TX_PACKET * pRxTail; ///< Tail of receive packet list\r
+ RX_TX_PACKET * pRxFree; ///< Free packet list\r
+ INT32 MulticastHash[2]; ///< Hash table for multicast destination addresses\r
+} NIC_DEVICE;\r
+\r
+#define DEV_FROM_SIMPLE_NETWORK(a) CR (a, NIC_DEVICE, SimpleNetwork, DEV_SIGNATURE) ///< Locate NIC_DEVICE from Simple Network Protocol\r
+\r
+//------------------------------------------------------------------------------\r
+// Simple Network Protocol\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
+/**\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
+/**\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
+/**\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
+/**\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
+/**\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
+/**\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
+/**\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
+//------------------------------------------------------------------------------\r
+// Support Routines\r
+//------------------------------------------------------------------------------\r
+\r
+/**\r
+ Get the MAC address\r
+\r
+ This routine calls ::Ax88772UsbCommand to request the MAC\r
+ address from the network adapter.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [out] pMacAddress Address of a six byte buffer to receive the MAC address.\r
+\r
+ @retval EFI_SUCCESS The MAC address is available.\r
+ @retval other The MAC address is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772MacAddressGet (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ OUT UINT8 * pMacAddress\r
+ );\r
+\r
+/**\r
+ Set the MAC address\r
+\r
+ This routine calls ::Ax88772UsbCommand to set the MAC address\r
+ in the network adapter.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address.\r
+\r
+ @retval EFI_SUCCESS The MAC address was set.\r
+ @retval other The MAC address was not set.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772MacAddressSet (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT8 * pMacAddress\r
+ );\r
+\r
+/**\r
+ Clear the multicast hash table\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+\r
+**/\r
+VOID\r
+Ax88772MulticastClear (\r
+ IN NIC_DEVICE * pNicDevice\r
+ );\r
+\r
+/**\r
+ Enable a multicast address in the multicast hash table\r
+\r
+ This routine calls ::Ax88772Crc to compute the hash bit for\r
+ this MAC address.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.\r
+\r
+**/\r
+VOID\r
+Ax88772MulticastSet (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT8 * pMacAddress\r
+ );\r
+\r
+/**\r
+ Start the link negotiation\r
+\r
+ This routine calls ::Ax88772PhyWrite to start the PHY's link\r
+ negotiation.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+\r
+ @retval EFI_SUCCESS The link negotiation was started.\r
+ @retval other Failed to start the link negotiation.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772NegotiateLinkStart (\r
+ IN NIC_DEVICE * pNicDevice\r
+ );\r
+\r
+/**\r
+ Complete the negotiation of the PHY link\r
+\r
+ This routine calls ::Ax88772PhyRead to determine if the\r
+ link negotiation is complete.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in, out] pPollCount Address of number of times this routine was polled\r
+ @param [out] pbComplete Address of boolean to receive complate status.\r
+ @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up.\r
+ @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps.\r
+ @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full.\r
+\r
+ @retval EFI_SUCCESS The MAC address is available.\r
+ @retval other The MAC address is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772NegotiateLinkComplete (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN OUT UINTN * pPollCount,\r
+ OUT BOOLEAN * pbComplete,\r
+ OUT BOOLEAN * pbLinkUp,\r
+ OUT BOOLEAN * pbHiSpeed,\r
+ OUT BOOLEAN * pbFullDuplex\r
+ );\r
+\r
+/**\r
+ Read a register from the PHY\r
+\r
+ This routine calls ::Ax88772UsbCommand to read a PHY register.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] RegisterAddress Number of the register to read.\r
+ @param [in, out] pPhyData Address of a buffer to receive the PHY register value\r
+\r
+ @retval EFI_SUCCESS The PHY data is available.\r
+ @retval other The PHY data is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772PhyRead (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT8 RegisterAddress,\r
+ IN OUT UINT16 * pPhyData\r
+ );\r
+\r
+/**\r
+ Write to a PHY register\r
+\r
+ This routine calls ::Ax88772UsbCommand to write a PHY register.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] RegisterAddress Number of the register to read.\r
+ @param [in] PhyData Address of a buffer to receive the PHY register value\r
+\r
+ @retval EFI_SUCCESS The PHY data was written.\r
+ @retval other Failed to wwrite the PHY register.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772PhyWrite (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT8 RegisterAddress,\r
+ IN UINT16 PhyData\r
+ );\r
+\r
+/**\r
+ Reset the AX88772\r
+\r
+ This routine uses ::Ax88772UsbCommand to reset the network\r
+ adapter. This routine also uses ::Ax88772PhyWrite to reset\r
+ the PHY.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+\r
+ @retval EFI_SUCCESS The MAC address is available.\r
+ @retval other The MAC address is not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772Reset (\r
+ IN NIC_DEVICE * pNicDevice\r
+ );\r
+\r
+/**\r
+ Receive a frame from the network.\r
+\r
+ This routine polls the USB receive interface for a packet. If a packet\r
+ is available, this routine adds the receive packet to the list of\r
+ pending receive packets.\r
+\r
+ This routine calls ::Ax88772NegotiateLinkComplete to verify\r
+ that the link is up. This routine also calls ::SN_Reset to\r
+ reset the network adapter when necessary. Finally this\r
+ routine attempts to receive one or more packets from the\r
+ network adapter.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] bUpdateLink TRUE = Update link status\r
+\r
+**/\r
+VOID\r
+Ax88772Rx (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN BOOLEAN bUpdateLink\r
+ );\r
+\r
+/**\r
+ Enable or disable the receiver\r
+\r
+ This routine calls ::Ax88772UsbCommand to update the\r
+ receiver state. This routine also calls ::Ax88772MacAddressSet\r
+ to establish the MAC address for the network adapter.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] RxFilter Simple network RX filter mask value\r
+\r
+ @retval EFI_SUCCESS The MAC address was set.\r
+ @retval other The MAC address was not set.\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772RxControl (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT32 RxFilter\r
+ );\r
+\r
+/**\r
+ Read an SROM location\r
+\r
+ This routine calls ::Ax88772UsbCommand to read data from the\r
+ SROM.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] Address SROM address\r
+ @param [out] pData Buffer to receive the data\r
+\r
+ @retval EFI_SUCCESS The read was successful\r
+ @retval other The read failed\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772SromRead (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN UINT32 Address,\r
+ OUT UINT16 * pData\r
+ );\r
+\r
+/**\r
+ This routine is called at a regular interval to poll for\r
+ receive packets.\r
+\r
+ This routine polls the link state and gets any receive packets\r
+ by calling ::Ax88772Rx.\r
+\r
+ @param [in] Event Timer event\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+\r
+**/\r
+VOID\r
+Ax88772Timer (\r
+ IN EFI_EVENT Event,\r
+ IN NIC_DEVICE * pNicDevice\r
+ );\r
+\r
+/**\r
+ Send a command to the USB device.\r
+\r
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
+ @param [in] pRequest Pointer to the request structure\r
+ @param [in, out] pBuffer Data buffer address\r
+\r
+ @retval EFI_SUCCESS The USB transfer was successful\r
+ @retval other The USB transfer failed\r
+\r
+**/\r
+EFI_STATUS\r
+Ax88772UsbCommand (\r
+ IN NIC_DEVICE * pNicDevice,\r
+ IN USB_DEVICE_REQUEST * pRequest,\r
+ IN OUT VOID * pBuffer\r
+ );\r
+\r
+//------------------------------------------------------------------------------\r
+// EFI Component Name Protocol Support\r
+//------------------------------------------------------------------------------\r
+\r
+extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; ///< Component name protocol declaration\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2; ///< Component name 2 protocol declaration\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 3066 or ISO 639-2 language code format.\r
+ @param [out] ppDriverName A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,\r
+ IN CHAR8 * pLanguage,\r
+ OUT CHAR16 ** ppDriverName\r
+ );\r
+\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param [in] ControllerHandle The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+ @param [in] ChildHandle The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 3066 or ISO 639-2 language code format.\r
+ @param [out] ppControllerName A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN OPTIONAL EFI_HANDLE ChildHandle,\r
+ IN CHAR8 * pLanguage,\r
+ OUT CHAR16 ** ppControllerName\r
+ );\r
+\r
+//------------------------------------------------------------------------------\r
+\r
+#endif // _AX88772_H_\r
--- /dev/null
+#/** @file\r
+# Component description file for ASIX AX88772 USB/Ethernet driver.\r
+#\r
+# This module provides support for the ASIX AX88772 USB/Ethernet adapter.\r
+# Copyright (c) 2011, Intel Corporation\r
+#\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
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = Ax88772\r
+ FILE_GUID = B15239D6-6A01-4808-A0F7-B7F20F073555\r
+ MODULE_TYPE = DXE_RUNTIME_DRIVER\r
+ VERSION_STRING = 1.0\r
+\r
+ ENTRY_POINT = EntryPoint\r
+\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ Ax88772.h\r
+ Ax88772.c\r
+ ComponentName.c\r
+ DriverBinding.c\r
+ SimpleNetwork.c\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ UefiRuntimeLib\r
+ UefiDriverEntryPoint\r
+\r
+[Protocols]\r
+ gEfiDevicePathProtocolGuid\r
+ gEfiSimpleNetworkProtocolGuid\r
+ gEfiUsbIoProtocolGuid ## TO_START\r
+\r
+[Guids]\r
+ gEfiEventExitBootServicesGuid ## PRODUCES ## Event\r
+ gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event\r
+ gEfiNicIp4ConfigVariableGuid\r
+\r
+[Depex]\r
+ gEfiBdsArchProtocolGuid AND\r
+ gEfiCpuArchProtocolGuid AND\r
+ gEfiMetronomeArchProtocolGuid AND\r
+ gEfiMonotonicCounterArchProtocolGuid AND\r
+ gEfiRealTimeClockArchProtocolGuid AND\r
+ gEfiResetArchProtocolGuid AND\r
+ gEfiRuntimeArchProtocolGuid AND\r
+ gEfiSecurityArchProtocolGuid AND\r
+ gEfiTimerArchProtocolGuid AND\r
+ gEfiVariableWriteArchProtocolGuid AND\r
+ gEfiVariableArchProtocolGuid AND\r
+ gEfiWatchdogTimerArchProtocolGuid\r
--- /dev/null
+/** @file\r
+ UEFI Component Name(2) protocol implementation.\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
+ EFI Component Name Protocol declaration\r
+**/\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
+ GetDriverName,\r
+ GetControllerName,\r
+ "eng"\r
+};\r
+\r
+/**\r
+ EFI Component Name 2 Protocol declaration\r
+**/\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GetControllerName,\r
+ "en"\r
+};\r
+\r
+\r
+/**\r
+ Driver name table declaration\r
+**/\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE\r
+mDriverNameTable[] = {\r
+ {"eng;en", L"AX88772 Ethernet Driver"},\r
+ {NULL, NULL}\r
+};\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 3066 or ISO 639-2 language code format.\r
+ @param [out] ppDriverName A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,\r
+ IN CHAR8 * pLanguage,\r
+ OUT CHAR16 ** ppDriverName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+ Status = LookupUnicodeString2 (\r
+ pLanguage,\r
+ pThis->SupportedLanguages,\r
+ mDriverNameTable,\r
+ ppDriverName,\r
+ (BOOLEAN)(pThis == &gComponentName)\r
+ );\r
+ DBG_EXIT_HEX ( Status );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param [in] ControllerHandle The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+ @param [in] ChildHandle The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 3066 or ISO 639-2 language code format.\r
+ @param [out] ppControllerName A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN OPTIONAL EFI_HANDLE ChildHandle,\r
+ IN CHAR8 * pLanguage,\r
+ OUT CHAR16 ** ppControllerName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Set the controller name\r
+ //\r
+ *ppControllerName = L"AX88772 10/100 Ethernet";\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_HEX ( Status );\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ Implement the driver binding protocol for Asix AX88772 Ethernet driver.\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
+ Verify the controller type\r
+\r
+ @param [in] pThis Protocol instance pointer.\r
+ @param [in] Controller Handle of device to test.\r
+ @param [in] pRemainingDevicePath Not used.\r
+\r
+ @retval EFI_SUCCESS This driver supports this device.\r
+ @retval other This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath\r
+ )\r
+{\r
+ EFI_USB_DEVICE_DESCRIPTOR Device;\r
+ EFI_USB_IO_PROTOCOL * pUsbIo;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Connect to the USB stack\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsbIoProtocolGuid,\r
+ (VOID **) &pUsbIo,\r
+ pThis->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (!EFI_ERROR ( Status )) {\r
+\r
+ //\r
+ // Get the interface descriptor to check the USB class and find a transport\r
+ // protocol handler.\r
+ //\r
+ Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );\r
+ if (!EFI_ERROR ( Status )) {\r
+\r
+ //\r
+ // Validate the adapter\r
+ //\r
+ if (( VENDOR_ID != Device.IdVendor )\r
+ || ( PRODUCT_ID != Device.IdProduct )) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Done with the USB stack\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsbIoProtocolGuid,\r
+ pThis->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+\r
+ //\r
+ // Return the device supported status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Start this driver on Controller by opening UsbIo and DevicePath protocols.\r
+ Initialize PXE structures, create a copy of the Controller Device Path with the\r
+ NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol\r
+ on the newly created Device Path.\r
+\r
+ @param [in] pThis Protocol instance pointer.\r
+ @param [in] Controller Handle of device to work with.\r
+ @param [in] pRemainingDevicePath Not used, always produce all possible children.\r
+\r
+ @retval EFI_SUCCESS This driver is added to Controller.\r
+ @retval other This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ NIC_DEVICE * pNicDevice;\r
+ UINTN LengthInBytes;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Allocate the device structure\r
+ //\r
+ LengthInBytes = sizeof ( *pNicDevice );\r
+ Status = gBS->AllocatePool (\r
+ EfiRuntimeServicesData,\r
+ LengthInBytes,\r
+ (VOID **) &pNicDevice\r
+ );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
+ "0x%08x: Allocate pNicDevice, %d bytes\r\n",\r
+ pNicDevice,\r
+ sizeof ( *pNicDevice )));\r
+\r
+ //\r
+ // Set the structure signature\r
+ //\r
+ ZeroMem ( pNicDevice, LengthInBytes );\r
+ pNicDevice->Signature = DEV_SIGNATURE;\r
+\r
+ //\r
+ // Connect to the USB I/O protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsbIoProtocolGuid,\r
+ (VOID **) &pNicDevice->pUsbIo,\r
+ pThis->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Allocate the necessary events\r
+ //\r
+ Status = gBS->CreateEvent ( EVT_TIMER,\r
+ TPL_AX88772,\r
+ (EFI_EVENT_NOTIFY)Ax88772Timer,\r
+ pNicDevice,\r
+ (VOID **)&pNicDevice->Timer );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "0x%08x: Allocated timer\r\n",\r
+ pNicDevice->Timer ));\r
+\r
+ //\r
+ // Initialize the simple network protocol\r
+ //\r
+ pNicDevice->Controller = Controller;\r
+ SN_Setup ( pNicDevice );\r
+\r
+ //\r
+ // Start the timer\r
+ //\r
+ Status = gBS->SetTimer ( pNicDevice->Timer,\r
+ TimerPeriodic,\r
+ TIMER_MSEC );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Install both the simple network and device path protocols.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Controller,\r
+ &gEfiCallerIdGuid,\r
+ pNicDevice,\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ &pNicDevice->SimpleNetwork,\r
+ NULL\r
+ );\r
+\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "Installed: gEfiCallerIdGuid on 0x%08x\r\n",\r
+ Controller ));\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "Installed: gEfiSimpleNetworkProtocolGuid on 0x%08x\r\n",\r
+ Controller ));\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+ }\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,\r
+ "ERROR - Failed to install gEfiSimpleNetworkProtocol on 0x%08x\r\n",\r
+ Controller ));\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,\r
+ "ERROR - Failed to start the timer, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,\r
+ "ERROR - Failed to create timer event, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+\r
+ //\r
+ // Done with the USB stack\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsbIoProtocolGuid,\r
+ pThis->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+\r
+ //\r
+ // Done with the device\r
+ //\r
+ gBS->FreePool ( pNicDevice );\r
+ }\r
+\r
+ //\r
+ // Display the driver start status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and\r
+ closing the DevicePath and PciIo protocols on Controller.\r
+\r
+ @param [in] pThis Protocol instance pointer.\r
+ @param [in] Controller Handle of device to stop driver on.\r
+ @param [in] NumberOfChildren How many children need to be stopped.\r
+ @param [in] pChildHandleBuffer Not used.\r
+\r
+ @retval EFI_SUCCESS This driver is removed Controller.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+ @retval other This driver was not removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE * pChildHandleBuffer\r
+ )\r
+{\r
+ NIC_DEVICE * pNicDevice;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Determine if this driver is already attached\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiCallerIdGuid,\r
+ (VOID **) &pNicDevice,\r
+ pThis->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // AX88772 driver is no longer running on this device\r
+ //\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Controller,\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ &pNicDevice->SimpleNetwork,\r
+ &gEfiCallerIdGuid,\r
+ pNicDevice,\r
+ NULL );\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
+ "Removed: gEfiSimpleNetworkProtocolGuid from 0x%08x\r\n",\r
+ Controller ));\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
+ "Removed: gEfiCallerIdGuid from 0x%08x\r\n",\r
+ Controller ));\r
+\r
+ //\r
+ // Stop the timer\r
+ //\r
+ if ( NULL != pNicDevice->Timer ) {\r
+ gBS->SetTimer ( pNicDevice->Timer, TimerCancel, 0 );\r
+ gBS->CloseEvent ( pNicDevice->Timer );\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "0x%08x: Released timer\r\n",\r
+ pNicDevice->Timer ));\r
+ }\r
+\r
+ //\r
+ // Done with the device context\r
+ //\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
+ "0x%08x: Free pNicDevice, %d bytes\r\n",\r
+ pNicDevice,\r
+ sizeof ( *pNicDevice )));\r
+ gBS->FreePool ( pNicDevice );\r
+ }\r
+\r
+ //\r
+ // Return the shutdown status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Driver binding protocol declaration\r
+**/\r
+EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
+ DriverSupported,\r
+ DriverStart,\r
+ DriverStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+\r
+/**\r
+ Ax88772 driver unload routine.\r
+\r
+ @param [in] ImageHandle Handle for the image.\r
+\r
+ @retval EFI_SUCCESS Image may be unloaded\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverUnload (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ UINTN BufferSize;\r
+ UINTN Index;\r
+ UINTN Max;\r
+ EFI_HANDLE * pHandle;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Determine which devices are using this driver\r
+ //\r
+ BufferSize = 0;\r
+ pHandle = NULL;\r
+ Status = gBS->LocateHandle (\r
+ ByProtocol,\r
+ &gEfiCallerIdGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ NULL );\r
+ if ( EFI_BUFFER_TOO_SMALL == Status ) {\r
+ for ( ; ; ) {\r
+ //\r
+ // One or more block IO devices are present\r
+ //\r
+ Status = gBS->AllocatePool (\r
+ EfiRuntimeServicesData,\r
+ BufferSize,\r
+ (VOID **) &pHandle\r
+ );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "Insufficient memory, failed handle buffer allocation\r\n" ));\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Locate the block IO devices\r
+ //\r
+ Status = gBS->LocateHandle (\r
+ ByProtocol,\r
+ &gEfiCallerIdGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ pHandle );\r
+ if ( EFI_ERROR ( Status )) {\r
+ //\r
+ // Error getting handles\r
+ //\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,\r
+ "Failure getting Telnet handles\r\n" ));\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Remove any use of the driver\r
+ //\r
+ Max = BufferSize / sizeof ( pHandle[ 0 ]);\r
+ for ( Index = 0; Max > Index; Index++ ) {\r
+ Status = DriverStop ( &gDriverBinding,\r
+ pHandle[ Index ],\r
+ 0,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_WARN | DEBUG_INIT | DEBUG_INFO,\r
+ "WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ]));\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ else {\r
+ if ( EFI_NOT_FOUND == Status ) {\r
+ //\r
+ // No devices were found\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Free the handle array\r
+ //\r
+ if ( NULL != pHandle ) {\r
+ gBS->FreePool ( pHandle );\r
+ }\r
+\r
+ //\r
+ // Remove the protocols installed by the EntryPoint routine.\r
+ //\r
+ if ( !EFI_ERROR ( Status )) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ ImageHandle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ &gDriverBinding,\r
+ &gEfiComponentNameProtocolGuid,\r
+ &gComponentName,\r
+ &gEfiComponentName2ProtocolGuid,\r
+ &gComponentName2,\r
+ NULL\r
+ );\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "Removed: gEfiComponentName2ProtocolGuid from 0x%08x\r\n",\r
+ ImageHandle ));\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "Removed: gEfiComponentNameProtocolGuid from 0x%08x\r\n",\r
+ ImageHandle ));\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "Removed: gEfiDriverBindingProtocolGuid from 0x%08x\r\n",\r
+ ImageHandle ));\r
+ }\r
+\r
+ //\r
+ // Return the unload status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+Ax88772 driver entry point.\r
+\r
+@param [in] ImageHandle Handle for the image.\r
+@param [in] pSystemTable Address of the system table.\r
+\r
+@retval EFI_SUCCESS Image successfully loaded.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE * pSystemTable\r
+ )\r
+{\r
+ EFI_LOADED_IMAGE_PROTOCOL * pLoadedImage;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Enable unload support\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ gImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **)&pLoadedImage\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ pLoadedImage->Unload = DriverUnload;\r
+ }\r
+\r
+ //\r
+ // Add the driver to the list of drivers\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ pSystemTable,\r
+ &gDriverBinding,\r
+ ImageHandle,\r
+ &gComponentName,\r
+ &gComponentName2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "Installed: gEfiDriverBindingProtocolGuid on 0x%08x\r\n",\r
+ ImageHandle ));\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "Installed: gEfiComponentNameProtocolGuid on 0x%08x\r\n",\r
+ ImageHandle ));\r
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+ "Installed: gEfiComponentName2ProtocolGuid on 0x%08x\r\n",\r
+ ImageHandle ));\r
+ }\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
--- /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