| /******************************************************************************* |
| Copyright (C) Marvell International Ltd. and its affiliates |
| |
| This software file (the "File") is owned and distributed by Marvell |
| International Ltd. and/or its affiliates ("Marvell") under the following |
| alternative licensing terms. Once you have made an election to distribute the |
| File under one of the following license alternatives, please (i) delete this |
| introductory statement regarding license alternatives, (ii) delete the two |
| license alternatives that you have not elected to use and (iii) preserve the |
| Marvell copyright notice above. |
| |
| ******************************************************************************** |
| Marvell Commercial License Option |
| |
| If you received this File from Marvell and you have entered into a commercial |
| license agreement (a "Commercial License") with Marvell, the File is licensed |
| to you under the terms of the applicable Commercial License. |
| |
| ******************************************************************************** |
| Marvell GPL License Option |
| |
| If you received this File from Marvell, you may opt to use, redistribute and/or |
| modify this File in accordance with the terms and conditions of the General |
| Public License Version 2, June 1991 (the "GPL License"), a copy of which is |
| available along with the File in the license.txt file or by writing to the Free |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or |
| on the worldwide web at http://www.gnu.org/licenses/gpl.txt. |
| |
| THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY |
| DISCLAIMED. The GPL License provides additional details about this warranty |
| disclaimer. |
| ******************************************************************************** |
| Marvell BSD License Option |
| |
| If you received this File from Marvell, you may opt to use, redistribute and/or |
| modify this File under the following licensing terms. |
| Redistribution and use in source and binary forms, with or without modification, |
| are permitted provided that the following conditions are met: |
| |
| * Redistributions of source code must retain the above copyright notice, |
| this list of conditions and the following disclaimer. |
| |
| * Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| |
| * Neither the name of Marvell nor the names of its contributors may be |
| used to endorse or promote products derived from this software without |
| specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |
| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| *******************************************************************************/ |
| |
| #ifndef __mvNeta_h__ |
| #define __mvNeta_h__ |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif /* __cplusplus */ |
| |
| #include "mvTypes.h" |
| #include "mvCommon.h" |
| #include "mvOs.h" |
| #include "mvNetaRegs.h" |
| #include "mvEthRegs.h" |
| |
| #ifdef CONFIG_MV_ETH_PNC |
| # include "pnc/mvPnc.h" |
| #endif /* CONFIG_MV_ETH_PNC */ |
| |
| #ifdef CONFIG_MV_NETA_DEBUG_CODE |
| # define mvNetaDebugPrintf mvOsPrintf |
| #else |
| # define mvNetaDebugPrintf(msg, ...) |
| #endif /* CONFIG_MV_NETA_DEBUG_CODE */ |
| |
| #ifndef MV_ETH_MAX_TCONT |
| # define MV_ETH_MAX_TCONT 1 |
| #endif |
| |
| #ifdef CONFIG_MV_ETH_NFP |
| |
| #ifdef CONFIG_MV_ETH_NFP_EXT |
| # define NFP_EXT_NUM CONFIG_MV_ETH_NFP_EXT_NUM |
| #else |
| # define NFP_EXT_NUM 0 |
| #endif |
| |
| #define NFP_MAX_PORTS (MV_ETH_MAX_PORTS + NFP_EXT_NUM) |
| |
| typedef struct { |
| void *dev; |
| MV_U32 tx_cmd; |
| MV_U32 diffL4[2]; |
| MV_U8 *pWrite; |
| MV_U16 flags; |
| MV_U16 mtu; |
| short shift; |
| MV_U8 txp; |
| MV_U8 txq; |
| MV_IP_HEADER_INFO ipInfo; |
| void *privateData; |
| } MV_NFP_RESULT; |
| |
| #define MV_NFP_RES_TXP_VALID 0x0001 |
| #define MV_NFP_RES_TXQ_VALID 0x0002 |
| #define MV_NFP_RES_IP_INFO_VALID 0x0004 |
| #define MV_NFP_RES_NETDEV_EXT 0x0010 |
| #define MV_NFP_RES_L4_CSUM_NEEDED 0x0020 |
| |
| #endif /* CONFIG_MV_ETH_NFP */ |
| |
| #define NETA_RX_IP_IS_FRAG(status) ((status) & NETA_RX_IP4_FRAG_MASK) |
| #define NETA_RX_IP_SET_FRAG(rxd) ((rxd)->status |= NETA_RX_IP4_FRAG_MASK) |
| |
| #define NETA_RX_L4_CSUM_IS_OK(status) ((status) & NETA_RX_L4_CSUM_OK_MASK) |
| #define NETA_RX_L4_CSUM_SET_OK(rxd) ((rxd)->status |= NETA_RX_L4_CSUM_OK_MASK) |
| |
| #define NETA_RX_GET_IPHDR_OFFSET(rxd) (((rxd)->status & NETA_RX_L3_OFFSET_MASK) >> NETA_RX_L3_OFFSET_OFFS) |
| #define NETA_RX_SET_IPHDR_OFFSET(rxd, offs) ((rxd)->status |= ((offs) << NETA_RX_L3_OFFSET_OFFS) & NETA_RX_L3_OFFSET_MASK) |
| |
| #define NETA_RX_GET_IPHDR_HDRLEN(rxd) (((rxd)->status & NETA_RX_IP_HLEN_MASK) >> NETA_RX_IP_HLEN_OFFS) |
| #define NETA_RX_SET_IPHDR_HDRLEN(rxd, hlen) ((rxd)->status |= ((hlen) << NETA_RX_IP_HLEN_OFFS) & NETA_RX_IP_HLEN_MASK) |
| |
| #define NETA_RX_GET_BPID(rxd) (((rxd)->status & NETA_RX_BM_POOL_ALL_MASK) >> NETA_RX_BM_POOL_ID_OFFS) |
| |
| |
| #ifdef CONFIG_MV_ETH_PNC |
| |
| #define NETA_RX_IS_PPPOE(rxd) ((rxd)->pncInfo & NETA_PNC_PPPOE) |
| #define NETA_RX_SET_PPPOE(rxd) ((rxd)->pncInfo |= NETA_PNC_PPPOE) |
| |
| #define NETA_RX_IS_VLAN(rxd) ((rxd)->pncInfo & NETA_PNC_VLAN) |
| #define NETA_RX_SET_VLAN(rxd) ((rxd)->pncInfo |= NETA_PNC_VLAN) |
| |
| #define NETA_RX_L3_IS_IP4(status) (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP4) |
| #define NETA_RX_L3_SET_IP4(rxd) ((rxd)->status |= NETA_RX_L3_IP4) |
| |
| #define NETA_RX_L3_IS_IP4_ERR(status) (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP4_ERR) |
| #define NETA_RX_L3_SET_IP4_ERR(rxd) ((rxd)->status |= NETA_RX_L3_IP4_ERR) |
| |
| #define NETA_RX_L3_IS_IP6(status) (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP6) |
| #define NETA_RX_L3_SET_IP6(rxd) ((rxd)->status |= NETA_RX_L3_IP6) |
| |
| #define NETA_RX_L3_IS_UN(status) (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_UN) |
| #define NETA_RX_L3_SET_UN(rxd) ((rxd)->status |= NETA_RX_L3_UN) |
| |
| #define NETA_RX_L4_IS_TCP(status) (((status) & NETA_RX_L4_MASK) == NETA_RX_L4_TCP) |
| #define NETA_RX_L4_SET_TCP(rxd) ((rxd)->status |= NETA_RX_L4_TCP) |
| |
| #define NETA_RX_L4_IS_UDP(status) (((status) & NETA_RX_L4_MASK) == NETA_RX_L4_UDP) |
| #define NETA_RX_L4_SET_UDP(rxd) ((rxd)->status |= NETA_RX_L4_UDP) |
| |
| #define NETA_RX_L4_IS_OTHER(status) (((status) & NETA_RX_L4_MASK) == NETA_RX_L4_OTHER) |
| #define NETA_RX_L4_SET_OTHER(rxd) ((rxd)->status |= NETA_RX_L4_OTHER) |
| |
| #else /* LEGACY parser */ |
| |
| #define NETA_RX_IS_PPPOE(rxd) (MV_FALSE) |
| #define NETA_RX_SET_PPPOE(rxd) |
| |
| #define NETA_RX_IS_VLAN(rxd) ((rxd)->status & ETH_RX_VLAN_TAGGED_FRAME_MASK) |
| #define NETA_RX_SET_VLAN(rxd) ((rxd)->status |= ETH_RX_VLAN_TAGGED_FRAME_MASK) |
| |
| #ifdef MV_ETH_LEGACY_PARSER_IPV6 |
| |
| #define NETA_RX_L3_IS_IP4(status) (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP4) |
| #define NETA_RX_L3_SET_IP4(rxd) ((rxd)->status |= NETA_RX_L3_IP4) |
| |
| #define NETA_RX_L3_IS_IP4_ERR(status) (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP4_ERR) |
| #define NETA_RX_L3_SET_IP4_ERR(rxd) ((rxd)->status |= NETA_RX_L3_IP4_ERR) |
| |
| #define NETA_RX_L3_IS_IP6(status) (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP6) |
| #define NETA_RX_L3_SET_IP6(rxd) ((rxd)->status |= NETA_RX_L3_IP6) |
| |
| #define NETA_RX_L3_IS_UN(status) (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_UN) |
| #define NETA_RX_L3_SET_UN(rxd) ((rxd)->status |= NETA_RX_L3_UN) |
| |
| #else |
| |
| #define NETA_RX_L3_IS_IP4(status) ((status) & ETH_RX_IP_HEADER_OK_MASK) |
| #define NETA_RX_L3_SET_IP4(rxd) ((rxd)->status |= (ETH_RX_IP_HEADER_OK_MASK | ETH_RX_IP_FRAME_TYPE_MASK)) |
| |
| #define NETA_RX_L3_IS_IP4_ERR(status) (((status) & ETH_RX_IP_FRAME_TYPE_MASK) && \ |
| !((status) & ETH_RX_IP_HEADER_OK_MASK)) |
| |
| #define NETA_RX_L3_SET_IP4_ERR(rxd) do { \ |
| ((rxd)->status |= ETH_RX_IP_FRAME_TYPE_MASK); \ |
| ((rxd)->status &= ~ETH_RX_IP_HEADER_OK_MASK); \ |
| } while (0) |
| |
| #define NETA_RX_L3_IS_IP6(status) (MV_FALSE) |
| #define NETA_RX_L3_SET_IP6(rxd) NETA_RX_L3_SET_UN(rxd) |
| |
| #define NETA_RX_L3_IS_UN(status) (((status) & ETH_RX_IP_FRAME_TYPE_MASK) == 0) |
| #define NETA_RX_L3_SET_UN(rxd) ((rxd)->status &= ~ETH_RX_IP_FRAME_TYPE_MASK) |
| |
| #endif /* MV_ETH_LEGACY_PARSER_IPV6 */ |
| |
| #define NETA_RX_L4_IS_TCP(status) (((status) & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_TCP_TYPE) |
| #define NETA_RX_L4_SET_TCP(rxd) ((rxd)->status |= ETH_RX_L4_TCP_TYPE) |
| |
| #define NETA_RX_L4_IS_UDP(status) (((status) & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_UDP_TYPE) |
| #define NETA_RX_L4_SET_UDP(rxd) ((rxd)->status |= ETH_RX_L4_UDP_TYPE) |
| |
| #define NETA_RX_L4_IS_OTHER(status) (((status) & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_OTHER_TYPE) |
| #define NETA_RX_L4_SET_OTHER(rxd) ((rxd)->status |= ETH_RX_L4_OTHER_TYPE) |
| |
| #endif /* CONFIG_MV_ETH_PNC */ |
| |
| /* Default port configuration value */ |
| #define PORT_CONFIG_VALUE(rxQ) \ |
| ( \ |
| ETH_DEF_RX_QUEUE_MASK(rxQ) | \ |
| ETH_DEF_RX_ARP_QUEUE_MASK(rxQ) | \ |
| ETH_DEF_RX_TCP_QUEUE_MASK(rxQ) | \ |
| ETH_DEF_RX_UDP_QUEUE_MASK(rxQ) | \ |
| ETH_DEF_RX_BPDU_QUEUE_MASK(rxQ) | \ |
| ETH_TX_NO_SET_ERROR_SUMMARY_MASK | \ |
| ETH_RX_CHECKSUM_WITH_PSEUDO_HDR \ |
| ) |
| |
| /* Default port extend configuration value */ |
| #define PORT_CONFIG_EXTEND_VALUE 0 |
| |
| #ifdef MV_ETH_GMAC_NEW |
| #define PORT_SERIAL_CONTROL_VALUE 0 |
| #else |
| #define PORT_SERIAL_CONTROL_VALUE \ |
| ( \ |
| ETH_DISABLE_FC_AUTO_NEG_MASK | \ |
| BIT9 | \ |
| ETH_DO_NOT_FORCE_LINK_FAIL_MASK | \ |
| ETH_SET_FULL_DUPLEX_MASK \ |
| ) |
| #endif /* MV_ETH_GMAC_NEW */ |
| |
| typedef enum { |
| MV_ETH_SPEED_AN, |
| MV_ETH_SPEED_10, |
| MV_ETH_SPEED_100, |
| MV_ETH_SPEED_1000 |
| } MV_ETH_PORT_SPEED; |
| |
| typedef enum { |
| MV_ETH_DUPLEX_AN, |
| MV_ETH_DUPLEX_HALF, |
| MV_ETH_DUPLEX_FULL |
| } MV_ETH_PORT_DUPLEX; |
| |
| typedef enum { |
| MV_ETH_FC_AN_NO, |
| MV_ETH_FC_AN_SYM, |
| MV_ETH_FC_AN_ASYM, |
| MV_ETH_FC_DISABLE, |
| MV_ETH_FC_ENABLE, |
| MV_ETH_FC_ACTIVE |
| |
| } MV_ETH_PORT_FC; |
| |
| |
| typedef enum { |
| MV_ETH_PRIO_FIXED = 0, /* Fixed priority mode */ |
| MV_ETH_PRIO_WRR = 1 /* Weighted round robin priority mode */ |
| } MV_ETH_PRIO_MODE; |
| |
| /* Ethernet port specific infomation */ |
| typedef struct eth_link_status { |
| MV_BOOL linkup; |
| MV_ETH_PORT_SPEED speed; |
| MV_ETH_PORT_DUPLEX duplex; |
| MV_ETH_PORT_FC rxFc; |
| MV_ETH_PORT_FC txFc; |
| |
| } MV_ETH_PORT_STATUS; |
| |
| typedef enum { |
| MV_NETA_MH_NONE = 0, |
| MV_NETA_MH = 1, |
| MV_NETA_DSA = 2, |
| MV_NETA_DSA_EXT = 3 |
| } MV_NETA_MH_MODE; |
| |
| typedef struct { |
| MV_U32 maxPort; |
| MV_U32 tClk; |
| MV_U32 cpuMask; |
| MV_BOOL iocc; |
| MV_U16 ctrlModel; /* Controller Model */ |
| MV_U8 ctrlRev; /* Controller Revision */ |
| |
| #ifdef CONFIG_MV_ETH_BM |
| MV_ULONG bmPhysBase; |
| MV_U8 *bmVirtBase; |
| #endif /* CONFIG_MV_ETH_BM */ |
| |
| #ifdef CONFIG_MV_ETH_PNC |
| MV_U32 pncTcamSize; |
| MV_ULONG pncPhysBase; |
| MV_U8 *pncVirtBase; |
| #endif /* CONFIG_MV_ETH_PNC */ |
| |
| /* Obsolete fields - unused */ |
| MV_U32 pClk; |
| MV_U32 portMask; |
| int maxCPUs; |
| } MV_NETA_HAL_DATA; |
| |
| typedef struct eth_pbuf { |
| void *osInfo; |
| MV_ULONG physAddr; |
| MV_U8 *pBuf; |
| MV_U16 bytes; |
| MV_U16 offset; |
| MV_U8 pool; |
| MV_U8 reserved; |
| MV_U16 vlanId; |
| } MV_ETH_PKT; |
| |
| typedef struct { |
| char *pFirst; |
| int lastDesc; |
| int nextToProc; |
| int descSize; |
| MV_BUF_INFO descBuf; |
| |
| } MV_NETA_QUEUE_CTRL; |
| |
| #define MV_NETA_QUEUE_DESC_PTR(pQueueCtrl, descIdx) \ |
| ((pQueueCtrl)->pFirst + ((descIdx) * NETA_DESC_ALIGNED_SIZE)) |
| |
| #define MV_NETA_QUEUE_NEXT_DESC(pQueueCtrl, descIdx) \ |
| (((descIdx) < (pQueueCtrl)->lastDesc) ? ((descIdx) + 1) : 0) |
| |
| #define MV_NETA_QUEUE_PREV_DESC(pQueueCtrl, descIdx) \ |
| (((descIdx) > 0) ? ((descIdx) - 1) : (pQueueCtrl)->lastDesc) |
| |
| #define MV_NETA_RX_LAST_DESC_PTR(pQueueCtrl) \ |
| (((NETA_RX_DESC *)pQueueCtrl.pFirst) + pQueueCtrl.lastDesc) |
| |
| typedef struct { |
| MV_NETA_QUEUE_CTRL queueCtrl; |
| |
| } MV_NETA_RXQ_CTRL; |
| |
| typedef struct { |
| MV_NETA_QUEUE_CTRL queueCtrl; |
| |
| } MV_NETA_TXQ_CTRL; |
| |
| typedef struct { |
| int portNo; |
| MV_NETA_RXQ_CTRL *pRxQueue; |
| MV_NETA_TXQ_CTRL *pTxQueue; |
| int rxqNum; |
| int txpNum; |
| int txqNum; |
| MV_U8 mcastCount[256]; |
| void *osHandle; |
| } MV_NETA_PORT_CTRL; |
| |
| extern MV_NETA_PORT_CTRL **mvNetaPortCtrl; |
| extern MV_NETA_HAL_DATA mvNetaHalData; |
| extern unsigned int neta_cap_bitmap; |
| /* NETA dynamic capabilities bitmap define */ |
| #define MV_ETH_CAP_PNC (0x00000001) |
| #define MV_ETH_CAP_BM (0x00000002) |
| #define MV_ETH_CAP_HWF (0x00000004) |
| #define MV_ETH_CAP_PME (0x00000008) |
| /* NETA dynamic capabilities macro */ |
| #define MV_NETA_BM_CAP() (MV_ETH_CAP_BM & neta_cap_bitmap) |
| #define MV_NETA_PNC_CAP() (MV_ETH_CAP_PNC & neta_cap_bitmap) |
| #define MV_NETA_HWF_CAP() (MV_ETH_CAP_HWF & neta_cap_bitmap) |
| #define MV_NETA_PMT_CAP() (MV_ETH_CAP_PME & neta_cap_bitmap) |
| |
| /* Get Giga port handler */ |
| static INLINE MV_NETA_PORT_CTRL *mvNetaPortHndlGet(int port) |
| { |
| return mvNetaPortCtrl[port]; |
| } |
| |
| /* Get RX queue handler */ |
| static INLINE MV_NETA_RXQ_CTRL *mvNetaRxqHndlGet(int port, int rxq) |
| { |
| return &mvNetaPortCtrl[port]->pRxQueue[rxq]; |
| } |
| |
| /* Get TX queue handler */ |
| static INLINE MV_NETA_TXQ_CTRL *mvNetaTxqHndlGet(int port, int txp, int txq) |
| { |
| MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortCtrl[port]; |
| |
| return &pPortCtrl->pTxQueue[txp * pPortCtrl->txqNum + txq]; |
| } |
| |
| #if defined(MV_CPU_BE) && defined(CONFIG_MV_ETH_BE_WA) |
| /* Swap RX descriptor to be BE */ |
| static INLINE void mvNetaRxqDescSwap(NETA_RX_DESC *pRxDesc) |
| { |
| pRxDesc->status = MV_BYTE_SWAP_32BIT(pRxDesc->status); |
| pRxDesc->pncInfo = MV_BYTE_SWAP_16BIT(pRxDesc->pncInfo); |
| pRxDesc->dataSize = MV_BYTE_SWAP_16BIT(pRxDesc->dataSize); |
| pRxDesc->bufPhysAddr = MV_BYTE_SWAP_32BIT(pRxDesc->bufPhysAddr); |
| pRxDesc->pncFlowId = MV_BYTE_SWAP_32BIT(pRxDesc->pncFlowId); |
| /* pRxDesc->bufCookie = MV_BYTE_SWAP_32BIT(pRxDesc->bufCookie); */ |
| pRxDesc->prefetchCmd = MV_BYTE_SWAP_16BIT(pRxDesc->prefetchCmd); |
| pRxDesc->csumL4 = MV_BYTE_SWAP_16BIT(pRxDesc->csumL4); |
| pRxDesc->pncExtra = MV_BYTE_SWAP_32BIT(pRxDesc->pncExtra); |
| pRxDesc->hw_cmd = MV_BYTE_SWAP_32BIT(pRxDesc->hw_cmd); |
| } |
| |
| /* Swap TX descriptor to be BE */ |
| static INLINE void mvNetaTxqDescSwap(NETA_TX_DESC *pTxDesc) |
| { |
| pTxDesc->command = MV_BYTE_SWAP_32BIT(pTxDesc->command); |
| pTxDesc->csumL4 = MV_BYTE_SWAP_16BIT(pTxDesc->csumL4); |
| pTxDesc->dataSize = MV_BYTE_SWAP_16BIT(pTxDesc->dataSize); |
| pTxDesc->bufPhysAddr = MV_BYTE_SWAP_32BIT(pTxDesc->bufPhysAddr); |
| pTxDesc->hw_cmd = MV_BYTE_SWAP_32BIT(pTxDesc->hw_cmd); |
| } |
| #else |
| static INLINE void mvNetaRxqDescSwap(NETA_RX_DESC *pRxDesc) |
| { |
| } |
| static INLINE void mvNetaTxqDescSwap(NETA_TX_DESC *pTxDesc) |
| { |
| } |
| #endif /* MV_CPU_BE && CONFIG_MV_ETH_BE_WA */ |
| |
| /* Get number of RX descriptors occupied by received packets */ |
| static INLINE int mvNetaRxqBusyDescNumGet(int port, int rxq) |
| { |
| MV_U32 regVal; |
| |
| regVal = MV_REG_READ(NETA_RXQ_STATUS_REG(port, rxq)); |
| |
| return (regVal & NETA_RXQ_OCCUPIED_DESC_ALL_MASK) >> NETA_RXQ_OCCUPIED_DESC_OFFS; |
| } |
| |
| /* Get number of free RX descriptors ready to received new packets */ |
| static INLINE int mvNetaRxqFreeDescNumGet(int port, int rxq) |
| { |
| MV_U32 regVal; |
| |
| regVal = MV_REG_READ(NETA_RXQ_STATUS_REG(port, rxq)); |
| |
| return (regVal & NETA_RXQ_NON_OCCUPIED_DESC_ALL_MASK) >> NETA_RXQ_NON_OCCUPIED_DESC_OFFS; |
| } |
| |
| /* Update HW with number of RX descriptors processed by SW: |
| * - decrement number of occupied descriptors |
| * - increment number of Non-occupied descriptors |
| */ |
| static INLINE void mvNetaRxqDescNumUpdate(int port, int rxq, int rx_done, int rx_filled) |
| { |
| MV_U32 regVal; |
| |
| if ((rx_done <= 0xFF) && (rx_filled <= 0xFF)) { |
| regVal = (rx_done << NETA_RXQ_DEC_OCCUPIED_OFFS) | (rx_filled << NETA_RXQ_ADD_NON_OCCUPIED_OFFS); |
| MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal); |
| return; |
| } |
| |
| /* Only 255 descriptors can be added at once */ |
| while ((rx_done > 0) || (rx_filled > 0)) { |
| if (rx_done <= 0xFF) { |
| regVal = (rx_done << NETA_RXQ_DEC_OCCUPIED_OFFS); |
| rx_done = 0; |
| } else { |
| regVal = (0xFF << NETA_RXQ_DEC_OCCUPIED_OFFS); |
| rx_done -= 0xFF; |
| } |
| if (rx_filled <= 0xFF) { |
| regVal |= (rx_filled << NETA_RXQ_ADD_NON_OCCUPIED_OFFS); |
| rx_filled = 0; |
| } else { |
| regVal |= (0xFF << NETA_RXQ_ADD_NON_OCCUPIED_OFFS); |
| rx_filled -= 0xFF; |
| } |
| MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal); |
| } |
| } |
| |
| /* Add number of descriptors are ready to receive new packets */ |
| static INLINE void mvNetaRxqNonOccupDescAdd(int port, int rxq, int rx_desc) |
| { |
| MV_U32 regVal; |
| |
| /* Only 255 descriptors can be added at once */ |
| while (rx_desc > 0xFF) { |
| regVal = (0xFF << NETA_RXQ_ADD_NON_OCCUPIED_OFFS); |
| MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal); |
| rx_desc = rx_desc - 0xFF; |
| } |
| regVal = (rx_desc << NETA_RXQ_ADD_NON_OCCUPIED_OFFS); |
| MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal); |
| } |
| |
| /* Decrement number of processed descriptors */ |
| static INLINE void mvNetaRxqOccupDescDec(int port, int rxq, int rx_desc) |
| { |
| MV_U32 regVal; |
| |
| /* Only 255 descriptors can be updated at once */ |
| while (rx_desc > 0xFF) { |
| regVal = (0xFF << NETA_RXQ_DEC_OCCUPIED_OFFS); |
| MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal); |
| rx_desc = rx_desc - 0xFF; |
| } |
| regVal = (rx_desc << NETA_RXQ_DEC_OCCUPIED_OFFS); |
| MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal); |
| } |
| |
| /* Decrement sent descriptors counter */ |
| static INLINE void mvNetaTxqSentDescDec(int port, int txp, int txq, int sent_desc) |
| { |
| MV_U32 regVal; |
| |
| /* Only 255 TX descriptors can be updated at once */ |
| while (sent_desc > 0xFF) { |
| regVal = (0xFF << NETA_TXQ_DEC_SENT_OFFS); |
| MV_REG_WRITE(NETA_TXQ_UPDATE_REG(port, txp, txq), regVal); |
| sent_desc = sent_desc - 0xFF; |
| } |
| regVal = (sent_desc << NETA_TXQ_DEC_SENT_OFFS); |
| MV_REG_WRITE(NETA_TXQ_UPDATE_REG(port, txp, txq), regVal); |
| } |
| |
| /* Get number of TX descriptors already sent by HW */ |
| static INLINE int mvNetaTxqSentDescNumGet(int port, int txp, int txq) |
| { |
| MV_U32 regVal; |
| int sent_desc; |
| |
| regVal = MV_REG_READ(NETA_TXQ_STATUS_REG(port, txp, txq)); |
| sent_desc = (regVal & NETA_TXQ_SENT_DESC_MASK) >> NETA_TXQ_SENT_DESC_OFFS; |
| |
| return sent_desc; |
| } |
| |
| /* Invalidate TXQ descriptor - buffer will not be sent, buffer will not be returned */ |
| static INLINE void mvNetaTxqDescInv(NETA_TX_DESC *pTxDesc) |
| { |
| pTxDesc->command |= NETA_TX_HWF_MASK; |
| pTxDesc->command &= ~NETA_TX_BM_ENABLE_MASK; |
| pTxDesc->hw_cmd |= NETA_TX_ES_MASK; |
| } |
| |
| /* Return: 1 - TX descriptor is valid, 0 - TX descriptor is invalid */ |
| static INLINE int mvNetaTxqDescIsValid(NETA_TX_DESC *pTxDesc) |
| { |
| return ((pTxDesc->hw_cmd & NETA_TX_ES_MASK) == 0); |
| } |
| |
| /* Get index of descripotor to be processed next in the specific TXQ */ |
| static INLINE int mvNetaTxqNextIndexGet(int port, int txp, int txq) |
| { |
| MV_U32 regVal; |
| |
| regVal = MV_REG_READ(NETA_TXQ_INDEX_REG(port, txp, txq)); |
| |
| return (regVal & NETA_TXQ_NEXT_DESC_INDEX_MASK) >> NETA_TXQ_NEXT_DESC_INDEX_OFFS; |
| } |
| |
| /* Get number of TX descriptors didn't send by HW yet and waiting for TX */ |
| static INLINE int mvNetaTxqPendDescNumGet(int port, int txp, int txq) |
| { |
| MV_U32 regVal; |
| |
| regVal = MV_REG_READ(NETA_TXQ_STATUS_REG(port, txp, txq)); |
| |
| return (regVal & NETA_TXQ_PENDING_DESC_MASK) >> NETA_TXQ_PENDING_DESC_OFFS; |
| } |
| |
| /* Update HW with number of TX descriptors to be sent */ |
| static INLINE void mvNetaTxqPendDescAdd(int port, int txp, int txq, int pend_desc) |
| { |
| MV_U32 regVal; |
| |
| /* Only 255 descriptors can be added at once - we don't check it for performance */ |
| while (pend_desc > 0xFF) { |
| regVal = (0xFF << NETA_TXQ_ADD_PENDING_OFFS); |
| MV_REG_WRITE(NETA_TXQ_UPDATE_REG(port, txp, txq), regVal); |
| pend_desc = pend_desc - 0xFF; |
| } |
| regVal = (pend_desc << NETA_TXQ_ADD_PENDING_OFFS); |
| MV_REG_WRITE(NETA_TXQ_UPDATE_REG(port, txp, txq), regVal); |
| } |
| |
| /* Get number of sent descriptors and descrement counter. Number of sent descriptors is returned. */ |
| static INLINE int mvNetaTxqSentDescProc(int port, int txp, int txq) |
| { |
| int sent_desc; |
| |
| /* Get number of sent descriptors */ |
| sent_desc = mvNetaTxqSentDescNumGet(port, txp, txq); |
| /* Decrement sent descriptors counter */ |
| if (sent_desc) |
| mvNetaTxqSentDescDec(port, txp, txq, sent_desc); |
| |
| return sent_desc; |
| } |
| |
| /* Get pointer to next RX descriptor to be processed by SW */ |
| static INLINE NETA_RX_DESC *mvNetaRxqNextDescGet(MV_NETA_RXQ_CTRL *pRxq) |
| { |
| NETA_RX_DESC *pRxDesc; |
| int rxDesc = pRxq->queueCtrl.nextToProc; |
| |
| pRxq->queueCtrl.nextToProc = MV_NETA_QUEUE_NEXT_DESC(&(pRxq->queueCtrl), rxDesc); |
| |
| pRxDesc = ((NETA_RX_DESC *)pRxq->queueCtrl.pFirst) + rxDesc; |
| |
| return pRxDesc; |
| } |
| |
| /* Get the next desc pointer following current desc */ |
| static INLINE NETA_RX_DESC *mvNetaRxqNextDescPtr(MV_NETA_RXQ_CTRL *pRxq, NETA_RX_DESC *pRxDesc) |
| { |
| NETA_RX_DESC *pNextDesc; |
| |
| if (pRxDesc == MV_NETA_RX_LAST_DESC_PTR(pRxq->queueCtrl)) |
| pNextDesc = (NETA_RX_DESC *)pRxq->queueCtrl.pFirst; |
| else |
| pNextDesc = ++pRxDesc; |
| |
| return pNextDesc; |
| } |
| |
| static INLINE NETA_RX_DESC *mvNetaRxqDescGet(MV_NETA_RXQ_CTRL *pRxq) |
| { |
| NETA_RX_DESC *pRxDesc; |
| |
| pRxDesc = ((NETA_RX_DESC *)pRxq->queueCtrl.pFirst) + pRxq->queueCtrl.nextToProc; |
| |
| return pRxDesc; |
| } |
| |
| /* Refill RX descriptor (when BM is not supported) */ |
| static INLINE void mvNetaRxDescFill(NETA_RX_DESC *pRxDesc, MV_U32 physAddr, MV_U32 cookie) |
| { |
| pRxDesc->bufCookie = (MV_U32)cookie; |
| |
| #if defined(CONFIG_MV_ETH_BE_WA) |
| pRxDesc->bufPhysAddr = MV_32BIT_LE(physAddr); |
| #else |
| pRxDesc->bufPhysAddr = physAddr; |
| #endif /* CONFIG_MV_ETH_BE_WA */ |
| } |
| |
| /* Get pointer to next TX descriptor to be processed (send) by HW */ |
| static INLINE NETA_TX_DESC *mvNetaTxqNextDescGet(MV_NETA_TXQ_CTRL *pTxq) |
| { |
| int txDesc = pTxq->queueCtrl.nextToProc; |
| |
| pTxq->queueCtrl.nextToProc = MV_NETA_QUEUE_NEXT_DESC(&(pTxq->queueCtrl), txDesc); |
| |
| return ((NETA_TX_DESC *) pTxq->queueCtrl.pFirst) + txDesc; |
| } |
| |
| /* Get pointer to previous TX descriptor in the ring for rollback when needed */ |
| static INLINE NETA_TX_DESC *mvNetaTxqPrevDescGet(MV_NETA_TXQ_CTRL *pTxq) |
| { |
| int txDesc = pTxq->queueCtrl.nextToProc; |
| |
| pTxq->queueCtrl.nextToProc = MV_NETA_QUEUE_PREV_DESC(&(pTxq->queueCtrl), txDesc); |
| |
| return ((NETA_TX_DESC *) pTxq->queueCtrl.pFirst) + txDesc; |
| } |
| |
| /* Set TXQ descriptors fields relevant for CSUM calculation */ |
| static INLINE MV_U32 mvNetaTxqDescCsum(int l3_offs, int l3_proto, int ip_hdr_len, int l4_proto) |
| { |
| MV_U32 command; |
| |
| /* fields: L3_offset, IP_hdrlen, L3_type, G_IPv4_chk, G_L4_chk, L4_type */ |
| /* required only for checksum calculation */ |
| command = (l3_offs << NETA_TX_L3_OFFSET_OFFS); |
| command |= (ip_hdr_len << NETA_TX_IP_HLEN_OFFS); |
| |
| if (l3_proto == MV_16BIT_BE(MV_IP_TYPE)) |
| command |= (NETA_TX_L3_IP4 | NETA_TX_IP_CSUM_MASK); |
| else |
| command |= NETA_TX_L3_IP6; |
| |
| if (l4_proto == MV_IP_PROTO_TCP) |
| command |= (NETA_TX_L4_TCP | NETA_TX_L4_CSUM_FULL); |
| else if (l4_proto == MV_IP_PROTO_UDP) |
| command |= (NETA_TX_L4_UDP | NETA_TX_L4_CSUM_FULL); |
| else |
| command |= NETA_TX_L4_CSUM_NOT; |
| |
| return command; |
| } |
| |
| static INLINE MV_ULONG netaDescVirtToPhys(MV_NETA_QUEUE_CTRL *pQueueCtrl, MV_U8 *pDesc) |
| { |
| return (pQueueCtrl->descBuf.bufPhysAddr + (pDesc - pQueueCtrl->descBuf.bufVirtPtr)); |
| } |
| |
| |
| #ifdef CONFIG_MV_PON |
| static INLINE void mvNetaPonTxqBytesAdd(int port, int txp, int txq, int bytes) |
| { |
| MV_U32 regVal; |
| |
| regVal = (NETA_TX_NEW_BYTES_MASK(bytes) | NETA_TX_NEW_BYTES_TXQ_MASK(txq) | NETA_TX_NEW_BYTES_COLOR_GREEN); |
| |
| MV_REG_WRITE(NETA_TX_ADD_BYTES_REG(port, txp), regVal); |
| } |
| #endif /* CONFIG_MV_PON */ |
| |
| /* Function prototypes */ |
| MV_STATUS mvNetaHalInit(MV_NETA_HAL_DATA *halData); |
| |
| MV_STATUS mvNetaWinInit(MV_U32 port, MV_UNIT_WIN_INFO *addrWinMap); |
| MV_STATUS mvNetaWinWrite(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin); |
| MV_STATUS mvNetaWinRead(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin); |
| MV_STATUS mvNetaWinEnable(MV_U32 port, MV_U32 winNum, MV_BOOL enable); |
| |
| int mvNetaAccMode(void); |
| MV_STATUS mvNetaMemMapGet(MV_ULONG physAddr, MV_U8 *pTarget, MV_U8 *pAttr); |
| |
| void *mvNetaPortInit(int port, void *osHandle); |
| void mvNetaPortDestroy(int portNo); |
| MV_NETA_TXQ_CTRL *mvNetaTxqInit(int port, int txp, int queue, int descrNum); |
| MV_NETA_RXQ_CTRL *mvNetaRxqInit(int port, int queue, int descrNum); |
| void mvNetaTxqDelete(int port, int txp, int queue); |
| void mvNetaRxqDelete(int port, int queue); |
| void mvNetaRxqAddrSet(int port, int queue, int descrNum); |
| void mvNetaTxqAddrSet(int port, int txp, int queue, int descrNum); |
| void mvNetaTxpRateMaxSet(int port, int txp); |
| void mvNetaTxqBandwidthSet(int port, int txp, int queue); |
| |
| void mvNetaRxReset(int port); |
| void mvNetaTxpReset(int port, int txp); |
| |
| MV_STATUS mvNetaPortDisable(int port); |
| MV_STATUS mvNetaPortEnable(int port); |
| MV_STATUS mvNetaPortUp(int port); |
| MV_STATUS mvNetaPortDown(int port); |
| |
| MV_BOOL mvNetaLinkIsUp(int port); |
| MV_STATUS mvNetaLinkStatus(int port, MV_ETH_PORT_STATUS *pStatus); |
| MV_STATUS mvNetaDefaultsSet(int port); |
| MV_STATUS mvNetaForceLinkModeSet(int portNo, MV_BOOL force_link_pass, MV_BOOL force_link_fail); |
| MV_STATUS mvNetaSpeedDuplexSet(int portNo, MV_ETH_PORT_SPEED speed, MV_ETH_PORT_DUPLEX duplex); |
| MV_STATUS mvNetaSpeedDuplexGet(int portNo, MV_ETH_PORT_SPEED *speed, MV_ETH_PORT_DUPLEX *duplex); |
| |
| |
| void mvNetaCpuDump(int port, int cpu, int RxTx); |
| MV_STATUS mvNetaTxqCpuMaskSet(int port, int txq_mask, int cpu); |
| MV_STATUS mvNetaRxqCpuMaskSet(int port, int rxq_mask, int cpu); |
| |
| |
| void mvNetaSetOtherMcastTable(int portNo, int queue); |
| void mvNetaSetUcastTable(int port, int queue); |
| void mvNetaSetSpecialMcastTable(int portNo, int queue); |
| |
| /************************ Legacy parse function start *******************************/ |
| MV_STATUS mvNetaRxUnicastPromiscSet(int port, MV_BOOL isPromisc); |
| |
| MV_STATUS mvNetaMcastAddrSet(int port, MV_U8 *pAddr, int queue); |
| MV_STATUS mvNetaMacAddrGet(int portNo, unsigned char *pAddr); |
| |
| MV_STATUS mvNetaTosToRxqSet(int port, int rxq, int tos); |
| int mvNetaTosToRxqGet(int port, int tos); |
| |
| MV_STATUS mvNetaVprioToRxqSet(int port, int vprio, int rxq); |
| int mvNetaVprioToRxqGet(int port, int vprio); |
| |
| MV_STATUS mvNetaTcpRxq(int port, int rxq); |
| MV_STATUS mvNetaUdpRxq(int port, int rxq); |
| MV_STATUS mvNetaArpRxq(int port, int rxq); |
| MV_STATUS mvNetaBpduRxq(int port, int rxq); |
| /************************ Legacy parse function end *******************************/ |
| |
| void mvNetaPhyAddrSet(int port, int phyAddr); |
| int mvNetaPhyAddrGet(int port); |
| void mvNetaPhyAddrPollingDisable(int port); |
| |
| void mvNetaPortPowerDown(int port); |
| void mvNetaPortPowerUp(int port, MV_BOOL isSgmii, MV_BOOL isRgmii, MV_BOOL isInband); |
| |
| /* Interrupt Coalesting functions */ |
| MV_STATUS mvNetaRxqTimeCoalSet(int port, int rxq, MV_U32 uSec); |
| MV_STATUS mvNetaRxqPktsCoalSet(int port, int rxq, MV_U32 pkts); |
| MV_STATUS mvNetaTxDonePktsCoalSet(int port, int txp, int txq, MV_U32 pkts); |
| MV_U32 mvNetaRxqTimeCoalGet(int port, int rxq); |
| MV_U32 mvNetaRxqPktsCoalGet(int port, int rxq); |
| MV_U32 mvNetaTxDonePktsCoalGet(int port, int txp, int txq); |
| |
| MV_STATUS mvNetaRxqBufSizeSet(int port, int rxq, int bufSize); |
| MV_STATUS mvNetaMhSet(int port, MV_NETA_MH_MODE mh); |
| MV_STATUS mvNetaTagSet(int port, MV_TAG_TYPE mh); |
| MV_STATUS mvNetaTxMhRegSet(int port, int txp, int reg, MV_U16 mh); |
| MV_STATUS mvNetaMaxRxSizeSet(int port, int maxRxSize); |
| MV_STATUS mvNetaMacAddrSet(int port, unsigned char *pAddr, int queue); |
| |
| MV_STATUS mvNetaRxqOffsetSet(int port, int rxq, int offset); |
| MV_STATUS mvNetaBmPoolBufSizeSet(int port, int pool, int bufsize); |
| MV_STATUS mvNetaRxqBmEnable(int port, int rxq, int smallPool, int largePool); |
| MV_STATUS mvNetaRxqBmDisable(int port, int rxq); |
| |
| MV_STATUS mvNetaTxpEjpSet(int port, int txp, int enable); |
| MV_STATUS mvNetaTxqFixPrioSet(int port, int txp, int txq); |
| MV_STATUS mvNetaTxqWrrPrioSet(int port, int txp, int txq, int weight); |
| MV_STATUS mvNetaTxpMaxTxSizeSet(int port, int txp, int maxTxSize); |
| MV_STATUS mvNetaTxpRateSet(int port, int txp, int bw); |
| MV_STATUS mvNetaTxqRateSet(int port, int txp, int txq, int bw); |
| MV_STATUS mvNetaTxpBurstSet(int port, int txp, int burst); |
| MV_STATUS mvNetaTxqBurstSet(int port, int txp, int txq, int burst); |
| MV_STATUS mvNetaTxpEjpBurstRateSet(int port, int txp, int txq, int rate); |
| MV_STATUS mvNetaTxpEjpMaxPktSizeSet(int port, int txp, int type, int size); |
| MV_STATUS mvNetaTxpEjpTxSpeedSet(int port, int txp, int type, int speed); |
| |
| int mvNetaPortCheck(int port); |
| int mvNetaTxpCheck(int port, int txp); |
| int mvNetaMaxCheck(int num, int limit, char *name); |
| |
| void mvNetaMibCountersClear(int port, int txp); |
| MV_U32 mvNetaMibCounterRead(int port, int txp, unsigned int mibOffset, MV_U32 *pHigh32); |
| |
| void mvEthPortRegs(int port); |
| void mvEthPortUcastShow(int port); |
| void mvEthPortMcastShow(int port); |
| void mvNetaPortRegs(int port); |
| void mvNetaPncRegs(void); |
| void mvNetaTxpRegs(int port, int txp); |
| void mvNetaRxqRegs(int port, int rxq); |
| void mvNetaTxqRegs(int port, int txp, int txq); |
| void mvNetaPortStatus(int port); |
| void mvNetaRxqShow(int port, int rxq, int mode); |
| void mvNetaTxqShow(int port, int txp, int txq, int mode); |
| |
| void mvEthTxpWrrRegs(int port, int txp); |
| void mvEthRegs(int port); |
| void mvEthPortCounters(int port, int mib); |
| void mvEthPortRmonCounters(int port, int mib); |
| |
| MV_STATUS mvNetaFlowCtrlSet(int port, MV_ETH_PORT_FC flowControl); |
| MV_STATUS mvNetaFlowCtrlGet(int port, MV_ETH_PORT_FC *flowControl); |
| |
| #ifdef MV_ETH_GMAC_NEW |
| MV_STATUS mvEthGmacRgmiiSet(int port, int enable); |
| MV_STATUS mvNetaGmacLpiSet(int port, int mode); |
| void mvNetaGmacRegs(int port); |
| #endif /* MV_ETH_GMAC_NEW */ |
| |
| #ifdef CONFIG_MV_PON |
| void mvNetaPonTxpRegs(int port, int txp); |
| MV_STATUS mvNetaPonRxMibDefault(int mib); |
| MV_STATUS mvNetaPonRxMibGemPid(int mib, MV_U16 gemPid); |
| #endif /* CONFIG_MV_PON */ |
| |
| #ifdef CONFIG_MV_ETH_HWF |
| typedef enum { |
| MV_NETA_HWF_MH_REG = 0, |
| MV_NETA_HWF_MH_PNC = 1 |
| } MV_NETA_HWF_MH_SRC; |
| |
| MV_STATUS mvNetaHwfInit(int port); |
| MV_STATUS mvNetaHwfEnable(int port, int enable); |
| MV_STATUS mvNetaHwfBmPoolsSet(int port, int short_pool, int long_pool); |
| MV_STATUS mvNetaHwfTxqInit(int p, int txp, int txq); |
| MV_STATUS mvNetaHwfTxqEnable(int port, int p, int txp, int txq, int enable); |
| MV_STATUS mvNetaHwfTxqDropSet(int port, int p, int txp, int txq, int thresh, int bits); |
| MV_STATUS mvNetaHwfMhSrcSet(int port, MV_NETA_HWF_MH_SRC src); |
| MV_STATUS mvNetaHwfMhSelSet(int port, MV_U8 mhSel); |
| MV_STATUS mvNetaHwfTxqNextIndexGet(int port, int tx_port, int txp, int txq, int *val); |
| |
| void mvNetaHwfRxpRegs(int port); |
| void mvNetaHwfTxpRegs(int port, int p, int txp); |
| void mvNetaHwfTxpCntrs(int port, int p, int txp); |
| #endif /* CONFIG_MV_ETH_HWF */ |
| |
| #ifdef __cplusplus |
| } |
| #endif /* __cplusplus */ |
| |
| #endif /* __mvNeta_h__ */ |