update OCF framework to version 20100325
[openwrt/openwrt.git] / target / linux / generic-2.6 / 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