d24e788fc781b9194ba495e775716aac62f0f267
[15.05/openwrt.git] / target / linux / generic / files / crypto / ocf / kirkwood / mvHal / mv_hal / eth / gbe / mvEth.c
1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
3
4 This software file (the "File") is owned and distributed by Marvell 
5 International Ltd. and/or its affiliates ("Marvell") under the following
6 alternative licensing terms.  Once you have made an election to distribute the
7 File under one of the following license alternatives, please (i) delete this
8 introductory statement regarding license alternatives, (ii) delete the two
9 license alternatives that you have not elected to use and (iii) preserve the
10 Marvell copyright notice above.
11
12 ********************************************************************************
13 Marvell Commercial License Option
14
15 If you received this File from Marvell and you have entered into a commercial
16 license agreement (a "Commercial License") with Marvell, the File is licensed
17 to you under the terms of the applicable Commercial License.
18
19 ********************************************************************************
20 Marvell GPL License Option
21
22 If you received this File from Marvell, you may opt to use, redistribute and/or 
23 modify this File in accordance with the terms and conditions of the General 
24 Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
25 available along with the File in the license.txt file or by writing to the Free 
26 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
27 on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
28
29 THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
30 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
31 DISCLAIMED.  The GPL License provides additional details about this warranty 
32 disclaimer.
33 ********************************************************************************
34 Marvell BSD License Option
35
36 If you received this File from Marvell, you may opt to use, redistribute and/or 
37 modify this File under the following licensing terms. 
38 Redistribution and use in source and binary forms, with or without modification, 
39 are 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     
52 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
53 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
54 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
55 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
56 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
57 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
58 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
59 ANY 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 
61 SOFTWARE, 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 */
115 MV_BOOL         ethDescInSram;
116 MV_BOOL         ethDescSwCoher;
117
118 /* This array holds the control structure of each port */
119 ETH_PORT_CTRL* ethPortCtrl[MV_ETH_MAX_PORTS];
120
121 /* Ethernet Port Local routines */
122
123 static void    ethInitRxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue);
124
125 static void    ethInitTxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue);
126
127 static void    ethSetUcastTable(int portNo, int queue);
128
129 static MV_BOOL ethSetUcastAddr (int ethPortNum, MV_U8 lastNibble, int queue);
130 static MV_BOOL ethSetSpecialMcastAddr(int ethPortNum, MV_U8 lastByte, int queue);
131 static MV_BOOL ethSetOtherMcastAddr(int ethPortNum, MV_U8 crc8, int queue);
132
133 static void    ethFreeDescrMemory(ETH_PORT_CTRL* pEthPortCtrl, MV_BUF_INFO* pDescBuf);
134 static MV_U8*  ethAllocDescrMemory(ETH_PORT_CTRL* pEthPortCtrl, int size, 
135                                    MV_ULONG* pPhysAddr, MV_U32 *memHandle);
136
137 static MV_U32 mvEthMruGet(MV_U32 maxRxPktSize);
138
139 static 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 *******************************************************************************/
162 void    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 *******************************************************************************/
224 void   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 *******************************************************************************/
281 void*   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 *******************************************************************************/
409 void    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 *******************************************************************************/
461 MV_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 *******************************************************************************/
642 MV_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 *******************************************************************************/
683 MV_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 *******************************************************************************/
818 MV_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 *******************************************************************************/
857 MV_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 *******************************************************************************/
903 MV_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 *******************************************************************************/
962 MV_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 *******************************************************************************/
1006 static 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 *******************************************************************************/
1054 MV_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 *******************************************************************************/
1101 MV_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 *******************************************************************************/
1142 MV_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 *******************************************************************************/
1186 MV_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 *******************************************************************************/
1228 MV_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 *******************************************************************************/
1279 MV_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 *******************************************************************************/
1321 MV_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 *******************************************************************************/
1355 MV_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 *******************************************************************************/
1464 MV_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 *******************************************************************************/
1532 static 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 *******************************************************************************/
1563 MV_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 *******************************************************************************/
1597 MV_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 *******************************************************************************/
1644 static 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 *******************************************************************************/
1702 static 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 *******************************************************************************/
1755 static 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 *******************************************************************************/
1812 MV_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 *******************************************************************************/
1848 void  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
1866 int     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 *******************************************************************************/
1901 MV_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 *******************************************************************************/
1946 MV_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 *******************************************************************************/
1992 MV_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 *******************************************************************************/
2049 MV_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 *******************************************************************************/
2101 MV_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 *******************************************************************************/
2152 MV_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 *******************************************************************************/
2212 MV_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 *******************************************************************************/
2305 MV_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 *******************************************************************************/
2368 MV_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 *******************************************************************************/
2449 MV_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 *******************************************************************************/
2497 void    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 *******************************************************************************/
2551 void    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 *******************************************************************************/
2580 int     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 *******************************************************************************/
2620 static 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
2663 void 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 *******************************************************************************/
2730 static 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
2776 void 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 *******************************************************************************/
2832 static 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 *******************************************************************************/
2871 void    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
2897 void 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
2914 void 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
2933 static 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