From 549ff2286a4d8a24a912b3123a10d264ddafcb88 Mon Sep 17 00:00:00 2001 From: Shivamurthy Shastri Date: Tue, 19 Mar 2013 15:49:50 +0530 Subject: [PATCH] PXE for Arndale. Still work is under progress. NOT A FINAL PATCH. --- .../UncachedMemoryAllocationLib.c | 13 +- MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c | 2 +- MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c | 2 +- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c | 3 +- MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h | 4 +- MdePkg/Library/BaseLib/String.c | 2 +- .../ArndaleBoardPkg/arndale-Exynos5250.dsc | 21 + .../ArndaleBoardPkg/arndale-Exynos5250.fdf | 16 + .../ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.c | 1314 +++++++++++++++++ .../ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.h | 976 +++++++++++++ .../Exynos5250/Drivers/EthDxe/Ax88772.inf | 57 + .../Exynos5250/Drivers/EthDxe/ComponentName.c | 184 +++ .../Exynos5250/Drivers/EthDxe/DriverBinding.c | 543 +++++++ .../ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.c | 788 ---------- .../ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.h | 612 -------- .../ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.inf | 59 - .../Exynos5250/Drivers/EthDxe/SimpleNetwork.c | 1533 ++++++++++++++++++++ .../ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.c | 2 +- .../Exynos5250/Drivers/PciEmulation/Exynos5_USB.c | 73 +- .../Exynos5250/Drivers/PciEmulation/PciEmulation.h | 1 + .../Drivers/PciEmulation/PciEmulation.inf | 1 + .../Exynos5250/Include/Platform/ArmPlatform.h | 4 + 22 files changed, 4727 insertions(+), 1483 deletions(-) create mode 100644 SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.c create mode 100644 SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.h create mode 100644 SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.inf create mode 100644 SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/ComponentName.c create mode 100644 SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/DriverBinding.c delete mode 100644 SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.c delete mode 100644 SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.h delete mode 100644 SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.inf create mode 100644 SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/SimpleNetwork.c diff --git a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c index 4db93db..9afd2ff 100644 --- a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c +++ b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c @@ -95,7 +95,7 @@ RemovePagesFromList ( *Pages = OldNode->Pages; RemoveEntryList (&OldNode->Link); - FreePool (OldNode); + //gBS->FreePool (OldNode); return; } } @@ -142,6 +142,17 @@ UncachedAllocatePages ( VOID * EFIAPI +UncachedAllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment); +} + + +VOID * +EFIAPI UncachedAllocateRuntimePages ( IN UINTN Pages ) diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c index 59891b8..470c2f4 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c @@ -948,7 +948,7 @@ ON_EXIT: gBS->RestoreTPL (OldTpl); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult)); + //DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult)); } return Status; diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c index 4dc8e1a..4d04c2a 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c @@ -718,7 +718,7 @@ EhcExecTransfer ( } if (!Finished) { - DEBUG ((EFI_D_ERROR, "EhcExecTransfer: transfer not finished in %dms\n", (UINT32)TimeOut)); +// DEBUG ((EFI_D_ERROR, "EhcExecTransfer: transfer not finished in %dms\n", (UINT32)TimeOut)); EhcDumpQh (Urb->Qh, NULL, FALSE); Status = EFI_TIMEOUT; diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c index 529b136..7328c8a 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c @@ -617,7 +617,8 @@ UsbGetOneString ( Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 2); if (EFI_ERROR (Status)) { - return NULL; + Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 0x4);// Need to change this code as per USB 2.0 spec. This is temp code for ASIX chip. + //return NULL; } Buf = AllocateZeroPool (Desc.Length); diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h b/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h index f94e208..b3d899a 100644 --- a/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h +++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h @@ -20,9 +20,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #define NET_ETHER_FCS_SIZE 4 -#define MNP_SYS_POLL_INTERVAL (10 * TICKS_PER_MS) // 10 milliseconds +#define MNP_SYS_POLL_INTERVAL (800 * TICKS_PER_MS) // 10 milliseconds #define MNP_TIMEOUT_CHECK_INTERVAL (50 * TICKS_PER_MS) // 50 milliseconds -#define MNP_MEDIA_DETECT_INTERVAL (500 * TICKS_PER_MS) // 500 milliseconds +#define MNP_MEDIA_DETECT_INTERVAL (100000 * TICKS_PER_MS) // 500 milliseconds #define MNP_TX_TIMEOUT_TIME (500 * TICKS_PER_MS) // 500 milliseconds #define MNP_INIT_NET_BUFFER_NUM 512 #define MNP_NET_BUFFER_INCREASEMENT 64 diff --git a/MdePkg/Library/BaseLib/String.c b/MdePkg/Library/BaseLib/String.c index 227a0dc..0294372 100644 --- a/MdePkg/Library/BaseLib/String.c +++ b/MdePkg/Library/BaseLib/String.c @@ -164,7 +164,7 @@ StrLen ( UINTN Length; ASSERT (String != NULL); - ASSERT (((UINTN) String & BIT0) == 0); + //ASSERT (((UINTN) String & BIT0) == 0); for (Length = 0; *String != L'\0'; String++, Length++) { // diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.dsc b/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.dsc index 941c6e5..5c75717 100755 --- a/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.dsc +++ b/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.dsc @@ -47,6 +47,10 @@ ArmGicSecLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSecLib.inf ArmGicLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicLib.inf ArmSmcLib|ArmPkg/Library/ArmSmcLibNull/ArmSmcLibNull.inf + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf + IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf + UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf [LibraryClasses.common.SEC] ArmLib|ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf @@ -352,6 +356,23 @@ MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + #Network + MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf + MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf + MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf + MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.inf + + # # Graphics for Exynos # diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.fdf b/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.fdf index 8b5a5a7..d89a8ab 100755 --- a/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.fdf +++ b/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.fdf @@ -213,6 +213,22 @@ READ_LOCK_STATUS = TRUE INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + #Network + INF MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf +# INF MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf + INF MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + INF MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + INF MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + INF MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf + INF MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + INF MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + INF MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf + INF MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + INF MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + INF MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + INF MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.inf + # # Graphics for Exynos # diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.c new file mode 100644 index 0000000..4d7c2f3 --- /dev/null +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.c @@ -0,0 +1,1314 @@ +/** @file + Implement the interface to the AX88772 Ethernet controller. + + This module implements the interface to the ASIX AX88772 + USB to Ethernet MAC with integrated 10/100 PHY. Note that this implementation + only supports the integrated PHY since no other test cases were available. + + Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Ax88772.h" + + +/** + Compute the CRC + + @param [in] pMacAddress Address of a six byte buffer to containing the MAC address. + + @returns The CRC-32 value associated with this MAC address + +**/ +UINT32 +Ax88772Crc ( + IN UINT8 * pMacAddress + ) +{ + UINT32 BitNumber; + INT32 Carry; + INT32 Crc; + UINT32 Data; + UINT8 * pEnd; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "Ax88772Crc\n")); + + // + // Walk the MAC address + // + Crc = -1; + pEnd = &pMacAddress[ PXE_HWADDR_LEN_ETHER ]; + while ( pEnd > pMacAddress ) { + Data = *pMacAddress++; + + + // + // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 + // + // 1 0000 0100 1100 0001 0001 1101 1011 0111 + // + for ( BitNumber = 0; 8 > BitNumber; BitNumber++ ) { + Carry = (( Crc >> 31 ) & 1 ) ^ ( Data & 1 ); + Crc <<= 1; + if ( 0 != Carry ) { + Crc ^= 0x04c11db7; + } + Data >>= 1; + } + } + + // + // Return the CRC value + // + DBG_EXIT_HEX ( Crc ); + return (UINT32) Crc; +} + + +/** + Get the MAC address + + This routine calls ::Ax88772UsbCommand to request the MAC + address from the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [out] pMacAddress Address of a six byte buffer to receive the MAC address. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772MacAddressGet ( + IN NIC_DEVICE * pNicDevice, + OUT UINT8 * pMacAddress + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "Ax88772MacAddressGet\n")); + + // + // Set the register address. + // + SetupMsg.RequestType = USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_MAC_ADDRESS_READ; + SetupMsg.Value = 0; + SetupMsg.Index = 0; + SetupMsg.Length = PXE_HWADDR_LEN_ETHER; + + // + // Read the PHY register + // + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + pMacAddress ); + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Set the MAC address + + This routine calls ::Ax88772UsbCommand to set the MAC address + in the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address. + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88772MacAddressSet ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 * pMacAddress + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "Ax88772MacAddressSet\n")); + + + DEBUG (( DEBUG_ERROR, "Ax88772MacAddressSet: SET MAC Before:")); + DEBUG (( DEBUG_ERROR, + "%02x:%02x:%02x:%02x:%02x:%02x\n", + pMacAddress[0], + pMacAddress[1], + pMacAddress[2], + pMacAddress[3], + pMacAddress[4], + pMacAddress[5])); + +/* pMacAddress[0] = 0x00; + pMacAddress[1] = 0x40; + pMacAddress[2] = 0x5C; + pMacAddress[3] = 0x26; + pMacAddress[4] = 0x0A; + pMacAddress[5] = 0x5B; + + DEBUG (( DEBUG_ERROR, "Ax88772MacAddressSet: SET MAC After:")); */ + // + // Set the register address. + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_MAC_ADDRESS_WRITE; + SetupMsg.Value = 0; + SetupMsg.Index = 0; + SetupMsg.Length = PXE_HWADDR_LEN_ETHER; + + + DEBUG (( DEBUG_ERROR, + "%02x:%02x:%02x:%02x:%02x:%02x\n", + pMacAddress[0], + pMacAddress[1], + pMacAddress[2], + pMacAddress[3], + pMacAddress[4], + pMacAddress[5])); + // + // Read the PHY register + // + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + pMacAddress ); + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Clear the multicast hash table + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + +**/ +VOID +Ax88772MulticastClear ( + IN NIC_DEVICE * pNicDevice + ) +{ + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "Ax88772MulticastClear\n")); + + // + // Clear the multicast hash table + // + pNicDevice->MulticastHash[0] = 0; + pNicDevice->MulticastHash[1] = 0; + + DBG_EXIT ( ); +} + + +/** + Enable a multicast address in the multicast hash table + + This routine calls ::Ax88772Crc to compute the hash bit for + this MAC address. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pMacAddress Address of a six byte buffer to containing the MAC address. + +**/ +VOID +Ax88772MulticastSet ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 * pMacAddress + ) +{ + UINT32 BitNumber; + UINT32 Crc; + UINT32 Mask; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "Ax88772MulticastSet\n")); + + // + // Compute the CRC on the destination address + // + Crc = Ax88772Crc ( pMacAddress ); + + // + // Set the bit corresponding to the destination address + // + BitNumber = Crc >> 26; + if ( 32 > BitNumber ) { + Mask = 1 << BitNumber; + pNicDevice->MulticastHash[0] |= Mask; + } + else { + Mask = 1 << ( BitNumber - 32 ); + pNicDevice->MulticastHash[1] |= Mask; + } + + // + // Display the multicast address + // + DEBUG (( DEBUG_RX_MULTICAST | DEBUG_ERROR, + "Enable multicast: 0x%02x-%02x-%02x-%02x-%02x-%02x, CRC: 0x%08x, Bit number: 0x%02x\r\n", + pMacAddress[0], + pMacAddress[1], + pMacAddress[2], + pMacAddress[3], + pMacAddress[4], + pMacAddress[5], + Crc, + BitNumber )); + + DBG_EXIT ( ); +} + + +/** + Start the link negotiation + + This routine calls ::Ax88772PhyWrite to start the PHY's link + negotiation. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The link negotiation was started. + @retval other Failed to start the link negotiation. + +**/ +EFI_STATUS +Ax88772NegotiateLinkStart ( + IN NIC_DEVICE * pNicDevice + ) +{ + UINT16 Control; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "Ax88772NegotiateLinkStart\n")); + + // + // Set the supported capabilities. + // + Status = Ax88772PhyWrite ( pNicDevice, + PHY_ANAR, + AN_CSMA_CD + | AN_TX_FDX | AN_TX_HDX + | AN_10_FDX | AN_10_HDX ); + if ( !EFI_ERROR ( Status )) { + // + // Set the link speed and duplex + // + Control = BMCR_AUTONEGOTIATION_ENABLE + | BMCR_RESTART_AUTONEGOTIATION; + if ( pNicDevice->b100Mbps ) { + Control |= BMCR_100MBPS; + } + if ( pNicDevice->bFullDuplex ) { + Control |= BMCR_FULL_DUPLEX; + } + Status = Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control ); + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Complete the negotiation of the PHY link + + This routine calls ::Ax88772PhyRead to determine if the + link negotiation is complete. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in, out] pPollCount Address of number of times this routine was polled + @param [out] pbComplete Address of boolean to receive complate status. + @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up. + @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps. + @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772NegotiateLinkComplete ( + IN NIC_DEVICE * pNicDevice, + IN OUT UINTN * pPollCount, + OUT BOOLEAN * pbComplete, + OUT BOOLEAN * pbLinkUp, + OUT BOOLEAN * pbHiSpeed, + OUT BOOLEAN * pbFullDuplex + ) +{ + UINT16 Mask; + UINT16 PhyData; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_ERROR, "Ax88772NegotiateLinkComplete\n")); + + // + // Determine if the link is up. + // + *pbComplete = FALSE; + + // + // Get the link status + // + Status = Ax88772PhyRead ( pNicDevice, + PHY_BMSR, + &PhyData ); + if ( !EFI_ERROR ( Status )) { + // + // Determine if the autonegotiation is complete. + // + DEBUG((DEBUG_ERROR, "PhyData:%x\n",PhyData)); + *pbLinkUp = (BOOLEAN)( 0 != ( PhyData & BMSR_LINKST )); + *pbComplete = *pbLinkUp; + if ( 0 != *pbComplete ) { + // + // Get the partners capabilities. + // + Status = Ax88772PhyRead ( pNicDevice, + PHY_ANLPAR, + &PhyData ); + if ( !EFI_ERROR ( Status )) { + // + // Autonegotiation is complete + // Determine the link speed. + // + *pbHiSpeed = (BOOLEAN)( 0 != ( PhyData & ( AN_TX_FDX | AN_TX_HDX ))); + + // + // Determine the link duplex. + // + Mask = ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX; + *pbFullDuplex = (BOOLEAN)( 0 != ( PhyData & Mask )); + } + } + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Read a register from the PHY + + This routine calls ::Ax88772UsbCommand to read a PHY register. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in, out] pPhyData Address of a buffer to receive the PHY register value + + @retval EFI_SUCCESS The PHY data is available. + @retval other The PHY data is not valid. + +**/ +EFI_STATUS +Ax88772PhyRead ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN OUT UINT16 * pPhyData + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_ERROR, "Ax88772PhyRead\n")); + + // + // Request access to the PHY + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE; + SetupMsg.Value = 0; + SetupMsg.Index = 0; + SetupMsg.Length = 0; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( !EFI_ERROR ( Status )) { + // + // Read the PHY register address. + // + SetupMsg.RequestType = USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_PHY_REG_READ; + SetupMsg.Value = pNicDevice->PhyId; + SetupMsg.Index = RegisterAddress; + SetupMsg.Length = sizeof ( *pPhyData ); + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + pPhyData ); + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_PHY | DEBUG_ERROR, + "PHY %d: 0x%02x --> 0x%04x\r\n", + pNicDevice->PhyId, + RegisterAddress, + *pPhyData )); + + // + // Release the PHY to the hardware + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE; + SetupMsg.Value = 0; + SetupMsg.Index = 0; + SetupMsg.Length = 0; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + } + } + + // + // Return the operation status. + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Write to a PHY register + + This routine calls ::Ax88772UsbCommand to write a PHY register. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in] PhyData Address of a buffer to receive the PHY register value + + @retval EFI_SUCCESS The PHY data was written. + @retval other Failed to wwrite the PHY register. + +**/ +EFI_STATUS +Ax88772PhyWrite ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN UINT16 PhyData + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "Ax88772PhyWrite\n")); + + // + // Request access to the PHY + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE; + SetupMsg.Value = 0; + SetupMsg.Index = 0; + SetupMsg.Length = 0; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( !EFI_ERROR ( Status )) { + // + // Write the PHY register + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_PHY_REG_WRITE; + SetupMsg.Value = pNicDevice->PhyId; + SetupMsg.Index = RegisterAddress; + SetupMsg.Length = sizeof ( PhyData ); + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + &PhyData ); + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_PHY | DEBUG_ERROR, + "PHY %d: 0x%02x <-- 0x%04x\r\n", + pNicDevice->PhyId, + RegisterAddress, + PhyData )); + + // + // Release the PHY to the hardware + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE; + SetupMsg.Value = 0; + SetupMsg.Index = 0; + SetupMsg.Length = 0; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + } + } + + // + // Return the operation status. + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Reset the AX88772 + + This routine uses ::Ax88772UsbCommand to reset the network + adapter. This routine also uses ::Ax88772PhyWrite to reset + the PHY. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772Reset ( + IN NIC_DEVICE * pNicDevice + ) +{ + + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "Ax88772Reset\n")); + + // + // Turn off the MAC + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_RX_CONTROL_WRITE; + SetupMsg.Value = 0; + SetupMsg.Index = 0; + SetupMsg.Length = 0; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_PHY | DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST + | DEBUG_RX_UNICAST | DEBUG_TX | DEBUG_ERROR, + "MAC reset\r\n" )); + + // + // The link is now idle + // + pNicDevice->bLinkIdle = TRUE; + + // + // Delay for a bit + // + gBS->Stall ( RESET_MSEC ); + + // + // Select the internal PHY + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_PHY_SELECT; + SetupMsg.Value = SPHY_PSEL; + SetupMsg.Index = 0; + SetupMsg.Length = 0; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( !EFI_ERROR ( Status )) { + // + // Delay for a bit + // + gBS->Stall ( PHY_RESET_MSEC ); + + // + // Clear the internal PHY reset + // + SetupMsg.Request = CMD_RESET; + SetupMsg.Value = SRR_IPRL | SRR_PRL; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( !EFI_ERROR ( Status )) { + // + // Reset the PHY + // + Status = Ax88772PhyWrite ( pNicDevice, + PHY_BMCR, + BMCR_RESET ); + if ( !EFI_ERROR ( Status )) { + // + // Set the gaps + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_GAPS_WRITE; + SetupMsg.Value = 0x0c15; + SetupMsg.Index = 0x0e; + SetupMsg.Length = 0; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + } + } + } + } + + // + // Return the operation status. + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Receive a frame from the network. + + This routine polls the USB receive interface for a packet. If a packet + is available, this routine adds the receive packet to the list of + pending receive packets. + + This routine calls ::Ax88772NegotiateLinkComplete to verify + that the link is up. This routine also calls ::SN_Reset to + reset the network adapter when necessary. Finally this + routine attempts to receive one or more packets from the + network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] bUpdateLink TRUE = Update link status + +**/ +VOID +Ax88772Rx ( + IN NIC_DEVICE * pNicDevice, + IN BOOLEAN bUpdateLink + ) +{ + BOOLEAN bFullDuplex; + BOOLEAN bLinkUp; + BOOLEAN bRxPacket; + BOOLEAN bSpeed100; + UINTN LengthInBytes; + RX_TX_PACKET Packet; + RX_TX_PACKET * pRxPacket; + EFI_USB_IO_PROTOCOL *pUsbIo; + EFI_STATUS Status; +// EFI_TPL TplPrevious; + UINT32 TransferStatus; + +// DEBUG((DEBUG_WARN, "Ax88772Rx\n")); + // + // Synchronize with Ax88772Timer + // +// VERIFY_TPL ( TPL_AX88772 ); +// TplPrevious = gBS->RaiseTPL ( TPL_AX88772 ); +// DEBUG (( DEBUG_TPL | DEBUG_ERROR, +// "%d: TPL\r\n", +// TPL_AX88772 )); + + // + // Get the link status + // + if ( bUpdateLink ) { + bLinkUp = pNicDevice->bLinkUp; + bSpeed100 = pNicDevice->b100Mbps; + bFullDuplex = pNicDevice->bFullDuplex; + Status = Ax88772NegotiateLinkComplete ( pNicDevice, + &pNicDevice->PollCount, + &pNicDevice->bComplete, + &pNicDevice->bLinkUp, + &pNicDevice->b100Mbps, + &pNicDevice->bFullDuplex ); + //DEBUG((DEBUG_ERROR, "Status:%r,PollCount:%x,bComplete:%x,bLinkUp:%x,b100Mbps:%x,bFullDuplex:%x\n",Status,pNicDevice->PollCount,pNicDevice->bComplete,pNicDevice->bLinkUp,pNicDevice->b100Mbps,pNicDevice->bFullDuplex)); + // + // Determine if the autonegotiation is complete + // + if ( pNicDevice->bComplete ) { + if ( pNicDevice->bLinkUp ) { + if (( bSpeed100 && ( !pNicDevice->b100Mbps )) + || (( !bSpeed100 ) && pNicDevice->b100Mbps ) + || ( bFullDuplex && ( !pNicDevice->bFullDuplex )) + || (( !bFullDuplex ) && pNicDevice->bFullDuplex )) { + pNicDevice->PollCount = 0; + DEBUG (( DEBUG_LINK | DEBUG_ERROR, + "Reset to establish proper link setup: %d Mbps, %s duplex\r\n", + pNicDevice->b100Mbps ? 100 : 10, + pNicDevice->bFullDuplex ? L"Full" : L"Half" )); + Status = SN_Reset ( &pNicDevice->SimpleNetwork, FALSE ); + } + if (( !bLinkUp ) && pNicDevice->bLinkUp ) { + // + // Display the autonegotiation status + // + DEBUG (( DEBUG_LINK | DEBUG_ERROR, + "Link: Up, %d Mbps, %s duplex\r\n", + pNicDevice->b100Mbps ? 100 : 10, + pNicDevice->bFullDuplex ? L"Full" : L"Half" )); + } + } + } + + // + // Update the link status + // + if ( bLinkUp && ( !pNicDevice->bLinkUp )) { + DEBUG (( DEBUG_LINK | DEBUG_ERROR, "Link: Down\r\n" )); + } + } + + // + // Loop until all the packets are emptied from the receiver + // +if (bUpdateLink == FALSE) { + do { + bRxPacket = FALSE; + + // + // Locate a packet for use + // + pRxPacket = pNicDevice->pRxFree; + LengthInBytes = sizeof ( *pRxPacket ) - sizeof ( pRxPacket->pNext ); + if ( NULL == pRxPacket ) { + Status = gBS->AllocatePool ( EfiRuntimeServicesData, + LengthInBytes, + (VOID **) &pRxPacket ); + if ( !EFI_ERROR ( Status )) { + // + // Add this packet to the free packet list + // + pNicDevice->pRxFree = pRxPacket; + pRxPacket->pNext = NULL; + } + else { + // + // Use the discard packet buffer + // + pRxPacket = &Packet; + } + } + + // + // Attempt to receive a packet + // + pUsbIo = pNicDevice->pUsbIo; + Status = pUsbIo->UsbBulkTransfer ( pUsbIo, + USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT, + &pRxPacket->Length, + &LengthInBytes, + 1, + &TransferStatus ); + + if (( !EFI_ERROR ( Status )) + && ( 0 < pRxPacket->Length ) + && ( pRxPacket->Length <= sizeof ( pRxPacket->Data ))) { + + // + // Determine if the packet should be received + // + bRxPacket = TRUE; + LengthInBytes = pRxPacket->Length; + pNicDevice->bLinkIdle = FALSE; + if ( pNicDevice->pRxFree == pRxPacket ) { + // + // Display the received packet + // + if ( 0 != ( pRxPacket->Data[0] & 1 )) { + if (( 0xff == pRxPacket->Data[0]) + && ( 0xff == pRxPacket->Data[1]) + && ( 0xff == pRxPacket->Data[2]) + && ( 0xff == pRxPacket->Data[3]) + && ( 0xff == pRxPacket->Data[4]) + && ( 0xff == pRxPacket->Data[5])) { + DEBUG (( DEBUG_RX_BROADCAST | DEBUG_ERROR, + "BROADRX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n", + pRxPacket->Data[0], + pRxPacket->Data[1], + pRxPacket->Data[2], + pRxPacket->Data[3], + pRxPacket->Data[4], + pRxPacket->Data[5], + pRxPacket->Data[6], + pRxPacket->Data[7], + pRxPacket->Data[8], + pRxPacket->Data[9], + pRxPacket->Data[10], + pRxPacket->Data[11], + pRxPacket->Data[12], + pRxPacket->Data[13], + LengthInBytes )); + } + else { + DEBUG (( DEBUG_RX_MULTICAST | DEBUG_ERROR, + "MULTIRX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n", + pRxPacket->Data[0], + pRxPacket->Data[1], + pRxPacket->Data[2], + pRxPacket->Data[3], + pRxPacket->Data[4], + pRxPacket->Data[5], + pRxPacket->Data[6], + pRxPacket->Data[7], + pRxPacket->Data[8], + pRxPacket->Data[9], + pRxPacket->Data[10], + pRxPacket->Data[11], + pRxPacket->Data[12], + pRxPacket->Data[13], + LengthInBytes )); + } + } + else { + DEBUG (( DEBUG_RX_UNICAST | DEBUG_ERROR, + "UNIRX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n", + pRxPacket->Data[0], + pRxPacket->Data[1], + pRxPacket->Data[2], + pRxPacket->Data[3], + pRxPacket->Data[4], + pRxPacket->Data[5], + pRxPacket->Data[6], + pRxPacket->Data[7], + pRxPacket->Data[8], + pRxPacket->Data[9], + pRxPacket->Data[10], + pRxPacket->Data[11], + pRxPacket->Data[12], + pRxPacket->Data[13], + LengthInBytes )); + } + + // + // Remove this packet from the free packet list + // + pNicDevice->pRxFree = pRxPacket->pNext; + pRxPacket->pNext = NULL; + + // + // Append this packet to the receive list + // + if ( NULL == pNicDevice->pRxTail ) { + pNicDevice->pRxHead = pRxPacket; + } + else { + pNicDevice->pRxTail->pNext = pRxPacket; + } + pNicDevice->pRxTail = pRxPacket; + } + else { + // + // Error, not enough buffers for this packet, discard packet + // + DEBUG (( DEBUG_ERROR | DEBUG_ERROR, + "WARNING - No buffer, discarding RX packet: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n", + pRxPacket->Data[0], + pRxPacket->Data[1], + pRxPacket->Data[2], + pRxPacket->Data[3], + pRxPacket->Data[4], + pRxPacket->Data[5], + pRxPacket->Data[6], + pRxPacket->Data[7], + pRxPacket->Data[8], + pRxPacket->Data[9], + pRxPacket->Data[10], + pRxPacket->Data[11], + pRxPacket->Data[12], + pRxPacket->Data[13], + LengthInBytes )); + } + } + }while ( bRxPacket ); + +} + + // + // Release the synchronization withhe Ax88772Timer + // +// gBS->RestoreTPL ( TplPrevious ); +// DEBUG (( DEBUG_TPL | DEBUG_ERROR, +// "%d: TPL\r\n", +// TplPrevious )); +} + + +/** + Enable or disable the receiver + + This routine calls ::Ax88772UsbCommand to update the + receiver state. This routine also calls ::Ax88772MacAddressSet + to establish the MAC address for the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RxFilter Simple network RX filter mask value + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88772RxControl ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 RxFilter + ) +{ + UINT16 MediumStatus; + INT32 MulticastHash[2]; + UINT16 RxControl; + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + DBG_ENTER ( ); + + DEBUG((DEBUG_WARN, "Ax88772RxControl\n")); + // + // Disable all multicast + // + MulticastHash[0] = 0; + MulticastHash[1] = 0; + + // + // Enable the receiver if something is to be received + // + Status = EFI_SUCCESS; + RxControl = RXC_SO | RXC_MFB_16384; + if ( 0 != RxFilter ) { + // + // Enable the receiver + // + SetupMsg.RequestType = USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_MEDIUM_STATUS_READ; + SetupMsg.Value = 0; + SetupMsg.Index = 0; + SetupMsg.Length = sizeof ( MediumStatus ); + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + &MediumStatus ); + if ( !EFI_ERROR ( Status )) { + if ( 0 == ( MediumStatus & MS_RE )) { + MediumStatus |= MS_RE | MS_ONE; + if ( pNicDevice->bFullDuplex ) { + MediumStatus |= MS_TFC | MS_RFC; + } + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE; + SetupMsg.Value = MediumStatus; + SetupMsg.Index = 0; + SetupMsg.Length = 0; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( EFI_ERROR ( Status )) { + DEBUG (( DEBUG_ERROR | DEBUG_ERROR, + "ERROR - Failed to enable receiver, Status: %r\r\n", + Status )); + } + } + } + else { + DEBUG (( DEBUG_ERROR | DEBUG_ERROR, + "ERROR - Failed to read receiver status, Status: %r\r\n", + Status )); + } + + // + // Enable multicast if requested + // + if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) { + RxControl |= RXC_AM; + MulticastHash[0] = pNicDevice->MulticastHash[0]; + MulticastHash[1] = pNicDevice->MulticastHash[1]; + } + + // + // Enable all multicast if requested + // + if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) { + RxControl |= RXC_AMALL; + MulticastHash[0] = -1; + MulticastHash[1] = -1; + } + + // + // Enable broadcast if requested + // + if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) { + RxControl |= RXC_AB; + } + + // + // Enable promiscuous mode if requested + // + if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) { + RxControl |= RXC_PRO; + MulticastHash[0] = -1; + MulticastHash[1] = -1; + } + } + + // + // Update the MAC address + // + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_ERROR, "Ax88772RxControl:Ax88772MacAddressSet\n")); + Status = Ax88772MacAddressSet ( pNicDevice, &pNicDevice->SimpleNetworkData.CurrentAddress.Addr[0]); + } + + // + // Update the receiver control + // + if ( !EFI_ERROR ( Status )) { + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_RX_CONTROL_WRITE; + SetupMsg.Value = RxControl; + SetupMsg.Index = 0; + SetupMsg.Length = 0; + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST | DEBUG_RX_UNICAST | DEBUG_ERROR, + "RxControl: 0x%04x\r\n", + RxControl )); + + // + // Update the multicast hash table + // + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_MULTICAST_HASH_WRITE; + SetupMsg.Value = 0; + SetupMsg.Index = 0; + SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash ); + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + &pNicDevice->MulticastHash ); + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_RX_MULTICAST | DEBUG_ERROR, + "Multicast Hash: 0x%02x %02x %02x %02x %02x %02x %02x %02x\r\n", + (UINT8) MulticastHash[0], + (UINT8)( MulticastHash[0] >> 8 ), + (UINT8)( MulticastHash[0] >> 16 ), + (UINT8)( MulticastHash[0] >> 24 ), + (UINT8) MulticastHash[1], + (UINT8)( MulticastHash[1] >> 8 ), + (UINT8)( MulticastHash[1] >> 16 ), + (UINT8)( MulticastHash[1] >> 24 ))); + } + else { + DEBUG (( DEBUG_ERROR | DEBUG_ERROR, + "ERROR - Failed to update multicast hash table, Status: %r\r\n", + Status )); + } + } + else { + DEBUG (( DEBUG_ERROR | DEBUG_ERROR, + "ERROR - Failed to set receiver control, Status: %r\r\n", + Status )); + } + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Read an SROM location + + This routine calls ::Ax88772UsbCommand to read data from the + SROM. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] Address SROM address + @param [out] pData Buffer to receive the data + + @retval EFI_SUCCESS The read was successful + @retval other The read failed + +**/ +EFI_STATUS +Ax88772SromRead ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 Address, + OUT UINT16 * pData + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "Ax88772SromRead\n")); + + // + // Read a value from the SROM + // + SetupMsg.RequestType = USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request = CMD_SROM_READ; + SetupMsg.Value = (UINT16) Address; + SetupMsg.Index = 0; + SetupMsg.Length = sizeof ( *pData ); + Status = Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + pData ); + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + This routine is called at a regular interval to poll for + receive packets. + + This routine polls the link state and gets any receive packets + by calling ::Ax88772Rx. + + @param [in] Event Timer event + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + +**/ +VOID +Ax88772Timer ( + IN EFI_EVENT Event, + IN NIC_DEVICE * pNicDevice + ) +{ + DEBUG((DEBUG_WARN, "Ax88772Timer\n")); + // + // Use explicit DEBUG messages since the output frequency is too + // high for DEBUG_ERROR to keep up and have spare cycles for the + // shell + // + DEBUG (( DEBUG_TIMER, "Entering Ax88772Timer\r\n" )); + + // + // Poll the link state and get any receive packets + // + Ax88772Rx ( pNicDevice, FALSE ); + + DEBUG (( DEBUG_TIMER, "Exiting Ax88772Timer\r\n" )); +} + + +/** + Send a command to the USB device. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pRequest Pointer to the request structure + @param [in, out] pBuffer Data buffer address + + @retval EFI_SUCCESS The USB transfer was successful + @retval other The USB transfer failed + +**/ +EFI_STATUS +Ax88772UsbCommand ( + IN NIC_DEVICE * pNicDevice, + IN USB_DEVICE_REQUEST * pRequest, + IN OUT VOID * pBuffer + ) +{ + UINT32 CmdStatus; + EFI_USB_DATA_DIRECTION Direction; + EFI_USB_IO_PROTOCOL * pUsbIo; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_ERROR, "Ax88772UsbCommand\n")); + + // + // Determine the transfer direction + // + Direction = EfiUsbNoData; + if ( 0 != pRequest->Length ) { + Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN )) + ? EfiUsbDataIn : EfiUsbDataOut; + } + + // + // Issue the command + // + pUsbIo = pNicDevice->pUsbIo; + Status = pUsbIo->UsbControlTransfer ( pUsbIo, + pRequest, + Direction, + USB_BUS_TIMEOUT, + pBuffer, + pRequest->Length, + &CmdStatus ); + + // + // Determine the operation status + // + if ( !EFI_ERROR ( Status )) { + Status = CmdStatus; + } + else { + // + // Display any errors + // + DEBUG (( DEBUG_ERROR, + "Ax88772UsbCommand - Status: %r\n", + Status )); + + // + // Only use status values associated with the Simple Network protocol + // + if ( EFI_TIMEOUT == Status ) { + Status = EFI_DEVICE_ERROR; + } + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.h new file mode 100644 index 0000000..5eaaaa5 --- /dev/null +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.h @@ -0,0 +1,976 @@ +/** @file + Definitions for ASIX AX88772 Ethernet adapter. + + Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _AX88772_H_ +#define _AX88772_H_ + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Macros +//------------------------------------------------------------------------------ +#undef DEBUG_WARN +#define DEBUG_WARN 0 + +#undef DEBUG_ERROR +#define DEBUG_ERROR 0 + +#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */ +#define DBG_ENTER() DEBUG (( DEBUG_ERROR, "Entering " __FUNCTION__ "\n" )) ///< Display routine entry +#define DBG_EXIT() DEBUG (( DEBUG_ERROR, "Exiting " __FUNCTION__ "\n" )) ///< Display routine exit +#define DBG_EXIT_DEC(Status) DEBUG (( DEBUG_ERROR, "Exiting " __FUNCTION__ ", Status: %d\n", Status )) ///< Display routine exit with decimal value +#define DBG_EXIT_HEX(Status) DEBUG (( DEBUG_ERROR, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status )) ///< Display routine exit with hex value +#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_ERROR, "Exiting " __FUNCTION__ ", Status: %r\n", Status )) ///< Display routine exit with status value +#define DBG_EXIT_TF(Status) DEBUG (( DEBUG_ERROR, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" )) ///< Display routine with TRUE/FALSE value +#else // _MSC_VER +#define DBG_ENTER() ///< Display routine entry +#define DBG_EXIT() ///< Display routine exit +#define DBG_EXIT_DEC(Status) ///< Display routine exit with decimal value +#define DBG_EXIT_HEX(Status) ///< Display routine exit with hex value +#define DBG_EXIT_STATUS(Status) ///< Display routine exit with status value +#define DBG_EXIT_TF(Status) ///< Display routine with TRUE/FALSE value +#endif // _MSC_VER + +#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) != 0) ///< Return TRUE/FALSE for IN direction +#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) == 0) ///< Return TRUE/FALSE for OUT direction +#define USB_IS_BULK_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_BULK) ///< Return TRUE/FALSE for BULK type +#define USB_IS_INTERRUPT_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) ///< Return TRUE/FALSE for INTERRUPT type + +//------------------------------------------------------------------------------ +// Constants +//------------------------------------------------------------------------------ + +#define DEBUG_RX_BROADCAST 0x40000000 ///< Display RX broadcast messages +#define DEBUG_RX_MULTICAST 0x20000000 ///< Display RX multicast messages +#define DEBUG_RX_UNICAST 0x10000000 ///< Display RX unicast messages +#define DEBUG_MAC_ADDRESS 0x08000000 ///< Display the MAC address +#define DEBUG_LINK 0x04000000 ///< Display the link status +#define DEBUG_TX 0x02000000 ///< Display the TX messages +#define DEBUG_PHY 0x01000000 ///< Display the PHY register values +#define DEBUG_SROM 0x00800000 ///< Display the SROM contents +#define DEBUG_TIMER 0x00400000 ///< Display the timer routine entry/exit +#define DEBUG_TPL 0x00200000 ///< Display the timer routine entry/exit + +#define AX88772_MAX_PKT_SIZE ( 2048 - 4 ) ///< Maximum packet size +#define ETHERNET_HEADER_SIZE sizeof ( ETHERNET_HEADER ) ///< Size in bytes of the Ethernet header +#define MIN_ETHERNET_PKT_SIZE 60 ///< Minimum packet size including Ethernet header +#define MAX_ETHERNET_PKT_SIZE 1500 ///< Ethernet spec 3.1.1: Minimum packet size + +#define USB_NETWORK_CLASS 0x09 ///< USB Network class code +#define USB_BUS_TIMEOUT 1000 ///< USB timeout in milliseconds + +#define TIMER_MSEC 20 ///< Polling interval for the NIC +#define TPL_AX88772 TPL_CALLBACK ///< TPL for routine synchronization + +/** + Verify new TPL value + + This macro which is enabled when debug is enabled verifies that + the new TPL value is >= the current TPL value. +**/ +#ifdef VERIFY_TPL +#undef VERIFY_TPL +#endif // VERIFY_TPL + +#if !defined(MDEPKG_NDEBUG) + +#define VERIFY_TPL(tpl) \ +{ \ + EFI_TPL PreviousTpl; \ + \ + PreviousTpl = gBS->RaiseTPL ( TPL_HIGH_LEVEL ); \ + gBS->RestoreTPL ( PreviousTpl ); \ + if ( PreviousTpl > tpl ) { \ + DEBUG (( DEBUG_ERROR, "Current TPL: %d, New TPL: %d\r\n", PreviousTpl, tpl )); \ + ASSERT ( PreviousTpl <= tpl ); \ + } \ +} + +#else // MDEPKG_NDEBUG + +#define VERIFY_TPL(tpl) + +#endif // MDEPKG_NDEBUG + +//------------------------------------------------------------------------------ +// Hardware Definition +//------------------------------------------------------------------------------ + +#define DEV_SIGNATURE SIGNATURE_32 ('A','X','8','8') ///< Signature of data structures in memory + +#define VENDOR_ID 0x0B95 ///< Vendor ID for Asix +#define PRODUCT_ID 0x772A ///< Product ID for the AX88772 USB 10/100 Ethernet controller + +#define RESET_MSEC 1000 ///< Reset duration +#define PHY_RESET_MSEC 500 ///< PHY reset duration + +// +// RX Control register +// + +#define RXC_PRO 0x0001 ///< Receive all packets +#define RXC_AMALL 0x0002 ///< Receive all multicast packets +#define RXC_SEP 0x0004 ///< Save error packets +#define RXC_AB 0x0008 ///< Receive broadcast packets +#define RXC_AM 0x0010 ///< Use multicast destination address hash table +#define RXC_AP 0x0020 ///< Accept physical address from Multicast Filter +#define RXC_SO 0x0080 ///< Start operation +#define RXC_MFB 0x0300 ///< Maximum frame burst +#define RXC_MFB_2048 0 ///< Maximum frame size: 2048 bytes +#define RXC_MFB_4096 0x0100 ///< Maximum frame size: 4096 bytes +#define RXC_MFB_8192 0x0200 ///< Maximum frame size: 8192 bytes +#define RXC_MFB_16384 0x0300 ///< Maximum frame size: 16384 bytes + +// +// Medium Status register +// + +#define MS_FD 0x0002 ///< Full duplex +#define MS_ONE 0x0004 ///< Must be one +#define MS_RFC 0x0010 ///< RX flow control enable +#define MS_TFC 0x0020 ///< TX flow control enable +#define MS_PF 0x0080 ///< Pause frame enable +#define MS_RE 0x0100 ///< Receive enable +#define MS_PS 0x0200 ///< Port speed 1=100, 0=10 Mbps +#define MS_SBP 0x0800 ///< Stop back pressure +#define MS_SM 0x1000 ///< Super MAC support + +// +// Software PHY Select register +// + +#define SPHY_PSEL 0x01 ///< Select internal PHY +#define SPHY_ASEL 0x02 ///< 1=Auto select, 0=Manual select + +// +// Software Reset register +// + +#define SRR_RR 0x01 ///< Clear receive frame length error +#define SRR_RT 0x02 ///< Clear transmit frame length error +#define SRR_PRTE 0x04 ///< External PHY reset pin tri-state enable +#define SRR_PRL 0x08 ///< External PHY reset pin level +#define SRR_BZ 0x10 ///< Force Bulk to return zero length packet +#define SRR_IPRL 0x20 ///< Internal PHY reset control +#define SRR_IPPD 0x40 ///< Internal PHY power down + +// +// PHY ID values +// + +#define PHY_ID_INTERNAL 0x0010 ///< Internal PHY + +// +// USB Commands +// + +#define CMD_PHY_ACCESS_SOFTWARE 0x06 ///< Software in control of PHY +#define CMD_PHY_REG_READ 0x07 ///< Read PHY register, Value: PHY, Index: Register, Data: Register value +#define CMD_PHY_REG_WRITE 0x08 ///< Write PHY register, Value: PHY, Index: Register, Data: New 16-bit value +#define CMD_PHY_ACCESS_HARDWARE 0x0a ///< Hardware in control of PHY +#define CMD_SROM_READ 0x0b ///< Read SROM register: Value: Address, Data: Value +#define CMD_RX_CONTROL_WRITE 0x10 ///< Set the RX control register, Value: New value +#define CMD_GAPS_WRITE 0x12 ///< Write the gaps register, Value: New value +#define CMD_MAC_ADDRESS_READ 0x13 ///< Read the MAC address, Data: 6 byte MAC address +#define CMD_MAC_ADDRESS_WRITE 0x14 ///< Set the MAC address, Data: New 6 byte MAC address +#define CMD_MULTICAST_HASH_WRITE 0x16 ///< Write the multicast hash table, Data: New 8 byte value +#define CMD_MEDIUM_STATUS_READ 0x1a ///< Read medium status register, Data: Register value +#define CMD_MEDIUM_STATUS_WRITE 0x1b ///< Write medium status register, Value: New value +#define CMD_RESET 0x20 ///< Reset register, Value: New value +#define CMD_PHY_SELECT 0x22 ///< PHY select register, Value: New value + +//------------------------------ +// USB Endpoints +//------------------------------ + +#define CONTROL_ENDPOINT 0 ///< Control endpoint +#define INTERRUPT_ENDPOINT 1 ///< Interrupt endpoint +#define BULK_IN_ENDPOINT 2 ///< Receive endpoint +#define BULK_OUT_ENDPOINT 3 ///< Transmit endpoint + +//------------------------------ +// PHY Registers +//------------------------------ + +#define PHY_BMCR 0 ///< Control register +#define PHY_BMSR 1 ///< Status register +#define PHY_ANAR 4 ///< Autonegotiation advertisement register +#define PHY_ANLPAR 5 ///< Autonegotiation link parter ability register +#define PHY_ANER 6 ///< Autonegotiation expansion register + +// BMCR - Register 0 + +#define BMCR_RESET 0x8000 ///< 1 = Reset the PHY, bit clears after reset +#define BMCR_LOOPBACK 0x4000 ///< 1 = Loopback enabled +#define BMCR_100MBPS 0x2000 ///< 100 Mbits/Sec +#define BMCR_10MBPS 0 ///< 10 Mbits/Sec +#define BMCR_AUTONEGOTIATION_ENABLE 0x1000 ///< 1 = Enable autonegotiation +#define BMCR_POWER_DOWN 0x0800 ///< 1 = Power down +#define BMCR_ISOLATE 0x0400 ///< 0 = Isolate PHY +#define BMCR_RESTART_AUTONEGOTIATION 0x0200 ///< 1 = Restart autonegotiation +#define BMCR_FULL_DUPLEX 0x0100 ///< Full duplex operation +#define BMCR_HALF_DUPLEX 0 ///< Half duplex operation +#define BMCR_COLLISION_TEST 0x0080 ///< 1 = Collision test enabled + +// BSMR - Register 1 + +#define BMSR_100BASET4 0x8000 ///< 1 = 100BASE-T4 mode +#define BMSR_100BASETX_FDX 0x4000 ///< 1 = 100BASE-TX full duplex +#define BMSR_100BASETX_HDX 0x2000 ///< 1 = 100BASE-TX half duplex +#define BMSR_10BASET_FDX 0x1000 ///< 1 = 10BASE-T full duplex +#define BMSR_10BASET_HDX 0x0800 ///< 1 = 10BASE-T half duplex +#define BMSR_MF 0x0040 ///< 1 = PHY accepts frames with preamble suppressed +#define BMSR_AUTONEG_CMPLT 0x0020 ///< 1 = Autonegotiation complete +#define BMSR_RF 0x0010 ///< 1 = Remote fault +#define BMSR_AUTONEG 0x0008 ///< 1 = Able to perform autonegotiation +#define BMSR_LINKST 0x0004 ///< 1 = Link up +#define BMSR_JABBER_DETECT 0x0002 ///< 1 = jabber condition detected +#define BMSR_EXTENDED_CAPABILITY 0x0001 ///< 1 = Extended register capable + +// ANAR and ANLPAR Registers 4, 5 + +#define AN_NP 0x8000 ///< 1 = Next page available +#define AN_ACK 0x4000 ///< 1 = Link partner acknowledged +#define AN_RF 0x2000 ///< 1 = Remote fault indicated by link partner +#define AN_FCS 0x0400 ///< 1 = Flow control ability +#define AN_T4 0x0200 ///< 1 = 100BASE-T4 support +#define AN_TX_FDX 0x0100 ///< 1 = 100BASE-TX Full duplex +#define AN_TX_HDX 0x0080 ///< 1 = 100BASE-TX support +#define AN_10_FDX 0x0040 ///< 1 = 10BASE-T Full duplex +#define AN_10_HDX 0x0020 ///< 1 = 10BASE-T support +#define AN_CSMA_CD 0x0001 ///< 1 = IEEE 802.3 CSMA/CD support + +//------------------------------------------------------------------------------ +// Data Types +//------------------------------------------------------------------------------ + +/** + Ethernet header layout + + IEEE 802.3-2002 Part 3 specification, section 3.1.1. +**/ +#pragma pack(1) +typedef struct { + UINT8 dest_addr[PXE_HWADDR_LEN_ETHER]; ///< Destination LAN address + UINT8 src_addr[PXE_HWADDR_LEN_ETHER]; ///< Source LAN address + UINT16 type; ///< Protocol or length +} ETHERNET_HEADER; +#pragma pack() + +/** + Receive and Transmit packet structure +**/ +#pragma pack(1) +typedef struct _RX_TX_PACKET { + struct _RX_TX_PACKET * pNext; ///< Next receive packet + UINT16 Length; ///< Packet length + UINT16 LengthBar; ///< Complement of the length + UINT8 Data[ AX88772_MAX_PKT_SIZE ]; ///< Received packet data +} RX_TX_PACKET; +#pragma pack() + +/** + AX88772 control structure + + The driver uses this structure to manage the Asix AX88772 10/100 + Ethernet controller. +**/ +typedef struct { + UINTN Signature; ///< Structure identification + + // + // USB data + // + EFI_HANDLE Controller; ///< Controller handle + EFI_USB_IO_PROTOCOL * pUsbIo; ///< USB driver interface + + // + // Simple network protocol data + // + EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork; ///< Driver's network stack interface + EFI_SIMPLE_NETWORK_MODE SimpleNetworkData; ///< Data for simple network + + // + // Ethernet controller data + // + BOOLEAN bInitialized; ///< Controller initialized + VOID * pTxBuffer; ///< Last transmit buffer + UINT16 PhyId; ///< PHY ID + + // + // Link state + // + BOOLEAN b100Mbps; ///< Current link speed, FALSE = 10 Mbps + BOOLEAN bComplete; ///< Current state of auto-negotiation + BOOLEAN bFullDuplex; ///< Current duplex + BOOLEAN bLinkUp; ///< Current link state + BOOLEAN bLinkIdle; ///< TRUE = No received traffic + EFI_EVENT Timer; ///< Timer to monitor link state and receive packets + UINTN PollCount; ///< Number of times the autonegotiation status was polled + + // + // Receive buffer list + // + RX_TX_PACKET * pRxHead; ///< Head of receive packet list + RX_TX_PACKET * pRxTail; ///< Tail of receive packet list + RX_TX_PACKET * pRxFree; ///< Free packet list + INT32 MulticastHash[2]; ///< Hash table for multicast destination addresses +} NIC_DEVICE; + +#define DEV_FROM_SIMPLE_NETWORK(a) CR (a, NIC_DEVICE, SimpleNetwork, DEV_SIGNATURE) ///< Locate NIC_DEVICE from Simple Network Protocol + +//------------------------------------------------------------------------------ +// Simple Network Protocol +//------------------------------------------------------------------------------ + +/** + Reset the network adapter. + + Resets a network adapter and reinitializes it with the parameters that + were provided in the previous call to Initialize (). The transmit and + receive queues are cleared. Receive filters, the station address, the + statistics, and the multicast-IP-to-HW MAC addresses are not reset by + this call. + + This routine calls ::Ax88772Reset to perform the adapter specific + reset operation. This routine also starts the link negotiation + by calling ::Ax88772NegotiateLinkStart. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device + during reset. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Reset ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bExtendedVerification + ); + +/** + Initialize the simple network protocol. + + This routine calls ::Ax88772MacAddressGet to obtain the + MAC address. + + @param [in] pNicDevice NIC_DEVICE_INSTANCE pointer + + @retval EFI_SUCCESS Setup was successful + +**/ +EFI_STATUS +SN_Setup ( + IN NIC_DEVICE * pNicDevice + ); + +/** + This routine starts the network interface. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_ALREADY_STARTED The network interface was already started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Start ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ); + +/** + Set the MAC address. + + This function modifies or resets the current station address of a + network interface. If Reset is TRUE, then the current station address + is set ot the network interface's permanent address. If Reset if FALSE + then the current station address is changed to the address specified by + pNew. + + This routine calls ::Ax88772MacAddressSet to update the MAC address + in the network adapter. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bReset Flag used to reset the station address to the + network interface's permanent address. + @param [in] pNew New station address to be used for the network + interface. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_StationAddress ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bReset, + IN EFI_MAC_ADDRESS * pNew + ); + +/** + This function resets or collects the statistics on a network interface. + If the size of the statistics table specified by StatisticsSize is not + big enough for all of the statistics that are collected by the network + interface, then a partial buffer of statistics is returned in + StatisticsTable. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bReset Set to TRUE to reset the statistics for the network interface. + @param [in, out] pStatisticsSize On input the size, in bytes, of StatisticsTable. On output + the size, in bytes, of the resulting table of statistics. + @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that + conains the statistics. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_BUFFER_TOO_SMALL The pStatisticsTable is NULL or the buffer is too small. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Statistics ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bReset, + IN OUT UINTN * pStatisticsSize, + OUT EFI_NETWORK_STATISTICS * pStatisticsTable + ); + +/** + This function stops a network interface. This call is only valid + if the network interface is in the started state. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Stop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ); + +/** + This function releases the memory buffers assigned in the Initialize() call. + Pending transmits and receives are lost, and interrupts are cleared and disabled. + After this call, only Initialize() and Stop() calls may be used. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Shutdown ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ); + +/** + Send a packet over the network. + + This function places the packet specified by Header and Buffer on + the transmit queue. This function performs a non-blocking transmit + operation. When the transmit is complete, the buffer is returned + via the GetStatus() call. + + This routine calls ::Ax88772Rx to empty the network adapter of + receive packets. The routine then passes the transmit packet + to the network adapter. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] HeaderSize The size, in bytes, of the media header to be filled in by + the Transmit() function. If HeaderSize is non-zero, then + it must be equal to SimpleNetwork->Mode->MediaHeaderSize + and DestAddr and Protocol parameters must not be NULL. + @param [in] BufferSize The size, in bytes, of the entire packet (media header and + data) to be transmitted through the network interface. + @param [in] pBuffer A pointer to the packet (media header followed by data) to + to be transmitted. This parameter can not be NULL. If + HeaderSize is zero, then the media header is Buffer must + already be filled in by the caller. If HeaderSize is nonzero, + then the media header will be filled in by the Transmit() + function. + @param [in] pSrcAddr The source HW MAC address. If HeaderSize is zero, then + this parameter is ignored. If HeaderSize is nonzero and + SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress + is used for the source HW MAC address. + @param [in] pDestAddr The destination HW MAC address. If HeaderSize is zero, then + this parameter is ignored. + @param [in] pProtocol The type of header to build. If HeaderSize is zero, then + this parameter is ignored. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + +**/ +EFI_STATUS +EFIAPI +SN_Transmit ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID * pBuffer, + IN EFI_MAC_ADDRESS * pSrcAddr, + IN EFI_MAC_ADDRESS * pDestAddr, + IN UINT16 * pProtocol + ); + +//------------------------------------------------------------------------------ +// Support Routines +//------------------------------------------------------------------------------ + +/** + Get the MAC address + + This routine calls ::Ax88772UsbCommand to request the MAC + address from the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [out] pMacAddress Address of a six byte buffer to receive the MAC address. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772MacAddressGet ( + IN NIC_DEVICE * pNicDevice, + OUT UINT8 * pMacAddress + ); + +/** + Set the MAC address + + This routine calls ::Ax88772UsbCommand to set the MAC address + in the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address. + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88772MacAddressSet ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 * pMacAddress + ); + +/** + Clear the multicast hash table + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + +**/ +VOID +Ax88772MulticastClear ( + IN NIC_DEVICE * pNicDevice + ); + +/** + Enable a multicast address in the multicast hash table + + This routine calls ::Ax88772Crc to compute the hash bit for + this MAC address. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pMacAddress Address of a six byte buffer to containing the MAC address. + +**/ +VOID +Ax88772MulticastSet ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 * pMacAddress + ); + +/** + Start the link negotiation + + This routine calls ::Ax88772PhyWrite to start the PHY's link + negotiation. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The link negotiation was started. + @retval other Failed to start the link negotiation. + +**/ +EFI_STATUS +Ax88772NegotiateLinkStart ( + IN NIC_DEVICE * pNicDevice + ); + +/** + Complete the negotiation of the PHY link + + This routine calls ::Ax88772PhyRead to determine if the + link negotiation is complete. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in, out] pPollCount Address of number of times this routine was polled + @param [out] pbComplete Address of boolean to receive complate status. + @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up. + @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps. + @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772NegotiateLinkComplete ( + IN NIC_DEVICE * pNicDevice, + IN OUT UINTN * pPollCount, + OUT BOOLEAN * pbComplete, + OUT BOOLEAN * pbLinkUp, + OUT BOOLEAN * pbHiSpeed, + OUT BOOLEAN * pbFullDuplex + ); + +/** + Read a register from the PHY + + This routine calls ::Ax88772UsbCommand to read a PHY register. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in, out] pPhyData Address of a buffer to receive the PHY register value + + @retval EFI_SUCCESS The PHY data is available. + @retval other The PHY data is not valid. + +**/ +EFI_STATUS +Ax88772PhyRead ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN OUT UINT16 * pPhyData + ); + +/** + Write to a PHY register + + This routine calls ::Ax88772UsbCommand to write a PHY register. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in] PhyData Address of a buffer to receive the PHY register value + + @retval EFI_SUCCESS The PHY data was written. + @retval other Failed to wwrite the PHY register. + +**/ +EFI_STATUS +Ax88772PhyWrite ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN UINT16 PhyData + ); + +/** + Reset the AX88772 + + This routine uses ::Ax88772UsbCommand to reset the network + adapter. This routine also uses ::Ax88772PhyWrite to reset + the PHY. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772Reset ( + IN NIC_DEVICE * pNicDevice + ); + +/** + Receive a frame from the network. + + This routine polls the USB receive interface for a packet. If a packet + is available, this routine adds the receive packet to the list of + pending receive packets. + + This routine calls ::Ax88772NegotiateLinkComplete to verify + that the link is up. This routine also calls ::SN_Reset to + reset the network adapter when necessary. Finally this + routine attempts to receive one or more packets from the + network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] bUpdateLink TRUE = Update link status + +**/ +VOID +Ax88772Rx ( + IN NIC_DEVICE * pNicDevice, + IN BOOLEAN bUpdateLink + ); + +/** + Enable or disable the receiver + + This routine calls ::Ax88772UsbCommand to update the + receiver state. This routine also calls ::Ax88772MacAddressSet + to establish the MAC address for the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RxFilter Simple network RX filter mask value + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88772RxControl ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 RxFilter + ); + +/** + Read an SROM location + + This routine calls ::Ax88772UsbCommand to read data from the + SROM. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] Address SROM address + @param [out] pData Buffer to receive the data + + @retval EFI_SUCCESS The read was successful + @retval other The read failed + +**/ +EFI_STATUS +Ax88772SromRead ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 Address, + OUT UINT16 * pData + ); + +/** + This routine is called at a regular interval to poll for + receive packets. + + This routine polls the link state and gets any receive packets + by calling ::Ax88772Rx. + + @param [in] Event Timer event + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + +**/ +VOID +Ax88772Timer ( + IN EFI_EVENT Event, + IN NIC_DEVICE * pNicDevice + ); + +/** + Send a command to the USB device. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pRequest Pointer to the request structure + @param [in, out] pBuffer Data buffer address + + @retval EFI_SUCCESS The USB transfer was successful + @retval other The USB transfer failed + +**/ +EFI_STATUS +Ax88772UsbCommand ( + IN NIC_DEVICE * pNicDevice, + IN USB_DEVICE_REQUEST * pRequest, + IN OUT VOID * pBuffer + ); + +//------------------------------------------------------------------------------ +// EFI Component Name Protocol Support +//------------------------------------------------------------------------------ + +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; ///< Component name protocol declaration +extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2; ///< Component name 2 protocol declaration + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param [in] pLanguage A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 3066 or ISO 639-2 language code format. + @param [out] ppDriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL * pThis, + IN CHAR8 * pLanguage, + OUT CHAR16 ** ppDriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param [in] ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + @param [in] ChildHandle The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + @param [in] pLanguage A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 3066 or ISO 639-2 language code format. + @param [out] ppControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL * pThis, + IN EFI_HANDLE ControllerHandle, + IN OPTIONAL EFI_HANDLE ChildHandle, + IN CHAR8 * pLanguage, + OUT CHAR16 ** ppControllerName + ); + +//------------------------------------------------------------------------------ + +#endif // _AX88772_H_ diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.inf new file mode 100644 index 0000000..065aeeb --- /dev/null +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/Ax88772.inf @@ -0,0 +1,57 @@ +## @file +# Component description file for ASIX AX88772 USB/Ethernet driver. +# +# This module provides support for the ASIX AX88772 USB/Ethernet adapter. +# Copyright (c) 2011, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = Ax88772 + FILE_GUID = B15239D6-6A01-4808-A0F7-B7F20F073555 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 0.1 + ENTRY_POINT = EntryPoint + +[Sources.common] + Ax88772.h + Ax88772.c + ComponentName.c + DriverBinding.c + SimpleNetwork.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec + SamsungPlatformPkg/SamsungPlatformPkg.dec + +[LibraryClasses] + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + UefiDriverEntryPoint + DevicePathLib + BaseLib + NetLib + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiSimpleNetworkProtocolGuid + gEfiUsbIoProtocolGuid ## TO_START + gSamsungPlatformGpioProtocolGuid + gEfiPxeBaseCodeProtocolGuid + +[Depex] + TRUE diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/ComponentName.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/ComponentName.c new file mode 100644 index 0000000..8fceb60 --- /dev/null +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/ComponentName.c @@ -0,0 +1,184 @@ +/** @file + UEFI Component Name(2) protocol implementation. + + Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Ax88772.h" + +/** + EFI Component Name Protocol declaration +**/ +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = { + GetDriverName, + GetControllerName, + "eng" +}; + +/** + EFI Component Name 2 Protocol declaration +**/ +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GetControllerName, + "en" +}; + + +/** + Driver name table declaration +**/ +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE +mDriverNameTable[] = { + {"eng;en", L"AX88772 Ethernet Driver"}, + {NULL, NULL} +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param [in] pLanguage A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 3066 or ISO 639-2 language code format. + @param [out] ppDriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL * pThis, + IN CHAR8 * pLanguage, + OUT CHAR16 ** ppDriverName + ) +{ + EFI_STATUS Status; + + DBG_ENTER ( ); + Status = LookupUnicodeString2 ( + pLanguage, + pThis->SupportedLanguages, + mDriverNameTable, + ppDriverName, + (BOOLEAN)(pThis == &gComponentName) + ); + DBG_EXIT_HEX ( Status ); + return Status; +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param [in] ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + @param [in] ChildHandle The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + @param [in] pLanguage A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 3066 or ISO 639-2 language code format. + @param [out] ppControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL * pThis, + IN EFI_HANDLE ControllerHandle, + IN OPTIONAL EFI_HANDLE ChildHandle, + IN CHAR8 * pLanguage, + OUT CHAR16 ** ppControllerName + ) +{ + EFI_STATUS Status; + + DBG_ENTER ( ); + + // + // Set the controller name + // + *ppControllerName = L"AX88772 10/100 Ethernet"; + Status = EFI_SUCCESS; + + // + // Return the operation status + // + DBG_EXIT_HEX ( Status ); + return Status; +} diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/DriverBinding.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/DriverBinding.c new file mode 100644 index 0000000..a88a340 --- /dev/null +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/DriverBinding.c @@ -0,0 +1,543 @@ +/** @file + Implement the driver binding protocol for Asix AX88772 Ethernet driver. + + Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Ax88772.h" +#include +#include "Protocol/ExynosGpio.h" +#include + +/** + Verify the controller type + + @param [in] pThis Protocol instance pointer. + @param [in] Controller Handle of device to test. + @param [in] pRemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +DriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL * pThis, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath + ) +{ + EFI_USB_DEVICE_DESCRIPTOR Device; + EFI_USB_IO_PROTOCOL * pUsbIo; + EFI_STATUS Status; + EXYNOS_GPIO *Gpio; + static int i = 0; + + // + // Connect to the USB stack + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &pUsbIo, + pThis->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (i == 0) { + if (Status == EFI_SUCCESS) { + i=i+1; + } else { + gBS->LocateProtocol(&gSamsungPlatformGpioProtocolGuid, NULL, (VOID **)&Gpio); + Gpio->Set(Gpio, USB_2_X3, GPIO_MODE_OUTPUT_0); + Gpio->Set(Gpio, USB_2_X3, GPIO_MODE_OUTPUT_1); + } + } + + if (!EFI_ERROR ( Status )) { + // + // Get the interface descriptor to check the USB class and find a transport + // protocol handler. + // + Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device ); + if (!EFI_ERROR ( Status )) { + // + // Validate the adapter + // + if (( VENDOR_ID != Device.IdVendor ) + || ( PRODUCT_ID != Device.IdProduct )) { + Status = EFI_UNSUPPORTED; + } + } + + // + // Done with the USB stack + // + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + } + + // + // Return the device supported status + // + return Status; +} + + +/** + Start this driver on Controller by opening UsbIo and DevicePath protocols. + Initialize PXE structures, create a copy of the Controller Device Path with the + NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol + on the newly created Device Path. + + @param [in] pThis Protocol instance pointer. + @param [in] Controller Handle of device to work with. + @param [in] pRemainingDevicePath Not used, always produce all possible children. + + @retval EFI_SUCCESS This driver is added to Controller. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +DriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL * pThis, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath + ) +{ + EFI_STATUS Status; + NIC_DEVICE * pNicDevice; + UINTN LengthInBytes; + + DBG_ENTER ( ); + + // + // Allocate the device structure + // + LengthInBytes = sizeof ( *pNicDevice ); + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + LengthInBytes, + (VOID **) &pNicDevice + ); + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_POOL | DEBUG_INIT, + "0x%08x: Allocate pNicDevice, %d bytes\r\n", + pNicDevice, + sizeof ( *pNicDevice ))); + + // + // Set the structure signature + // + ZeroMem ( pNicDevice, LengthInBytes ); + pNicDevice->Signature = DEV_SIGNATURE; + + // + // Connect to the USB I/O protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &pNicDevice->pUsbIo, + pThis->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if ( !EFI_ERROR ( Status )) { + // + // Allocate the necessary events + // + + Status = gBS->CreateEvent ( EVT_TIMER, + TPL_AX88772, + (EFI_EVENT_NOTIFY)Ax88772Timer, + pNicDevice, + (VOID **)&pNicDevice->Timer ); + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "0x%08x: Allocated timer\r\n", + pNicDevice->Timer )); + + // + // Initialize the simple network protocol + // + pNicDevice->Controller = Controller; + SN_Setup ( pNicDevice ); + + // + // Start the timer + // + Status = gBS->SetTimer ( pNicDevice->Timer, + TimerPeriodic, + TIMER_MSEC ); + if ( !EFI_ERROR ( Status )) { + // + // Install both the simple network and device path protocols. + // + + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiCallerIdGuid, + pNicDevice, + &gEfiSimpleNetworkProtocolGuid, + &pNicDevice->SimpleNetwork, + NULL + ); + + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "Installed: gEfiCallerIdGuid on 0x%08x\r\n", + Controller )); + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "Installed: gEfiSimpleNetworkProtocolGuid on 0x%08x\r\n", + Controller )); + DBG_EXIT_STATUS ( Status ); + return Status; + } + DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_ERROR, + "ERROR - Failed to install gEfiSimpleNetworkProtocol on 0x%08x\r\n", + Controller )); + } + else { + DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_ERROR, + "ERROR - Failed to start the timer, Status: %r\r\n", + Status )); + } + } + else { + DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_ERROR, + "ERROR - Failed to create timer event, Status: %r\r\n", + Status )); + } + + // + // Done with the USB stack + // + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + } + + // + // Done with the device + // + gBS->FreePool ( pNicDevice ); + } + + // + // Display the driver start status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and + closing the DevicePath and PciIo protocols on Controller. + + @param [in] pThis Protocol instance pointer. + @param [in] Controller Handle of device to stop driver on. + @param [in] NumberOfChildren How many children need to be stopped. + @param [in] pChildHandleBuffer Not used. + + @retval EFI_SUCCESS This driver is removed Controller. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + @retval other This driver was not removed from this device. + +**/ +EFI_STATUS +EFIAPI +DriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * pThis, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * pChildHandleBuffer + ) +{ + NIC_DEVICE * pNicDevice; + EFI_STATUS Status; + + DBG_ENTER ( ); + + // + // Determine if this driver is already attached + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiCallerIdGuid, + (VOID **) &pNicDevice, + pThis->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if ( !EFI_ERROR ( Status )) { + // + // AX88772 driver is no longer running on this device + // + gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiSimpleNetworkProtocolGuid, + &pNicDevice->SimpleNetwork, + &gEfiCallerIdGuid, + pNicDevice, + NULL ); + DEBUG (( DEBUG_POOL | DEBUG_INIT, + "Removed: gEfiSimpleNetworkProtocolGuid from 0x%08x\r\n", + Controller )); + DEBUG (( DEBUG_POOL | DEBUG_INIT, + "Removed: gEfiCallerIdGuid from 0x%08x\r\n", + Controller )); + + // + // Stop the timer + // + if ( NULL != pNicDevice->Timer ) { + gBS->SetTimer ( pNicDevice->Timer, TimerCancel, 0 ); + gBS->CloseEvent ( pNicDevice->Timer ); + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "0x%08x: Released timer\r\n", + pNicDevice->Timer )); + } + + // + // Done with the device context + // + DEBUG (( DEBUG_POOL | DEBUG_INIT, + "0x%08x: Free pNicDevice, %d bytes\r\n", + pNicDevice, + sizeof ( *pNicDevice ))); + gBS->FreePool ( pNicDevice ); + } + + // + // Return the shutdown status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Driver binding protocol declaration +**/ +EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = { + DriverSupported, + DriverStart, + DriverStop, + 0xa, + NULL, + NULL +}; + + +/** + Ax88772 driver unload routine. + + @param [in] ImageHandle Handle for the image. + + @retval EFI_SUCCESS Image may be unloaded + +**/ +EFI_STATUS +EFIAPI +DriverUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + UINTN BufferSize; + UINTN Index; + UINTN Max; + EFI_HANDLE * pHandle; + EFI_STATUS Status; + + // + // Determine which devices are using this driver + // + BufferSize = 0; + pHandle = NULL; + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiCallerIdGuid, + NULL, + &BufferSize, + NULL ); + if ( EFI_BUFFER_TOO_SMALL == Status ) { + for ( ; ; ) { + // + // One or more block IO devices are present + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + BufferSize, + (VOID **) &pHandle + ); + if ( EFI_ERROR ( Status )) { + DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "Insufficient memory, failed handle buffer allocation\r\n" )); + break; + } + + // + // Locate the block IO devices + // + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiCallerIdGuid, + NULL, + &BufferSize, + pHandle ); + if ( EFI_ERROR ( Status )) { + // + // Error getting handles + // + DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_ERROR, + "Failure getting Telnet handles\r\n" )); + break; + } + + // + // Remove any use of the driver + // + Max = BufferSize / sizeof ( pHandle[ 0 ]); + for ( Index = 0; Max > Index; Index++ ) { + Status = DriverStop ( &gDriverBinding, + pHandle[ Index ], + 0, + NULL ); + if ( EFI_ERROR ( Status )) { + DEBUG (( DEBUG_WARN | DEBUG_INIT | DEBUG_ERROR, + "WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ])); + break; + } + } + break; + } + } + else { + if ( EFI_NOT_FOUND == Status ) { + // + // No devices were found + // + Status = EFI_SUCCESS; + } + } + + // + // Free the handle array + // + if ( NULL != pHandle ) { + gBS->FreePool ( pHandle ); + } + + // + // Remove the protocols installed by the EntryPoint routine. + // + if ( !EFI_ERROR ( Status )) { + gBS->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEfiDriverBindingProtocolGuid, + &gDriverBinding, + &gEfiComponentNameProtocolGuid, + &gComponentName, + &gEfiComponentName2ProtocolGuid, + &gComponentName2, + NULL + ); + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "Removed: gEfiComponentName2ProtocolGuid from 0x%08x\r\n", + ImageHandle )); + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "Removed: gEfiComponentNameProtocolGuid from 0x%08x\r\n", + ImageHandle )); + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "Removed: gEfiDriverBindingProtocolGuid from 0x%08x\r\n", + ImageHandle )); + } + + // + // Return the unload status + // + return Status; +} + + +/** +Ax88772 driver entry point. + +@param [in] ImageHandle Handle for the image. +@param [in] pSystemTable Address of the system table. + +@retval EFI_SUCCESS Image successfully loaded. + +**/ +EFI_STATUS +EFIAPI +EntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE * pSystemTable + ) +{ + EFI_LOADED_IMAGE_PROTOCOL * pLoadedImage; + EFI_STATUS Status; + + DBG_ENTER ( ); + + // + // Enable unload support + // + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&pLoadedImage + ); + if (!EFI_ERROR (Status)) { + pLoadedImage->Unload = DriverUnload; + } + + // + // Add the driver to the list of drivers + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + pSystemTable, + &gDriverBinding, + ImageHandle, + &gComponentName, + &gComponentName2 + ); + ASSERT_EFI_ERROR (Status); + if ( !EFI_ERROR ( Status )) { + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "Installed: gEfiDriverBindingProtocolGuid on 0x%08x\r\n", + ImageHandle )); + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "Installed: gEfiComponentNameProtocolGuid on 0x%08x\r\n", + ImageHandle )); + DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_ERROR, + "Installed: gEfiComponentName2ProtocolGuid on 0x%08x\r\n", + ImageHandle )); + } + DBG_EXIT_STATUS ( Status ); + return Status; +} diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.c deleted file mode 100644 index 51a8c16..0000000 --- a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.c +++ /dev/null @@ -1,788 +0,0 @@ -/** @file - Template for Timer Architecture Protocol driver of the ARM flavor - - Copyright (c) 2012, Samsung Electronics Co. All rights reserved.
- - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "EthDxe.h" - - -ETH_DXE_PRIVATE_DATA gEthDxePrivateTemplate = { - ETH_DXE_PRIVATE_DATA_SIGNATURE, - { - EFI_SIMPLE_NETWORK_PROTOCOL_REVISION, - EthStart, - EthStop, - EthInitialize, - EthReset, - EthShutdown, - EthReceiveFilters, - EthStationAddress, - EthStatistics, - EthMCastIpToMac, - EthNvData, - EthGetStatus, - EthTransmit, - EthReceive, - NULL, - NULL - }, - { - EfiSimpleNetworkStopped, // State - NET_ETHER_ADDR_LEN, // HwAddressSize - NET_ETHER_HEADER_SIZE, // MediaHeaderSize - 1500, // MaxPacketSize - 0, // NvRamSize - 0, // NvRamAccessSize - 0, // ReceiveFilterMask - 0, // ReceiveFilterSetting - MAX_MCAST_FILTER_CNT, // MaxMCastFilterCount - 0, // MCastFilterCount - { - 0 - }, // MCastFilter - { - 0 - }, // CurrentAddress - { - 0 - }, // BroadcastAddress - { - 0 - }, // PermanentAddress - NET_IFTYPE_ETHERNET, // IfType - FALSE, // MacAddressChangeable - FALSE, // MultipleTxSupported - FALSE, // MediaPresentSupported - TRUE // MediaPresent - }, - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - (UINT8)(sizeof(VENDOR_DEVICE_PATH)), - (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8), - EFI_SIMPLE_NETWORK_PROTOCOL_GUID - }, - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - sizeof (EFI_DEVICE_PATH_PROTOCOL), - 0 - } - } -}; - - -UINT32 smc911x_reg_read(UINT32 offset) -{ - UINT32 regBase = PcdGet32(PcdSMC911XBase); - UINT32 val; - - val = (MmioRead16(regBase + offset) & 0xFFFF) | ((MmioRead16(regBase + offset + 2) & 0xFFFF) << 16); - - return val; -} - -VOID smc911x_reg_write(UINT32 offset, UINT32 val) -{ - UINT32 regBase = PcdGet32(PcdSMC911XBase); - - MmioWrite16(regBase + offset, ((UINT16)(val & 0xFFFF))); - MmioWrite16(regBase + offset + 2, ((UINT16)((val & 0xFFFF0000)>>16))); -} - -UINT32 smc911x_get_mac_csr(UINT8 reg) -{ - while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - smc911x_reg_write(MAC_CSR_CMD, (MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg)); - while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - return smc911x_reg_read(MAC_CSR_DATA); -} - -VOID smc911x_set_mac_csr(UINT8 reg, UINT32 data) -{ - while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - smc911x_reg_write(MAC_CSR_DATA, data); - smc911x_reg_write(MAC_CSR_CMD, (MAC_CSR_CMD_CSR_BUSY | reg)); - while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; -} - -VOID smc911x_reset(VOID) -{ - INT32 timeout; - - /* Take out of PM setting first */ - if (smc911x_reg_read(PMT_CTRL) & PMT_CTRL_READY) { - /* Write to the bytetest will take out of powerdown */ - smc911x_reg_write(BYTE_TEST, 0x0); - - timeout = 10; - - while (timeout-- && !(smc911x_reg_read(PMT_CTRL) & PMT_CTRL_READY)) - MicroSecondDelay(10); - if (!timeout) { - DEBUG((EFI_D_ERROR, "smc911x_reset: timeout waiting for PM restore\n")); - return; - } - } - - /* Disable interrupts */ - smc911x_reg_write(INT_EN, 0); - - smc911x_reg_write(HW_CFG, HW_CFG_SRST); - - timeout = 1000; - while (timeout-- && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY)) - MicroSecondDelay(10); - - if (!timeout) { - DEBUG((EFI_D_ERROR, "smc911x_reset: reset timeout\n")); - return; - } - - /* Reset the FIFO level and flow control settings */ - smc911x_set_mac_csr(FLOW, FLOW_FCPT | FLOW_FCEN); - smc911x_reg_write(AFC_CFG, 0x0050287F); - - /* Set to LED outputs */ - smc911x_reg_write(GPIO_CFG, 0x70070000); -} - -VOID smc911x_phy_reset(VOID) -{ - UINT32 reg; - - reg = smc911x_reg_read(PMT_CTRL); - reg &= ~0xfffff030; - reg |= PMT_CTRL_PHY_RST; - smc911x_reg_write(PMT_CTRL, reg); - - MicroSecondDelay(100000); -} - -VOID smc911x_miiphy_read(UINT8 phy, UINT8 reg, UINT16 *val) -{ - while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY) - ; - - smc911x_set_mac_csr(MII_ACC, (phy << 11 | reg << 6 | MII_ACC_MII_BUSY)); - - while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY) - ; - - *val = smc911x_get_mac_csr(MII_DATA); -} - -VOID smc911x_miiphy_write(UINT8 phy, UINT8 reg, UINT16 val) -{ - while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY) - ; - - smc911x_set_mac_csr(MII_DATA, val); - smc911x_set_mac_csr(MII_ACC, (phy << 11 | reg << 6 | MII_ACC_MII_BUSY | MII_ACC_MII_WRITE)); - - while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY) - ; -} - -VOID smc911x_phy_configure(VOID) -{ - INT32 timeout; - UINT16 status; - - smc911x_phy_reset(); - - smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_RESET); - MicroSecondDelay(1000); - smc911x_miiphy_write(1, PHY_ANAR, 0x01e1); - smc911x_miiphy_write(1, PHY_BMCR, (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG)); - - timeout = 5000; - do { - MicroSecondDelay(1000); - if ((timeout--) == 0) - goto err_out; - - smc911x_miiphy_read(1, PHY_BMSR, &status); - } while (!(status & PHY_BMSR_LS)); - - DEBUG((EFI_D_ERROR, "smc911x_phy_configure: PHY initialized\n")); - - return; - -err_out: - DEBUG((EFI_D_ERROR, "smc911x_phy_configure: autonegotiation timed out\n")); -} - -VOID smc911x_handle_mac_address(ETH_DXE_PRIVATE_DATA *Private) -{ - UINT32 addrh, addrl; - - addrl = Private->Mode.CurrentAddress.Addr[0] | \ - (Private->Mode.CurrentAddress.Addr[1] << 8) | \ - (Private->Mode.CurrentAddress.Addr[2] << 16) | \ - (Private->Mode.CurrentAddress.Addr[3] << 24); - addrh = Private->Mode.CurrentAddress.Addr[4] | \ - (Private->Mode.CurrentAddress.Addr[5] << 8); - - smc911x_set_mac_csr(ADDRL, addrl); - smc911x_set_mac_csr(ADDRH, addrh); -} - -VOID smc911x_enable(VOID) -{ - /* Enable TX */ - smc911x_reg_write(HW_CFG, (8 << 16 | HW_CFG_SF)); - - smc911x_reg_write(GPT_CFG, (GPT_CFG_TIMER_EN | 10000)); - - smc911x_reg_write(TX_CFG, TX_CFG_TX_ON); - - /* no padding to start of packets */ - smc911x_reg_write(RX_CFG, 0); - - smc911x_set_mac_csr(MAC_CR, (MAC_CR_TXEN | MAC_CR_RXEN | MAC_CR_HBDIS /*| MAC_CR_PADSTR*/)); -} - -EFI_STATUS -EFIAPI -EthStart( - EFI_SIMPLE_NETWORK_PROTOCOL *This -) -{ - ETH_DXE_PRIVATE_DATA *Private; - - Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This); - - switch ( Private->Snp.Mode->State ) - { - case EfiSimpleNetworkStopped: - break; - - case EfiSimpleNetworkStarted: - case EfiSimpleNetworkInitialized: - return( EFI_ALREADY_STARTED ); - break; - - default: - return( EFI_DEVICE_ERROR ); - break; - } - - /* gpio configuration */ - MmioAndThenOr32(0x11000000 + 0x120, ~((0xFF<<16)|(0xFF<<4)), ((0x22<<16)|(0x52<<4))); - - /* 16 Bit bus width */ - MmioWrite32(0x11000000 + 0x1C0, 0x22222222); - MmioWrite32(0x11000000 + 0x1E0, 0x22222222); - - /* SROM BANK1 */ - MmioAndThenOr32(0x12570000, ~(0xF<<4), (((1<<0)|(0<<2)|(1<<3))<<4)); - - /* set timing for nCS1 suitable for ethernet chip */ - MmioWrite32(0x12570008, ((0x1 << 0) | (0x9 << 4) | (0xC << 8) | (0x1 << 12) | \ - (0x6 << 16) | (0x1 << 24) | (0x1 << 28))); - - Private->Snp.Mode->State = EfiSimpleNetworkStarted; - - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -EthStop( - EFI_SIMPLE_NETWORK_PROTOCOL *This -) -{ - ETH_DXE_PRIVATE_DATA *Private; - - Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This); - - switch ( Private->Snp.Mode->State ) - { - case EfiSimpleNetworkStarted: - break; - - case EfiSimpleNetworkStopped: - return( EFI_NOT_STARTED ); - break; - - default: - return( EFI_DEVICE_ERROR ); - break; - } - - Private->Snp.Mode->State = EfiSimpleNetworkStopped; - - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -EthInitialize( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINTN ExtraRxBufferSize, - UINTN ExtraTxBufferSize -) -{ - UINT32 val, i, addrh, addrl; - ETH_DXE_PRIVATE_DATA *Private; - - Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This); - - switch ( Private->Snp.Mode->State ) - { - case EfiSimpleNetworkStarted: - break; - - case EfiSimpleNetworkStopped: - return( EFI_NOT_STARTED ); - break; - - default: - return( EFI_DEVICE_ERROR ); - break; - } - - val = smc911x_reg_read(BYTE_TEST); - - if(val == 0xFFFFFFFF) { - return EFI_NO_MEDIA; - } - else if(val != 0x87654321) { - DEBUG((EFI_D_ERROR,"EthInitialize: Invalid chip endian 0x%x\n", val)); - return EFI_NO_MEDIA; - } - - val = smc911x_reg_read(ID_REV) >> 16; - for(i=0;chip_ids[i].id != 0;i++) { - if(chip_ids[i].id == val) - break; - } - - if(!chip_ids[i].id) { - DEBUG((EFI_D_ERROR,"EthInitialize: Unknown chip id 0x%x\n", val)); - return EFI_NO_MEDIA; - } - else { - DEBUG((EFI_D_ERROR,"EthInitialize: Chip id 0x%x\n", val)); - } - - addrh = smc911x_get_mac_csr(ADDRH); - addrl = smc911x_get_mac_csr(ADDRL); - - if (addrl == 0xffffffff && addrh == 0x0000ffff) { - addrh = 0x00000040; - addrl = 0x5c260a5b; - } - - Private->Mode.CurrentAddress.Addr[0] = (addrl & 0xFF); - Private->Mode.CurrentAddress.Addr[1] = (addrl & 0xFF00)>>8; - Private->Mode.CurrentAddress.Addr[2] = (addrl & 0xFF0000)>>16; - Private->Mode.CurrentAddress.Addr[3] = (addrl & 0xFF000000)>>24; - Private->Mode.CurrentAddress.Addr[4] = (addrh & 0xFF); - Private->Mode.CurrentAddress.Addr[5] = (addrh & 0xFF00)>>8; - gBS->CopyMem((VOID *)&Private->Mode.PermanentAddress, \ - (VOID *)&Private->Mode.CurrentAddress, \ - sizeof(EFI_MAC_ADDRESS)); - - DEBUG((EFI_D_ERROR,"EthInitialize: MAC address is ")); - - for(i=6;i>0;i--) { - DEBUG((EFI_D_ERROR,"%02x", Private->Mode.CurrentAddress.Addr[i - 1])); - if(i > 1) - DEBUG((EFI_D_ERROR,":")); - else - DEBUG((EFI_D_ERROR,"\n")); - } - - smc911x_reset(); - - /* Configure the PHY, initialize the link state */ - smc911x_phy_configure(); - - smc911x_handle_mac_address(Private); - - /* Turn on Tx + Rx */ - smc911x_enable(); - - Private->Snp.Mode->State = EfiSimpleNetworkInitialized; - - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -EthReset( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN ExtendedVerification -) -{ - ETH_DXE_PRIVATE_DATA *Private; - - Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This); - - switch ( Private->Snp.Mode->State ) - { - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return( EFI_NOT_STARTED ); - break; - - default: - return( EFI_DEVICE_ERROR ); - break; - } - - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -EthShutdown( - EFI_SIMPLE_NETWORK_PROTOCOL *This -) -{ - ETH_DXE_PRIVATE_DATA *Private; - - Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This); - - switch ( Private->Snp.Mode->State ) - { - case EfiSimpleNetworkInitialized: - break; - - case EfiSimpleNetworkStopped: - return( EFI_NOT_STARTED ); - break; - - default: - return( EFI_DEVICE_ERROR ); - break; - } - - Private->Snp.Mode->State = EfiSimpleNetworkStarted; - - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -EthReceiveFilters( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINT32 Enable, - UINT32 Disable, - BOOLEAN ResetMCastFilter, - UINTN MCastFilterCnt, - EFI_MAC_ADDRESS *MCastFilter -) -{ - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -EthStationAddress( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN Reset, - EFI_MAC_ADDRESS *New -) -{ - return EFI_UNSUPPORTED; -} - -EFI_STATUS -EFIAPI -EthStatistics( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN Reset, - UINTN *StatisticsSize, - EFI_NETWORK_STATISTICS *StatisticsTable -) -{ - return EFI_UNSUPPORTED; -} - -EFI_STATUS -EFIAPI -EthMCastIpToMac( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN IPv6, - EFI_IP_ADDRESS *IP, - EFI_MAC_ADDRESS *MAC -) -{ - return EFI_UNSUPPORTED; -} - -EFI_STATUS -EFIAPI -EthNvData( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN ReadWrite, - UINTN Offset, - UINTN BufferSize, - VOID *Buffer -) -{ - return EFI_UNSUPPORTED; -} - -EFI_STATUS -EFIAPI -EthGetStatus( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINT32 *InterruptStatus, - VOID **TxBuf -) -{ - if ( TxBuf != NULL ) { - *( ( UINT8 ** ) TxBuf ) = ( UINT8 * ) 1; - } - - if ( InterruptStatus != NULL ) { - *InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; - } - - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -EthTransmit( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINTN HeaderSize, - UINTN BufferSize, - VOID *Buffer, - EFI_MAC_ADDRESS *SrcAddr, - EFI_MAC_ADDRESS *DestAddr, - UINT16 *Protocol -) -{ - UINT32 *data = (UINT32 *)Buffer; - UINT32 tmpSize; - UINT32 status; - EthernetHeader *EnetHeader; - - if ( This->Mode->State < EfiSimpleNetworkStarted ) { - return( EFI_NOT_STARTED ); - } - - if ( HeaderSize != 0 ) { - if ( ( DestAddr == NULL ) || ( Protocol == NULL ) || \ - ( HeaderSize != This->Mode->MediaHeaderSize ) ) { - return( EFI_INVALID_PARAMETER ); - } - - if ( SrcAddr == NULL ) { - SrcAddr = &This->Mode->CurrentAddress; - } - - EnetHeader = (EthernetHeader *)Buffer; - - CopyMem( EnetHeader->DstAddr, DestAddr, NET_ETHER_ADDR_LEN ); - CopyMem( EnetHeader->SrcAddr, SrcAddr, NET_ETHER_ADDR_LEN ); - - EnetHeader->Type = HTONS( *Protocol ); - } - - smc911x_reg_write(TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG | TX_CMD_A_INT_LAST_SEG | BufferSize); - smc911x_reg_write(TX_DATA_FIFO, BufferSize); - - tmpSize = (BufferSize + 3) / 4; - - while (tmpSize--) - smc911x_reg_write(TX_DATA_FIFO, *data++); - - /* wait for transmission */ - while (!((smc911x_reg_read(TX_FIFO_INF) & TX_FIFO_INF_TSUSED) >> 16)) - ; - - /* get status. Ignore 'no carrier' error, it has no meaning for - * full duplex operation - */ - status = smc911x_reg_read(TX_STATUS_FIFO) & \ - (TX_STS_LOC | TX_STS_LATE_COLL | \ - TX_STS_MANY_COLL | TX_STS_MANY_DEFER | \ - TX_STS_UNDERRUN); - - if (!status) - return EFI_SUCCESS; - - DEBUG((EFI_D_ERROR, "EthTransmit: Failed to send packet: %s%s%s%s%s\n", - status & TX_STS_LOC ? "TX_STS_LOC " : "", - status & TX_STS_LATE_COLL ? "TX_STS_LATE_COLL " : "", - status & TX_STS_MANY_COLL ? "TX_STS_MANY_COLL " : "", - status & TX_STS_MANY_DEFER ? "TX_STS_MANY_DEFER " : "", - status & TX_STS_UNDERRUN ? "TX_STS_UNDERRUN" : "")); - - return EFI_DEVICE_ERROR; -} - -EFI_STATUS -EFIAPI -EthReceive( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINTN *HeaderSize, - UINTN *BufferSize, - VOID *Buffer, - EFI_MAC_ADDRESS *SrcAddr, - EFI_MAC_ADDRESS *DestAddr, - UINT16 *Protocol -) -{ - UINT32 *data = (UINT32 *)Buffer; - UINT32 pktSize, tmpSize; - UINT32 status, i; - EthernetHeader *EnetHeader; - - /* workaround: delay for rx packet should be added here. - * because NetLoop does not guarantee the RX packet delay. - */ - for (i=0; i<0x100000; i++) { - if ((smc911x_reg_read(RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) - break; - } - - if (i == 0x100000) { - DEBUG((EFI_D_ERROR, "EthReceive: timeout in RX\n")); - return EFI_TIMEOUT; - } - - if ((smc911x_reg_read(RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) { - status = smc911x_reg_read(RX_STATUS_FIFO); - pktSize = (status & RX_STS_PKT_LEN) >> 16; - - smc911x_reg_write(RX_CFG, 0); - - tmpSize = (pktSize + 3) / 4; - i = 0; - while (tmpSize--) - *data++ = smc911x_reg_read(RX_DATA_FIFO); - - if (status & RX_STS_ES) { - DEBUG((EFI_D_ERROR, "EthReceive: dropped bad packet. Status: 0x%x\n", status)); - } - - *BufferSize = pktSize -4; //discard 4 bytes of FCS - - } - -#if 0 - { - UINT8 *tmpBuffer = (UINT8 *)Buffer; - - for(i=0;i<*BufferSize;i++) { - DEBUG((EFI_D_ERROR, "%02x", *tmpBuffer++)); - if((i%16) < 15) - DEBUG((EFI_D_ERROR, " ")); - else - DEBUG((EFI_D_ERROR, "\n")); - } - - DEBUG((EFI_D_ERROR, "\n")); - } -#endif - - if(HeaderSize != NULL) { - *HeaderSize = sizeof(EthernetHeader); - } - - EnetHeader = (EthernetHeader *)Buffer; - - if(SrcAddr != NULL) { - ZeroMem(SrcAddr, sizeof(EFI_MAC_ADDRESS)); - CopyMem(SrcAddr, EnetHeader->SrcAddr, NET_ETHER_ADDR_LEN); - } - - if(DestAddr != NULL) { - ZeroMem(DestAddr, sizeof(EFI_MAC_ADDRESS)); - CopyMem(DestAddr, EnetHeader->DstAddr, NET_ETHER_ADDR_LEN); - } - - if (Protocol != NULL) { - *Protocol = NTOHS(EnetHeader->Type); - } - - return EFI_SUCCESS; -} - - -/** - Initialize the state information for the Display Dxe - - @param ImageHandle of the loaded driver - @param SystemTable Pointer to the System Table - - @retval EFI_SUCCESS Protocol registered - @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure - @retval EFI_DEVICE_ERROR Hardware problems - -**/ -EFI_STATUS -EFIAPI -EthDxeInitialize ( - EFI_HANDLE ImageHandle, - EFI_SYSTEM_TABLE *SystemTable -) -{ - EFI_STATUS Status = EFI_SUCCESS; - EFI_GUID SimpleNetworkProtocolGuid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; - EFI_GUID DevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID; - ETH_DXE_PRIVATE_DATA *Private; - - /* Allocate the private data */ - Private = (ETH_DXE_PRIVATE_DATA *)AllocateCopyPool(sizeof(ETH_DXE_PRIVATE_DATA), &gEthDxePrivateTemplate ); - if ( Private == NULL ) { - Status = EFI_OUT_OF_RESOURCES; - ASSERT_EFI_ERROR(Status); - } - - Private->Snp.Mode = &Private->Mode; - - /* Set the broadcast address */ - SetMem( &Private->Mode.BroadcastAddress, sizeof( EFI_MAC_ADDRESS ), 0xFF ); - - Status = gBS->InstallMultipleProtocolInterfaces ( - &ImageHandle, - &DevicePathProtocolGuid, - &Private->DevicePath, - &SimpleNetworkProtocolGuid, - &Private->Snp, - NULL); - - return Status; -} diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.h deleted file mode 100644 index 3b9a790..0000000 --- a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.h +++ /dev/null @@ -1,612 +0,0 @@ -/** @file -* -* Copyright (c) 2012, Samsung Electronics Co. All rights reserved. -* -* This program and the accompanying materials -* are licensed and made available under the terms and conditions of the BSD License -* which accompanies this distribution. The full text of the license may be found at -* http://opensource.org/licenses/bsd-license.php -* -* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -* -**/ - - -#ifndef _EthDxe_H__ -#define _EthDxe_H__ - -#define NET_ETHER_HEADER_SIZE 14 - -typedef struct -{ - UINT8 DstAddr[ NET_ETHER_ADDR_LEN ]; - UINT8 SrcAddr[ NET_ETHER_ADDR_LEN ]; - UINT16 Type; -} EthernetHeader; - -/* Chip ID values */ -#define CHIP_9115 0x115 -#define CHIP_9116 0x116 -#define CHIP_9117 0x117 -#define CHIP_9118 0x118 -#define CHIP_9211 0x9211 -#define CHIP_9215 0x115a -#define CHIP_9216 0x116a -#define CHIP_9217 0x117a -#define CHIP_9218 0x118a -#define CHIP_9220 0x9220 -#define CHIP_9221 0x9221 - -struct chip_id { - UINT16 id; - CHAR8 *name; -}; - -static const struct chip_id chip_ids[] = { - { CHIP_9115, "LAN9115" }, - { CHIP_9116, "LAN9116" }, - { CHIP_9117, "LAN9117" }, - { CHIP_9118, "LAN9118" }, - { CHIP_9211, "LAN9211" }, - { CHIP_9215, "LAN9215" }, - { CHIP_9216, "LAN9216" }, - { CHIP_9217, "LAN9217" }, - { CHIP_9218, "LAN9218" }, - { CHIP_9220, "LAN9220" }, - { CHIP_9221, "LAN9221" }, - { 0, NULL }, -}; - - -/* Below are the register offsets and bit definitions - * of the Lan911x memory space - */ -#define RX_DATA_FIFO 0x00 - -#define TX_DATA_FIFO 0x20 -#define TX_CMD_A_INT_ON_COMP 0x80000000 -#define TX_CMD_A_INT_BUF_END_ALGN 0x03000000 -#define TX_CMD_A_INT_4_BYTE_ALGN 0x00000000 -#define TX_CMD_A_INT_16_BYTE_ALGN 0x01000000 -#define TX_CMD_A_INT_32_BYTE_ALGN 0x02000000 -#define TX_CMD_A_INT_DATA_OFFSET 0x001F0000 -#define TX_CMD_A_INT_FIRST_SEG 0x00002000 -#define TX_CMD_A_INT_LAST_SEG 0x00001000 -#define TX_CMD_A_BUF_SIZE 0x000007FF -#define TX_CMD_B_PKT_TAG 0xFFFF0000 -#define TX_CMD_B_ADD_CRC_DISABLE 0x00002000 -#define TX_CMD_B_DISABLE_PADDING 0x00001000 -#define TX_CMD_B_PKT_BYTE_LENGTH 0x000007FF - -#define RX_STATUS_FIFO 0x40 -#define RX_STS_PKT_LEN 0x3FFF0000 -#define RX_STS_ES 0x00008000 -#define RX_STS_BCST 0x00002000 -#define RX_STS_LEN_ERR 0x00001000 -#define RX_STS_RUNT_ERR 0x00000800 -#define RX_STS_MCAST 0x00000400 -#define RX_STS_TOO_LONG 0x00000080 -#define RX_STS_COLL 0x00000040 -#define RX_STS_ETH_TYPE 0x00000020 -#define RX_STS_WDOG_TMT 0x00000010 -#define RX_STS_MII_ERR 0x00000008 -#define RX_STS_DRIBBLING 0x00000004 -#define RX_STS_CRC_ERR 0x00000002 -#define RX_STATUS_FIFO_PEEK 0x44 -#define TX_STATUS_FIFO 0x48 -#define TX_STS_TAG 0xFFFF0000 -#define TX_STS_ES 0x00008000 -#define TX_STS_LOC 0x00000800 -#define TX_STS_NO_CARR 0x00000400 -#define TX_STS_LATE_COLL 0x00000200 -#define TX_STS_MANY_COLL 0x00000100 -#define TX_STS_COLL_CNT 0x00000078 -#define TX_STS_MANY_DEFER 0x00000004 -#define TX_STS_UNDERRUN 0x00000002 -#define TX_STS_DEFERRED 0x00000001 -#define TX_STATUS_FIFO_PEEK 0x4C -#define ID_REV 0x50 -#define ID_REV_CHIP_ID 0xFFFF0000 /* RO */ -#define ID_REV_REV_ID 0x0000FFFF /* RO */ - -#define INT_CFG 0x54 -#define INT_CFG_INT_DEAS 0xFF000000 /* R/W */ -#define INT_CFG_INT_DEAS_CLR 0x00004000 -#define INT_CFG_INT_DEAS_STS 0x00002000 -#define INT_CFG_IRQ_INT 0x00001000 /* RO */ -#define INT_CFG_IRQ_EN 0x00000100 /* R/W */ - /* R/W Not Affected by SW Reset */ -#define INT_CFG_IRQ_POL 0x00000010 - /* R/W Not Affected by SW Reset */ -#define INT_CFG_IRQ_TYPE 0x00000001 - -#define INT_STS 0x58 -#define INT_STS_SW_INT 0x80000000 /* R/WC */ -#define INT_STS_TXSTOP_INT 0x02000000 /* R/WC */ -#define INT_STS_RXSTOP_INT 0x01000000 /* R/WC */ -#define INT_STS_RXDFH_INT 0x00800000 /* R/WC */ -#define INT_STS_RXDF_INT 0x00400000 /* R/WC */ -#define INT_STS_TX_IOC 0x00200000 /* R/WC */ -#define INT_STS_RXD_INT 0x00100000 /* R/WC */ -#define INT_STS_GPT_INT 0x00080000 /* R/WC */ -#define INT_STS_PHY_INT 0x00040000 /* RO */ -#define INT_STS_PME_INT 0x00020000 /* R/WC */ -#define INT_STS_TXSO 0x00010000 /* R/WC */ -#define INT_STS_RWT 0x00008000 /* R/WC */ -#define INT_STS_RXE 0x00004000 /* R/WC */ -#define INT_STS_TXE 0x00002000 /* R/WC */ -/*#define INT_STS_ERX 0x00001000*/ /* R/WC */ -#define INT_STS_TDFU 0x00000800 /* R/WC */ -#define INT_STS_TDFO 0x00000400 /* R/WC */ -#define INT_STS_TDFA 0x00000200 /* R/WC */ -#define INT_STS_TSFF 0x00000100 /* R/WC */ -#define INT_STS_TSFL 0x00000080 /* R/WC */ -/*#define INT_STS_RXDF 0x00000040*/ /* R/WC */ -#define INT_STS_RDFO 0x00000040 /* R/WC */ -#define INT_STS_RDFL 0x00000020 /* R/WC */ -#define INT_STS_RSFF 0x00000010 /* R/WC */ -#define INT_STS_RSFL 0x00000008 /* R/WC */ -#define INT_STS_GPIO2_INT 0x00000004 /* R/WC */ -#define INT_STS_GPIO1_INT 0x00000002 /* R/WC */ -#define INT_STS_GPIO0_INT 0x00000001 /* R/WC */ -#define INT_EN 0x5C -#define INT_EN_SW_INT_EN 0x80000000 /* R/W */ -#define INT_EN_TXSTOP_INT_EN 0x02000000 /* R/W */ -#define INT_EN_RXSTOP_INT_EN 0x01000000 /* R/W */ -#define INT_EN_RXDFH_INT_EN 0x00800000 /* R/W */ -/*#define INT_EN_RXDF_INT_EN 0x00400000*/ /* R/W */ -#define INT_EN_TIOC_INT_EN 0x00200000 /* R/W */ -#define INT_EN_RXD_INT_EN 0x00100000 /* R/W */ -#define INT_EN_GPT_INT_EN 0x00080000 /* R/W */ -#define INT_EN_PHY_INT_EN 0x00040000 /* R/W */ -#define INT_EN_PME_INT_EN 0x00020000 /* R/W */ -#define INT_EN_TXSO_EN 0x00010000 /* R/W */ -#define INT_EN_RWT_EN 0x00008000 /* R/W */ -#define INT_EN_RXE_EN 0x00004000 /* R/W */ -#define INT_EN_TXE_EN 0x00002000 /* R/W */ -/*#define INT_EN_ERX_EN 0x00001000*/ /* R/W */ -#define INT_EN_TDFU_EN 0x00000800 /* R/W */ -#define INT_EN_TDFO_EN 0x00000400 /* R/W */ -#define INT_EN_TDFA_EN 0x00000200 /* R/W */ -#define INT_EN_TSFF_EN 0x00000100 /* R/W */ -#define INT_EN_TSFL_EN 0x00000080 /* R/W */ -/*#define INT_EN_RXDF_EN 0x00000040*/ /* R/W */ -#define INT_EN_RDFO_EN 0x00000040 /* R/W */ -#define INT_EN_RDFL_EN 0x00000020 /* R/W */ -#define INT_EN_RSFF_EN 0x00000010 /* R/W */ -#define INT_EN_RSFL_EN 0x00000008 /* R/W */ -#define INT_EN_GPIO2_INT 0x00000004 /* R/W */ -#define INT_EN_GPIO1_INT 0x00000002 /* R/W */ -#define INT_EN_GPIO0_INT 0x00000001 /* R/W */ - -#define BYTE_TEST 0x64 -#define FIFO_INT 0x68 -#define FIFO_INT_TX_AVAIL_LEVEL 0xFF000000 /* R/W */ -#define FIFO_INT_TX_STS_LEVEL 0x00FF0000 /* R/W */ -#define FIFO_INT_RX_AVAIL_LEVEL 0x0000FF00 /* R/W */ -#define FIFO_INT_RX_STS_LEVEL 0x000000FF /* R/W */ - -#define RX_CFG 0x6C -#define RX_CFG_RX_END_ALGN 0xC0000000 /* R/W */ -#define RX_CFG_RX_END_ALGN4 0x00000000 /* R/W */ -#define RX_CFG_RX_END_ALGN16 0x40000000 /* R/W */ -#define RX_CFG_RX_END_ALGN32 0x80000000 /* R/W */ -#define RX_CFG_RX_DMA_CNT 0x0FFF0000 /* R/W */ -#define RX_CFG_RX_DUMP 0x00008000 /* R/W */ -#define RX_CFG_RXDOFF 0x00001F00 /* R/W */ -/*#define RX_CFG_RXBAD 0x00000001*/ /* R/W */ - -#define TX_CFG 0x70 -/*#define TX_CFG_TX_DMA_LVL 0xE0000000*/ /* R/W */ - /* R/W Self Clearing */ -/*#define TX_CFG_TX_DMA_CNT 0x0FFF0000*/ -#define TX_CFG_TXS_DUMP 0x00008000 /* Self Clearing */ -#define TX_CFG_TXD_DUMP 0x00004000 /* Self Clearing */ -#define TX_CFG_TXSAO 0x00000004 /* R/W */ -#define TX_CFG_TX_ON 0x00000002 /* R/W */ -#define TX_CFG_STOP_TX 0x00000001 /* Self Clearing */ - -#define HW_CFG 0x74 -#define HW_CFG_TTM 0x00200000 /* R/W */ -#define HW_CFG_SF 0x00100000 /* R/W */ -#define HW_CFG_TX_FIF_SZ 0x000F0000 /* R/W */ -#define HW_CFG_TR 0x00003000 /* R/W */ -#define HW_CFG_PHY_CLK_SEL 0x00000060 /* R/W */ -#define HW_CFG_PHY_CLK_SEL_INT_PHY 0x00000000 /* R/W */ -#define HW_CFG_PHY_CLK_SEL_EXT_PHY 0x00000020 /* R/W */ -#define HW_CFG_PHY_CLK_SEL_CLK_DIS 0x00000040 /* R/W */ -#define HW_CFG_SMI_SEL 0x00000010 /* R/W */ -#define HW_CFG_EXT_PHY_DET 0x00000008 /* RO */ -#define HW_CFG_EXT_PHY_EN 0x00000004 /* R/W */ -#define HW_CFG_32_16_BIT_MODE 0x00000004 /* RO */ -#define HW_CFG_SRST_TO 0x00000002 /* RO */ -#define HW_CFG_SRST 0x00000001 /* Self Clearing */ - -#define RX_DP_CTRL 0x78 -#define RX_DP_CTRL_RX_FFWD 0x80000000 /* R/W */ -#define RX_DP_CTRL_FFWD_BUSY 0x80000000 /* RO */ - -#define RX_FIFO_INF 0x7C -#define RX_FIFO_INF_RXSUSED 0x00FF0000 /* RO */ -#define RX_FIFO_INF_RXDUSED 0x0000FFFF /* RO */ - -#define TX_FIFO_INF 0x80 -#define TX_FIFO_INF_TSUSED 0x00FF0000 /* RO */ -#define TX_FIFO_INF_TDFREE 0x0000FFFF /* RO */ - -#define PMT_CTRL 0x84 -#define PMT_CTRL_PM_MODE 0x00003000 /* Self Clearing */ -#define PMT_CTRL_PHY_RST 0x00000400 /* Self Clearing */ -#define PMT_CTRL_WOL_EN 0x00000200 /* R/W */ -#define PMT_CTRL_ED_EN 0x00000100 /* R/W */ - /* R/W Not Affected by SW Reset */ -#define PMT_CTRL_PME_TYPE 0x00000040 -#define PMT_CTRL_WUPS 0x00000030 /* R/WC */ -#define PMT_CTRL_WUPS_NOWAKE 0x00000000 /* R/WC */ -#define PMT_CTRL_WUPS_ED 0x00000010 /* R/WC */ -#define PMT_CTRL_WUPS_WOL 0x00000020 /* R/WC */ -#define PMT_CTRL_WUPS_MULTI 0x00000030 /* R/WC */ -#define PMT_CTRL_PME_IND 0x00000008 /* R/W */ -#define PMT_CTRL_PME_POL 0x00000004 /* R/W */ - /* R/W Not Affected by SW Reset */ -#define PMT_CTRL_PME_EN 0x00000002 -#define PMT_CTRL_READY 0x00000001 /* RO */ - -#define GPIO_CFG 0x88 -#define GPIO_CFG_LED3_EN 0x40000000 /* R/W */ -#define GPIO_CFG_LED2_EN 0x20000000 /* R/W */ -#define GPIO_CFG_LED1_EN 0x10000000 /* R/W */ -#define GPIO_CFG_GPIO2_INT_POL 0x04000000 /* R/W */ -#define GPIO_CFG_GPIO1_INT_POL 0x02000000 /* R/W */ -#define GPIO_CFG_GPIO0_INT_POL 0x01000000 /* R/W */ -#define GPIO_CFG_EEPR_EN 0x00700000 /* R/W */ -#define GPIO_CFG_GPIOBUF2 0x00040000 /* R/W */ -#define GPIO_CFG_GPIOBUF1 0x00020000 /* R/W */ -#define GPIO_CFG_GPIOBUF0 0x00010000 /* R/W */ -#define GPIO_CFG_GPIODIR2 0x00000400 /* R/W */ -#define GPIO_CFG_GPIODIR1 0x00000200 /* R/W */ -#define GPIO_CFG_GPIODIR0 0x00000100 /* R/W */ -#define GPIO_CFG_GPIOD4 0x00000010 /* R/W */ -#define GPIO_CFG_GPIOD3 0x00000008 /* R/W */ -#define GPIO_CFG_GPIOD2 0x00000004 /* R/W */ -#define GPIO_CFG_GPIOD1 0x00000002 /* R/W */ -#define GPIO_CFG_GPIOD0 0x00000001 /* R/W */ - -#define GPT_CFG 0x8C -#define GPT_CFG_TIMER_EN 0x20000000 /* R/W */ -#define GPT_CFG_GPT_LOAD 0x0000FFFF /* R/W */ - -#define GPT_CNT 0x90 -#define GPT_CNT_GPT_CNT 0x0000FFFF /* RO */ - -#define ENDIAN 0x98 -#define FREE_RUN 0x9C -#define RX_DROP 0xA0 -#define MAC_CSR_CMD 0xA4 -#define MAC_CSR_CMD_CSR_BUSY 0x80000000 /* Self Clearing */ -#define MAC_CSR_CMD_R_NOT_W 0x40000000 /* R/W */ -#define MAC_CSR_CMD_CSR_ADDR 0x000000FF /* R/W */ - -#define MAC_CSR_DATA 0xA8 -#define AFC_CFG 0xAC -#define AFC_CFG_AFC_HI 0x00FF0000 /* R/W */ -#define AFC_CFG_AFC_LO 0x0000FF00 /* R/W */ -#define AFC_CFG_BACK_DUR 0x000000F0 /* R/W */ -#define AFC_CFG_FCMULT 0x00000008 /* R/W */ -#define AFC_CFG_FCBRD 0x00000004 /* R/W */ -#define AFC_CFG_FCADD 0x00000002 /* R/W */ -#define AFC_CFG_FCANY 0x00000001 /* R/W */ - -#define E2P_CMD 0xB0 -#define E2P_CMD_EPC_BUSY 0x80000000 /* Self Clearing */ -#define E2P_CMD_EPC_CMD 0x70000000 /* R/W */ -#define E2P_CMD_EPC_CMD_READ 0x00000000 /* R/W */ -#define E2P_CMD_EPC_CMD_EWDS 0x10000000 /* R/W */ -#define E2P_CMD_EPC_CMD_EWEN 0x20000000 /* R/W */ -#define E2P_CMD_EPC_CMD_WRITE 0x30000000 /* R/W */ -#define E2P_CMD_EPC_CMD_WRAL 0x40000000 /* R/W */ -#define E2P_CMD_EPC_CMD_ERASE 0x50000000 /* R/W */ -#define E2P_CMD_EPC_CMD_ERAL 0x60000000 /* R/W */ -#define E2P_CMD_EPC_CMD_RELOAD 0x70000000 /* R/W */ -#define E2P_CMD_EPC_TIMEOUT 0x00000200 /* RO */ -#define E2P_CMD_MAC_ADDR_LOADED 0x00000100 /* RO */ -#define E2P_CMD_EPC_ADDR 0x000000FF /* R/W */ - -#define E2P_DATA 0xB4 -#define E2P_DATA_EEPROM_DATA 0x000000FF /* R/W */ -/* end of LAN register offsets and bit definitions */ - -/* MAC Control and Status registers */ -#define MAC_CR 0x01 /* R/W */ - -/* MAC_CR - MAC Control Register */ -#define MAC_CR_RXALL 0x80000000 -/* TODO: delete this bit? It is not described in the data sheet. */ -#define MAC_CR_HBDIS 0x10000000 -#define MAC_CR_RCVOWN 0x00800000 -#define MAC_CR_LOOPBK 0x00200000 -#define MAC_CR_FDPX 0x00100000 -#define MAC_CR_MCPAS 0x00080000 -#define MAC_CR_PRMS 0x00040000 -#define MAC_CR_INVFILT 0x00020000 -#define MAC_CR_PASSBAD 0x00010000 -#define MAC_CR_HFILT 0x00008000 -#define MAC_CR_HPFILT 0x00002000 -#define MAC_CR_LCOLL 0x00001000 -#define MAC_CR_BCAST 0x00000800 -#define MAC_CR_DISRTY 0x00000400 -#define MAC_CR_PADSTR 0x00000100 -#define MAC_CR_BOLMT_MASK 0x000000C0 -#define MAC_CR_DFCHK 0x00000020 -#define MAC_CR_TXEN 0x00000008 -#define MAC_CR_RXEN 0x00000004 - -#define ADDRH 0x02 /* R/W mask 0x0000FFFFUL */ -#define ADDRL 0x03 /* R/W mask 0xFFFFFFFFUL */ -#define HASHH 0x04 /* R/W */ -#define HASHL 0x05 /* R/W */ - -#define MII_ACC 0x06 /* R/W */ -#define MII_ACC_PHY_ADDR 0x0000F800 -#define MII_ACC_MIIRINDA 0x000007C0 -#define MII_ACC_MII_WRITE 0x00000002 -#define MII_ACC_MII_BUSY 0x00000001 - -#define MII_DATA 0x07 /* R/W mask 0x0000FFFFUL */ - -#define FLOW 0x08 /* R/W */ -#define FLOW_FCPT 0xFFFF0000 -#define FLOW_FCPASS 0x00000004 -#define FLOW_FCEN 0x00000002 -#define FLOW_FCBSY 0x00000001 - -#define VLAN1 0x09 /* R/W mask 0x0000FFFFUL */ -#define VLAN1_VTI1 0x0000ffff - -#define VLAN2 0x0A /* R/W mask 0x0000FFFFUL */ -#define VLAN2_VTI2 0x0000ffff - -#define WUFF 0x0B /* WO */ - -#define WUCSR 0x0C /* R/W */ -#define WUCSR_GUE 0x00000200 -#define WUCSR_WUFR 0x00000040 -#define WUCSR_MPR 0x00000020 -#define WUCSR_WAKE_EN 0x00000004 -#define WUCSR_MPEN 0x00000002 - -/* phy register offsets */ -#define PHY_BMCR 0x00 -#define PHY_BMSR 0x01 -#define PHY_PHYIDR1 0x02 -#define PHY_PHYIDR2 0x03 -#define PHY_ANAR 0x04 -#define PHY_ANLPAR 0x05 -#define PHY_ANER 0x06 -#define PHY_ANNPTR 0x07 -#define PHY_ANLPNP 0x08 -#define PHY_1000BTCR 0x09 -#define PHY_1000BTSR 0x0A -#define PHY_EXSR 0x0F -#define PHY_PHYSTS 0x10 -#define PHY_MIPSCR 0x11 -#define PHY_MIPGSR 0x12 -#define PHY_DCR 0x13 -#define PHY_FCSCR 0x14 -#define PHY_RECR 0x15 -#define PHY_PCSR 0x16 -#define PHY_LBR 0x17 -#define PHY_10BTSCR 0x18 -#define PHY_PHYCTRL 0x19 - -/* PHY BMCR */ -#define PHY_BMCR_RESET 0x8000 -#define PHY_BMCR_LOOP 0x4000 -#define PHY_BMCR_100MB 0x2000 -#define PHY_BMCR_AUTON 0x1000 -#define PHY_BMCR_POWD 0x0800 -#define PHY_BMCR_ISO 0x0400 -#define PHY_BMCR_RST_NEG 0x0200 -#define PHY_BMCR_DPLX 0x0100 -#define PHY_BMCR_COL_TST 0x0080 - -#define PHY_BMCR_SPEED_MASK 0x2040 -#define PHY_BMCR_1000_MBPS 0x0040 -#define PHY_BMCR_100_MBPS 0x2000 -#define PHY_BMCR_10_MBPS 0x0000 - -/* phy BMSR */ -#define PHY_BMSR_100T4 0x8000 -#define PHY_BMSR_100TXF 0x4000 -#define PHY_BMSR_100TXH 0x2000 -#define PHY_BMSR_10TF 0x1000 -#define PHY_BMSR_10TH 0x0800 -#define PHY_BMSR_EXT_STAT 0x0100 -#define PHY_BMSR_PRE_SUP 0x0040 -#define PHY_BMSR_AUTN_COMP 0x0020 -#define PHY_BMSR_RF 0x0010 -#define PHY_BMSR_AUTN_ABLE 0x0008 -#define PHY_BMSR_LS 0x0004 -#define PHY_BMSR_JD 0x0002 -#define PHY_BMSR_EXT 0x0001 - -/*phy ANLPAR */ -#define PHY_ANLPAR_NP 0x8000 -#define PHY_ANLPAR_ACK 0x4000 -#define PHY_ANLPAR_RF 0x2000 -#define PHY_ANLPAR_ASYMP 0x0800 -#define PHY_ANLPAR_PAUSE 0x0400 -#define PHY_ANLPAR_T4 0x0200 -#define PHY_ANLPAR_TXFD 0x0100 -#define PHY_ANLPAR_TX 0x0080 -#define PHY_ANLPAR_10FD 0x0040 -#define PHY_ANLPAR_10 0x0020 -#define PHY_ANLPAR_100 0x0380 /* we can run at 100 */ -/* phy ANLPAR 1000BASE-X */ -#define PHY_X_ANLPAR_NP 0x8000 -#define PHY_X_ANLPAR_ACK 0x4000 -#define PHY_X_ANLPAR_RF_MASK 0x3000 -#define PHY_X_ANLPAR_PAUSE_MASK 0x0180 -#define PHY_X_ANLPAR_HD 0x0040 -#define PHY_X_ANLPAR_FD 0x0020 - -#define PHY_ANLPAR_PSB_MASK 0x001f -#define PHY_ANLPAR_PSB_802_3 0x0001 -#define PHY_ANLPAR_PSB_802_9 0x0002 - -/* phy 1000BTCR */ -#define PHY_1000BTCR_1000FD 0x0200 -#define PHY_1000BTCR_1000HD 0x0100 - -/* phy 1000BTSR */ -#define PHY_1000BTSR_MSCF 0x8000 -#define PHY_1000BTSR_MSCR 0x4000 -#define PHY_1000BTSR_LRS 0x2000 -#define PHY_1000BTSR_RRS 0x1000 -#define PHY_1000BTSR_1000FD 0x0800 -#define PHY_1000BTSR_1000HD 0x0400 - -/* phy EXSR */ -#define PHY_EXSR_1000XF 0x8000 -#define PHY_EXSR_1000XH 0x4000 -#define PHY_EXSR_1000TF 0x2000 -#define PHY_EXSR_1000TH 0x1000 - - - -typedef struct { - VENDOR_DEVICE_PATH EthDevicePath; - EFI_DEVICE_PATH EndDevicePath; -} ETH_DEVICE_PATH; - -// -// Private data for driver. -// -#define ETH_DXE_PRIVATE_DATA_SIGNATURE SIGNATURE_32( 'E', 'T', 'H', 'D' ) - -typedef struct -{ - UINT32 Signature; - EFI_SIMPLE_NETWORK_PROTOCOL Snp; - EFI_SIMPLE_NETWORK_MODE Mode; - ETH_DEVICE_PATH DevicePath; -} ETH_DXE_PRIVATE_DATA; - -#define ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(a) \ - CR( a, ETH_DXE_PRIVATE_DATA, Snp, ETH_DXE_PRIVATE_DATA_SIGNATURE ) - - -EFI_STATUS -EFIAPI -EthStart( - EFI_SIMPLE_NETWORK_PROTOCOL *This -); - -EFI_STATUS -EFIAPI -EthStop( - EFI_SIMPLE_NETWORK_PROTOCOL *This -); - -EFI_STATUS -EFIAPI -EthInitialize( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINTN ExtraRxBufferSize, - UINTN ExtraTxBufferSize -); - -EFI_STATUS -EFIAPI -EthReset( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN ExtendedVerification -); - -EFI_STATUS -EFIAPI -EthShutdown( - EFI_SIMPLE_NETWORK_PROTOCOL *This -); - -EFI_STATUS -EFIAPI -EthReceiveFilters( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINT32 Enable, - UINT32 Disable, - BOOLEAN ResetMCastFilter, - UINTN MCastFilterCnt, - EFI_MAC_ADDRESS *MCastFilter -); - -EFI_STATUS -EFIAPI -EthStationAddress( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN Reset, - EFI_MAC_ADDRESS *New -); - -EFI_STATUS -EFIAPI -EthStatistics( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN Reset, - UINTN *StatisticsSize, - EFI_NETWORK_STATISTICS *StatisticsTable -); - -EFI_STATUS -EFIAPI -EthMCastIpToMac( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN IPv6, - EFI_IP_ADDRESS *IP, - EFI_MAC_ADDRESS *MAC -); - -EFI_STATUS -EFIAPI -EthNvData( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - BOOLEAN ReadWrite, - UINTN Offset, - UINTN BufferSize, - VOID *Buffer -); - -EFI_STATUS -EFIAPI -EthGetStatus( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINT32 *InterruptStatus, - VOID **TxBuf -); - -EFI_STATUS -EFIAPI -EthTransmit( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINTN HeaderSize, - UINTN BufferSize, - VOID *Buffer, - EFI_MAC_ADDRESS *SrcAddr, - EFI_MAC_ADDRESS *DestAddr, - UINT16 *Protocol -); - -EFI_STATUS -EFIAPI -EthReceive( - EFI_SIMPLE_NETWORK_PROTOCOL *This, - UINTN *HeaderSize, - UINTN *BufferSize, - VOID *Buffer, - EFI_MAC_ADDRESS *SrcAddr, - EFI_MAC_ADDRESS *DestAddr, - UINT16 *Protocol -); - -#endif // _Eth_Dxe_H__ diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.inf deleted file mode 100644 index e9f649e..0000000 --- a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.inf +++ /dev/null @@ -1,59 +0,0 @@ -## @file -# -# Component description file for GraphicsConsole module -# -# This is the main routine for initializing the Graphics Console support routines. -# -# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.
-# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -# -## - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = EthDxe - FILE_GUID = 25ac458a-cf60-476e-861a-211c757657a6 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = EthDxeInitialize - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# -# DRIVER_BINDING = -# COMPONENT_NAME = -# COMPONENT_NAME2 = -# - -[Sources] - EthDxe.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - SamsungPlatformPkg/ExynosPkg/Exynos4210/ExynosPkg.dec - SamsungPlatformPkg/SamsungPlatformPkg.dec - -[LibraryClasses] - BaseLib - UefiLib - MemoryAllocationLib - UefiDriverEntryPoint - IoLib - TimerLib - -[Protocols] - gEfiSimpleNetworkProtocolGuid ## TO_START - -[Guids] - -[Pcd] - gExynosPkgTokenSpaceGuid.PcdSMC911XBase diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/SimpleNetwork.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/SimpleNetwork.c new file mode 100644 index 0000000..cad1693 --- /dev/null +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/SimpleNetwork.c @@ -0,0 +1,1533 @@ +/** @file + Provides the Simple Network functions. + + Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Ax88772.h" + +/** + This function updates the filtering on the receiver. + + This support routine calls ::Ax88772MacAddressSet to update + the MAC address. This routine then rebuilds the multicast + hash by calling ::Ax88772MulticastClear and ::Ax88772MulticastSet. + Finally this routine enables the receiver by calling + ::Ax88772RxControl. + + @param [in] pSimpleNetwork Simple network mode pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +ReceiveFilterUpdate ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + NIC_DEVICE * pNicDevice; + EFI_STATUS Status; + UINT32 Index; + + DBG_ENTER ( ); + + DEBUG((DEBUG_WARN, "ReceiveFilterUpdate\n")); + // + // Set the MAC address + // + pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode = pSimpleNetwork->Mode; + DEBUG((DEBUG_ERROR, "ReceiveFilterUpdate:Ax88772MacAddressSet\n")); + Status = Ax88772MacAddressSet ( pNicDevice, + &pMode->CurrentAddress.Addr[0]); + if ( !EFI_ERROR ( Status )) { + // + // Clear the multicast hash table + // + Ax88772MulticastClear ( pNicDevice ); + + // + // Load the multicast hash table + // + if ( 0 != ( pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) { + for ( Index = 0; + ( !EFI_ERROR ( Status )) && ( Index < pMode->MCastFilterCount ); + Index++ ) { + // + // Enable the next multicast address + // + Ax88772MulticastSet ( pNicDevice, + &pMode->MCastFilter[ Index ].Addr[0]); + } + } + + // + // Enable the receiver + // + if ( !EFI_ERROR ( Status )) { + Status = Ax88772RxControl ( pNicDevice, pMode->ReceiveFilterSetting ); + } + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + This function updates the SNP driver status. + + This function gets the current interrupt and recycled transmit + buffer status from the network interface. The interrupt status + and the media status are returned as a bit mask in InterruptStatus. + If InterruptStatus is NULL, the interrupt status will not be read. + Upon successful return of the media status, the MediaPresent field + of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change + of media status. If TxBuf is not NULL, a recycled transmit buffer + address will be retrived. If a recycled transmit buffer address + is returned in TxBuf, then the buffer has been successfully + transmitted, and the status for that buffer is cleared. + + This function calls ::Ax88772Rx to update the media status and + queue any receive packets. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] pInterruptStatus A pointer to the bit mask of the current active interrupts. + If this is NULL, the interrupt status will not be read from + the device. If this is not NULL, the interrupt status will + be read from teh device. When the interrupt status is read, + it will also be cleared. Clearing the transmit interrupt + does not empty the recycled transmit buffer array. + @param [out] ppTxBuf Recycled transmit buffer address. The network interface will + not transmit if its internal recycled transmit buffer array is + full. Reading the transmit buffer does not clear the transmit + interrupt. If this is NULL, then the transmit buffer status + will not be read. If there are not transmit buffers to recycle + and TxBuf is not NULL, *TxBuf will be set to NULL. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + +**/ +EFI_STATUS +EFIAPI +SN_GetStatus ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + OUT UINT32 * pInterruptStatus, + OUT VOID ** ppTxBuf + ) +{ + BOOLEAN bLinkIdle; + EFI_SIMPLE_NETWORK_MODE * pMode; + NIC_DEVICE * pNicDevice; + EFI_STATUS Status; +// EFI_TPL TplPrevious; + + DBG_ENTER ( ); + DEBUG((DEBUG_ERROR, "SN_GetStatus\n")); + + // + // Verify the parameters + // + if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) { + // + // Return the transmit buffer + // + pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + if (( NULL != ppTxBuf ) && ( NULL != pNicDevice->pTxBuffer )) { + *ppTxBuf = pNicDevice->pTxBuffer; + pNicDevice->pTxBuffer = NULL; + return EFI_SUCCESS; + } + + // + // Determine if interface is running + // + pMode = pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStopped != pMode->State ) { + // + // Synchronize with Ax88772Timer + // +// VERIFY_TPL ( TPL_AX88772 ); +// TplPrevious = gBS->RaiseTPL ( TPL_AX88772 ); + + // + // Update the link status + // + bLinkIdle = pNicDevice->bLinkIdle; + pNicDevice->bLinkIdle = TRUE; + Ax88772Rx ( pNicDevice, bLinkIdle ); + pMode->MediaPresent = pNicDevice->bLinkUp; + + // + // Release the synchronization with Ax88772Timer + // +// gBS->RestoreTPL ( TplPrevious ); + + // + // Return the interrupt status + // + if ( NULL != pInterruptStatus ) { + *pInterruptStatus = 0; + } + Status = EFI_SUCCESS; + } + else { + Status = EFI_NOT_STARTED; + } + } + else { + Status = EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Resets the network adapter and allocates the transmit and receive buffers + required by the network interface; optionally, also requests allocation of + additional transmit and receive buffers. This routine must be called before + any other routine in the Simple Network protocol is called. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer allocation + @param [in] ExtraTxBufferSize Size in bytes to add to the transmit buffer allocation + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_OUT_OF_RESORUCES There was not enough memory for the transmit and receive buffers + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Initialize ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINTN ExtraRxBufferSize, + IN UINTN ExtraTxBufferSize + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_Initialize\n")); + + // + // Verify the parameters + // + if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) { + // + // Determine if the interface is already started + // + pMode = pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStarted == pMode->State ) { + if (( 0 == ExtraRxBufferSize ) && ( 0 == ExtraTxBufferSize )) { + // + // Start the adapter + // + Status = SN_Reset ( pSimpleNetwork, FALSE ); + if ( !EFI_ERROR ( Status )) { + // + // Update the network state + // + pMode->State = EfiSimpleNetworkInitialized; + } + } + else { + Status = EFI_UNSUPPORTED; + } + } + else { + Status = EFI_NOT_STARTED; + } + } + else { + Status = EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + This function converts a multicast IP address to a multicast HW MAC address + for all packet transactions. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bIPv6 Set to TRUE if the multicast IP address is IPv6 [RFC2460]. + Set to FALSE if the multicast IP address is IPv4 [RFC 791]. + @param [in] pIP The multicast IP address that is to be converted to a + multicast HW MAC address. + @param [in] pMAC The multicast HW MAC address that is to be generated from IP. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_MCastIPtoMAC ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bIPv6, + IN EFI_IP_ADDRESS * pIP, + IN EFI_MAC_ADDRESS * pMAC + ) +{ + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_MCastIPtoMAC\n")); + + // + // This is not currently supported + // + Status = EFI_UNSUPPORTED; + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + This function performs read and write operations on the NVRAM device + attached to a network interface. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] ReadWrite TRUE for read operations, FALSE for write operations. + @param [in] Offset Byte offset in the NVRAM device at which to start the + read or write operation. This must be a multiple of + NvRamAccessSize and less than NvRamSize. + @param [in] BufferSize The number of bytes to read or write from the NVRAM device. + This must also be a multiple of NvramAccessSize. + @param [in, out] pBuffer A pointer to the data buffer. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_NvData ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID * pBuffer + ) +{ + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_NvData\n")); + + // + // This is not currently supported + // + Status = EFI_UNSUPPORTED; + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Attempt to receive a packet from the network adapter. + + This function retrieves one packet from the receive queue of the network + interface. If there are no packets on the receive queue, then EFI_NOT_READY + will be returned. If there is a packet on the receive queue, and the size + of the packet is smaller than BufferSize, then the contents of the packet + will be placed in Buffer, and BufferSize will be udpated with the actual + size of the packet. In addition, if SrcAddr, DestAddr, and Protocol are + not NULL, then these values will be extracted from the media header and + returned. If BufferSize is smaller than the received packet, then the + size of the receive packet will be placed in BufferSize and + EFI_BUFFER_TOO_SMALL will be returned. + + This routine calls ::Ax88772Rx to update the media status and + empty the network adapter of receive packets. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [out] pHeaderSize The size, in bytes, of the media header to be filled in by + the Transmit() function. If HeaderSize is non-zero, then + it must be equal to SimpleNetwork->Mode->MediaHeaderSize + and DestAddr and Protocol parameters must not be NULL. + @param [out] pBufferSize The size, in bytes, of the entire packet (media header and + data) to be transmitted through the network interface. + @param [out] pBuffer A pointer to the packet (media header followed by data) to + to be transmitted. This parameter can not be NULL. If + HeaderSize is zero, then the media header is Buffer must + already be filled in by the caller. If HeaderSize is nonzero, + then the media header will be filled in by the Transmit() + function. + @param [out] pSrcAddr The source HW MAC address. If HeaderSize is zero, then + this parameter is ignored. If HeaderSize is nonzero and + SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress + is used for the source HW MAC address. + @param [out] pDestAddr The destination HW MAC address. If HeaderSize is zero, then + this parameter is ignored. + @param [out] pProtocol The type of header to build. If HeaderSize is zero, then + this parameter is ignored. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_NOT_READY No packets have been received on the network interface. + @retval EFI_BUFFER_TOO_SMALL The packet is larger than BufferSize bytes. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + +**/ +EFI_STATUS +EFIAPI +SN_Receive ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + OUT UINTN * pHeaderSize, + OUT UINTN * pBufferSize, + OUT VOID * pBuffer, + OUT EFI_MAC_ADDRESS * pSrcAddr, + OUT EFI_MAC_ADDRESS * pDestAddr, + OUT UINT16 * pProtocol + ) +{ + ETHERNET_HEADER * pHeader; + EFI_SIMPLE_NETWORK_MODE * pMode; + NIC_DEVICE * pNicDevice; + RX_TX_PACKET * pRxPacket; + EFI_STATUS Status; +// EFI_TPL TplPrevious; + UINT16 Type; + + DBG_ENTER ( ); +// DEBUG((DEBUG_WARN, "SN_Receive\n")); + + + // + // Verify the parameters + // + if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) { + // + // The interface must be running + // + pMode = pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized == pMode->State ) { + // + // Synchronize with Ax88772Timer + // +// VERIFY_TPL ( TPL_AX88772 ); +// TplPrevious = gBS->RaiseTPL ( TPL_AX88772 ); + + // + // Update the link status + // + pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + Ax88772Rx ( pNicDevice, FALSE ); + pMode->MediaPresent = pNicDevice->bLinkUp; + if ( pMode->MediaPresent ) { + // + // Attempt to receive a packet + // + pRxPacket = pNicDevice->pRxHead; + if ( NULL != pRxPacket ) { + pNicDevice->pRxHead = pRxPacket->pNext; + if ( NULL == pNicDevice->pRxHead ) { + pNicDevice->pRxTail = NULL; + } + + // + // Copy the received packet into the receive buffer + // + *pBufferSize = pRxPacket->Length; + CopyMem ( pBuffer, &pRxPacket->Data[0], pRxPacket->Length ); + pHeader = (ETHERNET_HEADER *) &pRxPacket->Data[0]; + if ( NULL != pHeaderSize ) { + *pHeaderSize = sizeof ( *pHeader ); + } + if ( NULL != pDestAddr ) { + CopyMem ( pDestAddr, &pHeader->dest_addr, PXE_HWADDR_LEN_ETHER ); + } + if ( NULL != pSrcAddr ) { + CopyMem ( pSrcAddr, &pHeader->src_addr, PXE_HWADDR_LEN_ETHER ); + } + if ( NULL != pProtocol ) { + Type = pHeader->type; + Type = (UINT16)(( Type >> 8 ) | ( Type << 8 )); + *pProtocol = Type; + } + Status = EFI_SUCCESS; + } + else { + // + // No receive packets available + // + Status = EFI_NOT_READY; + } + } + else { + // + // Link no up + // + Status = EFI_NOT_READY; + } + + // + // Release the synchronization with Ax88772Timer + // +// gBS->RestoreTPL ( TplPrevious ); + } + else { + Status = EFI_NOT_STARTED; + } + } + else { + Status = EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + This function is used to enable and disable the hardware and software receive + filters for the underlying network device. + + The receive filter change is broken down into three steps: + + 1. The filter mask bits that are set (ON) in the Enable parameter + are added to the current receive filter settings. + + 2. The filter mask bits that are set (ON) in the Disable parameter + are subtracted from the updated receive filter settins. + + 3. If the resulting filter settigns is not supported by the hardware + a more liberal setting is selected. + + If the same bits are set in the Enable and Disable parameters, then the bits + in the Disable parameter takes precedence. + + If the ResetMCastFilter parameter is TRUE, then the multicast address list + filter is disabled (irregardless of what other multicast bits are set in + the enable and Disable parameters). The SNP->Mode->MCastFilterCount field + is set to zero. The SNP->Mode->MCastFilter contents are undefined. + + After enableing or disabling receive filter settings, software should + verify the new settings by checking the SNP->Mode->ReceeiveFilterSettings, + SNP->Mode->MCastFilterCount and SNP->Mode->MCastFilter fields. + + Note: Some network drivers and/or devices will automatically promote + receive filter settings if the requested setting can not be honored. + For example, if a request for four multicast addresses is made and + the underlying hardware only supports two multicast addresses the + driver might set the promiscuous or promiscuous multicast receive filters + instead. The receiving software is responsible for discarding any extra + packets that get through the hardware receive filters. + + If ResetMCastFilter is TRUE, then the multicast receive filter list + on the network interface will be reset to the default multicast receive + filter list. If ResetMCastFilter is FALSE, and this network interface + allows the multicast receive filter list to be modified, then the + MCastFilterCnt and MCastFilter are used to update the current multicast + receive filter list. The modified receive filter list settings can be + found in the MCastFilter field of EFI_SIMPLE_NETWORK_MODE. + + This routine calls ::ReceiveFilterUpdate to update the receive + state in the network adapter. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] Enable A bit mask of receive filters to enable on the network interface. + @param [in] Disable A bit mask of receive filters to disable on the network interface. + For backward compatibility with EFI 1.1 platforms, the + EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit must be set + when the ResetMCastFilter parameter is TRUE. + @param [in] bResetMCastFilter Set to TRUE to reset the contents of the multicast receive + filters on the network interface to their default values. + @param [in] MCastFilterCnt Number of multicast HW MAC address in the new MCastFilter list. + This value must be less than or equal to the MaxMCastFilterCnt + field of EFI_SIMPLE_NETWORK_MODE. This field is optional if + ResetMCastFilter is TRUE. + @param [in] pMCastFilter A pointer to a list of new multicast receive filter HW MAC + addresses. This list will replace any existing multicast + HW MAC address list. This field is optional if ResetMCastFilter + is TRUE. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_ReceiveFilters ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN bResetMCastFilter, + IN UINTN MCastFilterCnt, + IN EFI_MAC_ADDRESS * pMCastFilter + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_MAC_ADDRESS * pMulticastAddress; + EFI_MAC_ADDRESS * pTableEnd; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_ReceiveFilters\n")); + + // + // Verify the parameters + // + Status = EFI_INVALID_PARAMETER; + if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) { + pMode = pSimpleNetwork->Mode; + + // + // Update the multicast list if necessary + // + if ( !bResetMCastFilter ) { + if ( 0 != MCastFilterCnt ) { + if (( MAX_MCAST_FILTER_CNT >= MCastFilterCnt ) + && ( NULL != pMCastFilter )) { + // + // Verify the multicast addresses + // + pMulticastAddress = pMCastFilter; + pTableEnd = pMulticastAddress + MCastFilterCnt; + while ( pTableEnd > pMulticastAddress ) { + // + // The first digit of the multicast address must have the LSB set + // + if ( 0 == ( pMulticastAddress->Addr[0] & 1 )) { + // + // Invalid multicast address + // + break; + } + pMulticastAddress += 1; + } + if ( pTableEnd == pMulticastAddress ) { + // + // Update the multicast filter list. + // + CopyMem (&pMode->MCastFilter[0], + pMCastFilter, + MCastFilterCnt * sizeof ( *pMCastFilter )); + Status = EFI_SUCCESS; + } + } + } + else { + Status = EFI_SUCCESS; + } + } + else { + // + // No multicast address list is specified + // + MCastFilterCnt = 0; + Status = EFI_SUCCESS; + } + if ( !EFI_ERROR ( Status )) { + // + // The parameters are valid! + // + pMode->ReceiveFilterSetting |= Enable; + pMode->ReceiveFilterSetting &= ~Disable; + pMode->MCastFilterCount = (UINT32)MCastFilterCnt; + + // + // Update the receive filters in the adapter + // + Status = ReceiveFilterUpdate ( pSimpleNetwork ); + } + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Reset the network adapter. + + Resets a network adapter and reinitializes it with the parameters that + were provided in the previous call to Initialize (). The transmit and + receive queues are cleared. Receive filters, the station address, the + statistics, and the multicast-IP-to-HW MAC addresses are not reset by + this call. + + This routine calls ::Ax88772Reset to perform the adapter specific + reset operation. This routine also starts the link negotiation + by calling ::Ax88772NegotiateLinkStart. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device + during reset. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Reset ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bExtendedVerification + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + NIC_DEVICE * pNicDevice; + RX_TX_PACKET * pRxPacket; + EFI_STATUS Status; +// EFI_TPL TplPrevious; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_Reset\n")); + + // + // Verify the parameters + // + if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) { + // + // Synchronize with Ax88772Timer + // +// VERIFY_TPL ( TPL_AX88772 ); +// TplPrevious = gBS->RaiseTPL ( TPL_AX88772 ); + + // + // Update the device state + // + pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pNicDevice->bComplete = FALSE; + pNicDevice->bLinkUp = FALSE; + + pMode = pSimpleNetwork->Mode; + pMode->MediaPresent = FALSE; + + // + // Discard any received packets + // + while ( NULL != pNicDevice->pRxHead ) { + // + // Remove the packet from the received packet list + // + pRxPacket = pNicDevice->pRxHead; + pNicDevice->pRxHead = pRxPacket->pNext; + + // + // Queue the packet to the free list + // + pRxPacket->pNext = pNicDevice->pRxFree; + pNicDevice->pRxFree = pRxPacket; + } + pNicDevice->pRxTail = NULL; + + // + // Reset the device + // + Status = Ax88772Reset ( pNicDevice ); + if ( !EFI_ERROR ( Status )) { + // + // Update the receive filters in the adapter + // + Status = ReceiveFilterUpdate ( pSimpleNetwork ); + + // + // Try to get a connection to the network + // + if ( !EFI_ERROR ( Status )) { + // + // Start the autonegotiation + // + Status = Ax88772NegotiateLinkStart ( pNicDevice ); + } + } + + // + // Release the synchronization with Ax88772Timer + // +// gBS->RestoreTPL ( TplPrevious ); + } + else { + Status = EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Initialize the simple network protocol. + + This routine calls ::Ax88772MacAddressGet to obtain the + MAC address. + + @param [in] pNicDevice NIC_DEVICE_INSTANCE pointer + + @retval EFI_SUCCESS Setup was successful + +**/ +EFI_STATUS +SN_Setup ( + IN NIC_DEVICE * pNicDevice + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_Setup\n")); + + // + // Initialize the simple network protocol + // + pSimpleNetwork = &pNicDevice->SimpleNetwork; + pSimpleNetwork->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; + pSimpleNetwork->Start = (EFI_SIMPLE_NETWORK_START)SN_Start; + pSimpleNetwork->Stop = (EFI_SIMPLE_NETWORK_STOP)SN_Stop; + pSimpleNetwork->Initialize = (EFI_SIMPLE_NETWORK_INITIALIZE)SN_Initialize; + pSimpleNetwork->Reset = (EFI_SIMPLE_NETWORK_RESET)SN_Reset; + pSimpleNetwork->Shutdown = (EFI_SIMPLE_NETWORK_SHUTDOWN)SN_Shutdown; + pSimpleNetwork->ReceiveFilters = (EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)SN_ReceiveFilters; + pSimpleNetwork->StationAddress = (EFI_SIMPLE_NETWORK_STATION_ADDRESS)SN_StationAddress; + pSimpleNetwork->Statistics = (EFI_SIMPLE_NETWORK_STATISTICS)SN_Statistics; + pSimpleNetwork->MCastIpToMac = (EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)SN_MCastIPtoMAC; + pSimpleNetwork->NvData = (EFI_SIMPLE_NETWORK_NVDATA)SN_NvData; + pSimpleNetwork->GetStatus = (EFI_SIMPLE_NETWORK_GET_STATUS)SN_GetStatus; + pSimpleNetwork->Transmit = (EFI_SIMPLE_NETWORK_TRANSMIT)SN_Transmit; + pSimpleNetwork->Receive = (EFI_SIMPLE_NETWORK_RECEIVE)SN_Receive; + pSimpleNetwork->WaitForPacket = NULL; + pMode = &pNicDevice->SimpleNetworkData; + pSimpleNetwork->Mode = pMode; + + pMode->State = EfiSimpleNetworkStopped; + pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER; + pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER ); + pMode->MaxPacketSize = AX88772_MAX_PKT_SIZE; + pMode->NvRamSize = 0; + pMode->NvRamAccessSize = 0; + pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST + | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST + | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST + | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS + | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST + | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT; + pMode->MCastFilterCount = 0; + SetMem ( &pMode->BroadcastAddress, + PXE_HWADDR_LEN_ETHER, + 0xff ); + pMode->IfType = EfiNetworkInterfaceUndi; + pMode->MacAddressChangeable = TRUE; + pMode->MultipleTxSupported = TRUE; + pMode->MediaPresentSupported = TRUE; + pMode->MediaPresent = FALSE; + + // + // Read the MAC address + // + pNicDevice->PhyId = PHY_ID_INTERNAL; + pNicDevice->b100Mbps = TRUE; + pNicDevice->bFullDuplex = TRUE; + pMode->PermanentAddress.Addr[0] = 0x00; + pMode->PermanentAddress.Addr[1] = 0x40; + pMode->PermanentAddress.Addr[2] = 0x5C; + pMode->PermanentAddress.Addr[3] = 0x26; + pMode->PermanentAddress.Addr[4] = 0x0A; + pMode->PermanentAddress.Addr[5] = 0x5B; + Status = Ax88772MacAddressSet (pNicDevice, &pMode->PermanentAddress.Addr[0]); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "SN_Setup:Ax88772MacAddressSet:Status:%x\n",Status)); + } + Status = Ax88772MacAddressGet ( + pNicDevice, + &pMode->PermanentAddress.Addr[0]); + if ( !EFI_ERROR ( Status )) { + // + // Display the MAC address + // + /*pMode->PermanentAddress.Addr[0] = 0x00; + pMode->PermanentAddress.Addr[1] = 0x40; + pMode->PermanentAddress.Addr[2] = 0x5C; + pMode->PermanentAddress.Addr[3] = 0x26; + pMode->PermanentAddress.Addr[4] = 0x0A; + pMode->PermanentAddress.Addr[5] = 0x5B;*/ + + DEBUG (( DEBUG_MAC_ADDRESS | DEBUG_ERROR, + "MAC: %02x-%02x-%02x-%02x-%02x-%02x\n", + pMode->PermanentAddress.Addr[0], + pMode->PermanentAddress.Addr[1], + pMode->PermanentAddress.Addr[2], + pMode->PermanentAddress.Addr[3], + pMode->PermanentAddress.Addr[4], + pMode->PermanentAddress.Addr[5])); + + // + // Use the hardware address as the current address + // + CopyMem ( &pMode->CurrentAddress, + &pMode->PermanentAddress, + PXE_HWADDR_LEN_ETHER ); + } + + // + // Return the setup status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + This routine starts the network interface. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_ALREADY_STARTED The network interface was already started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Start ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ) +{ + NIC_DEVICE * pNicDevice; + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_Start\n")); + + // + // Verify the parameters + // + Status = EFI_INVALID_PARAMETER; + if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) { + pMode = pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStopped == pMode->State ) { + // + // Initialize the mode structure + // NVRAM access is not supported + // + ZeroMem ( pMode, sizeof ( *pMode )); + + pMode->State = EfiSimpleNetworkStarted; + pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER; + pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER ); + pMode->MaxPacketSize = AX88772_MAX_PKT_SIZE; + pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST + | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST + | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST + | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS + | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; + pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT; + pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + Status = Ax88772MacAddressGet ( pNicDevice, &pMode->PermanentAddress.Addr[0]); + CopyMem ( &pMode->CurrentAddress, + &pMode->PermanentAddress, + sizeof ( pMode->CurrentAddress )); + pMode->BroadcastAddress.Addr[0] = 0xff; + pMode->BroadcastAddress.Addr[1] = 0xff; + pMode->BroadcastAddress.Addr[2] = 0xff; + pMode->BroadcastAddress.Addr[3] = 0xff; + pMode->BroadcastAddress.Addr[4] = 0xff; + pMode->BroadcastAddress.Addr[5] = 0xff; + pMode->IfType = 1; + pMode->MacAddressChangeable = TRUE; + pMode->MultipleTxSupported = TRUE; + pMode->MediaPresentSupported = TRUE; + pMode->MediaPresent = FALSE; + } + else { + Status = EFI_ALREADY_STARTED; + } + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Set the MAC address. + + This function modifies or resets the current station address of a + network interface. If Reset is TRUE, then the current station address + is set ot the network interface's permanent address. If Reset if FALSE + then the current station address is changed to the address specified by + pNew. + + This routine calls ::Ax88772MacAddressSet to update the MAC address + in the network adapter. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bReset Flag used to reset the station address to the + network interface's permanent address. + @param [in] pNew New station address to be used for the network + interface. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_StationAddress ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bReset, + IN EFI_MAC_ADDRESS * pNew + ) +{ + NIC_DEVICE * pNicDevice; + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_StationAddress\n")); + + DEBUG((DEBUG_ERROR, "SN_StationAddress\n")); + // + // Verify the parameters + // + if (( NULL != pSimpleNetwork ) + && ( NULL != pSimpleNetwork->Mode ) + && (( !bReset ) || ( bReset && ( NULL != pNew )))) { + // + // Verify that the adapter is already started + // + pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode = pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStarted == pMode->State ) { + // + // Determine the adapter MAC address + // + if ( bReset ) { + // + // Use the permanent address + // + CopyMem ( &pMode->CurrentAddress, + &pMode->PermanentAddress, + sizeof ( pMode->CurrentAddress )); + } + else { + // + // Use the specified address + // + CopyMem ( &pMode->CurrentAddress, + pNew, + sizeof ( pMode->CurrentAddress )); + } + + // + // Update the address on the adapter + // + DEBUG((DEBUG_ERROR, "SN_StationAddress:Ax88772MacAddressSet\n")); + Status = Ax88772MacAddressSet ( pNicDevice, &pMode->CurrentAddress.Addr[0]); + } + else { + Status = EFI_NOT_STARTED; + } + } + else { + Status = EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + This function resets or collects the statistics on a network interface. + If the size of the statistics table specified by StatisticsSize is not + big enough for all of the statistics that are collected by the network + interface, then a partial buffer of statistics is returned in + StatisticsTable. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bReset Set to TRUE to reset the statistics for the network interface. + @param [in, out] pStatisticsSize On input the size, in bytes, of StatisticsTable. On output + the size, in bytes, of the resulting table of statistics. + @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that + conains the statistics. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_BUFFER_TOO_SMALL The pStatisticsTable is NULL or the buffer is too small. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Statistics ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bReset, + IN OUT UINTN * pStatisticsSize, + OUT EFI_NETWORK_STATISTICS * pStatisticsTable + ) +{ + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_Statistics\n")); + + // + // This is not currently supported + // + Status = EFI_UNSUPPORTED; + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + This function stops a network interface. This call is only valid + if the network interface is in the started state. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Stop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_Stop\n")); + + // + // Verify the parameters + // + if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) { + // + // Determine if the interface is started + // + pMode = pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStopped != pMode->State ) { + if ( EfiSimpleNetworkStarted == pMode->State ) { + // + // Release the resources acquired in SN_Start + // + + // + // Mark the adapter as stopped + // + pMode->State = EfiSimpleNetworkStopped; + Status = EFI_SUCCESS; + } + else { + Status = EFI_UNSUPPORTED; + } + } + else { + Status = EFI_NOT_STARTED; + } + } + else { + Status = EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + This function releases the memory buffers assigned in the Initialize() call. + Pending transmits and receives are lost, and interrupts are cleared and disabled. + After this call, only Initialize() and Stop() calls may be used. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. + +**/ +EFI_STATUS +EFIAPI +SN_Shutdown ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + UINT32 RxFilter; + EFI_STATUS Status; + + DBG_ENTER ( ); + DEBUG((DEBUG_WARN, "SN_Shutdown\n")); + + // + // Verify the parameters + // + if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) { + // + // Determine if the interface is already started + // + pMode = pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized == pMode->State ) { + // + // Stop the adapter + // + RxFilter = pMode->ReceiveFilterSetting; + pMode->ReceiveFilterSetting = 0; + Status = SN_Reset ( pSimpleNetwork, FALSE ); + pMode->ReceiveFilterSetting = RxFilter; + if ( !EFI_ERROR ( Status )) { + // + // Release the resources acquired by SN_Initialize + // + + // + // Update the network state + // + pMode->State = EfiSimpleNetworkStarted; + } + } + else { + Status = EFI_NOT_STARTED; + } + } + else { + Status = EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Send a packet over the network. + + This function places the packet specified by Header and Buffer on + the transmit queue. This function performs a non-blocking transmit + operation. When the transmit is complete, the buffer is returned + via the GetStatus() call. + + This routine calls ::Ax88772Rx to empty the network adapter of + receive packets. The routine then passes the transmit packet + to the network adapter. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] HeaderSize The size, in bytes, of the media header to be filled in by + the Transmit() function. If HeaderSize is non-zero, then + it must be equal to SimpleNetwork->Mode->MediaHeaderSize + and DestAddr and Protocol parameters must not be NULL. + @param [in] BufferSize The size, in bytes, of the entire packet (media header and + data) to be transmitted through the network interface. + @param [in] pBuffer A pointer to the packet (media header followed by data) to + to be transmitted. This parameter can not be NULL. If + HeaderSize is zero, then the media header is Buffer must + already be filled in by the caller. If HeaderSize is nonzero, + then the media header will be filled in by the Transmit() + function. + @param [in] pSrcAddr The source HW MAC address. If HeaderSize is zero, then + this parameter is ignored. If HeaderSize is nonzero and + SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress + is used for the source HW MAC address. + @param [in] pDestAddr The destination HW MAC address. If HeaderSize is zero, then + this parameter is ignored. + @param [in] pProtocol The type of header to build. If HeaderSize is zero, then + this parameter is ignored. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + +**/ +EFI_STATUS +EFIAPI +SN_Transmit ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID * pBuffer, + IN EFI_MAC_ADDRESS * pSrcAddr, + IN EFI_MAC_ADDRESS * pDestAddr, + IN UINT16 * pProtocol + ) +{ + RX_TX_PACKET Packet; + ETHERNET_HEADER * pHeader; + EFI_SIMPLE_NETWORK_MODE * pMode; + NIC_DEVICE * pNicDevice; + EFI_USB_IO_PROTOCOL * pUsbIo; + EFI_STATUS Status; +// EFI_TPL TplPrevious; + UINTN TransferLength; + UINT32 TransferStatus; + UINT16 Type; + + DBG_ENTER ( ); + DEBUG((DEBUG_ERROR, "SN_Transmit\n")); + + // + // Verify the parameters + // + if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) { + // + // The interface must be running + // + pMode = pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized == pMode->State ) { + // + // Synchronize with Ax88772Timer + // +// VERIFY_TPL ( TPL_AX88772 ); +// TplPrevious = gBS->RaiseTPL ( TPL_AX88772 ); + + // + // Update the link status + // + pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + Ax88772Rx ( pNicDevice, FALSE ); + pMode->MediaPresent = pNicDevice->bLinkUp; + + // + // Release the synchronization with Ax88772Timer + // +// gBS->RestoreTPL ( TplPrevious ); + if ( pMode->MediaPresent ) { + // + // Copy the packet into the USB buffer + // + CopyMem ( &Packet.Data[0], pBuffer, BufferSize ); + Packet.Length = (UINT16) BufferSize; + + // + // Transmit the packet + // + pHeader = (ETHERNET_HEADER *) &Packet.Data[0]; + if ( 0 != HeaderSize ) { + if ( NULL != pDestAddr ) { + CopyMem ( &pHeader->dest_addr, pDestAddr, PXE_HWADDR_LEN_ETHER ); + } + if ( NULL != pSrcAddr ) { + CopyMem ( &pHeader->src_addr, pSrcAddr, PXE_HWADDR_LEN_ETHER ); + } + else { + CopyMem ( &pHeader->src_addr, &pMode->CurrentAddress.Addr[0], PXE_HWADDR_LEN_ETHER ); + } + if ( NULL != pProtocol ) { + Type = *pProtocol; + } + else { + Type = Packet.Length; + } + Type = (UINT16)(( Type >> 8 ) | ( Type << 8 )); + pHeader->type = Type; + } + if ( Packet.Length < MIN_ETHERNET_PKT_SIZE ) { + Packet.Length = MIN_ETHERNET_PKT_SIZE; + ZeroMem ( &Packet.Data[ BufferSize ], + Packet.Length - BufferSize ); + } + DEBUG (( DEBUG_TX | DEBUG_ERROR, + "TX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n", + Packet.Data[0], + Packet.Data[1], + Packet.Data[2], + Packet.Data[3], + Packet.Data[4], + Packet.Data[5], + Packet.Data[6], + Packet.Data[7], + Packet.Data[8], + Packet.Data[9], + Packet.Data[10], + Packet.Data[11], + Packet.Data[12], + Packet.Data[13], + Packet.Length )); + Packet.LengthBar = ~Packet.Length; + TransferLength = sizeof ( Packet.Length ) + + sizeof ( Packet.LengthBar ) + + Packet.Length; + + // + // Work around USB bus driver bug where a timeout set by receive + // succeeds but the timeout expires immediately after, causing the + // transmit operation to timeout. + // + pUsbIo = pNicDevice->pUsbIo; + Status = pUsbIo->UsbBulkTransfer ( pUsbIo, + BULK_OUT_ENDPOINT, + &Packet.Length, + &TransferLength, + 0xfffffffe, + &TransferStatus ); + if ( !EFI_ERROR ( Status )) { + Status = TransferStatus; + } + if (( !EFI_ERROR ( Status )) + && ( TransferLength != (UINTN)( Packet.Length + 4 ))) { + Status = EFI_WARN_WRITE_FAILURE; + } + if ( EFI_SUCCESS == Status ) { + pNicDevice->pTxBuffer = pBuffer; + } + else { + DEBUG (( DEBUG_ERROR | DEBUG_ERROR, + "Ax88772 USB transmit error, TransferLength: %d, Status: %r\r\n", + sizeof ( Packet.Length ) + Packet.Length, + Status )); + // + // Reset the controller to fix the error + // + if ( EFI_DEVICE_ERROR == Status ) { + SN_Reset ( pSimpleNetwork, FALSE ); + } + } + } + else { + // + // No packets available. + // + Status = EFI_NOT_READY; + } + } + else { + Status = EFI_NOT_STARTED; + } + } + else { + DEBUG (( DEBUG_ERROR | DEBUG_ERROR, + "Ax88772 invalid transmit parameter\r\n" + " 0x%08x: HeaderSize\r\n" + " 0x%08x: BufferSize\r\n" + " 0x%08x: Buffer\r\n" + " 0x%08x: SrcAddr\r\n" + " 0x%08x: DestAddr\r\n" + " 0x%04x: Protocol\r\n", + HeaderSize, + BufferSize, + pBuffer, + pSrcAddr, + pDestAddr, + pProtocol )); + Status = EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.c index cdd4102..92c4953 100644 --- a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.c +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.c @@ -73,7 +73,7 @@ Set ( case GPIO_MODE_INPUT: break; case GPIO_MODE_OUTPUT_0: - MmioAndThenOr32(OutputRegister, ~GPIO_SFN_MASK(Pin), GPIO_OP_EN(Pin)); + MmioAndThenOr32(OutputRegister, ~GPIO_SFN_MASK(Pin), GPIO_OP_DIS(Pin)); MmioAndThenOr32((GpioBase(Port) + GPIO_DATAIN), ~GPIO_DATAIN_MASK(Pin), GPIO_DATA_LOW(Pin)); break; case GPIO_MODE_OUTPUT_1: diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB.c index e89ba4b..fb3b1b7 100644 --- a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB.c +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB.c @@ -39,7 +39,6 @@ enum usb_phy_type { USB_PHY_HSIC1 = (0x1 << 2), }; - static void usb_clk_get(enum usb_clk_type clk_type) { if( clk_type == USBOTG_CLK) { @@ -55,6 +54,7 @@ static void usb_clk_get(enum usb_clk_type clk_type) return; } +#if 0 static void usb_clk_put(enum usb_clk_type clk_type) { if( clk_type == USBOTG_CLK) { @@ -69,6 +69,7 @@ static void usb_clk_put(enum usb_clk_type clk_type) return; } +#endif //------------------------------------------------------------------------------------ @@ -89,10 +90,12 @@ void USBPHY_Ctr48MhzClk(UINT8 bEnable_48Mhz) MmioWrite32(rUPHY_OHCICTRL, uTemp); } +#if 0 static int exynos5_usb_host_phy20_is_on(void) { return (MmioRead32(EXYNOS5_USB2_PHY_HOST_CTRL0) & HOST_CTRL0_PHYSWRSTALL) ? 0 : 1; } +#endif static void exynos5_usb_phy_control(enum usb_phy_type phy_type , int on) { @@ -104,6 +107,7 @@ static void exynos5_usb_phy_control(enum usb_phy_type phy_type , int on) void exynos5_usb_phy20_init(void) { + EFI_STATUS Status; EXYNOS_GPIO *Gpio; UINT32 hostphy_ctrl0; @@ -115,26 +119,46 @@ void exynos5_usb_phy20_init(void) Status = gBS->LocateProtocol(&gSamsungPlatformGpioProtocolGuid, NULL, (VOID **)&Gpio); ASSERT_EFI_ERROR(Status); - if(PcdGetBool(PcdExynos5250Evt1)) - { - Gpio->Set(Gpio, USB_2_EVT1, GPIO_MODE_OUTPUT_1); - Gpio->SetPull(Gpio, USB_2_EVT1, GPIO_PULL_NONE); - } - + //if(PcdGetBool(PcdExynos5250Evt1)) + //{ + Gpio->Set(Gpio, USB_2_X3, GPIO_MODE_OUTPUT_0); + //Gpio->SetPull(Gpio, USB_2_X3, GPIO_PULL_NONE); + Gpio->Set(Gpio, USB_2_D1, GPIO_MODE_OUTPUT_0); + //Gpio->SetPull(Gpio, USB_2_D1, GPIO_PULL_NONE); + //} +#if 0 if (exynos5_usb_host_phy20_is_on()) { DEBUG ((EFI_D_ERROR, "Already power on PHY $$$\n")); return; } +#endif // Must be enable usbhost & usbotg clk - usb_clk_get(USBHOST_CLK); - usb_clk_get(USBOTG_CLK); + //usb_clk_get(USBHOST_CLK); + //usb_clk_get(USBOTG_CLK); - MmioWrite32(ETC6PUD, (MmioRead32(ETC6PUD) & ~(0x3 << 14)) | (0x3 << 14)); + MmioWrite32(0x10050230, 0x1); + //MmioWrite32(ETC6PUD, (MmioRead32(ETC6PUD) & ~(0x3 << 14)) | (0x3 << 14)); exynos5_usb_phy_control(USB_PHY1, PHY_ENABLE); + hostphy_ctrl0 = MmioRead32(EXYNOS5_USB2_PHY_HOST_CTRL0); + hostphy_ctrl0 &= ~(HOST_CTRL0_FSEL_MASK | HOST_CTRL0_COMMONONN | HOST_CTRL0_PHYSWRST | HOST_CTRL0_PHYSWRSTALL | HOST_CTRL0_SIDDQ | HOST_CTRL0_FORCESUSPEND | HOST_CTRL0_FORCESLEEP); + MmioWrite32(EXYNOS5_USB2_PHY_HOST_CTRL0, hostphy_ctrl0); + + hostphy_ctrl0 = MmioRead32(EXYNOS5_USB2_PHY_HOST_CTRL0); + hostphy_ctrl0 |= (CLKSEL_24M | HOST_CTRL0_LINKSWRST | HOST_CTRL0_UTMISWRST); + MmioWrite32(EXYNOS5_USB2_PHY_HOST_CTRL0, hostphy_ctrl0); + MicroSecondDelay(10); + MicroSecondDelay(10); + hostphy_ctrl0 = MmioRead32(EXYNOS5_USB2_PHY_HOST_CTRL0); + hostphy_ctrl0 &= ~(HOST_CTRL0_LINKSWRST | HOST_CTRL0_UTMISWRST); + MmioWrite32(EXYNOS5_USB2_PHY_HOST_CTRL0, hostphy_ctrl0); + MicroSecondDelay(20); + MicroSecondDelay(20); + +#if 0 /* Host and Device should be set at the same time */ hostphy_ctrl0 = MmioRead32(EXYNOS5_USB2_PHY_HOST_CTRL0); hostphy_ctrl0 &= ~(HOST_CTRL0_FSEL_MASK); @@ -155,18 +179,25 @@ void exynos5_usb_phy20_init(void) MicroSecondDelay(10); hostphy_ctrl0 &= ~(HOST_CTRL0_LINKSWRST | HOST_CTRL0_UTMISWRST); MmioWrite32(EXYNOS5_USB2_PHY_HOST_CTRL0, hostphy_ctrl0); + MicroSecondDelay(20); + MicroSecondDelay(20); +#endif DEBUG ((EFI_D_ERROR, "exynos5_usb_phy20_init Clk set $$$\n")); /* HSIC phy reset */ - hsic_ctrl = (HSIC_CTRL_REFCLKDIV(0x24) | HSIC_CTRL_REFCLKSEL(0x2) |HSIC_CTRL_PHYSWRST); + MmioAnd32(PHY_HSIC_CTRL1, ~(0x7 << 4)); + MmioAnd32(PHY_HSIC_CTRL2, ~(0x7 << 4)); + hsic_ctrl = (HSIC_CTRL_REFCLKDIV(0x24) | HSIC_CTRL_REFCLKSEL(0x2) | HSIC_CTRL_PHYSWRST); MmioWrite32(PHY_HSIC_CTRL1, hsic_ctrl); MmioWrite32(PHY_HSIC_CTRL2, hsic_ctrl); MicroSecondDelay(10); MicroSecondDelay(10); - hsic_ctrl = (HSIC_CTRL_REFCLKDIV(0x24) | HSIC_CTRL_REFCLKSEL(0x2)); - MmioWrite32(PHY_HSIC_CTRL1, hsic_ctrl); - MmioWrite32(PHY_HSIC_CTRL2, hsic_ctrl); + MmioAnd32(PHY_HSIC_CTRL1, ~(HSIC_CTRL_PHYSWRST)); + MmioAnd32(PHY_HSIC_CTRL2, ~(HSIC_CTRL_PHYSWRST)); + //hsic_ctrl = (HSIC_CTRL_REFCLKDIV(0x24) | HSIC_CTRL_REFCLKSEL(0x2)); + //MmioWrite32(PHY_HSIC_CTRL1, hsic_ctrl); + //MmioWrite32(PHY_HSIC_CTRL2, hsic_ctrl); MicroSecondDelay(80); MicroSecondDelay(80); @@ -176,11 +207,22 @@ void exynos5_usb_phy20_init(void) ehcictrl |= (EHCICTRL_ENAINCRXALIGN | EHCICTRL_ENAINCR4 |EHCICTRL_ENAINCR8 | EHCICTRL_ENAINCR16); MmioWrite32(PHY_HOST_EHCICTRL, ehcictrl); +// Gpio->Set(Gpio, USB_2_X3, GPIO_MODE_OUTPUT_1); +// MicroSecondDelay(8000); + Gpio->Set(Gpio, USB_2_D1, GPIO_MODE_OUTPUT_1); + MicroSecondDelay(8000); + Gpio->Set(Gpio, USB_2_X3, GPIO_MODE_OUTPUT_1); + MicroSecondDelay(8000); + DEBUG ((EFI_D_ERROR, "exynos5_usb_phy20_init END $$$\n")); } void exynos5_usb_phy20_off(void) { + + MmioWrite32(EXYNOS5_USB2_PHY_HOST_CTRL0, HOST_CTRL0_PHYSWRST | HOST_CTRL0_PHYSWRSTALL | HOST_CTRL0_SIDDQ | HOST_CTRL0_FORCESUSPEND | HOST_CTRL0_FORCESLEEP); + exynos5_usb_phy_control(USB_PHY1, PHY_DISABLE); +#if 0 UINT32 uTemp; uTemp = MmioRead32(rUPHY_USBCTRL0); @@ -189,9 +231,9 @@ void exynos5_usb_phy20_off(void) usb_clk_put(USBOTG_CLK); usb_clk_put(USBHOST_CLK); +#endif } - void exynos5_usb_phy30_init(void) { UINT32 reg; @@ -350,4 +392,3 @@ UINT32 exynos_xhci_change_mode(void) DEBUG ((EFI_D_ERROR, "Change xHCI host mode %x\n", gctl)); return gctl; } - diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.h index 7f0e310..1b596d8 100644 --- a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.h +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.h @@ -36,6 +36,7 @@ #include #include +#include //#define OHCI_SUPPORT diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf index f56fe6c..2c021c7 100644 --- a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf @@ -57,6 +57,7 @@ gEfiPciHostBridgeResourceAllocationProtocolGuid gEfiPciIoProtocolGuid gSamsungPlatformGpioProtocolGuid ## GPIO Protocol + gEfiUsbIoProtocolGuid [Depex] gEfiMetronomeArchProtocolGuid diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/ArmPlatform.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/ArmPlatform.h index 4d5f7d8..5cc960b 100755 --- a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/ArmPlatform.h +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/ArmPlatform.h @@ -577,6 +577,7 @@ #define GPIO_SFN_EN(x) (2UL << (x*4)) #define GPIO_OP_EN(x) (1UL << (x*4)) +#define GPIO_OP_DIS(x) (0UL << (x*4)) #define GPIO_PUD_DIS(x) (0UL << (x*2)) #define GPIO_PDN_EN(x) (1UL << (x*2)) @@ -671,6 +672,9 @@ /* USB 2.0 GPIO Pin Configuration for GAIA Evt1 */ #define USB_2_EVT1 GPIO(GPX2,PIN6) +#define USB_2_X3 GPIO(GPX3,PIN5) +#define USB_2_D1 GPIO(GPD1,PIN7) + /* SDHC CH0 GPIO Pin Configuration for GAIA */ #define SD_0_CLK GPIO(GPC0,PIN0) -- 1.8.2