Root/target/linux/generic/files/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEth.c

1/*******************************************************************************
2Copyright (C) Marvell International Ltd. and its affiliates
3
4This software file (the "File") is owned and distributed by Marvell
5International Ltd. and/or its affiliates ("Marvell") under the following
6alternative licensing terms. Once you have made an election to distribute the
7File under one of the following license alternatives, please (i) delete this
8introductory statement regarding license alternatives, (ii) delete the two
9license alternatives that you have not elected to use and (iii) preserve the
10Marvell copyright notice above.
11
12********************************************************************************
13Marvell Commercial License Option
14
15If you received this File from Marvell and you have entered into a commercial
16license agreement (a "Commercial License") with Marvell, the File is licensed
17to you under the terms of the applicable Commercial License.
18
19********************************************************************************
20Marvell GPL License Option
21
22If you received this File from Marvell, you may opt to use, redistribute and/or
23modify this File in accordance with the terms and conditions of the General
24Public License Version 2, June 1991 (the "GPL License"), a copy of which is
25available along with the File in the license.txt file or by writing to the Free
26Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
27on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
28
29THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
30WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
31DISCLAIMED. The GPL License provides additional details about this warranty
32disclaimer.
33********************************************************************************
34Marvell BSD License Option
35
36If you received this File from Marvell, you may opt to use, redistribute and/or
37modify this File under the following licensing terms.
38Redistribution and use in source and binary forms, with or without modification,
39are permitted provided that the following conditions are met:
40
41    * Redistributions of source code must retain the above copyright notice,
42        this list of conditions and the following disclaimer.
43
44    * Redistributions in binary form must reproduce the above copyright
45        notice, this list of conditions and the following disclaimer in the
46        documentation and/or other materials provided with the distribution.
47
48    * Neither the name of Marvell nor the names of its contributors may be
49        used to endorse or promote products derived from this software without
50        specific prior written permission.
51    
52THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
53ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
56ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
57(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
59ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
61SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
63*******************************************************************************/
64
65/*******************************************************************************
66* mvEth.c - Marvell's Gigabit Ethernet controller low level driver
67*
68* DESCRIPTION:
69* This file introduce OS independent APIs to Marvell's Gigabit Ethernet
70* controller. This Gigabit Ethernet Controller driver API controls
71* 1) Operations (i.e. port Init, Finish, Up, Down, PhyReset etc').
72* 2) Data flow (i.e. port Send, Receive etc').
73* 3) MAC Filtering functions (ethSetMcastAddr, ethSetRxFilterMode, etc.)
74* 4) MIB counters support (ethReadMibCounter)
75* 5) Debug functions (ethPortRegs, ethPortCounters, ethPortQueues, etc.)
76* Each Gigabit Ethernet port is controlled via ETH_PORT_CTRL struct.
77* This struct includes configuration information as well as driver
78* internal data needed for its operations.
79*
80* Supported Features:
81* - OS independent. All required OS services are implemented via external
82* OS dependent components (like osLayer or ethOsg)
83* - The user is free from Rx/Tx queue managing.
84* - Simple Gigabit Ethernet port operation API.
85* - Simple Gigabit Ethernet port data flow API.
86* - Data flow and operation API support per queue functionality.
87* - Support cached descriptors for better performance.
88* - PHY access and control API.
89* - Port Configuration API.
90* - Full control over Special and Other Multicast MAC tables.
91*
92*******************************************************************************/
93/* includes */
94#include "mvTypes.h"
95#include "mv802_3.h"
96#include "mvDebug.h"
97#include "mvCommon.h"
98#include "mvOs.h"
99#include "ctrlEnv/mvCtrlEnvLib.h"
100#include "eth-phy/mvEthPhy.h"
101#include "eth/mvEth.h"
102#include "eth/gbe/mvEthGbe.h"
103#include "cpu/mvCpu.h"
104
105#ifdef INCLUDE_SYNC_BARR
106#include "sys/mvCpuIf.h"
107#endif
108
109#ifdef MV_RT_DEBUG
110# define ETH_DEBUG
111#endif
112
113
114/* locals */
115MV_BOOL ethDescInSram;
116MV_BOOL ethDescSwCoher;
117
118/* This array holds the control structure of each port */
119ETH_PORT_CTRL* ethPortCtrl[MV_ETH_MAX_PORTS];
120
121/* Ethernet Port Local routines */
122
123static void ethInitRxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue);
124
125static void ethInitTxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue);
126
127static void ethSetUcastTable(int portNo, int queue);
128
129static MV_BOOL ethSetUcastAddr (int ethPortNum, MV_U8 lastNibble, int queue);
130static MV_BOOL ethSetSpecialMcastAddr(int ethPortNum, MV_U8 lastByte, int queue);
131static MV_BOOL ethSetOtherMcastAddr(int ethPortNum, MV_U8 crc8, int queue);
132
133static void ethFreeDescrMemory(ETH_PORT_CTRL* pEthPortCtrl, MV_BUF_INFO* pDescBuf);
134static MV_U8* ethAllocDescrMemory(ETH_PORT_CTRL* pEthPortCtrl, int size,
135                                   MV_ULONG* pPhysAddr, MV_U32 *memHandle);
136
137static MV_U32 mvEthMruGet(MV_U32 maxRxPktSize);
138
139static void mvEthPortSgmiiConfig(int port);
140
141
142
143/******************************************************************************/
144/* EthDrv Initialization functions */
145/******************************************************************************/
146
147/*******************************************************************************
148* mvEthHalInit - Initialize the Giga Ethernet unit
149*
150* DESCRIPTION:
151* This function initialize the Giga Ethernet unit.
152* 1) Configure Address decode windows of the unit
153* 2) Set registers to HW default values.
154* 3) Clear and Disable interrupts
155*
156* INPUT: NONE
157*
158* RETURN: NONE
159*
160* NOTE: this function is called once in the boot process.
161*******************************************************************************/
162void mvEthHalInit(void)
163{
164    int port;
165
166    /* Init static data structures */
167    for (port=0; port<MV_ETH_MAX_PORTS; port++)
168    {
169        ethPortCtrl[port] = NULL;
170    }
171    /* Power down all existing ports */
172    for(port=0; port<mvCtrlEthMaxPortGet(); port++)
173    {
174
175#if defined (MV78200)
176        /* Skip ports mapped to another CPU*/
177    if (MV_FALSE == mvSocUnitIsMappedToThisCpu(GIGA0+port))
178    {
179            continue;
180    }
181#endif
182
183    /* Skip power down ports */
184    if (MV_FALSE == mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port)) continue;
185
186        /* Disable Giga Ethernet Unit interrupts */
187        MV_REG_WRITE(ETH_UNIT_INTR_MASK_REG(port), 0);
188
189        /* Clear ETH_UNIT_INTR_CAUSE_REG register */
190        MV_REG_WRITE(ETH_UNIT_INTR_CAUSE_REG(port), 0);
191
192    }
193
194    mvEthMemAttrGet(&ethDescInSram, &ethDescSwCoher);
195
196#if defined(ETH_DESCR_IN_SRAM)
197    if(ethDescInSram == MV_FALSE)
198    {
199        mvOsPrintf("ethDrv: WARNING! Descriptors will be allocated in DRAM instead of SRAM.\n");
200    }
201#endif /* ETH_DESCR_IN_SRAM */
202}
203
204/*******************************************************************************
205* mvEthMemAttrGet - Define properties (SRAM/DRAM, SW_COHER / HW_COHER / UNCACHED)
206* of of memory location for RX and TX descriptors.
207*
208* DESCRIPTION:
209* This function allocates memory for RX and TX descriptors.
210* - If ETH_DESCR_IN_SRAM defined, allocate from SRAM memory.
211* - If ETH_DESCR_IN_SDRAM defined, allocate from SDRAM memory.
212*
213* INPUT:
214* MV_BOOL* pIsSram - place of descriptors:
215* MV_TRUE - in SRAM
216* MV_FALSE - in DRAM
217* MV_BOOL* pIsSwCoher - cache coherency of descriptors:
218* MV_TRUE - driver is responsible for cache coherency
219* MV_FALSE - driver is not responsible for cache coherency
220*
221* RETURN:
222*
223*******************************************************************************/
224void mvEthMemAttrGet(MV_BOOL* pIsSram, MV_BOOL* pIsSwCoher)
225{
226    MV_BOOL isSram, isSwCoher;
227
228    isSram = MV_FALSE;
229#if (ETHER_DRAM_COHER == MV_CACHE_COHER_SW)
230    isSwCoher = MV_TRUE;
231#else
232    isSwCoher = MV_FALSE;
233#endif
234
235#if defined(ETH_DESCR_IN_SRAM)
236    if( mvCtrlSramSizeGet() > 0)
237    {
238        isSram = MV_TRUE;
239        #if (INTEG_SRAM_COHER == MV_CACHE_COHER_SW)
240            isSwCoher = MV_TRUE;
241        #else
242            isSwCoher = MV_FALSE;
243        #endif
244    }
245#endif /* ETH_DESCR_IN_SRAM */
246
247    if(pIsSram != NULL)
248        *pIsSram = isSram;
249
250    if(pIsSwCoher != NULL)
251        *pIsSwCoher = isSwCoher;
252}
253
254
255
256/******************************************************************************/
257/* Port Initialization functions */
258/******************************************************************************/
259
260/*******************************************************************************
261* mvEthPortInit - Initialize the Ethernet port driver
262*
263* DESCRIPTION:
264* This function initialize the ethernet port.
265* 1) Allocate and initialize internal port Control structure.
266* 2) Create RX and TX descriptor rings for default RX and TX queues
267* 3) Disable RX and TX operations, clear cause registers and
268* mask all interrupts.
269* 4) Set all registers to default values and clean all MAC tables.
270*
271* INPUT:
272* int portNo - Ethernet port number
273* ETH_PORT_INIT *pEthPortInit - Ethernet port init structure
274*
275* RETURN:
276* void* - ethernet port handler, that should be passed to the most other
277* functions dealing with this port.
278*
279* NOTE: This function is called once per port when loading the eth module.
280*******************************************************************************/
281void* mvEthPortInit(int portNo, MV_ETH_PORT_INIT *pEthPortInit)
282{
283    int queue, descSize;
284    ETH_PORT_CTRL* pPortCtrl;
285
286    /* Check validity of parameters */
287    if( (portNo >= (int)mvCtrlEthMaxPortGet()) ||
288        (pEthPortInit->rxDefQ >= MV_ETH_RX_Q_NUM) ||
289        (pEthPortInit->maxRxPktSize < 1518) )
290    {
291        mvOsPrintf("EthPort #%d: Bad initialization parameters\n", portNo);
292        return NULL;
293    }
294    if( (pEthPortInit->rxDescrNum[pEthPortInit->rxDefQ]) == 0)
295    {
296        mvOsPrintf("EthPort #%d: rxDefQ (%d) must be created\n",
297                    portNo, pEthPortInit->rxDefQ);
298        return NULL;
299    }
300
301    pPortCtrl = (ETH_PORT_CTRL*)mvOsMalloc( sizeof(ETH_PORT_CTRL) );
302    if(pPortCtrl == NULL)
303    {
304       mvOsPrintf("EthDrv: Can't allocate %dB for port #%d control structure!\n",
305                   (int)sizeof(ETH_PORT_CTRL), portNo);
306       return NULL;
307    }
308
309    memset(pPortCtrl, 0, sizeof(ETH_PORT_CTRL) );
310    ethPortCtrl[portNo] = pPortCtrl;
311
312    pPortCtrl->portState = MV_UNDEFINED_STATE;
313
314    pPortCtrl->portNo = portNo;
315
316    pPortCtrl->osHandle = pEthPortInit->osHandle;
317
318    /* Copy Configuration parameters */
319    pPortCtrl->portConfig.maxRxPktSize = pEthPortInit->maxRxPktSize;
320    pPortCtrl->portConfig.rxDefQ = pEthPortInit->rxDefQ;
321    pPortCtrl->portConfig.ejpMode = 0;
322
323    for( queue=0; queue<MV_ETH_RX_Q_NUM; queue++ )
324    {
325        pPortCtrl->rxQueueConfig[queue].descrNum = pEthPortInit->rxDescrNum[queue];
326    }
327    for( queue=0; queue<MV_ETH_TX_Q_NUM; queue++ )
328    {
329        pPortCtrl->txQueueConfig[queue].descrNum = pEthPortInit->txDescrNum[queue];
330    }
331
332    mvEthPortDisable(pPortCtrl);
333
334    /* Set the board information regarding PHY address */
335    mvEthPhyAddrSet(pPortCtrl, mvBoardPhyAddrGet(portNo) );
336
337    /* Create all requested RX queues */
338    for(queue=0; queue<MV_ETH_RX_Q_NUM; queue++)
339    {
340        if(pPortCtrl->rxQueueConfig[queue].descrNum == 0)
341            continue;
342
343        /* Allocate memory for RX descriptors */
344        descSize = ((pPortCtrl->rxQueueConfig[queue].descrNum * ETH_RX_DESC_ALIGNED_SIZE) +
345                                                        CPU_D_CACHE_LINE_SIZE);
346 
347        pPortCtrl->rxQueue[queue].descBuf.bufVirtPtr =
348                        ethAllocDescrMemory(pPortCtrl, descSize,
349                        &pPortCtrl->rxQueue[queue].descBuf.bufPhysAddr,
350                        &pPortCtrl->rxQueue[queue].descBuf.memHandle);
351        pPortCtrl->rxQueue[queue].descBuf.bufSize = descSize;
352        if(pPortCtrl->rxQueue[queue].descBuf.bufVirtPtr == NULL)
353        {
354            mvOsPrintf("EthPort #%d, rxQ=%d: Can't allocate %d bytes in %s for %d RX descr\n",
355                        pPortCtrl->portNo, queue, descSize,
356                        ethDescInSram ? "SRAM" : "DRAM",
357                        pPortCtrl->rxQueueConfig[queue].descrNum);
358            return NULL;
359        }
360
361        ethInitRxDescRing(pPortCtrl, queue);
362    }
363    /* Create TX queues */
364    for(queue=0; queue<MV_ETH_TX_Q_NUM; queue++)
365    {
366        if(pPortCtrl->txQueueConfig[queue].descrNum == 0)
367            continue;
368
369        /* Allocate memory for TX descriptors */
370        descSize = ((pPortCtrl->txQueueConfig[queue].descrNum * ETH_TX_DESC_ALIGNED_SIZE) +
371                                                        CPU_D_CACHE_LINE_SIZE);
372 
373        pPortCtrl->txQueue[queue].descBuf.bufVirtPtr =
374        ethAllocDescrMemory(pPortCtrl, descSize,
375                    &pPortCtrl->txQueue[queue].descBuf.bufPhysAddr,
376                    &pPortCtrl->txQueue[queue].descBuf.memHandle);
377        pPortCtrl->txQueue[queue].descBuf.bufSize = descSize;
378        if(pPortCtrl->txQueue[queue].descBuf.bufVirtPtr == NULL)
379        {
380            mvOsPrintf("EthPort #%d, txQ=%d: Can't allocate %d bytes in %s for %d TX descr\n",
381                        pPortCtrl->portNo, queue, descSize, ethDescInSram ? "SRAM" : "DRAM",
382                        pPortCtrl->txQueueConfig[queue].descrNum);
383            return NULL;
384        }
385
386        ethInitTxDescRing(pPortCtrl, queue);
387    }
388    mvEthDefaultsSet(pPortCtrl);
389
390    pPortCtrl->portState = MV_IDLE;
391    return pPortCtrl;
392}
393
394/*******************************************************************************
395* ethPortFinish - Finish the Ethernet port driver
396*
397* DESCRIPTION:
398* This function finish the ethernet port.
399* 1) Down ethernet port if needed.
400* 2) Delete RX and TX descriptor rings for all created RX and TX queues
401* 3) Free internal port Control structure.
402*
403* INPUT:
404* void* pEthPortHndl - Ethernet port handler
405*
406* RETURN: NONE.
407*
408*******************************************************************************/
409void mvEthPortFinish(void* pPortHndl)
410{
411    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
412    int queue, portNo = pPortCtrl->portNo;
413
414    if(pPortCtrl->portState == MV_ACTIVE)
415    {
416        mvOsPrintf("ethPort #%d: Warning !!! Finish port in Active state\n",
417                 portNo);
418        mvEthPortDisable(pPortHndl);
419    }
420
421    /* Free all allocated RX queues */
422    for(queue=0; queue<MV_ETH_RX_Q_NUM; queue++)
423    {
424        ethFreeDescrMemory(pPortCtrl, &pPortCtrl->rxQueue[queue].descBuf);
425    }
426
427    /* Free all allocated TX queues */
428    for(queue=0; queue<MV_ETH_TX_Q_NUM; queue++)
429    {
430        ethFreeDescrMemory(pPortCtrl, &pPortCtrl->txQueue[queue].descBuf);
431    }
432
433    /* Free port control structure */
434    mvOsFree(pPortCtrl);
435
436    ethPortCtrl[portNo] = NULL;
437}
438
439/*******************************************************************************
440* mvEthDefaultsSet - Set defaults to the ethernet port
441*
442* DESCRIPTION:
443* This function set default values to the ethernet port.
444* 1) Clear Cause registers and Mask all interrupts
445* 2) Clear all MAC tables
446* 3) Set defaults to all registers
447* 4) Reset all created RX and TX descriptors ring
448* 5) Reset PHY
449*
450* INPUT:
451* void* pEthPortHndl - Ethernet port handler
452*
453* RETURN: MV_STATUS
454* MV_OK - Success, Others - Failure
455* NOTE:
456* This function update all the port configuration except those set
457* Initialy by the OsGlue by MV_ETH_PORT_INIT.
458* This function can be called after portDown to return the port setting
459* to defaults.
460*******************************************************************************/
461MV_STATUS mvEthDefaultsSet(void* pPortHndl)
462{
463    int ethPortNo, queue;
464    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
465    ETH_QUEUE_CTRL* pQueueCtrl;
466    MV_U32 txPrio;
467    MV_U32 portCfgReg, portCfgExtReg, portSerialCtrlReg, portSerialCtrl1Reg, portSdmaCfgReg;
468    MV_BOARD_MAC_SPEED boardMacCfg;
469
470    ethPortNo = pPortCtrl->portNo;
471
472    /* Clear Cause registers */
473    MV_REG_WRITE(ETH_INTR_CAUSE_REG(ethPortNo),0);
474    MV_REG_WRITE(ETH_INTR_CAUSE_EXT_REG(ethPortNo),0);
475
476    /* Mask all interrupts */
477    MV_REG_WRITE(ETH_INTR_MASK_REG(ethPortNo),0);
478    MV_REG_WRITE(ETH_INTR_MASK_EXT_REG(ethPortNo),0);
479
480    portCfgReg = PORT_CONFIG_VALUE;
481    portCfgExtReg = PORT_CONFIG_EXTEND_VALUE;
482
483    boardMacCfg = mvBoardMacSpeedGet(ethPortNo);
484
485    if(boardMacCfg == BOARD_MAC_SPEED_100M)
486    {
487        portSerialCtrlReg = PORT_SERIAL_CONTROL_100MB_FORCE_VALUE;
488    }
489    else if(boardMacCfg == BOARD_MAC_SPEED_1000M)
490    {
491        portSerialCtrlReg = PORT_SERIAL_CONTROL_1000MB_FORCE_VALUE;
492    }
493    else
494    {
495        portSerialCtrlReg = PORT_SERIAL_CONTROL_VALUE;
496    }
497
498    /* build PORT_SDMA_CONFIG_REG */
499    portSdmaCfgReg = ETH_TX_INTR_COAL_MASK(0);
500    portSdmaCfgReg |= ETH_TX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE);
501
502#if ( (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) || \
503      (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) )
504    /* some devices have restricted RX burst size when using HW coherency */
505    portSdmaCfgReg |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_4_64BIT_VALUE);
506#else
507    portSdmaCfgReg |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE);
508#endif
509
510#if defined(MV_CPU_BE)
511    /* big endian */
512# if defined(MV_ARM)
513    portSdmaCfgReg |= (ETH_RX_NO_DATA_SWAP_MASK |
514                       ETH_TX_NO_DATA_SWAP_MASK |
515                       ETH_DESC_SWAP_MASK);
516# elif defined(MV_PPC)
517    portSdmaCfgReg |= (ETH_RX_DATA_SWAP_MASK |
518                       ETH_TX_DATA_SWAP_MASK |
519                       ETH_NO_DESC_SWAP_MASK);
520# else
521# error "Giga Ethernet Swap policy is not defined for the CPU_ARCH"
522# endif /* MV_ARM / MV_PPC */
523
524#else /* MV_CPU_LE */
525    /* little endian */
526    portSdmaCfgReg |= (ETH_RX_NO_DATA_SWAP_MASK |
527                       ETH_TX_NO_DATA_SWAP_MASK |
528                       ETH_NO_DESC_SWAP_MASK);
529#endif /* MV_CPU_BE / MV_CPU_LE */
530
531    pPortCtrl->portRxQueueCmdReg = 0;
532    pPortCtrl->portTxQueueCmdReg = 0;
533
534#if (MV_ETH_VERSION >= 4)
535    if(pPortCtrl->portConfig.ejpMode == MV_TRUE)
536    {
537        MV_REG_WRITE(ETH_TXQ_CMD_1_REG(ethPortNo), ETH_TX_EJP_ENABLE_MASK);
538    }
539    else
540    {
541        MV_REG_WRITE(ETH_TXQ_CMD_1_REG(ethPortNo), 0)
542    }
543#endif /* (MV_ETH_VERSION >= 4) */
544
545    ethSetUcastTable(ethPortNo, -1);
546    mvEthSetSpecialMcastTable(ethPortNo, -1);
547    mvEthSetOtherMcastTable(ethPortNo, -1);
548
549    portSerialCtrlReg &= ~ETH_MAX_RX_PACKET_SIZE_MASK;
550
551    portSerialCtrlReg |= mvEthMruGet(pPortCtrl->portConfig.maxRxPktSize);
552
553    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo), portSerialCtrlReg);
554
555    /* Update value of PortConfig register accordingly with all RxQueue types */
556    pPortCtrl->portConfig.rxArpQ = pPortCtrl->portConfig.rxDefQ;
557    pPortCtrl->portConfig.rxBpduQ = pPortCtrl->portConfig.rxDefQ;
558    pPortCtrl->portConfig.rxTcpQ = pPortCtrl->portConfig.rxDefQ;
559    pPortCtrl->portConfig.rxUdpQ = pPortCtrl->portConfig.rxDefQ;
560
561    portCfgReg &= ~ETH_DEF_RX_QUEUE_ALL_MASK;
562    portCfgReg |= ETH_DEF_RX_QUEUE_MASK(pPortCtrl->portConfig.rxDefQ);
563    
564    portCfgReg &= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK;
565    portCfgReg |= ETH_DEF_RX_ARP_QUEUE_MASK(pPortCtrl->portConfig.rxArpQ);
566
567    portCfgReg &= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK;
568    portCfgReg |= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl->portConfig.rxBpduQ);
569
570    portCfgReg &= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK;
571    portCfgReg |= ETH_DEF_RX_TCP_QUEUE_MASK(pPortCtrl->portConfig.rxTcpQ);
572
573    portCfgReg &= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK;
574    portCfgReg |= ETH_DEF_RX_UDP_QUEUE_MASK(pPortCtrl->portConfig.rxUdpQ);
575
576    /* Assignment of Tx CTRP of given queue */
577    txPrio = 0;
578
579    for(queue=0; queue<MV_ETH_TX_Q_NUM; queue++)
580    {
581        pQueueCtrl = &pPortCtrl->txQueue[queue];
582
583        if(pQueueCtrl->pFirstDescr != NULL)
584        {
585            ethResetTxDescRing(pPortCtrl, queue);
586
587            MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo, queue),
588                         0x3fffffff);
589            MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo, queue),
590                         0x03ffffff);
591        }
592        else
593        {
594            MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo, queue), 0x0);
595            MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo, queue), 0x0);
596        }
597    }
598
599    /* Assignment of Rx CRDP of given queue */
600    for(queue=0; queue<MV_ETH_RX_Q_NUM; queue++)
601    {
602        ethResetRxDescRing(pPortCtrl, queue);
603    }
604
605    /* Allow receiving packes with odd number of preamble nibbles */
606    portSerialCtrl1Reg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(ethPortNo));
607    portSerialCtrl1Reg |= ETH_EN_MII_ODD_PRE_MASK;
608    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(ethPortNo), portSerialCtrl1Reg);
609
610    /* Assign port configuration and command. */
611    MV_REG_WRITE(ETH_PORT_CONFIG_REG(ethPortNo), portCfgReg);
612
613    MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(ethPortNo), portCfgExtReg);
614
615    /* Assign port SDMA configuration */
616    MV_REG_WRITE(ETH_SDMA_CONFIG_REG(ethPortNo), portSdmaCfgReg);
617    
618    /* Turn off the port/queue bandwidth limitation */
619    MV_REG_WRITE(ETH_MAX_TRANSMIT_UNIT_REG(ethPortNo), 0x0);
620
621    return MV_OK;
622}
623
624/*******************************************************************************
625* ethPortUp - Start the Ethernet port RX and TX activity.
626*
627* DESCRIPTION:
628* This routine start Rx and Tx activity:
629*
630* Note: Each Rx and Tx queue descriptor's list must be initialized prior
631* to calling this function (use etherInitTxDescRing for Tx queues and
632* etherInitRxDescRing for Rx queues).
633*
634* INPUT:
635* void* pEthPortHndl - Ethernet port handler
636*
637* RETURN: MV_STATUS
638* MV_OK - Success, Others - Failure.
639*
640* NOTE : used for port link up.
641*******************************************************************************/
642MV_STATUS mvEthPortUp(void* pEthPortHndl)
643{
644    int ethPortNo;
645    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl;
646
647    ethPortNo = pPortCtrl->portNo;
648    
649    if( (pPortCtrl->portState != MV_ACTIVE) &&
650        (pPortCtrl->portState != MV_PAUSED) )
651    {
652        mvOsPrintf("ethDrv port%d: Unexpected port state %d\n",
653                        ethPortNo, pPortCtrl->portState);
654        return MV_BAD_STATE;
655    }
656    
657    ethPortNo = pPortCtrl->portNo;
658
659    /* Enable port RX. */
660    MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNo), pPortCtrl->portRxQueueCmdReg);
661
662    /* Enable port TX. */
663    MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(ethPortNo)) = pPortCtrl->portTxQueueCmdReg;
664
665    pPortCtrl->portState = MV_ACTIVE;
666
667    return MV_OK;
668}
669
670/*******************************************************************************
671* ethPortDown - Stop the Ethernet port activity.
672*
673* DESCRIPTION:
674*
675* INPUT:
676* void* pEthPortHndl - Ethernet port handler
677*
678* RETURN: MV_STATUS
679* MV_OK - Success, Others - Failure.
680*
681* NOTE : used for port link down.
682*******************************************************************************/
683MV_STATUS mvEthPortDown(void* pEthPortHndl)
684{
685    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl;
686    int ethPortNum = pPortCtrl->portNo;
687    unsigned int regData;
688    volatile int uDelay, mDelay;
689
690    /* Stop Rx port activity. Check port Rx activity. */
691    regData = (MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum))) & ETH_RXQ_ENABLE_MASK;
692    if(regData != 0)
693    {
694        /* Issue stop command for active channels only */
695        MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNum), (regData << ETH_RXQ_DISABLE_OFFSET));
696    }
697
698    /* Stop Tx port activity. Check port Tx activity. */
699    regData = (MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum))) & ETH_TXQ_ENABLE_MASK;
700    if(regData != 0)
701    {
702        /* Issue stop command for active channels only */
703        MV_REG_WRITE(ETH_TX_QUEUE_COMMAND_REG(ethPortNum),
704                            (regData << ETH_TXQ_DISABLE_OFFSET) );
705    }
706
707    /* Force link down */
708/*
709    regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum));
710    regData &= ~(ETH_DO_NOT_FORCE_LINK_FAIL_MASK);
711    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData);
712*/
713    /* Wait for all Rx activity to terminate. */
714    mDelay = 0;
715    do
716    {
717        if(mDelay >= RX_DISABLE_TIMEOUT_MSEC)
718        {
719            mvOsPrintf("ethPort_%d: TIMEOUT for RX stopped !!! rxQueueCmd - 0x08%x\n",
720                        ethPortNum, regData);
721            break;
722        }
723        mvOsDelay(1);
724        mDelay++;
725        
726        /* Check port RX Command register that all Rx queues are stopped */
727        regData = MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum));
728    }
729    while(regData & 0xFF);
730
731    /* Wait for all Tx activity to terminate. */
732    mDelay = 0;
733    do
734    {
735        if(mDelay >= TX_DISABLE_TIMEOUT_MSEC)
736        {
737            mvOsPrintf("ethPort_%d: TIMEOUT for TX stoped !!! txQueueCmd - 0x08%x\n",
738                        ethPortNum, regData);
739            break;
740        }
741        mvOsDelay(1);
742        mDelay++;
743
744        /* Check port TX Command register that all Tx queues are stopped */
745        regData = MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum));
746    }
747    while(regData & 0xFF);
748    
749    /* Double check to Verify that TX FIFO is Empty */
750    mDelay = 0;
751    while(MV_TRUE)
752    {
753        do
754        {
755            if(mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC)
756            {
757                mvOsPrintf("\n ethPort_%d: TIMEOUT for TX FIFO empty !!! portStatus - 0x08%x\n",
758                            ethPortNum, regData);
759                break;
760            }
761            mvOsDelay(1);
762            mDelay++;
763
764            regData = MV_REG_READ(ETH_PORT_STATUS_REG(ethPortNum));
765        }
766        while( ((regData & ETH_TX_FIFO_EMPTY_MASK) == 0) ||
767               ((regData & ETH_TX_IN_PROGRESS_MASK) != 0) );
768
769        if(mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC)
770            break;
771
772        /* Double check */
773        regData = MV_REG_READ(ETH_PORT_STATUS_REG(ethPortNum));
774        if( ((regData & ETH_TX_FIFO_EMPTY_MASK) != 0) &&
775            ((regData & ETH_TX_IN_PROGRESS_MASK) == 0) )
776        {
777            break;
778        }
779        else
780            mvOsPrintf("ethPort_%d: TX FIFO Empty double check failed. %d msec, portStatus=0x%x\n",
781                                ethPortNum, mDelay, regData);
782    }
783
784    /* Do NOT force link down */
785/*
786    regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum));
787    regData |= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK);
788    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData);
789*/
790    /* Wait about 2500 tclk cycles */
791    uDelay = (PORT_DISABLE_WAIT_TCLOCKS/(mvBoardTclkGet()/1000000));
792    mvOsUDelay(uDelay);
793
794    pPortCtrl->portState = MV_PAUSED;
795
796    return MV_OK;
797}
798
799
800/*******************************************************************************
801* ethPortEnable - Enable the Ethernet port and Start RX and TX.
802*
803* DESCRIPTION:
804* This routine enable the Ethernet port and Rx and Tx activity:
805*
806* Note: Each Rx and Tx queue descriptor's list must be initialized prior
807* to calling this function (use etherInitTxDescRing for Tx queues and
808* etherInitRxDescRing for Rx queues).
809*
810* INPUT:
811* void* pEthPortHndl - Ethernet port handler
812*
813* RETURN: MV_STATUS
814* MV_OK - Success, Others - Failure.
815*
816* NOTE: main usage is to enable the port after ifconfig up.
817*******************************************************************************/
818MV_STATUS mvEthPortEnable(void* pEthPortHndl)
819{
820    int ethPortNo;
821    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl;
822    MV_U32 portSerialCtrlReg;
823
824    ethPortNo = pPortCtrl->portNo;
825
826    /* Enable port */
827    portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNo));
828    portSerialCtrlReg |= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK | ETH_PORT_ENABLE_MASK);
829
830    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo), portSerialCtrlReg);
831
832    mvEthMibCountersClear(pEthPortHndl);
833
834    pPortCtrl->portState = MV_PAUSED;
835
836    /* If Link is UP, Start RX and TX traffic */
837    if( MV_REG_READ( ETH_PORT_STATUS_REG(ethPortNo) ) & ETH_LINK_UP_MASK)
838        return( mvEthPortUp(pEthPortHndl) );
839    
840    return MV_NOT_READY;
841}
842
843
844/*******************************************************************************
845* mvEthPortDisable - Stop RX and TX activities and Disable the Ethernet port.
846*
847* DESCRIPTION:
848*
849* INPUT:
850* void* pEthPortHndl - Ethernet port handler
851*
852* RETURN: MV_STATUS
853* MV_OK - Success, Others - Failure.
854*
855* NOTE: main usage is to disable the port after ifconfig down.
856*******************************************************************************/
857MV_STATUS mvEthPortDisable(void* pEthPortHndl)
858{
859    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl;
860    int ethPortNum = pPortCtrl->portNo;
861    unsigned int regData;
862    volatile int mvDelay;
863
864    if(pPortCtrl->portState == MV_ACTIVE)
865    {
866        /* Stop RX and TX activities */
867        mvEthPortDown(pEthPortHndl);
868    }
869
870    /* Reset the Enable bit in the Serial Control Register */
871    regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum));
872    regData &= ~(ETH_PORT_ENABLE_MASK);
873    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData);
874
875    /* Wait about 2500 tclk cycles */
876    mvDelay = (PORT_DISABLE_WAIT_TCLOCKS*(mvCpuPclkGet()/mvBoardTclkGet()));
877    for(mvDelay; mvDelay>0; mvDelay--);
878
879    pPortCtrl->portState = MV_IDLE;
880    return MV_OK;
881}
882
883/*******************************************************************************
884* mvEthPortForceTxDone - Get next buffer from TX queue in spite of buffer ownership.
885*
886* DESCRIPTION:
887* This routine used to free buffers attached to the Tx ring and should
888* be called only when Giga Ethernet port is Down
889*
890* INPUT:
891* void* pEthPortHndl - Ethernet Port handler.
892* int txQueue - Number of TX queue.
893*
894* OUTPUT:
895* MV_PKT_INFO *pPktInfo - Pointer to packet was sent.
896*
897* RETURN:
898* MV_EMPTY - There is no more buffers in this queue.
899* MV_OK - Buffer detached from the queue and pPktInfo structure
900* filled with relevant information.
901*
902*******************************************************************************/
903MV_PKT_INFO* mvEthPortForceTxDone(void* pEthPortHndl, int txQueue)
904{
905    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl;
906    ETH_QUEUE_CTRL* pQueueCtrl;
907    MV_PKT_INFO* pPktInfo;
908    ETH_TX_DESC* pTxDesc;
909    int port = pPortCtrl->portNo;
910       
911    pQueueCtrl = &pPortCtrl->txQueue[txQueue];
912
913    while( (pQueueCtrl->pUsedDescr != pQueueCtrl->pCurrentDescr) ||
914           (pQueueCtrl->resource == 0) )
915    {
916        /* Free next descriptor */
917        pQueueCtrl->resource++;
918        pTxDesc = (ETH_TX_DESC*)pQueueCtrl->pUsedDescr;
919
920    /* pPktInfo is available only in descriptors which are last descriptors */
921        pPktInfo = (MV_PKT_INFO*)pTxDesc->returnInfo;
922    if (pPktInfo)
923            pPktInfo->status = pTxDesc->cmdSts;
924
925        pTxDesc->cmdSts = 0x0;
926        pTxDesc->returnInfo = 0x0;
927        ETH_DESCR_FLUSH_INV(pPortCtrl, pTxDesc);
928
929        pQueueCtrl->pUsedDescr = TX_NEXT_DESC_PTR(pTxDesc, pQueueCtrl);
930
931        if (pPktInfo)
932        if (pPktInfo->status & ETH_TX_LAST_DESC_MASK)
933                    return pPktInfo;
934    }
935    MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(port, txQueue),
936                    (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) );
937    return NULL;
938}
939
940        
941
942/*******************************************************************************
943* mvEthPortForceRx - Get next buffer from RX queue in spite of buffer ownership.
944*
945* DESCRIPTION:
946* This routine used to free buffers attached to the Rx ring and should
947* be called only when Giga Ethernet port is Down
948*
949* INPUT:
950* void* pEthPortHndl - Ethernet Port handler.
951* int rxQueue - Number of Rx queue.
952*
953* OUTPUT:
954* MV_PKT_INFO *pPktInfo - Pointer to received packet.
955*
956* RETURN:
957* MV_EMPTY - There is no more buffers in this queue.
958* MV_OK - Buffer detached from the queue and pBufInfo structure
959* filled with relevant information.
960*
961*******************************************************************************/
962MV_PKT_INFO* mvEthPortForceRx(void* pEthPortHndl, int rxQueue)
963{
964    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl;
965    ETH_QUEUE_CTRL* pQueueCtrl;
966    ETH_RX_DESC* pRxDesc;
967    MV_PKT_INFO* pPktInfo;
968    int port = pPortCtrl->portNo;
969       
970    pQueueCtrl = &pPortCtrl->rxQueue[rxQueue];
971
972    if(pQueueCtrl->resource == 0)
973    {
974        MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(port, rxQueue),
975                    (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) );
976
977        return NULL;
978    }
979    /* Free next descriptor */
980    pQueueCtrl->resource--;
981    pRxDesc = (ETH_RX_DESC*)pQueueCtrl->pCurrentDescr;
982    pPktInfo = (MV_PKT_INFO*)pRxDesc->returnInfo;
983
984    pPktInfo->status = pRxDesc->cmdSts;
985    pRxDesc->cmdSts = 0x0;
986    pRxDesc->returnInfo = 0x0;
987    ETH_DESCR_FLUSH_INV(pPortCtrl, pRxDesc);
988
989    pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxDesc, pQueueCtrl);
990    return pPktInfo;
991}
992
993
994/******************************************************************************/
995/* Port Configuration functions */
996/******************************************************************************/
997/*******************************************************************************
998* mvEthMruGet - Get MRU configuration for Max Rx packet size.
999*
1000* INPUT:
1001* MV_U32 maxRxPktSize - max packet size.
1002*
1003* RETURN: MV_U32 - MRU configuration.
1004*
1005*******************************************************************************/
1006static MV_U32 mvEthMruGet(MV_U32 maxRxPktSize)
1007{
1008    MV_U32 portSerialCtrlReg = 0;
1009
1010    if(maxRxPktSize > 9192)
1011        portSerialCtrlReg |= ETH_MAX_RX_PACKET_9700BYTE;
1012    else if(maxRxPktSize > 9022)
1013        portSerialCtrlReg |= ETH_MAX_RX_PACKET_9192BYTE;
1014    else if(maxRxPktSize > 1552)
1015        portSerialCtrlReg |= ETH_MAX_RX_PACKET_9022BYTE;
1016    else if(maxRxPktSize > 1522)
1017        portSerialCtrlReg |= ETH_MAX_RX_PACKET_1552BYTE;
1018    else if(maxRxPktSize > 1518)
1019        portSerialCtrlReg |= ETH_MAX_RX_PACKET_1522BYTE;
1020    else
1021        portSerialCtrlReg |= ETH_MAX_RX_PACKET_1518BYTE;
1022
1023    return portSerialCtrlReg;
1024}
1025
1026/*******************************************************************************
1027* mvEthRxCoalSet - Sets coalescing interrupt mechanism on RX path
1028*
1029* DESCRIPTION:
1030* This routine sets the RX coalescing interrupt mechanism parameter.
1031* This parameter is a timeout counter, that counts in 64 tClk
1032* chunks, that when timeout event occurs a maskable interrupt occurs.
1033* The parameter is calculated using the tCLK frequency of the
1034* MV-64xxx chip, and the required number is in micro seconds.
1035*
1036* INPUT:
1037* void* pPortHndl - Ethernet Port handler.
1038* MV_U32 uSec - Number of micro seconds between
1039* RX interrupts
1040*
1041* RETURN:
1042* None.
1043*
1044* COMMENT:
1045* 1 sec - TCLK_RATE clocks
1046* 1 uSec - TCLK_RATE / 1,000,000 clocks
1047*
1048* Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64)
1049*
1050* RETURN:
1051* None.
1052*
1053*******************************************************************************/
1054MV_U32 mvEthRxCoalSet (void* pPortHndl, MV_U32 uSec)
1055{
1056    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
1057    MV_U32 coal = ((uSec * (mvBoardTclkGet() / 1000000)) / 64);
1058    MV_U32 portSdmaCfgReg;
1059
1060    portSdmaCfgReg = MV_REG_READ(ETH_SDMA_CONFIG_REG(pPortCtrl->portNo));
1061    portSdmaCfgReg &= ~ETH_RX_INTR_COAL_ALL_MASK;
1062
1063    portSdmaCfgReg |= ETH_RX_INTR_COAL_MASK(coal);
1064
1065#if (MV_ETH_VERSION >= 2)
1066    /* Set additional bit if needed ETH_RX_INTR_COAL_MSB_BIT (25) */
1067    if(ETH_RX_INTR_COAL_MASK(coal) > ETH_RX_INTR_COAL_ALL_MASK)
1068        portSdmaCfgReg |= ETH_RX_INTR_COAL_MSB_MASK;
1069#endif /* MV_ETH_VERSION >= 2 */
1070
1071    MV_REG_WRITE (ETH_SDMA_CONFIG_REG(pPortCtrl->portNo), portSdmaCfgReg);
1072    return coal;
1073}
1074
1075/*******************************************************************************
1076* mvEthTxCoalSet - Sets coalescing interrupt mechanism on TX path
1077*
1078* DESCRIPTION:
1079* This routine sets the TX coalescing interrupt mechanism parameter.
1080* This parameter is a timeout counter, that counts in 64 tClk
1081* chunks, that when timeout event occurs a maskable interrupt
1082* occurs.
1083* The parameter is calculated using the tCLK frequency of the
1084* MV-64xxx chip, and the required number is in micro seconds.
1085*
1086* INPUT:
1087* void* pPortHndl - Ethernet Port handler.
1088* MV_U32 uSec - Number of micro seconds between
1089* RX interrupts
1090*
1091* RETURN:
1092* None.
1093*
1094* COMMENT:
1095* 1 sec - TCLK_RATE clocks
1096* 1 uSec - TCLK_RATE / 1,000,000 clocks
1097*
1098* Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64)
1099*
1100*******************************************************************************/
1101MV_U32 mvEthTxCoalSet(void* pPortHndl, MV_U32 uSec)
1102{
1103    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
1104    MV_U32 coal = ((uSec * (mvBoardTclkGet() / 1000000)) / 64);
1105    MV_U32 regVal;
1106
1107    regVal = MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo));
1108    regVal &= ~ETH_TX_INTR_COAL_ALL_MASK;
1109    regVal |= ETH_TX_INTR_COAL_MASK(coal);
1110
1111    /* Set TX Coalescing mechanism */
1112    MV_REG_WRITE (ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo), regVal);
1113    return coal;
1114}
1115
1116/*******************************************************************************
1117* mvEthCoalGet - Gets RX and TX coalescing values in micro seconds
1118*
1119* DESCRIPTION:
1120* This routine gets the RX and TX coalescing interrupt values.
1121* The parameter is calculated using the tCLK frequency of the
1122* MV-64xxx chip, and the returned numbers are in micro seconds.
1123*
1124* INPUTs:
1125* void* pPortHndl - Ethernet Port handler.
1126*
1127* OUTPUTs:
1128* MV_U32* pRxCoal - Number of micro seconds between RX interrupts
1129* MV_U32* pTxCoal - Number of micro seconds between TX interrupts
1130*
1131* RETURN:
1132* MV_STATUS MV_OK - success
1133* Others - failure.
1134*
1135* COMMENT:
1136* 1 sec - TCLK_RATE clocks
1137* 1 uSec - TCLK_RATE / 1,000,000 clocks
1138*
1139* Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64)
1140*
1141*******************************************************************************/
1142MV_STATUS mvEthCoalGet(void* pPortHndl, MV_U32* pRxCoal, MV_U32* pTxCoal)
1143{
1144    MV_U32 regVal, coal, usec;
1145
1146    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
1147
1148    /* get TX Coalescing */
1149    regVal = MV_REG_READ (ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo));
1150    coal = ((regVal & ETH_TX_INTR_COAL_ALL_MASK) >> ETH_TX_INTR_COAL_OFFSET);
1151
1152    usec = (coal * 64) / (mvBoardTclkGet() / 1000000);
1153    if(pTxCoal != NULL)
1154        *pTxCoal = usec;
1155
1156    /* Get RX Coalescing */
1157    regVal = MV_REG_READ(ETH_SDMA_CONFIG_REG(pPortCtrl->portNo));
1158    coal = ((regVal & ETH_RX_INTR_COAL_ALL_MASK) >> ETH_RX_INTR_COAL_OFFSET);
1159
1160#if (MV_ETH_VERSION >= 2)
1161    if(regVal & ETH_RX_INTR_COAL_MSB_MASK)
1162    {
1163        /* Add MSB */
1164        coal |= (ETH_RX_INTR_COAL_ALL_MASK + 1);
1165    }
1166#endif /* MV_ETH_VERSION >= 2 */
1167
1168    usec = (coal * 64) / (mvBoardTclkGet() / 1000000);
1169    if(pRxCoal != NULL)
1170        *pRxCoal = usec;
1171
1172    return MV_OK;
1173}
1174
1175/*******************************************************************************
1176* mvEthMaxRxSizeSet -
1177*
1178* DESCRIPTION:
1179* Change maximum receive size of the port. This configuration will take place
1180* after next call of ethPortSetDefaults() function.
1181*
1182* INPUT:
1183*
1184* RETURN:
1185*******************************************************************************/
1186MV_STATUS mvEthMaxRxSizeSet(void* pPortHndl, int maxRxSize)
1187{
1188    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
1189    MV_U32 portSerialCtrlReg;
1190
1191    if((maxRxSize < 1518) || (maxRxSize & ~ETH_RX_BUFFER_MASK))
1192       return MV_BAD_PARAM;
1193    
1194    pPortCtrl->portConfig.maxRxPktSize = maxRxSize;
1195
1196    portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo));
1197    portSerialCtrlReg &= ~ETH_MAX_RX_PACKET_SIZE_MASK;
1198    portSerialCtrlReg |= mvEthMruGet(pPortCtrl->portConfig.maxRxPktSize);
1199    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo), portSerialCtrlReg);
1200
1201    return MV_OK;
1202}
1203
1204
1205/******************************************************************************/
1206/* MAC Filtering functions */
1207/******************************************************************************/
1208
1209/*******************************************************************************
1210* mvEthRxFilterModeSet - Configure Fitering mode of Ethernet port
1211*
1212* DESCRIPTION:
1213* This routine used to free buffers attached to the Rx ring and should
1214* be called only when Giga Ethernet port is Down
1215*
1216* INPUT:
1217* void* pEthPortHndl - Ethernet Port handler.
1218* MV_BOOL isPromisc - Promiscous mode
1219* MV_TRUE - accept all Broadcast, Multicast
1220* and Unicast packets
1221* MV_FALSE - accept all Broadcast,
1222* specially added Multicast and
1223* single Unicast packets
1224*
1225* RETURN: MV_STATUS MV_OK - Success, Other - Failure
1226*
1227*******************************************************************************/
1228MV_STATUS mvEthRxFilterModeSet(void* pEthPortHndl, MV_BOOL isPromisc)
1229{
1230    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl;
1231    int queue;
1232    MV_U32 portCfgReg;
1233
1234    portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
1235    /* Set / Clear UPM bit in port configuration register */
1236    if(isPromisc)
1237    {
1238        /* Accept all multicast packets to RX default queue */
1239        queue = pPortCtrl->portConfig.rxDefQ;
1240        portCfgReg |= ETH_UNICAST_PROMISCUOUS_MODE_MASK;
1241        memset(pPortCtrl->mcastCount, 1, sizeof(pPortCtrl->mcastCount));
1242        MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(pPortCtrl->portNo),0xFFFF);
1243        MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(pPortCtrl->portNo),0xFFFFFFFF);
1244    }
1245    else
1246    {
1247        /* Reject all Multicast addresses */
1248        queue = -1;
1249        portCfgReg &= ~ETH_UNICAST_PROMISCUOUS_MODE_MASK;
1250        /* Clear all mcastCount */
1251        memset(pPortCtrl->mcastCount, 0, sizeof(pPortCtrl->mcastCount));
1252    }
1253    MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
1254
1255    /* Set Special Multicast and Other Multicast tables */
1256    mvEthSetSpecialMcastTable(pPortCtrl->portNo, queue);
1257    mvEthSetOtherMcastTable(pPortCtrl->portNo, queue);
1258    ethSetUcastTable(pPortCtrl->portNo, queue);
1259
1260    return MV_OK;
1261}
1262
1263/*******************************************************************************
1264* mvEthMacAddrSet - This function Set the port Unicast address.
1265*
1266* DESCRIPTION:
1267* This function Set the port Ethernet MAC address. This address
1268* will be used to send Pause frames if enabled. Packets with this
1269* address will be accepted and dispatched to default RX queue
1270*
1271* INPUT:
1272* void* pEthPortHndl - Ethernet port handler.
1273* char* pAddr - Address to be set
1274*
1275* RETURN: MV_STATUS
1276* MV_OK - Success, Other - Faulure
1277*
1278*******************************************************************************/
1279MV_STATUS mvEthMacAddrSet(void* pPortHndl, unsigned char *pAddr, int queue)
1280{
1281    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
1282    unsigned int macH;
1283    unsigned int macL;
1284
1285    if(queue >= MV_ETH_RX_Q_NUM)
1286    {
1287        mvOsPrintf("ethDrv: RX queue #%d is out of range\n", queue);
1288        return MV_BAD_PARAM;
1289    }
1290
1291    if(queue != -1)
1292    {
1293        macL = (pAddr[4] << 8) | (pAddr[5]);
1294        macH = (pAddr[0] << 24)| (pAddr[1] << 16) |
1295                (pAddr[2] << 8) | (pAddr[3] << 0);
1296
1297        MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(pPortCtrl->portNo), macL);
1298        MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(pPortCtrl->portNo), macH);
1299    }
1300
1301    /* Accept frames of this address */
1302    ethSetUcastAddr(pPortCtrl->portNo, pAddr[5], queue);
1303
1304    return MV_OK;
1305}
1306
1307/*******************************************************************************
1308* mvEthMacAddrGet - This function returns the port Unicast address.
1309*
1310* DESCRIPTION:
1311* This function returns the port Ethernet MAC address.
1312*
1313* INPUT:
1314* int portNo - Ethernet port number.
1315* char* pAddr - Pointer where address will be written to
1316*
1317* RETURN: MV_STATUS
1318* MV_OK - Success, Other - Faulure
1319*
1320*******************************************************************************/
1321MV_STATUS mvEthMacAddrGet(int portNo, unsigned char *pAddr)
1322{
1323    unsigned int macH;
1324    unsigned int macL;
1325
1326    if(pAddr == NULL)
1327    {
1328        mvOsPrintf("mvEthMacAddrGet: NULL pointer.\n");
1329        return MV_BAD_PARAM;
1330    }
1331
1332    macH = MV_REG_READ(ETH_MAC_ADDR_HIGH_REG(portNo));
1333    macL = MV_REG_READ(ETH_MAC_ADDR_LOW_REG(portNo));
1334    pAddr[0] = (macH >> 24) & 0xff;
1335    pAddr[1] = (macH >> 16) & 0xff;
1336    pAddr[2] = (macH >> 8) & 0xff;
1337    pAddr[3] = macH & 0xff;
1338    pAddr[4] = (macL >> 8) & 0xff;
1339    pAddr[5] = macL & 0xff;
1340
1341    return MV_OK;
1342}
1343
1344/*******************************************************************************
1345* mvEthMcastCrc8Get - Calculate CRC8 of MAC address.
1346*
1347* DESCRIPTION:
1348*
1349* INPUT:
1350* MV_U8* pAddr - Address to calculate CRC-8
1351*
1352* RETURN: MV_U8 - CRC-8 of this MAC address
1353*
1354*******************************************************************************/
1355MV_U8 mvEthMcastCrc8Get(MV_U8* pAddr)
1356{
1357    unsigned int macH;
1358    unsigned int macL;
1359    int macArray[48];
1360    int crc[8];
1361    int i;
1362    unsigned char crcResult = 0;
1363
1364        /* Calculate CRC-8 out of the given address */
1365    macH = (pAddr[0] << 8) | (pAddr[1]);
1366    macL = (pAddr[2] << 24)| (pAddr[3] << 16) |
1367            (pAddr[4] << 8) | (pAddr[5] << 0);
1368
1369    for(i=0; i<32; i++)
1370        macArray[i] = (macL >> i) & 0x1;
1371
1372    for(i=32; i<48; i++)
1373        macArray[i] = (macH >> (i - 32)) & 0x1;
1374
1375    crc[0] = macArray[45] ^ macArray[43] ^ macArray[40] ^ macArray[39] ^
1376             macArray[35] ^ macArray[34] ^ macArray[31] ^ macArray[30] ^
1377             macArray[28] ^ macArray[23] ^ macArray[21] ^ macArray[19] ^
1378             macArray[18] ^ macArray[16] ^ macArray[14] ^ macArray[12] ^
1379             macArray[8] ^ macArray[7] ^ macArray[6] ^ macArray[0];
1380
1381    crc[1] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^
1382             macArray[41] ^ macArray[39] ^ macArray[36] ^ macArray[34] ^
1383             macArray[32] ^ macArray[30] ^ macArray[29] ^ macArray[28] ^
1384             macArray[24] ^ macArray[23] ^ macArray[22] ^ macArray[21] ^
1385             macArray[20] ^ macArray[18] ^ macArray[17] ^ macArray[16] ^
1386             macArray[15] ^ macArray[14] ^ macArray[13] ^ macArray[12] ^
1387             macArray[9] ^ macArray[6] ^ macArray[1] ^ macArray[0];
1388
1389    crc[2] = macArray[47] ^ macArray[46] ^ macArray[44] ^ macArray[43] ^
1390             macArray[42] ^ macArray[39] ^ macArray[37] ^ macArray[34] ^
1391             macArray[33] ^ macArray[29] ^ macArray[28] ^ macArray[25] ^
1392             macArray[24] ^ macArray[22] ^ macArray[17] ^ macArray[15] ^
1393             macArray[13] ^ macArray[12] ^ macArray[10] ^ macArray[8] ^
1394             macArray[6] ^ macArray[2] ^ macArray[1] ^ macArray[0];
1395
1396    crc[3] = macArray[47] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^
1397             macArray[40] ^ macArray[38] ^ macArray[35] ^ macArray[34] ^
1398             macArray[30] ^ macArray[29] ^ macArray[26] ^ macArray[25] ^
1399             macArray[23] ^ macArray[18] ^ macArray[16] ^ macArray[14] ^
1400             macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[7] ^
1401             macArray[3] ^ macArray[2] ^ macArray[1];
1402
1403    crc[4] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[41] ^
1404             macArray[39] ^ macArray[36] ^ macArray[35] ^ macArray[31] ^
1405             macArray[30] ^ macArray[27] ^ macArray[26] ^ macArray[24] ^
1406             macArray[19] ^ macArray[17] ^ macArray[15] ^ macArray[14] ^
1407             macArray[12] ^ macArray[10] ^ macArray[8] ^ macArray[4] ^
1408             macArray[3] ^ macArray[2];
1409
1410    crc[5] = macArray[47] ^ macArray[46] ^ macArray[45] ^ macArray[42] ^
1411             macArray[40] ^ macArray[37] ^ macArray[36] ^ macArray[32] ^
1412             macArray[31] ^ macArray[28] ^ macArray[27] ^ macArray[25] ^
1413             macArray[20] ^ macArray[18] ^ macArray[16] ^ macArray[15] ^
1414             macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[5] ^
1415             macArray[4] ^ macArray[3];
1416
1417    crc[6] = macArray[47] ^ macArray[46] ^ macArray[43] ^ macArray[41] ^
1418             macArray[38] ^ macArray[37] ^ macArray[33] ^ macArray[32] ^
1419             macArray[29] ^ macArray[28] ^ macArray[26] ^ macArray[21] ^
1420             macArray[19] ^ macArray[17] ^ macArray[16] ^ macArray[14] ^
1421             macArray[12] ^ macArray[10] ^ macArray[6] ^ macArray[5] ^
1422             macArray[4];
1423
1424    crc[7] = macArray[47] ^ macArray[44] ^ macArray[42] ^ macArray[39] ^
1425             macArray[38] ^ macArray[34] ^ macArray[33] ^ macArray[30] ^
1426             macArray[29] ^ macArray[27] ^ macArray[22] ^ macArray[20] ^
1427             macArray[18] ^ macArray[17] ^ macArray[15] ^ macArray[13] ^
1428             macArray[11] ^ macArray[7] ^ macArray[6] ^ macArray[5];
1429
1430    for(i=0; i<8; i++)
1431        crcResult = crcResult | (crc[i] << i);
1432
1433    return crcResult;
1434}
1435/*******************************************************************************
1436* mvEthMcastAddrSet - Multicast address settings.
1437*
1438* DESCRIPTION:
1439* This API controls the MV device MAC multicast support.
1440* The MV device supports multicast using two tables:
1441* 1) Special Multicast Table for MAC addresses of the form
1442* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF).
1443* The MAC DA[7:0] bits are used as a pointer to the Special Multicast
1444* Table entries in the DA-Filter table.
1445* In this case, the function calls ethPortSmcAddr() routine to set the
1446* Special Multicast Table.
1447* 2) Other Multicast Table for multicast of another type. A CRC-8bit
1448* is used as an index to the Other Multicast Table entries in the
1449* DA-Filter table.
1450* In this case, the function calculates the CRC-8bit value and calls
1451* ethPortOmcAddr() routine to set the Other Multicast Table.
1452*
1453* INPUT:
1454* void* pEthPortHndl - Ethernet port handler.
1455* MV_U8* pAddr - Address to be set
1456* int queue - RX queue to capture all packets with this
1457* Multicast MAC address.
1458* -1 means delete this Multicast address.
1459*
1460* RETURN: MV_STATUS
1461* MV_TRUE - Success, Other - Failure
1462*
1463*******************************************************************************/
1464MV_STATUS mvEthMcastAddrSet(void* pPortHndl, MV_U8 *pAddr, int queue)
1465{
1466    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
1467    unsigned char crcResult = 0;
1468
1469    if(queue >= MV_ETH_RX_Q_NUM)
1470    {
1471        mvOsPrintf("ethPort %d: RX queue #%d is out of range\n",
1472                    pPortCtrl->portNo, queue);
1473        return MV_BAD_PARAM;
1474    }
1475
1476    if((pAddr[0] == 0x01) &&
1477       (pAddr[1] == 0x00) &&
1478       (pAddr[2] == 0x5E) &&
1479       (pAddr[3] == 0x00) &&
1480       (pAddr[4] == 0x00))
1481    {
1482        ethSetSpecialMcastAddr(pPortCtrl->portNo, pAddr[5], queue);
1483    }
1484    else
1485    {
1486        crcResult = mvEthMcastCrc8Get(pAddr);
1487
1488        /* Check Add counter for this CRC value */
1489        if(queue == -1)
1490        {
1491            if(pPortCtrl->mcastCount[crcResult] == 0)
1492            {
1493                mvOsPrintf("ethPort #%d: No valid Mcast for crc8=0x%02x\n",
1494                            pPortCtrl->portNo, (unsigned)crcResult);
1495                return MV_NO_SUCH;
1496            }
1497
1498            pPortCtrl->mcastCount[crcResult]--;
1499            if(pPortCtrl->mcastCount[crcResult] != 0)
1500            {
1501                mvOsPrintf("ethPort #%d: After delete there are %d valid Mcast for crc8=0x%02x\n",
1502                            pPortCtrl->portNo, pPortCtrl->mcastCount[crcResult],
1503                            (unsigned)crcResult);
1504                return MV_NO_CHANGE;
1505            }
1506        }
1507        else
1508        {
1509            pPortCtrl->mcastCount[crcResult]++;
1510            if(pPortCtrl->mcastCount[crcResult] > 1)
1511            {
1512                mvOsPrintf("ethPort #%d: Valid Mcast for crc8=0x%02x already exists\n",
1513                                pPortCtrl->portNo, (unsigned)crcResult);
1514                return MV_NO_CHANGE;
1515            }
1516        }
1517        ethSetOtherMcastAddr(pPortCtrl->portNo, crcResult, queue);
1518    }
1519    return MV_OK;
1520}
1521
1522/*******************************************************************************
1523* ethSetUcastTable - Unicast address settings.
1524*
1525* DESCRIPTION:
1526* Set all entries in the Unicast MAC Table queue==-1 means reject all
1527* INPUT:
1528*
1529* RETURN:
1530*
1531*******************************************************************************/
1532static void ethSetUcastTable(int portNo, int queue)
1533{
1534    int offset;
1535    MV_U32 regValue;
1536
1537    if(queue == -1)
1538    {
1539        regValue = 0;
1540    }
1541    else
1542    {
1543        regValue = (((0x01 | (queue<<1)) << 0) |
1544                    ((0x01 | (queue<<1)) << 8) |
1545                    ((0x01 | (queue<<1)) << 16) |
1546                    ((0x01 | (queue<<1)) << 24));
1547    }
1548
1549    for (offset=0; offset<=0xC; offset+=4)
1550        MV_REG_WRITE((ETH_DA_FILTER_UCAST_BASE(portNo) + offset), regValue);
1551}
1552
1553/*******************************************************************************
1554* mvEthSetSpecialMcastTable - Special Multicast address settings.
1555*
1556* DESCRIPTION:
1557* Set all entries to the Special Multicast MAC Table. queue==-1 means reject all
1558* INPUT:
1559*
1560* RETURN:
1561*
1562*******************************************************************************/
1563MV_VOID mvEthSetSpecialMcastTable(int portNo, int queue)
1564{
1565    int offset;
1566    MV_U32 regValue;
1567
1568    if(queue == -1)
1569    {
1570        regValue = 0;
1571    }
1572    else
1573    {
1574        regValue = (((0x01 | (queue<<1)) << 0) |
1575                    ((0x01 | (queue<<1)) << 8) |
1576                    ((0x01 | (queue<<1)) << 16) |
1577                    ((0x01 | (queue<<1)) << 24));
1578    }
1579
1580    for (offset=0; offset<=0xFC; offset+=4)
1581    {
1582        MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(portNo) +
1583                      offset), regValue);
1584    }
1585}
1586
1587/*******************************************************************************
1588* mvEthSetOtherMcastTable - Other Multicast address settings.
1589*
1590* DESCRIPTION:
1591* Set all entries to the Other Multicast MAC Table. queue==-1 means reject all
1592* INPUT:
1593*
1594* RETURN:
1595*
1596*******************************************************************************/
1597MV_VOID mvEthSetOtherMcastTable(int portNo, int queue)
1598{
1599    int offset;
1600    MV_U32 regValue;
1601
1602    if(queue == -1)
1603    {
1604        regValue = 0;
1605    }
1606    else
1607    {
1608        regValue = (((0x01 | (queue<<1)) << 0) |
1609                    ((0x01 | (queue<<1)) << 8) |
1610                    ((0x01 | (queue<<1)) << 16) |
1611                    ((0x01 | (queue<<1)) << 24));
1612    }
1613
1614    for (offset=0; offset<=0xFC; offset+=4)
1615    {
1616        MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(portNo) +
1617                      offset), regValue);
1618    }
1619}
1620
1621/*******************************************************************************
1622* ethSetUcastAddr - This function Set the port unicast address table
1623*
1624* DESCRIPTION:
1625* This function locates the proper entry in the Unicast table for the
1626* specified MAC nibble and sets its properties according to function
1627* parameters.
1628*
1629* INPUT:
1630* int ethPortNum - Port number.
1631* MV_U8 lastNibble - Unicast MAC Address last nibble.
1632* int queue - Rx queue number for this MAC address.
1633* value "-1" means remove address
1634*
1635* OUTPUT:
1636* This function add/removes MAC addresses from the port unicast address
1637* table.
1638*
1639* RETURN:
1640* MV_TRUE is output succeeded.
1641* MV_FALSE if option parameter is invalid.
1642*
1643*******************************************************************************/
1644static MV_BOOL ethSetUcastAddr(int portNo, MV_U8 lastNibble, int queue)
1645{
1646    unsigned int unicastReg;
1647    unsigned int tblOffset;
1648    unsigned int regOffset;
1649
1650    /* Locate the Unicast table entry */
1651    lastNibble = (0xf & lastNibble);
1652    tblOffset = (lastNibble / 4) * 4; /* Register offset from unicast table base*/
1653    regOffset = lastNibble % 4; /* Entry offset within the above register */
1654
1655
1656    unicastReg = MV_REG_READ( (ETH_DA_FILTER_UCAST_BASE(portNo) +
1657                               tblOffset));
1658                 
1659
1660    if(queue == -1)
1661    {
1662        /* Clear accepts frame bit at specified unicast DA table entry */
1663        unicastReg &= ~(0xFF << (8*regOffset));
1664    }
1665    else
1666    {
1667        unicastReg &= ~(0xFF << (8*regOffset));
1668        unicastReg |= ((0x01 | (queue<<1)) << (8*regOffset));
1669    }
1670    MV_REG_WRITE( (ETH_DA_FILTER_UCAST_BASE(portNo) + tblOffset),
1671                  unicastReg);
1672
1673    return MV_TRUE;
1674}
1675
1676/*******************************************************************************
1677* ethSetSpecialMcastAddr - Special Multicast address settings.
1678*
1679* DESCRIPTION:
1680* This routine controls the MV device special MAC multicast support.
1681* The Special Multicast Table for MAC addresses supports MAC of the form
1682* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF).
1683* The MAC DA[7:0] bits are used as a pointer to the Special Multicast
1684* Table entries in the DA-Filter table.
1685* This function set the Special Multicast Table appropriate entry
1686* according to the argument given.
1687*
1688* INPUT:
1689* int ethPortNum Port number.
1690* unsigned char mcByte Multicast addr last byte (MAC DA[7:0] bits).
1691* int queue Rx queue number for this MAC address.
1692* int option 0 = Add, 1 = remove address.
1693*
1694* OUTPUT:
1695* See description.
1696*
1697* RETURN:
1698* MV_TRUE is output succeeded.
1699* MV_FALSE if option parameter is invalid.
1700*
1701*******************************************************************************/
1702static MV_BOOL ethSetSpecialMcastAddr(int ethPortNum, MV_U8 lastByte, int queue)
1703{
1704    unsigned int smcTableReg;
1705    unsigned int tblOffset;
1706    unsigned int regOffset;
1707
1708    /* Locate the SMC table entry */
1709    tblOffset = (lastByte / 4); /* Register offset from SMC table base */
1710    regOffset = lastByte % 4; /* Entry offset within the above register */
1711
1712    smcTableReg = MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum) + tblOffset*4));
1713    
1714    if(queue == -1)
1715    {
1716        /* Clear accepts frame bit at specified Special DA table entry */
1717        smcTableReg &= ~(0xFF << (8 * regOffset));
1718    }
1719    else
1720    {
1721        smcTableReg &= ~(0xFF << (8 * regOffset));
1722        smcTableReg |= ((0x01 | (queue<<1)) << (8 * regOffset));
1723    }
1724    MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum) +
1725                  tblOffset*4), smcTableReg);
1726
1727    return MV_TRUE;
1728}
1729
1730/*******************************************************************************
1731* ethSetOtherMcastAddr - Multicast address settings.
1732*
1733* DESCRIPTION:
1734* This routine controls the MV device Other MAC multicast support.
1735* The Other Multicast Table is used for multicast of another type.
1736* A CRC-8bit is used as an index to the Other Multicast Table entries
1737* in the DA-Filter table.
1738* The function gets the CRC-8bit value from the calling routine and
1739* set the Other Multicast Table appropriate entry according to the
1740* CRC-8 argument given.
1741*
1742* INPUT:
1743* int ethPortNum Port number.
1744* MV_U8 crc8 A CRC-8bit (Polynomial: x^8+x^2+x^1+1).
1745* int queue Rx queue number for this MAC address.
1746*
1747* OUTPUT:
1748* See description.
1749*
1750* RETURN:
1751* MV_TRUE is output succeeded.
1752* MV_FALSE if option parameter is invalid.
1753*
1754*******************************************************************************/
1755static MV_BOOL ethSetOtherMcastAddr(int ethPortNum, MV_U8 crc8, int queue)
1756{
1757    unsigned int omcTableReg;
1758    unsigned int tblOffset;
1759    unsigned int regOffset;
1760
1761    /* Locate the OMC table entry */
1762    tblOffset = (crc8 / 4) * 4; /* Register offset from OMC table base */
1763    regOffset = crc8 % 4; /* Entry offset within the above register */
1764
1765    omcTableReg = MV_REG_READ(
1766        (ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum) + tblOffset));
1767
1768    if(queue == -1)
1769    {
1770        /* Clear accepts frame bit at specified Other DA table entry */
1771        omcTableReg &= ~(0xFF << (8 * regOffset));
1772    }
1773    else
1774    {
1775        omcTableReg &= ~(0xFF << (8 * regOffset));
1776        omcTableReg |= ((0x01 | (queue<<1)) << (8 * regOffset));
1777    }
1778
1779    MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum) + tblOffset),
1780                    omcTableReg);
1781
1782    return MV_TRUE;
1783}
1784
1785
1786/******************************************************************************/
1787/* MIB Counters functions */
1788/******************************************************************************/
1789
1790
1791/*******************************************************************************
1792* mvEthMibCounterRead - Read a MIB counter
1793*
1794* DESCRIPTION:
1795* This function reads a MIB counter of a specific ethernet port.
1796* NOTE - Read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW or
1797* ETH_MIB_GOOD_OCTETS_SENT_LOW counters will return 64 bits value,
1798* so pHigh32 pointer should not be NULL in this case.
1799*
1800* INPUT:
1801* int ethPortNum - Ethernet Port number.
1802* unsigned int mibOffset - MIB counter offset.
1803*
1804* OUTPUT:
1805* MV_U32* pHigh32 - pointer to place where 32 most significant bits
1806* of the counter will be stored.
1807*
1808* RETURN:
1809* 32 low sgnificant bits of MIB counter value.
1810*
1811*******************************************************************************/
1812MV_U32 mvEthMibCounterRead(void* pPortHandle, unsigned int mibOffset,
1813                            MV_U32* pHigh32)
1814{
1815    int portNo;
1816    MV_U32 valLow32, valHigh32;
1817    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
1818
1819    portNo = pPortCtrl->portNo;
1820
1821    valLow32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo) + mibOffset);
1822    
1823    /* Implement FEr ETH. Erroneous Value when Reading the Upper 32-bits */
1824    /* of a 64-bit MIB Counter. */
1825    if( (mibOffset == ETH_MIB_GOOD_OCTETS_RECEIVED_LOW) ||
1826        (mibOffset == ETH_MIB_GOOD_OCTETS_SENT_LOW) )
1827    {
1828        valHigh32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo) + mibOffset + 4);
1829        if(pHigh32 != NULL)
1830            *pHigh32 = valHigh32;
1831    }
1832    return valLow32;
1833}
1834
1835/*******************************************************************************
1836* mvEthMibCountersClear - Clear all MIB counters
1837*
1838* DESCRIPTION:
1839* This function clears all MIB counters
1840*
1841* INPUT:
1842* int ethPortNum - Ethernet Port number.
1843*
1844*
1845* RETURN: void
1846*
1847*******************************************************************************/
1848void mvEthMibCountersClear(void* pPortHandle)
1849{
1850    int i, portNo;
1851    unsigned int dummy;
1852    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
1853
1854    portNo = pPortCtrl->portNo;
1855
1856    /* Perform dummy reads from MIB counters */
1857    for(i=ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i<ETH_MIB_LATE_COLLISION; i+=4)
1858        dummy = MV_REG_READ((ETH_MIB_COUNTERS_BASE(portNo) + i));
1859}
1860    
1861
1862/******************************************************************************/
1863/* RX Dispatching configuration routines */
1864/******************************************************************************/
1865
1866int mvEthTosToRxqGet(void* pPortHandle, int tos)
1867{
1868    MV_U32 regValue;
1869    int regIdx, regOffs, rxq;
1870    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
1871
1872    if(tos > 0xFF)
1873    {
1874        mvOsPrintf("eth_%d: tos=0x%x is out of range\n", pPortCtrl->portNo, tos);
1875        return -1;
1876    }
1877    regIdx = mvOsDivide(tos>>2, 10);
1878    regOffs = mvOsReminder(tos>>2, 10);
1879    
1880    regValue = MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(pPortCtrl->portNo, regIdx) );
1881    rxq = (regValue >> (regOffs*3));
1882    rxq &= 0x7;
1883
1884    return rxq;
1885}
1886
1887/*******************************************************************************
1888* mvEthTosToRxqSet - Map packets with special TOS value to special RX queue
1889*
1890* DESCRIPTION:
1891*
1892* INPUT:
1893* void* pPortHandle - Pointer to port specific handler;
1894* int tos - TOS value in the IP header of the packet
1895* int rxq - RX Queue for packets with the configured TOS value
1896* Negative value (-1) means no special processing for these packets,
1897* so they will be processed as regular packets.
1898*
1899* RETURN: MV_STATUS
1900*******************************************************************************/
1901MV_STATUS mvEthTosToRxqSet(void* pPortHandle, int tos, int rxq)
1902{
1903    MV_U32 regValue;
1904    int regIdx, regOffs;
1905    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
1906
1907    if( (rxq < 0) || (rxq >= MV_ETH_RX_Q_NUM) )
1908    {
1909        mvOsPrintf("eth_%d: RX queue #%d is out of range\n", pPortCtrl->portNo, rxq);
1910        return MV_BAD_PARAM;
1911    }
1912    if(tos > 0xFF)
1913    {
1914        mvOsPrintf("eth_%d: tos=0x%x is out of range\n", pPortCtrl->portNo, tos);
1915        return MV_BAD_PARAM;
1916    }
1917    regIdx = mvOsDivide(tos>>2, 10);
1918    regOffs = mvOsReminder(tos>>2, 10);
1919    
1920    regValue = MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(pPortCtrl->portNo, regIdx) );
1921    regValue &= ~(0x7 << (regOffs*3));
1922    regValue |= (rxq << (regOffs*3));
1923
1924    MV_REG_WRITE(ETH_DIFF_SERV_PRIO_REG(pPortCtrl->portNo, regIdx), regValue);
1925    return MV_OK;
1926}
1927
1928/*******************************************************************************
1929* mvEthVlanPrioRxQueue - Configure RX queue to capture VLAN tagged packets with
1930* special priority bits [0-2]
1931*
1932* DESCRIPTION:
1933*
1934* INPUT:
1935* void* pPortHandle - Pointer to port specific handler;
1936* int bpduQueue - Special queue to capture VLAN tagged packets with special
1937* priority.
1938* Negative value (-1) means no special processing for these packets,
1939* so they will be processed as regular packets.
1940*
1941* RETURN: MV_STATUS
1942* MV_OK - Success
1943* MV_FAIL - Failed.
1944*
1945*******************************************************************************/
1946MV_STATUS mvEthVlanPrioRxQueue(void* pPortHandle, int vlanPrio, int vlanPrioQueue)
1947{
1948    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
1949    MV_U32 vlanPrioReg;
1950
1951    if(vlanPrioQueue >= MV_ETH_RX_Q_NUM)
1952    {
1953        mvOsPrintf("ethDrv: RX queue #%d is out of range\n", vlanPrioQueue);
1954        return MV_BAD_PARAM;
1955    }
1956    if(vlanPrio >= 8)
1957    {
1958        mvOsPrintf("ethDrv: vlanPrio=%d is out of range\n", vlanPrio);
1959        return MV_BAD_PARAM;
1960    }
1961  
1962    vlanPrioReg = MV_REG_READ(ETH_VLAN_TAG_TO_PRIO_REG(pPortCtrl->portNo));
1963    vlanPrioReg &= ~(0x7 << (vlanPrio*3));
1964    vlanPrioReg |= (vlanPrioQueue << (vlanPrio*3));
1965    MV_REG_WRITE(ETH_VLAN_TAG_TO_PRIO_REG(pPortCtrl->portNo), vlanPrioReg);
1966
1967    return MV_OK;
1968}
1969
1970
1971/*******************************************************************************
1972* mvEthBpduRxQueue - Configure RX queue to capture BPDU packets.
1973*
1974* DESCRIPTION:
1975* This function defines processing of BPDU packets.
1976* BPDU packets can be accepted and captured to one of RX queues
1977* or can be processing as regular Multicast packets.
1978*
1979* INPUT:
1980* void* pPortHandle - Pointer to port specific handler;
1981* int bpduQueue - Special queue to capture BPDU packets (DA is equal to
1982* 01-80-C2-00-00-00 through 01-80-C2-00-00-FF,
1983* except for the Flow-Control Pause packets).
1984* Negative value (-1) means no special processing for BPDU,
1985* packets so they will be processed as regular Multicast packets.
1986*
1987* RETURN: MV_STATUS
1988* MV_OK - Success
1989* MV_FAIL - Failed.
1990*
1991*******************************************************************************/
1992MV_STATUS mvEthBpduRxQueue(void* pPortHandle, int bpduQueue)
1993{
1994    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
1995    MV_U32 portCfgReg;
1996    MV_U32 portCfgExtReg;
1997
1998    if(bpduQueue >= MV_ETH_RX_Q_NUM)
1999    {
2000        mvOsPrintf("ethDrv: RX queue #%d is out of range\n", bpduQueue);
2001        return MV_BAD_PARAM;
2002    }
2003  
2004    portCfgExtReg = MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl->portNo));
2005
2006    portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
2007    if(bpduQueue >= 0)
2008    {
2009        pPortCtrl->portConfig.rxBpduQ = bpduQueue;
2010
2011        portCfgReg &= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK;
2012        portCfgReg |= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl->portConfig.rxBpduQ);
2013
2014        MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
2015
2016        portCfgExtReg |= ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK;
2017    }
2018    else
2019    {
2020        pPortCtrl->portConfig.rxBpduQ = -1;
2021        /* no special processing for BPDU packets */
2022        portCfgExtReg &= (~ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK);
2023    }
2024
2025    MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl->portNo), portCfgExtReg);
2026
2027    return MV_OK;
2028}
2029
2030
2031/*******************************************************************************
2032* mvEthArpRxQueue - Configure RX queue to capture ARP packets.
2033*
2034* DESCRIPTION:
2035* This function defines processing of ARP (type=0x0806) packets.
2036* ARP packets can be accepted and captured to one of RX queues
2037* or can be processed as other Broadcast packets.
2038*
2039* INPUT:
2040* void* pPortHandle - Pointer to port specific handler;
2041* int arpQueue - Special queue to capture ARP packets (type=0x806).
2042* Negative value (-1) means discard ARP packets
2043*
2044* RETURN: MV_STATUS
2045* MV_OK - Success
2046* MV_FAIL - Failed.
2047*
2048*******************************************************************************/
2049MV_STATUS mvEthArpRxQueue(void* pPortHandle, int arpQueue)
2050{
2051    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2052    MV_U32 portCfgReg;
2053
2054    if(arpQueue >= MV_ETH_RX_Q_NUM)
2055    {
2056        mvOsPrintf("ethDrv: RX queue #%d is out of range\n", arpQueue);
2057        return MV_BAD_PARAM;
2058    }
2059
2060    portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
2061
2062    if(arpQueue >= 0)
2063    {
2064        pPortCtrl->portConfig.rxArpQ = arpQueue;
2065        portCfgReg &= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK;
2066        portCfgReg |= ETH_DEF_RX_ARP_QUEUE_MASK(pPortCtrl->portConfig.rxArpQ);
2067
2068        portCfgReg &= (~ETH_REJECT_ARP_BCAST_MASK);
2069    }
2070    else
2071    {
2072        pPortCtrl->portConfig.rxArpQ = -1;
2073        portCfgReg |= ETH_REJECT_ARP_BCAST_MASK;
2074    }
2075
2076    MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
2077
2078    return MV_OK;
2079}
2080
2081
2082/*******************************************************************************
2083* mvEthTcpRxQueue - Configure RX queue to capture TCP packets.
2084*
2085* DESCRIPTION:
2086* This function defines processing of TCP packets.
2087* TCP packets can be accepted and captured to one of RX queues
2088* or can be processed as regular Unicast packets.
2089*
2090* INPUT:
2091* void* pPortHandle - Pointer to port specific handler;
2092* int tcpQueue - Special queue to capture TCP packets. Value "-1"
2093* means no special processing for TCP packets,
2094* so they will be processed as regular
2095*
2096* RETURN: MV_STATUS
2097* MV_OK - Success
2098* MV_FAIL - Failed.
2099*
2100*******************************************************************************/
2101MV_STATUS mvEthTcpRxQueue(void* pPortHandle, int tcpQueue)
2102{
2103    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2104    MV_U32 portCfgReg;
2105
2106    if(tcpQueue >= MV_ETH_RX_Q_NUM)
2107    {
2108        mvOsPrintf("ethDrv: RX queue #%d is out of range\n", tcpQueue);
2109        return MV_BAD_PARAM;
2110    }
2111    portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
2112
2113    if(tcpQueue >= 0)
2114    {
2115        pPortCtrl->portConfig.rxTcpQ = tcpQueue;
2116        portCfgReg &= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK;
2117        portCfgReg |= ETH_DEF_RX_TCP_QUEUE_MASK(pPortCtrl->portConfig.rxTcpQ);
2118
2119        portCfgReg |= ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK;
2120    }
2121    else
2122    {
2123        pPortCtrl->portConfig.rxTcpQ = -1;
2124        portCfgReg &= (~ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK);
2125    }
2126
2127    MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
2128
2129    return MV_OK;
2130}
2131
2132
2133/*******************************************************************************
2134* mvEthUdpRxQueue - Configure RX queue to capture UDP packets.
2135*
2136* DESCRIPTION:
2137* This function defines processing of UDP packets.
2138* TCP packets can be accepted and captured to one of RX queues
2139* or can be processed as regular Unicast packets.
2140*
2141* INPUT:
2142* void* pPortHandle - Pointer to port specific handler;
2143* int udpQueue - Special queue to capture UDP packets. Value "-1"
2144* means no special processing for UDP packets,
2145* so they will be processed as regular
2146*
2147* RETURN: MV_STATUS
2148* MV_OK - Success
2149* MV_FAIL - Failed.
2150*
2151*******************************************************************************/
2152MV_STATUS mvEthUdpRxQueue(void* pPortHandle, int udpQueue)
2153{
2154    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2155    MV_U32 portCfgReg;
2156
2157    if(udpQueue >= MV_ETH_RX_Q_NUM)
2158    {
2159        mvOsPrintf("ethDrv: RX queue #%d is out of range\n", udpQueue);
2160        return MV_BAD_PARAM;
2161    }
2162
2163    portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
2164
2165    if(udpQueue >= 0)
2166    {
2167        pPortCtrl->portConfig.rxUdpQ = udpQueue;
2168        portCfgReg &= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK;
2169        portCfgReg |= ETH_DEF_RX_UDP_QUEUE_MASK(pPortCtrl->portConfig.rxUdpQ);
2170
2171        portCfgReg |= ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK;
2172    }
2173    else
2174    {
2175        pPortCtrl->portConfig.rxUdpQ = -1;
2176        portCfgReg &= ~ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK;
2177    }
2178
2179    MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
2180
2181    return MV_OK;
2182}
2183
2184
2185/******************************************************************************/
2186/* Speed, Duplex, FlowControl routines */
2187/******************************************************************************/
2188
2189/*******************************************************************************
2190* mvEthSpeedDuplexSet - Set Speed and Duplex of the port.
2191*
2192* DESCRIPTION:
2193* This function configure the port to work with desirable Duplex and Speed.
2194* Changing of these parameters are allowed only when port is disabled.
2195* This function disable the port if was enabled, change duplex and speed
2196* and, enable the port back if needed.
2197*
2198* INPUT:
2199* void* pPortHandle - Pointer to port specific handler;
2200* ETH_PORT_SPEED speed - Speed of the port.
2201* ETH_PORT_SPEED duplex - Duplex of the port.
2202*
2203* RETURN: MV_STATUS
2204* MV_OK - Success
2205* MV_OUT_OF_RANGE - Failed. Port is out of valid range
2206* MV_NOT_FOUND - Failed. Port is not initialized.
2207* MV_BAD_PARAM - Input parameters (speed/duplex) in conflict.
2208* MV_BAD_VALUE - Value of one of input parameters (speed, duplex)
2209* is not valid
2210*
2211*******************************************************************************/
2212MV_STATUS mvEthSpeedDuplexSet(void* pPortHandle, MV_ETH_PORT_SPEED speed,
2213                                MV_ETH_PORT_DUPLEX duplex)
2214{
2215    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2216    int port = pPortCtrl->portNo;
2217    MV_U32 portSerialCtrlReg;
2218    
2219    if( (port < 0) || (port >= (int)mvCtrlEthMaxPortGet()) )
2220        return MV_OUT_OF_RANGE;
2221
2222    pPortCtrl = ethPortCtrl[port];
2223    if(pPortCtrl == NULL)
2224        return MV_NOT_FOUND;
2225
2226    /* Check validity */
2227    if( (speed == MV_ETH_SPEED_1000) && (duplex == MV_ETH_DUPLEX_HALF) )
2228        return MV_BAD_PARAM;
2229
2230    portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port));
2231    /* Set Speed */
2232    switch(speed)
2233    {
2234        case MV_ETH_SPEED_AN:
2235            portSerialCtrlReg &= ~ETH_DISABLE_SPEED_AUTO_NEG_MASK;
2236            break;
2237
2238        case MV_ETH_SPEED_10:
2239            portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK;
2240            portSerialCtrlReg &= ~ETH_SET_GMII_SPEED_1000_MASK;
2241            portSerialCtrlReg &= ~ETH_SET_MII_SPEED_100_MASK;
2242            break;
2243
2244        case MV_ETH_SPEED_100:
2245            portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK;
2246            portSerialCtrlReg &= ~ETH_SET_GMII_SPEED_1000_MASK;
2247            portSerialCtrlReg |= ETH_SET_MII_SPEED_100_MASK;
2248            break;
2249
2250        case MV_ETH_SPEED_1000:
2251            portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK;
2252            portSerialCtrlReg |= ETH_SET_GMII_SPEED_1000_MASK;
2253            break;
2254
2255        default:
2256            mvOsPrintf("ethDrv: Unexpected Speed value %d\n", speed);
2257            return MV_BAD_VALUE;
2258    }
2259    /* Set duplex */
2260    switch(duplex)
2261    {
2262        case MV_ETH_DUPLEX_AN:
2263            portSerialCtrlReg &= ~ETH_DISABLE_DUPLEX_AUTO_NEG_MASK;
2264            break;
2265
2266        case MV_ETH_DUPLEX_HALF:
2267            portSerialCtrlReg |= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK;
2268            portSerialCtrlReg &= ~ETH_SET_FULL_DUPLEX_MASK;
2269            break;
2270
2271        case MV_ETH_DUPLEX_FULL:
2272            portSerialCtrlReg |= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK;
2273            portSerialCtrlReg |= ETH_SET_FULL_DUPLEX_MASK;
2274            break;
2275
2276        default:
2277            mvOsPrintf("ethDrv: Unexpected Duplex value %d\n", duplex);
2278            return MV_BAD_VALUE;
2279    }
2280    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), portSerialCtrlReg);
2281
2282    return MV_OK;
2283}
2284
2285/*******************************************************************************
2286* mvEthFlowCtrlSet - Set Flow Control of the port.
2287*
2288* DESCRIPTION:
2289* This function configure the port to work with desirable Duplex and
2290* Speed. Changing of these parameters are allowed only when port is
2291* disabled. This function disable the port if was enabled, change
2292* duplex and speed and, enable the port back if needed.
2293*
2294* INPUT:
2295* void* pPortHandle - Pointer to port specific handler;
2296* MV_ETH_PORT_FC flowControl - Flow control of the port.
2297*
2298* RETURN: MV_STATUS
2299* MV_OK - Success
2300* MV_OUT_OF_RANGE - Failed. Port is out of valid range
2301* MV_NOT_FOUND - Failed. Port is not initialized.
2302* MV_BAD_VALUE - Value flowControl parameters is not valid
2303*
2304*******************************************************************************/
2305MV_STATUS mvEthFlowCtrlSet(void* pPortHandle, MV_ETH_PORT_FC flowControl)
2306{
2307    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2308    int port = pPortCtrl->portNo;
2309    MV_U32 portSerialCtrlReg;
2310    
2311    if( (port < 0) || (port >= (int)mvCtrlEthMaxPortGet() ) )
2312        return MV_OUT_OF_RANGE;
2313
2314    pPortCtrl = ethPortCtrl[port];
2315    if(pPortCtrl == NULL)
2316        return MV_NOT_FOUND;
2317
2318    portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port));
2319    switch(flowControl)
2320    {
2321        case MV_ETH_FC_AN_ADV_DIS:
2322            portSerialCtrlReg &= ~ETH_DISABLE_FC_AUTO_NEG_MASK;
2323            portSerialCtrlReg &= ~ETH_ADVERTISE_SYM_FC_MASK;
2324            break;
2325
2326        case MV_ETH_FC_AN_ADV_SYM:
2327            portSerialCtrlReg &= ~ETH_DISABLE_FC_AUTO_NEG_MASK;
2328            portSerialCtrlReg |= ETH_ADVERTISE_SYM_FC_MASK;
2329            break;
2330
2331        case MV_ETH_FC_DISABLE:
2332            portSerialCtrlReg |= ETH_DISABLE_FC_AUTO_NEG_MASK;
2333            portSerialCtrlReg &= ~ETH_SET_FLOW_CTRL_MASK;
2334            break;
2335
2336        case MV_ETH_FC_ENABLE:
2337            portSerialCtrlReg |= ETH_DISABLE_FC_AUTO_NEG_MASK;
2338            portSerialCtrlReg |= ETH_SET_FLOW_CTRL_MASK;
2339            break;
2340
2341        default:
2342            mvOsPrintf("ethDrv: Unexpected FlowControl value %d\n", flowControl);
2343            return MV_BAD_VALUE;
2344    }
2345    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), portSerialCtrlReg);
2346
2347    return MV_OK;
2348}
2349
2350/*******************************************************************************
2351* mvEthHeaderModeSet - Set port header mode.
2352*
2353* DESCRIPTION:
2354* This function configures the port to work in Marvell-Header mode.
2355*
2356* INPUT:
2357* void* pPortHandle - Pointer to port specific handler;
2358* MV_ETH_HEADER_MODE headerMode - The header mode to set the port in.
2359*
2360* RETURN: MV_STATUS
2361* MV_OK - Success
2362* MV_NOT_SUPPORTED- Feature not supported.
2363* MV_OUT_OF_RANGE - Failed. Port is out of valid range
2364* MV_NOT_FOUND - Failed. Port is not initialized.
2365* MV_BAD_VALUE - Value of headerMode or numRxQueue parameter is not valid.
2366*
2367*******************************************************************************/
2368MV_STATUS mvEthHeaderModeSet(void* pPortHandle, MV_ETH_HEADER_MODE headerMode)
2369{
2370    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2371    int port = pPortCtrl->portNo;
2372    MV_U32 mvHeaderReg;
2373    MV_U32 numRxQ = MV_ETH_RX_Q_NUM;
2374    
2375    if((port < 0) || (port >= mvCtrlEthMaxPortGet()))
2376        return MV_OUT_OF_RANGE;
2377
2378    pPortCtrl = ethPortCtrl[port];
2379    if(pPortCtrl == NULL)
2380        return MV_NOT_FOUND;
2381
2382    mvHeaderReg = MV_REG_READ(ETH_PORT_MARVELL_HEADER_REG(port));
2383    /* Disable header mode. */
2384    mvHeaderReg &= ~ETH_MVHDR_EN_MASK;
2385
2386    if(headerMode != MV_ETH_DISABLE_HEADER_MODE)
2387    {
2388        /* Enable Header mode. */
2389        mvHeaderReg |= ETH_MVHDR_EN_MASK;
2390
2391        /* Clear DA-Prefix & MHMask fields.*/
2392        mvHeaderReg &= ~(ETH_MVHDR_DAPREFIX_MASK | ETH_MVHDR_MHMASK_MASK);
2393
2394        if(numRxQ > 1)
2395        {
2396            switch (headerMode)
2397            {
2398                case(MV_ETH_ENABLE_HEADER_MODE_PRI_2_1):
2399                    mvHeaderReg |= ETH_MVHDR_DAPREFIX_PRI_1_2;
2400                    break;
2401                case(MV_ETH_ENABLE_HEADER_MODE_PRI_DBNUM):
2402                    mvHeaderReg |= ETH_MVHDR_DAPREFIX_DBNUM_PRI;
2403                    break;
2404                case(MV_ETH_ENABLE_HEADER_MODE_PRI_SPID):
2405                    mvHeaderReg |= ETH_MVHDR_DAPREFIX_SPID_PRI;
2406                    break;
2407                default:
2408                    break;
2409            }
2410
2411            switch (numRxQ)
2412            {
2413                case (4):
2414                    mvHeaderReg |= ETH_MVHDR_MHMASK_4_QUEUE;
2415                    break;
2416                case (8):
2417                    mvHeaderReg |= ETH_MVHDR_MHMASK_8_QUEUE;
2418                    break;
2419                default:
2420                    break;
2421            }
2422        }
2423    }
2424
2425    MV_REG_WRITE(ETH_PORT_MARVELL_HEADER_REG(port), mvHeaderReg);
2426
2427    return MV_OK;
2428}
2429
2430#if (MV_ETH_VERSION >= 4)
2431/*******************************************************************************
2432* mvEthEjpModeSet - Enable / Disable EJP policy for TX.
2433*
2434* DESCRIPTION:
2435* This function
2436*
2437* INPUT:
2438* void* pPortHandle - Pointer to port specific handler;
2439* MV_BOOL TRUE - enable EJP mode
2440* FALSE - disable EJP mode
2441*
2442* OUTPUT: MV_STATUS
2443* MV_OK - Success
2444* Other - Failure
2445*
2446* RETURN: None.
2447*
2448*******************************************************************************/
2449MV_STATUS mvEthEjpModeSet(void* pPortHandle, int mode)
2450{
2451    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2452    int port = pPortCtrl->portNo;
2453    
2454    if((port < 0) || (port >= mvCtrlEthMaxPortGet()))
2455        return MV_OUT_OF_RANGE;
2456
2457    pPortCtrl = ethPortCtrl[port];
2458    if(pPortCtrl == NULL)
2459        return MV_NOT_FOUND;
2460    
2461    pPortCtrl->portConfig.ejpMode = mode;
2462    if(mode)
2463    {
2464        /* EJP enabled */
2465        MV_REG_WRITE(ETH_TXQ_CMD_1_REG(port), ETH_TX_EJP_ENABLE_MASK);
2466    }
2467    else
2468    {
2469        /* EJP disabled */
2470        MV_REG_WRITE(ETH_TXQ_CMD_1_REG(port), 0);
2471    }
2472    mvOsPrintf("eth_%d: EJP %s - ETH_TXQ_CMD_1_REG: 0x%x = 0x%08x\n",
2473        port, mode ? "Enabled" : "Disabled", ETH_TXQ_CMD_1_REG(port),
2474                    MV_REG_READ(ETH_TXQ_CMD_1_REG(port)));
2475
2476    return MV_OK;
2477}
2478#endif /* MV_ETH_VERSION >= 4 */
2479
2480/*******************************************************************************
2481* mvEthStatusGet - Get major properties of the port .
2482*
2483* DESCRIPTION:
2484* This function get major properties of the port (link, speed, duplex,
2485* flowControl, etc) and return them using the single structure.
2486*
2487* INPUT:
2488* void* pPortHandle - Pointer to port specific handler;
2489*
2490* OUTPUT:
2491* MV_ETH_PORT_STATUS* pStatus - Pointer to structure, were port status
2492* will be placed.
2493*
2494* RETURN: None.
2495*
2496*******************************************************************************/
2497void mvEthStatusGet(void* pPortHandle, MV_ETH_PORT_STATUS* pStatus)
2498{
2499    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2500    int port = pPortCtrl->portNo;
2501
2502    MV_U32 regValue;
2503
2504    regValue = MV_REG_READ( ETH_PORT_STATUS_REG(port) );
2505
2506    if(regValue & ETH_GMII_SPEED_1000_MASK)
2507        pStatus->speed = MV_ETH_SPEED_1000;
2508    else if(regValue & ETH_MII_SPEED_100_MASK)
2509        pStatus->speed = MV_ETH_SPEED_100;
2510    else
2511        pStatus->speed = MV_ETH_SPEED_10;
2512
2513    if(regValue & ETH_LINK_UP_MASK)
2514        pStatus->isLinkUp = MV_TRUE;
2515    else
2516        pStatus->isLinkUp = MV_FALSE;
2517
2518    if(regValue & ETH_FULL_DUPLEX_MASK)
2519        pStatus->duplex = MV_ETH_DUPLEX_FULL;
2520    else
2521        pStatus->duplex = MV_ETH_DUPLEX_HALF;
2522
2523
2524    if(regValue & ETH_ENABLE_RCV_FLOW_CTRL_MASK)
2525        pStatus->flowControl = MV_ETH_FC_ENABLE;
2526    else
2527        pStatus->flowControl = MV_ETH_FC_DISABLE;
2528}
2529
2530
2531/******************************************************************************/
2532/* PHY Control Functions */
2533/******************************************************************************/
2534
2535
2536/*******************************************************************************
2537* mvEthPhyAddrSet - Set the ethernet port PHY address.
2538*
2539* DESCRIPTION:
2540* This routine set the ethernet port PHY address according to given
2541* parameter.
2542*
2543* INPUT:
2544* void* pPortHandle - Pointer to port specific handler;
2545* int phyAddr - PHY address
2546*
2547* RETURN:
2548* None.
2549*
2550*******************************************************************************/
2551void mvEthPhyAddrSet(void* pPortHandle, int phyAddr)
2552{
2553    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2554    int port = pPortCtrl->portNo;
2555    unsigned int regData;
2556
2557    regData = MV_REG_READ(ETH_PHY_ADDR_REG(port));
2558
2559    regData &= ~ETH_PHY_ADDR_MASK;
2560    regData |= phyAddr;
2561
2562    MV_REG_WRITE(ETH_PHY_ADDR_REG(port), regData);
2563
2564    return;
2565}
2566
2567/*******************************************************************************
2568* mvEthPhyAddrGet - Get the ethernet port PHY address.
2569*
2570* DESCRIPTION:
2571* This routine returns the given ethernet port PHY address.
2572*
2573* INPUT:
2574* void* pPortHandle - Pointer to port specific handler;
2575*
2576*
2577* RETURN: int - PHY address.
2578*
2579*******************************************************************************/
2580int mvEthPhyAddrGet(void* pPortHandle)
2581{
2582    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
2583    int port = pPortCtrl->portNo;
2584    unsigned int regData;
2585
2586    regData = MV_REG_READ(ETH_PHY_ADDR_REG(port));
2587
2588    return ((regData >> (5 * port)) & 0x1f);
2589}
2590
2591/******************************************************************************/
2592/* Descriptor handling Functions */
2593/******************************************************************************/
2594
2595/*******************************************************************************
2596* etherInitRxDescRing - Curve a Rx chain desc list and buffer in memory.
2597*
2598* DESCRIPTION:
2599* This function prepares a Rx chained list of descriptors and packet
2600* buffers in a form of a ring. The routine must be called after port
2601* initialization routine and before port start routine.
2602* The Ethernet SDMA engine uses CPU bus addresses to access the various
2603* devices in the system (i.e. DRAM). This function uses the ethernet
2604* struct 'virtual to physical' routine (set by the user) to set the ring
2605* with physical addresses.
2606*
2607* INPUT:
2608* ETH_QUEUE_CTRL *pEthPortCtrl Ethernet Port Control srtuct.
2609* int rxQueue Number of Rx queue.
2610* int rxDescNum Number of Rx descriptors
2611* MV_U8* rxDescBaseAddr Rx descriptors memory area base addr.
2612*
2613* OUTPUT:
2614* The routine updates the Ethernet port control struct with information
2615* regarding the Rx descriptors and buffers.
2616*
2617* RETURN: None
2618*
2619*******************************************************************************/
2620static void ethInitRxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue)
2621{
2622    ETH_RX_DESC *pRxDescBase, *pRxDesc, *pRxPrevDesc;
2623    int ix, rxDescNum = pPortCtrl->rxQueueConfig[queue].descrNum;
2624    ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->rxQueue[queue];
2625
2626    /* Make sure descriptor address is cache line size aligned */
2627    pRxDescBase = (ETH_RX_DESC*)MV_ALIGN_UP((MV_ULONG)pQueueCtrl->descBuf.bufVirtPtr,
2628                                     CPU_D_CACHE_LINE_SIZE);
2629
2630    pRxDesc = (ETH_RX_DESC*)pRxDescBase;
2631    pRxPrevDesc = pRxDesc;
2632
2633    /* initialize the Rx descriptors ring */
2634    for (ix=0; ix<rxDescNum; ix++)
2635    {
2636        pRxDesc->bufSize = 0x0;
2637        pRxDesc->byteCnt = 0x0;
2638        pRxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST;
2639        pRxDesc->bufPtr = 0x0;
2640        pRxDesc->returnInfo = 0x0;
2641        pRxPrevDesc = pRxDesc;
2642        if(ix == (rxDescNum-1))
2643        {
2644            /* Closing Rx descriptors ring */
2645            pRxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pRxDescBase);
2646        }
2647        else
2648        {
2649            pRxDesc = (ETH_RX_DESC*)((MV_ULONG)pRxDesc + ETH_RX_DESC_ALIGNED_SIZE);
2650            pRxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pRxDesc);
2651        }
2652        ETH_DESCR_FLUSH_INV(pPortCtrl, pRxPrevDesc);
2653    }
2654
2655    pQueueCtrl->pCurrentDescr = pRxDescBase;
2656    pQueueCtrl->pUsedDescr = pRxDescBase;
2657    
2658    pQueueCtrl->pFirstDescr = pRxDescBase;
2659    pQueueCtrl->pLastDescr = pRxDesc;
2660    pQueueCtrl->resource = 0;
2661}
2662
2663void ethResetRxDescRing(void* pPortHndl, int queue)
2664{
2665    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
2666    ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->rxQueue[queue];
2667    ETH_RX_DESC* pRxDesc = (ETH_RX_DESC*)pQueueCtrl->pFirstDescr;
2668
2669    pQueueCtrl->resource = 0;
2670    if(pQueueCtrl->pFirstDescr != NULL)
2671    {
2672        while(MV_TRUE)
2673        {
2674            pRxDesc->bufSize = 0x0;
2675            pRxDesc->byteCnt = 0x0;
2676            pRxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST;
2677            pRxDesc->bufPtr = 0x0;
2678            pRxDesc->returnInfo = 0x0;
2679            ETH_DESCR_FLUSH_INV(pPortCtrl, pRxDesc);
2680            if( (void*)pRxDesc == pQueueCtrl->pLastDescr)
2681                    break;
2682            pRxDesc = RX_NEXT_DESC_PTR(pRxDesc, pQueueCtrl);
2683        }
2684        pQueueCtrl->pCurrentDescr = pQueueCtrl->pFirstDescr;
2685        pQueueCtrl->pUsedDescr = pQueueCtrl->pFirstDescr;
2686
2687        /* Update RX Command register */
2688        pPortCtrl->portRxQueueCmdReg |= (1 << queue);
2689
2690        /* update HW */
2691        MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue),
2692                 (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) );
2693    }
2694    else
2695    {
2696        /* Update RX Command register */
2697        pPortCtrl->portRxQueueCmdReg &= ~(1 << queue);
2698
2699        /* update HW */
2700        MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), 0);
2701    }
2702}
2703
2704/*******************************************************************************
2705* etherInitTxDescRing - Curve a Tx chain desc list and buffer in memory.
2706*
2707* DESCRIPTION:
2708* This function prepares a Tx chained list of descriptors and packet
2709* buffers in a form of a ring. The routine must be called after port
2710* initialization routine and before port start routine.
2711* The Ethernet SDMA engine uses CPU bus addresses to access the various
2712* devices in the system (i.e. DRAM). This function uses the ethernet
2713* struct 'virtual to physical' routine (set by the user) to set the ring
2714* with physical addresses.
2715*
2716* INPUT:
2717* ETH_PORT_CTRL *pEthPortCtrl Ethernet Port Control srtuct.
2718* int txQueue Number of Tx queue.
2719* int txDescNum Number of Tx descriptors
2720* int txBuffSize Size of Tx buffer
2721* MV_U8* pTxDescBase Tx descriptors memory area base addr.
2722*
2723* OUTPUT:
2724* The routine updates the Ethernet port control struct with information
2725* regarding the Tx descriptors and buffers.
2726*
2727* RETURN: None.
2728*
2729*******************************************************************************/
2730static void ethInitTxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue)
2731{
2732    ETH_TX_DESC *pTxDescBase, *pTxDesc, *pTxPrevDesc;
2733    int ix, txDescNum = pPortCtrl->txQueueConfig[queue].descrNum;
2734    ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->txQueue[queue];
2735
2736    /* Make sure descriptor address is cache line size aligned */
2737    pTxDescBase = (ETH_TX_DESC*)MV_ALIGN_UP((MV_ULONG)pQueueCtrl->descBuf.bufVirtPtr,
2738                                     CPU_D_CACHE_LINE_SIZE);
2739
2740    pTxDesc = (ETH_TX_DESC*)pTxDescBase;
2741    pTxPrevDesc = pTxDesc;
2742
2743    /* initialize the Tx descriptors ring */
2744    for (ix=0; ix<txDescNum; ix++)
2745    {
2746        pTxDesc->byteCnt = 0x0000;
2747        pTxDesc->L4iChk = 0x0000;
2748        pTxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST;
2749        pTxDesc->bufPtr = 0x0;
2750        pTxDesc->returnInfo = 0x0;
2751
2752        pTxPrevDesc = pTxDesc;
2753
2754        if(ix == (txDescNum-1))
2755        {
2756            /* Closing Tx descriptors ring */
2757            pTxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pTxDescBase);
2758        }
2759        else
2760        {
2761            pTxDesc = (ETH_TX_DESC*)((MV_ULONG)pTxDesc + ETH_TX_DESC_ALIGNED_SIZE);
2762            pTxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pTxDesc);
2763        }
2764        ETH_DESCR_FLUSH_INV(pPortCtrl, pTxPrevDesc);
2765    }
2766
2767    pQueueCtrl->pCurrentDescr = pTxDescBase;
2768    pQueueCtrl->pUsedDescr = pTxDescBase;
2769    
2770    pQueueCtrl->pFirstDescr = pTxDescBase;
2771    pQueueCtrl->pLastDescr = pTxDesc;
2772    /* Leave one TX descriptor out of use */
2773    pQueueCtrl->resource = txDescNum - 1;
2774}
2775
2776void ethResetTxDescRing(void* pPortHndl, int queue)
2777{
2778    ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl;
2779    ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->txQueue[queue];
2780    ETH_TX_DESC* pTxDesc = (ETH_TX_DESC*)pQueueCtrl->pFirstDescr;
2781    
2782    pQueueCtrl->resource = 0;
2783    if(pQueueCtrl->pFirstDescr != NULL)
2784    {
2785        while(MV_TRUE)
2786        {
2787            pTxDesc->byteCnt = 0x0000;
2788            pTxDesc->L4iChk = 0x0000;
2789            pTxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST;
2790            pTxDesc->bufPtr = 0x0;
2791            pTxDesc->returnInfo = 0x0;
2792            ETH_DESCR_FLUSH_INV(pPortCtrl, pTxDesc);
2793            pQueueCtrl->resource++;
2794            if( (void*)pTxDesc == pQueueCtrl->pLastDescr)
2795                    break;
2796            pTxDesc = TX_NEXT_DESC_PTR(pTxDesc, pQueueCtrl);
2797        }
2798        /* Leave one TX descriptor out of use */
2799        pQueueCtrl->resource--;
2800        pQueueCtrl->pCurrentDescr = pQueueCtrl->pFirstDescr;
2801        pQueueCtrl->pUsedDescr = pQueueCtrl->pFirstDescr;
2802
2803        /* Update TX Command register */
2804        pPortCtrl->portTxQueueCmdReg |= MV_32BIT_LE_FAST(1 << queue);
2805        /* update HW */
2806        MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue),
2807        (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) );
2808    }
2809    else
2810    {
2811        /* Update TX Command register */
2812        pPortCtrl->portTxQueueCmdReg &= MV_32BIT_LE_FAST(~(1 << queue));
2813        /* update HW */
2814        MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), 0 );
2815    }
2816}
2817
2818/*******************************************************************************
2819* ethAllocDescrMemory - Free memory allocated for RX and TX descriptors.
2820*
2821* DESCRIPTION:
2822* This function allocates memory for RX and TX descriptors.
2823* - If ETH_DESCR_IN_SRAM defined, allocate memory from SRAM.
2824* - If ETH_DESCR_IN_SDRAM defined, allocate memory in SDRAM.
2825*
2826* INPUT:
2827* int size - size of memory should be allocated.
2828*
2829* RETURN: None
2830*
2831*******************************************************************************/
2832static MV_U8* ethAllocDescrMemory(ETH_PORT_CTRL* pPortCtrl, int descSize,
2833                            MV_ULONG* pPhysAddr, MV_U32 *memHandle)
2834{
2835    MV_U8* pVirt;
2836
2837#if defined(ETH_DESCR_IN_SRAM)
2838    if(ethDescInSram == MV_TRUE)
2839        pVirt = (char*)mvSramMalloc(descSize, pPhysAddr);
2840    else
2841#endif /* ETH_DESCR_IN_SRAM */
2842    {
2843#ifdef ETH_DESCR_UNCACHED
2844        pVirt = (MV_U8*)mvOsIoUncachedMalloc(pPortCtrl->osHandle, descSize,
2845                        pPhysAddr,memHandle);
2846#else
2847        pVirt = (MV_U8*)mvOsIoCachedMalloc(pPortCtrl->osHandle, descSize,
2848                      pPhysAddr, memHandle);
2849#endif /* ETH_DESCR_UNCACHED */
2850    }
2851    memset(pVirt, 0, descSize);
2852
2853    return pVirt;
2854}
2855
2856/*******************************************************************************
2857* ethFreeDescrMemory - Free memory allocated for RX and TX descriptors.
2858*
2859* DESCRIPTION:
2860* This function frees memory allocated for RX and TX descriptors.
2861* - If ETH_DESCR_IN_SRAM defined, free memory using gtSramFree() function.
2862* - If ETH_DESCR_IN_SDRAM defined, free memory using mvOsFree() function.
2863*
2864* INPUT:
2865* void* pVirtAddr - virtual pointer to memory allocated for RX and TX
2866* desriptors.
2867*
2868* RETURN: None
2869*
2870*******************************************************************************/
2871void ethFreeDescrMemory(ETH_PORT_CTRL* pPortCtrl, MV_BUF_INFO* pDescBuf)
2872{
2873    if( (pDescBuf == NULL) || (pDescBuf->bufVirtPtr == NULL) )
2874        return;
2875
2876#if defined(ETH_DESCR_IN_SRAM)
2877    if( ethDescInSram )
2878    {
2879        mvSramFree(pDescBuf->bufSize, pDescBuf->bufPhysAddr, pDescBuf->bufVirtPtr);
2880        return;
2881    }
2882#endif /* ETH_DESCR_IN_SRAM */
2883
2884#ifdef ETH_DESCR_UNCACHED
2885    mvOsIoUncachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr,
2886                     pDescBuf->bufVirtPtr,pDescBuf->memHandle);
2887#else
2888    mvOsIoCachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr,
2889                     pDescBuf->bufVirtPtr,pDescBuf->memHandle);
2890#endif /* ETH_DESCR_UNCACHED */
2891}
2892                                                                                                                             
2893/******************************************************************************/
2894/* Other Functions */
2895/******************************************************************************/
2896
2897void mvEthPortPowerUp(int port)
2898{
2899    MV_U32 regVal;
2900
2901    /* MAC Cause register should be cleared */
2902    MV_REG_WRITE(ETH_UNIT_INTR_CAUSE_REG(port), 0);
2903
2904    if (mvBoardIsPortInSgmii(port))
2905    mvEthPortSgmiiConfig(port);
2906
2907    /* Cancel Port Reset */
2908    regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port));
2909    regVal &= (~ETH_PORT_RESET_MASK);
2910    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal);
2911    while( (MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)) & ETH_PORT_RESET_MASK) != 0);
2912}
2913
2914void mvEthPortPowerDown(int port)
2915{
2916    MV_U32 regVal;
2917
2918    /* Port must be DISABLED */
2919    regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port));
2920    if( (regVal & ETH_PORT_ENABLE_MASK) != 0)
2921    {
2922        mvOsPrintf("ethPort #%d: PowerDown - port must be Disabled (PSC=0x%x)\n",
2923                    port, regVal);
2924        return;
2925    }
2926
2927    /* Port Reset (Read after write the register as a precaution) */
2928    regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port));
2929    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal | ETH_PORT_RESET_MASK);
2930    while((MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)) & ETH_PORT_RESET_MASK) == 0);
2931}
2932
2933static void mvEthPortSgmiiConfig(int port)
2934{
2935    MV_U32 regVal;
2936
2937    regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port));
2938
2939    regVal |= (ETH_SGMII_MODE_MASK /*| ETH_INBAND_AUTO_NEG_ENABLE_MASK */);
2940    regVal &= (~ETH_INBAND_AUTO_NEG_BYPASS_MASK);
2941
2942    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal);
2943}
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953

Archive Download this file



interactive