1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
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.
12 ********************************************************************************
13 Marvell Commercial License Option
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.
19 ********************************************************************************
20 Marvell GPL License Option
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.
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
33 ********************************************************************************
34 Marvell BSD License Option
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:
41 * Redistributions of source code must retain the above copyright notice,
42 this list of conditions and the following disclaimer.
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.
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.
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.
63 *******************************************************************************/
65 /*******************************************************************************
66 * mvEth.c - Marvell's Gigabit Ethernet controller low level driver
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.
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.
92 *******************************************************************************/
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"
105 #ifdef INCLUDE_SYNC_BARR
106 #include "sys/mvCpuIf.h"
115 MV_BOOL ethDescInSram
;
116 MV_BOOL ethDescSwCoher
;
118 /* This array holds the control structure of each port */
119 ETH_PORT_CTRL
* ethPortCtrl
[MV_ETH_MAX_PORTS
];
121 /* Ethernet Port Local routines */
123 static void ethInitRxDescRing(ETH_PORT_CTRL
* pPortCtrl
, int queue
);
125 static void ethInitTxDescRing(ETH_PORT_CTRL
* pPortCtrl
, int queue
);
127 static void ethSetUcastTable(int portNo
, int queue
);
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
);
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
);
137 static MV_U32
mvEthMruGet(MV_U32 maxRxPktSize
);
139 static void mvEthPortSgmiiConfig(int port
);
143 /******************************************************************************/
144 /* EthDrv Initialization functions */
145 /******************************************************************************/
147 /*******************************************************************************
148 * mvEthHalInit - Initialize the Giga Ethernet unit
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
160 * NOTE: this function is called once in the boot process.
161 *******************************************************************************/
162 void mvEthHalInit(void)
166 /* Init static data structures */
167 for (port
=0; port
<MV_ETH_MAX_PORTS
; port
++)
169 ethPortCtrl
[port
] = NULL
;
171 /* Power down all existing ports */
172 for(port
=0; port
<mvCtrlEthMaxPortGet(); port
++)
175 #if defined (MV78200)
176 /* Skip ports mapped to another CPU*/
177 if (MV_FALSE
== mvSocUnitIsMappedToThisCpu(GIGA0
+port
))
183 /* Skip power down ports */
184 if (MV_FALSE
== mvCtrlPwrClckGet(ETH_GIG_UNIT_ID
, port
)) continue;
186 /* Disable Giga Ethernet Unit interrupts */
187 MV_REG_WRITE(ETH_UNIT_INTR_MASK_REG(port
), 0);
189 /* Clear ETH_UNIT_INTR_CAUSE_REG register */
190 MV_REG_WRITE(ETH_UNIT_INTR_CAUSE_REG(port
), 0);
194 mvEthMemAttrGet(ðDescInSram
, ðDescSwCoher
);
196 #if defined(ETH_DESCR_IN_SRAM)
197 if(ethDescInSram
== MV_FALSE
)
199 mvOsPrintf("ethDrv: WARNING! Descriptors will be allocated in DRAM instead of SRAM.\n");
201 #endif /* ETH_DESCR_IN_SRAM */
204 /*******************************************************************************
205 * mvEthMemAttrGet - Define properties (SRAM/DRAM, SW_COHER / HW_COHER / UNCACHED)
206 * of of memory location for RX and TX descriptors.
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.
214 * MV_BOOL* pIsSram - place of descriptors:
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
223 *******************************************************************************/
224 void mvEthMemAttrGet(MV_BOOL
* pIsSram
, MV_BOOL
* pIsSwCoher
)
226 MV_BOOL isSram
, isSwCoher
;
229 #if (ETHER_DRAM_COHER == MV_CACHE_COHER_SW)
232 isSwCoher
= MV_FALSE
;
235 #if defined(ETH_DESCR_IN_SRAM)
236 if( mvCtrlSramSizeGet() > 0)
239 #if (INTEG_SRAM_COHER == MV_CACHE_COHER_SW)
242 isSwCoher
= MV_FALSE
;
245 #endif /* ETH_DESCR_IN_SRAM */
250 if(pIsSwCoher
!= NULL
)
251 *pIsSwCoher
= isSwCoher
;
256 /******************************************************************************/
257 /* Port Initialization functions */
258 /******************************************************************************/
260 /*******************************************************************************
261 * mvEthPortInit - Initialize the Ethernet port driver
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.
272 * int portNo - Ethernet port number
273 * ETH_PORT_INIT *pEthPortInit - Ethernet port init structure
276 * void* - ethernet port handler, that should be passed to the most other
277 * functions dealing with this port.
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
)
284 ETH_PORT_CTRL
* pPortCtrl
;
286 /* Check validity of parameters */
287 if( (portNo
>= (int)mvCtrlEthMaxPortGet()) ||
288 (pEthPortInit
->rxDefQ
>= MV_ETH_RX_Q_NUM
) ||
289 (pEthPortInit
->maxRxPktSize
< 1518) )
291 mvOsPrintf("EthPort #%d: Bad initialization parameters\n", portNo
);
294 if( (pEthPortInit
->rxDescrNum
[pEthPortInit
->rxDefQ
]) == 0)
296 mvOsPrintf("EthPort #%d: rxDefQ (%d) must be created\n",
297 portNo
, pEthPortInit
->rxDefQ
);
301 pPortCtrl
= (ETH_PORT_CTRL
*)mvOsMalloc( sizeof(ETH_PORT_CTRL
) );
302 if(pPortCtrl
== NULL
)
304 mvOsPrintf("EthDrv: Can't allocate %dB for port #%d control structure!\n",
305 (int)sizeof(ETH_PORT_CTRL
), portNo
);
309 memset(pPortCtrl
, 0, sizeof(ETH_PORT_CTRL
) );
310 ethPortCtrl
[portNo
] = pPortCtrl
;
312 pPortCtrl
->portState
= MV_UNDEFINED_STATE
;
314 pPortCtrl
->portNo
= portNo
;
316 pPortCtrl
->osHandle
= pEthPortInit
->osHandle
;
318 /* Copy Configuration parameters */
319 pPortCtrl
->portConfig
.maxRxPktSize
= pEthPortInit
->maxRxPktSize
;
320 pPortCtrl
->portConfig
.rxDefQ
= pEthPortInit
->rxDefQ
;
321 pPortCtrl
->portConfig
.ejpMode
= 0;
323 for( queue
=0; queue
<MV_ETH_RX_Q_NUM
; queue
++ )
325 pPortCtrl
->rxQueueConfig
[queue
].descrNum
= pEthPortInit
->rxDescrNum
[queue
];
327 for( queue
=0; queue
<MV_ETH_TX_Q_NUM
; queue
++ )
329 pPortCtrl
->txQueueConfig
[queue
].descrNum
= pEthPortInit
->txDescrNum
[queue
];
332 mvEthPortDisable(pPortCtrl
);
334 /* Set the board information regarding PHY address */
335 mvEthPhyAddrSet(pPortCtrl
, mvBoardPhyAddrGet(portNo
) );
337 /* Create all requested RX queues */
338 for(queue
=0; queue
<MV_ETH_RX_Q_NUM
; queue
++)
340 if(pPortCtrl
->rxQueueConfig
[queue
].descrNum
== 0)
343 /* Allocate memory for RX descriptors */
344 descSize
= ((pPortCtrl
->rxQueueConfig
[queue
].descrNum
* ETH_RX_DESC_ALIGNED_SIZE
) +
345 CPU_D_CACHE_LINE_SIZE
);
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
)
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
);
361 ethInitRxDescRing(pPortCtrl
, queue
);
363 /* Create TX queues */
364 for(queue
=0; queue
<MV_ETH_TX_Q_NUM
; queue
++)
366 if(pPortCtrl
->txQueueConfig
[queue
].descrNum
== 0)
369 /* Allocate memory for TX descriptors */
370 descSize
= ((pPortCtrl
->txQueueConfig
[queue
].descrNum
* ETH_TX_DESC_ALIGNED_SIZE
) +
371 CPU_D_CACHE_LINE_SIZE
);
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
)
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
);
386 ethInitTxDescRing(pPortCtrl
, queue
);
388 mvEthDefaultsSet(pPortCtrl
);
390 pPortCtrl
->portState
= MV_IDLE
;
394 /*******************************************************************************
395 * ethPortFinish - Finish the Ethernet port driver
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.
404 * void* pEthPortHndl - Ethernet port handler
408 *******************************************************************************/
409 void mvEthPortFinish(void* pPortHndl
)
411 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHndl
;
412 int queue
, portNo
= pPortCtrl
->portNo
;
414 if(pPortCtrl
->portState
== MV_ACTIVE
)
416 mvOsPrintf("ethPort #%d: Warning !!! Finish port in Active state\n",
418 mvEthPortDisable(pPortHndl
);
421 /* Free all allocated RX queues */
422 for(queue
=0; queue
<MV_ETH_RX_Q_NUM
; queue
++)
424 ethFreeDescrMemory(pPortCtrl
, &pPortCtrl
->rxQueue
[queue
].descBuf
);
427 /* Free all allocated TX queues */
428 for(queue
=0; queue
<MV_ETH_TX_Q_NUM
; queue
++)
430 ethFreeDescrMemory(pPortCtrl
, &pPortCtrl
->txQueue
[queue
].descBuf
);
433 /* Free port control structure */
436 ethPortCtrl
[portNo
] = NULL
;
439 /*******************************************************************************
440 * mvEthDefaultsSet - Set defaults to the ethernet port
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
451 * void* pEthPortHndl - Ethernet port handler
454 * MV_OK - Success, Others - Failure
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
460 *******************************************************************************/
461 MV_STATUS
mvEthDefaultsSet(void* pPortHndl
)
463 int ethPortNo
, queue
;
464 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHndl
;
465 ETH_QUEUE_CTRL
* pQueueCtrl
;
467 MV_U32 portCfgReg
, portCfgExtReg
, portSerialCtrlReg
, portSerialCtrl1Reg
, portSdmaCfgReg
;
468 MV_BOARD_MAC_SPEED boardMacCfg
;
470 ethPortNo
= pPortCtrl
->portNo
;
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);
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);
480 portCfgReg
= PORT_CONFIG_VALUE
;
481 portCfgExtReg
= PORT_CONFIG_EXTEND_VALUE
;
483 boardMacCfg
= mvBoardMacSpeedGet(ethPortNo
);
485 if(boardMacCfg
== BOARD_MAC_SPEED_100M
)
487 portSerialCtrlReg
= PORT_SERIAL_CONTROL_100MB_FORCE_VALUE
;
489 else if(boardMacCfg
== BOARD_MAC_SPEED_1000M
)
491 portSerialCtrlReg
= PORT_SERIAL_CONTROL_1000MB_FORCE_VALUE
;
495 portSerialCtrlReg
= PORT_SERIAL_CONTROL_VALUE
;
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
);
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
);
507 portSdmaCfgReg
|= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE
);
510 #if defined(MV_CPU_BE)
513 portSdmaCfgReg
|= (ETH_RX_NO_DATA_SWAP_MASK
|
514 ETH_TX_NO_DATA_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
);
521 # error "Giga Ethernet Swap policy is not defined for the CPU_ARCH"
522 # endif /* MV_ARM / MV_PPC */
524 #else /* MV_CPU_LE */
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 */
531 pPortCtrl
->portRxQueueCmdReg
= 0;
532 pPortCtrl
->portTxQueueCmdReg
= 0;
534 #if (MV_ETH_VERSION >= 4)
535 if(pPortCtrl
->portConfig
.ejpMode
== MV_TRUE
)
537 MV_REG_WRITE(ETH_TXQ_CMD_1_REG(ethPortNo
), ETH_TX_EJP_ENABLE_MASK
);
541 MV_REG_WRITE(ETH_TXQ_CMD_1_REG(ethPortNo
), 0)
543 #endif /* (MV_ETH_VERSION >= 4) */
545 ethSetUcastTable(ethPortNo
, -1);
546 mvEthSetSpecialMcastTable(ethPortNo
, -1);
547 mvEthSetOtherMcastTable(ethPortNo
, -1);
549 portSerialCtrlReg
&= ~ETH_MAX_RX_PACKET_SIZE_MASK
;
551 portSerialCtrlReg
|= mvEthMruGet(pPortCtrl
->portConfig
.maxRxPktSize
);
553 MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo
), portSerialCtrlReg
);
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
;
561 portCfgReg
&= ~ETH_DEF_RX_QUEUE_ALL_MASK
;
562 portCfgReg
|= ETH_DEF_RX_QUEUE_MASK(pPortCtrl
->portConfig
.rxDefQ
);
564 portCfgReg
&= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK
;
565 portCfgReg
|= ETH_DEF_RX_ARP_QUEUE_MASK(pPortCtrl
->portConfig
.rxArpQ
);
567 portCfgReg
&= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK
;
568 portCfgReg
|= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl
->portConfig
.rxBpduQ
);
570 portCfgReg
&= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK
;
571 portCfgReg
|= ETH_DEF_RX_TCP_QUEUE_MASK(pPortCtrl
->portConfig
.rxTcpQ
);
573 portCfgReg
&= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK
;
574 portCfgReg
|= ETH_DEF_RX_UDP_QUEUE_MASK(pPortCtrl
->portConfig
.rxUdpQ
);
576 /* Assignment of Tx CTRP of given queue */
579 for(queue
=0; queue
<MV_ETH_TX_Q_NUM
; queue
++)
581 pQueueCtrl
= &pPortCtrl
->txQueue
[queue
];
583 if(pQueueCtrl
->pFirstDescr
!= NULL
)
585 ethResetTxDescRing(pPortCtrl
, queue
);
587 MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo
, queue
),
589 MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo
, queue
),
594 MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo
, queue
), 0x0);
595 MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo
, queue
), 0x0);
599 /* Assignment of Rx CRDP of given queue */
600 for(queue
=0; queue
<MV_ETH_RX_Q_NUM
; queue
++)
602 ethResetRxDescRing(pPortCtrl
, queue
);
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
);
610 /* Assign port configuration and command. */
611 MV_REG_WRITE(ETH_PORT_CONFIG_REG(ethPortNo
), portCfgReg
);
613 MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(ethPortNo
), portCfgExtReg
);
615 /* Assign port SDMA configuration */
616 MV_REG_WRITE(ETH_SDMA_CONFIG_REG(ethPortNo
), portSdmaCfgReg
);
618 /* Turn off the port/queue bandwidth limitation */
619 MV_REG_WRITE(ETH_MAX_TRANSMIT_UNIT_REG(ethPortNo
), 0x0);
624 /*******************************************************************************
625 * ethPortUp - Start the Ethernet port RX and TX activity.
628 * This routine start Rx and Tx activity:
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).
635 * void* pEthPortHndl - Ethernet port handler
638 * MV_OK - Success, Others - Failure.
640 * NOTE : used for port link up.
641 *******************************************************************************/
642 MV_STATUS
mvEthPortUp(void* pEthPortHndl
)
645 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pEthPortHndl
;
647 ethPortNo
= pPortCtrl
->portNo
;
649 if( (pPortCtrl
->portState
!= MV_ACTIVE
) &&
650 (pPortCtrl
->portState
!= MV_PAUSED
) )
652 mvOsPrintf("ethDrv port%d: Unexpected port state %d\n",
653 ethPortNo
, pPortCtrl
->portState
);
657 ethPortNo
= pPortCtrl
->portNo
;
659 /* Enable port RX. */
660 MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNo
), pPortCtrl
->portRxQueueCmdReg
);
662 /* Enable port TX. */
663 MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(ethPortNo
)) = pPortCtrl
->portTxQueueCmdReg
;
665 pPortCtrl
->portState
= MV_ACTIVE
;
670 /*******************************************************************************
671 * ethPortDown - Stop the Ethernet port activity.
676 * void* pEthPortHndl - Ethernet port handler
679 * MV_OK - Success, Others - Failure.
681 * NOTE : used for port link down.
682 *******************************************************************************/
683 MV_STATUS
mvEthPortDown(void* pEthPortHndl
)
685 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pEthPortHndl
;
686 int ethPortNum
= pPortCtrl
->portNo
;
687 unsigned int regData
;
688 volatile int uDelay
, mDelay
;
690 /* Stop Rx port activity. Check port Rx activity. */
691 regData
= (MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum
))) & ETH_RXQ_ENABLE_MASK
;
694 /* Issue stop command for active channels only */
695 MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNum
), (regData
<< ETH_RXQ_DISABLE_OFFSET
));
698 /* Stop Tx port activity. Check port Tx activity. */
699 regData
= (MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum
))) & ETH_TXQ_ENABLE_MASK
;
702 /* Issue stop command for active channels only */
703 MV_REG_WRITE(ETH_TX_QUEUE_COMMAND_REG(ethPortNum
),
704 (regData
<< ETH_TXQ_DISABLE_OFFSET
) );
707 /* Force link down */
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);
713 /* Wait for all Rx activity to terminate. */
717 if(mDelay
>= RX_DISABLE_TIMEOUT_MSEC
)
719 mvOsPrintf("ethPort_%d: TIMEOUT for RX stopped !!! rxQueueCmd - 0x08%x\n",
720 ethPortNum
, regData
);
726 /* Check port RX Command register that all Rx queues are stopped */
727 regData
= MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum
));
729 while(regData
& 0xFF);
731 /* Wait for all Tx activity to terminate. */
735 if(mDelay
>= TX_DISABLE_TIMEOUT_MSEC
)
737 mvOsPrintf("ethPort_%d: TIMEOUT for TX stoped !!! txQueueCmd - 0x08%x\n",
738 ethPortNum
, regData
);
744 /* Check port TX Command register that all Tx queues are stopped */
745 regData
= MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum
));
747 while(regData
& 0xFF);
749 /* Double check to Verify that TX FIFO is Empty */
755 if(mDelay
>= TX_FIFO_EMPTY_TIMEOUT_MSEC
)
757 mvOsPrintf("\n ethPort_%d: TIMEOUT for TX FIFO empty !!! portStatus - 0x08%x\n",
758 ethPortNum
, regData
);
764 regData
= MV_REG_READ(ETH_PORT_STATUS_REG(ethPortNum
));
766 while( ((regData
& ETH_TX_FIFO_EMPTY_MASK
) == 0) ||
767 ((regData
& ETH_TX_IN_PROGRESS_MASK
) != 0) );
769 if(mDelay
>= TX_FIFO_EMPTY_TIMEOUT_MSEC
)
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) )
780 mvOsPrintf("ethPort_%d: TX FIFO Empty double check failed. %d msec, portStatus=0x%x\n",
781 ethPortNum
, mDelay
, regData
);
784 /* Do NOT force link down */
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);
790 /* Wait about 2500 tclk cycles */
791 uDelay
= (PORT_DISABLE_WAIT_TCLOCKS
/(mvBoardTclkGet()/1000000));
794 pPortCtrl
->portState
= MV_PAUSED
;
800 /*******************************************************************************
801 * ethPortEnable - Enable the Ethernet port and Start RX and TX.
804 * This routine enable the Ethernet port and Rx and Tx activity:
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).
811 * void* pEthPortHndl - Ethernet port handler
814 * MV_OK - Success, Others - Failure.
816 * NOTE: main usage is to enable the port after ifconfig up.
817 *******************************************************************************/
818 MV_STATUS
mvEthPortEnable(void* pEthPortHndl
)
821 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pEthPortHndl
;
822 MV_U32 portSerialCtrlReg
;
824 ethPortNo
= pPortCtrl
->portNo
;
827 portSerialCtrlReg
= MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNo
));
828 portSerialCtrlReg
|= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK
| ETH_PORT_ENABLE_MASK
);
830 MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo
), portSerialCtrlReg
);
832 mvEthMibCountersClear(pEthPortHndl
);
834 pPortCtrl
->portState
= MV_PAUSED
;
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
) );
844 /*******************************************************************************
845 * mvEthPortDisable - Stop RX and TX activities and Disable the Ethernet port.
850 * void* pEthPortHndl - Ethernet port handler
853 * MV_OK - Success, Others - Failure.
855 * NOTE: main usage is to disable the port after ifconfig down.
856 *******************************************************************************/
857 MV_STATUS
mvEthPortDisable(void* pEthPortHndl
)
859 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pEthPortHndl
;
860 int ethPortNum
= pPortCtrl
->portNo
;
861 unsigned int regData
;
862 volatile int mvDelay
;
864 if(pPortCtrl
->portState
== MV_ACTIVE
)
866 /* Stop RX and TX activities */
867 mvEthPortDown(pEthPortHndl
);
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
);
875 /* Wait about 2500 tclk cycles */
876 mvDelay
= (PORT_DISABLE_WAIT_TCLOCKS
*(mvCpuPclkGet()/mvBoardTclkGet()));
877 for(mvDelay
; mvDelay
>0; mvDelay
--);
879 pPortCtrl
->portState
= MV_IDLE
;
883 /*******************************************************************************
884 * mvEthPortForceTxDone - Get next buffer from TX queue in spite of buffer ownership.
887 * This routine used to free buffers attached to the Tx ring and should
888 * be called only when Giga Ethernet port is Down
891 * void* pEthPortHndl - Ethernet Port handler.
892 * int txQueue - Number of TX queue.
895 * MV_PKT_INFO *pPktInfo - Pointer to packet was sent.
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.
902 *******************************************************************************/
903 MV_PKT_INFO
* mvEthPortForceTxDone(void* pEthPortHndl
, int txQueue
)
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
;
911 pQueueCtrl
= &pPortCtrl
->txQueue
[txQueue
];
913 while( (pQueueCtrl
->pUsedDescr
!= pQueueCtrl
->pCurrentDescr
) ||
914 (pQueueCtrl
->resource
== 0) )
916 /* Free next descriptor */
917 pQueueCtrl
->resource
++;
918 pTxDesc
= (ETH_TX_DESC
*)pQueueCtrl
->pUsedDescr
;
920 /* pPktInfo is available only in descriptors which are last descriptors */
921 pPktInfo
= (MV_PKT_INFO
*)pTxDesc
->returnInfo
;
923 pPktInfo
->status
= pTxDesc
->cmdSts
;
925 pTxDesc
->cmdSts
= 0x0;
926 pTxDesc
->returnInfo
= 0x0;
927 ETH_DESCR_FLUSH_INV(pPortCtrl
, pTxDesc
);
929 pQueueCtrl
->pUsedDescr
= TX_NEXT_DESC_PTR(pTxDesc
, pQueueCtrl
);
932 if (pPktInfo
->status
& ETH_TX_LAST_DESC_MASK
)
935 MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(port
, txQueue
),
936 (MV_U32
)ethDescVirtToPhy(pQueueCtrl
, pQueueCtrl
->pCurrentDescr
) );
942 /*******************************************************************************
943 * mvEthPortForceRx - Get next buffer from RX queue in spite of buffer ownership.
946 * This routine used to free buffers attached to the Rx ring and should
947 * be called only when Giga Ethernet port is Down
950 * void* pEthPortHndl - Ethernet Port handler.
951 * int rxQueue - Number of Rx queue.
954 * MV_PKT_INFO *pPktInfo - Pointer to received packet.
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.
961 *******************************************************************************/
962 MV_PKT_INFO
* mvEthPortForceRx(void* pEthPortHndl
, int rxQueue
)
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
;
970 pQueueCtrl
= &pPortCtrl
->rxQueue
[rxQueue
];
972 if(pQueueCtrl
->resource
== 0)
974 MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(port
, rxQueue
),
975 (MV_U32
)ethDescVirtToPhy(pQueueCtrl
, pQueueCtrl
->pCurrentDescr
) );
979 /* Free next descriptor */
980 pQueueCtrl
->resource
--;
981 pRxDesc
= (ETH_RX_DESC
*)pQueueCtrl
->pCurrentDescr
;
982 pPktInfo
= (MV_PKT_INFO
*)pRxDesc
->returnInfo
;
984 pPktInfo
->status
= pRxDesc
->cmdSts
;
985 pRxDesc
->cmdSts
= 0x0;
986 pRxDesc
->returnInfo
= 0x0;
987 ETH_DESCR_FLUSH_INV(pPortCtrl
, pRxDesc
);
989 pQueueCtrl
->pCurrentDescr
= RX_NEXT_DESC_PTR(pRxDesc
, pQueueCtrl
);
994 /******************************************************************************/
995 /* Port Configuration functions */
996 /******************************************************************************/
997 /*******************************************************************************
998 * mvEthMruGet - Get MRU configuration for Max Rx packet size.
1001 * MV_U32 maxRxPktSize - max packet size.
1003 * RETURN: MV_U32 - MRU configuration.
1005 *******************************************************************************/
1006 static MV_U32
mvEthMruGet(MV_U32 maxRxPktSize
)
1008 MV_U32 portSerialCtrlReg
= 0;
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
;
1021 portSerialCtrlReg
|= ETH_MAX_RX_PACKET_1518BYTE
;
1023 return portSerialCtrlReg
;
1026 /*******************************************************************************
1027 * mvEthRxCoalSet - Sets coalescing interrupt mechanism on RX path
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.
1037 * void* pPortHndl - Ethernet Port handler.
1038 * MV_U32 uSec - Number of micro seconds between
1045 * 1 sec - TCLK_RATE clocks
1046 * 1 uSec - TCLK_RATE / 1,000,000 clocks
1048 * Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64)
1053 *******************************************************************************/
1054 MV_U32
mvEthRxCoalSet (void* pPortHndl
, MV_U32 uSec
)
1056 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHndl
;
1057 MV_U32 coal
= ((uSec
* (mvBoardTclkGet() / 1000000)) / 64);
1058 MV_U32 portSdmaCfgReg
;
1060 portSdmaCfgReg
= MV_REG_READ(ETH_SDMA_CONFIG_REG(pPortCtrl
->portNo
));
1061 portSdmaCfgReg
&= ~ETH_RX_INTR_COAL_ALL_MASK
;
1063 portSdmaCfgReg
|= ETH_RX_INTR_COAL_MASK(coal
);
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 */
1071 MV_REG_WRITE (ETH_SDMA_CONFIG_REG(pPortCtrl
->portNo
), portSdmaCfgReg
);
1075 /*******************************************************************************
1076 * mvEthTxCoalSet - Sets coalescing interrupt mechanism on TX path
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
1083 * The parameter is calculated using the tCLK frequency of the
1084 * MV-64xxx chip, and the required number is in micro seconds.
1087 * void* pPortHndl - Ethernet Port handler.
1088 * MV_U32 uSec - Number of micro seconds between
1095 * 1 sec - TCLK_RATE clocks
1096 * 1 uSec - TCLK_RATE / 1,000,000 clocks
1098 * Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64)
1100 *******************************************************************************/
1101 MV_U32
mvEthTxCoalSet(void* pPortHndl
, MV_U32 uSec
)
1103 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHndl
;
1104 MV_U32 coal
= ((uSec
* (mvBoardTclkGet() / 1000000)) / 64);
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
);
1111 /* Set TX Coalescing mechanism */
1112 MV_REG_WRITE (ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl
->portNo
), regVal
);
1116 /*******************************************************************************
1117 * mvEthCoalGet - Gets RX and TX coalescing values in micro seconds
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.
1125 * void* pPortHndl - Ethernet Port handler.
1128 * MV_U32* pRxCoal - Number of micro seconds between RX interrupts
1129 * MV_U32* pTxCoal - Number of micro seconds between TX interrupts
1132 * MV_STATUS MV_OK - success
1136 * 1 sec - TCLK_RATE clocks
1137 * 1 uSec - TCLK_RATE / 1,000,000 clocks
1139 * Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64)
1141 *******************************************************************************/
1142 MV_STATUS
mvEthCoalGet(void* pPortHndl
, MV_U32
* pRxCoal
, MV_U32
* pTxCoal
)
1144 MV_U32 regVal
, coal
, usec
;
1146 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHndl
;
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
);
1152 usec
= (coal
* 64) / (mvBoardTclkGet() / 1000000);
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
);
1160 #if (MV_ETH_VERSION >= 2)
1161 if(regVal
& ETH_RX_INTR_COAL_MSB_MASK
)
1164 coal
|= (ETH_RX_INTR_COAL_ALL_MASK
+ 1);
1166 #endif /* MV_ETH_VERSION >= 2 */
1168 usec
= (coal
* 64) / (mvBoardTclkGet() / 1000000);
1175 /*******************************************************************************
1176 * mvEthMaxRxSizeSet -
1179 * Change maximum receive size of the port. This configuration will take place
1180 * after next call of ethPortSetDefaults() function.
1185 *******************************************************************************/
1186 MV_STATUS
mvEthMaxRxSizeSet(void* pPortHndl
, int maxRxSize
)
1188 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHndl
;
1189 MV_U32 portSerialCtrlReg
;
1191 if((maxRxSize
< 1518) || (maxRxSize
& ~ETH_RX_BUFFER_MASK
))
1192 return MV_BAD_PARAM
;
1194 pPortCtrl
->portConfig
.maxRxPktSize
= maxRxSize
;
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
);
1205 /******************************************************************************/
1206 /* MAC Filtering functions */
1207 /******************************************************************************/
1209 /*******************************************************************************
1210 * mvEthRxFilterModeSet - Configure Fitering mode of Ethernet port
1213 * This routine used to free buffers attached to the Rx ring and should
1214 * be called only when Giga Ethernet port is Down
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
1225 * RETURN: MV_STATUS MV_OK - Success, Other - Failure
1227 *******************************************************************************/
1228 MV_STATUS
mvEthRxFilterModeSet(void* pEthPortHndl
, MV_BOOL isPromisc
)
1230 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pEthPortHndl
;
1234 portCfgReg
= MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
));
1235 /* Set / Clear UPM bit in port configuration register */
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);
1247 /* Reject all Multicast addresses */
1249 portCfgReg
&= ~ETH_UNICAST_PROMISCUOUS_MODE_MASK
;
1250 /* Clear all mcastCount */
1251 memset(pPortCtrl
->mcastCount
, 0, sizeof(pPortCtrl
->mcastCount
));
1253 MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
), portCfgReg
);
1255 /* Set Special Multicast and Other Multicast tables */
1256 mvEthSetSpecialMcastTable(pPortCtrl
->portNo
, queue
);
1257 mvEthSetOtherMcastTable(pPortCtrl
->portNo
, queue
);
1258 ethSetUcastTable(pPortCtrl
->portNo
, queue
);
1263 /*******************************************************************************
1264 * mvEthMacAddrSet - This function Set the port Unicast address.
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
1272 * void* pEthPortHndl - Ethernet port handler.
1273 * char* pAddr - Address to be set
1276 * MV_OK - Success, Other - Faulure
1278 *******************************************************************************/
1279 MV_STATUS
mvEthMacAddrSet(void* pPortHndl
, unsigned char *pAddr
, int queue
)
1281 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHndl
;
1285 if(queue
>= MV_ETH_RX_Q_NUM
)
1287 mvOsPrintf("ethDrv: RX queue #%d is out of range\n", queue
);
1288 return MV_BAD_PARAM
;
1293 macL
= (pAddr
[4] << 8) | (pAddr
[5]);
1294 macH
= (pAddr
[0] << 24)| (pAddr
[1] << 16) |
1295 (pAddr
[2] << 8) | (pAddr
[3] << 0);
1297 MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(pPortCtrl
->portNo
), macL
);
1298 MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(pPortCtrl
->portNo
), macH
);
1301 /* Accept frames of this address */
1302 ethSetUcastAddr(pPortCtrl
->portNo
, pAddr
[5], queue
);
1307 /*******************************************************************************
1308 * mvEthMacAddrGet - This function returns the port Unicast address.
1311 * This function returns the port Ethernet MAC address.
1314 * int portNo - Ethernet port number.
1315 * char* pAddr - Pointer where address will be written to
1318 * MV_OK - Success, Other - Faulure
1320 *******************************************************************************/
1321 MV_STATUS
mvEthMacAddrGet(int portNo
, unsigned char *pAddr
)
1328 mvOsPrintf("mvEthMacAddrGet: NULL pointer.\n");
1329 return MV_BAD_PARAM
;
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;
1344 /*******************************************************************************
1345 * mvEthMcastCrc8Get - Calculate CRC8 of MAC address.
1350 * MV_U8* pAddr - Address to calculate CRC-8
1352 * RETURN: MV_U8 - CRC-8 of this MAC address
1354 *******************************************************************************/
1355 MV_U8
mvEthMcastCrc8Get(MV_U8
* pAddr
)
1362 unsigned char crcResult
= 0;
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);
1370 macArray
[i
] = (macL
>> i
) & 0x1;
1372 for(i
=32; i
<48; i
++)
1373 macArray
[i
] = (macH
>> (i
- 32)) & 0x1;
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];
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];
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];
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];
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];
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];
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] ^
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];
1431 crcResult
= crcResult
| (crc
[i
] << i
);
1435 /*******************************************************************************
1436 * mvEthMcastAddrSet - Multicast address settings.
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
1450 * In this case, the function calculates the CRC-8bit value and calls
1451 * ethPortOmcAddr() routine to set the Other Multicast Table.
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.
1461 * MV_TRUE - Success, Other - Failure
1463 *******************************************************************************/
1464 MV_STATUS
mvEthMcastAddrSet(void* pPortHndl
, MV_U8
*pAddr
, int queue
)
1466 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHndl
;
1467 unsigned char crcResult
= 0;
1469 if(queue
>= MV_ETH_RX_Q_NUM
)
1471 mvOsPrintf("ethPort %d: RX queue #%d is out of range\n",
1472 pPortCtrl
->portNo
, queue
);
1473 return MV_BAD_PARAM
;
1476 if((pAddr
[0] == 0x01) &&
1477 (pAddr
[1] == 0x00) &&
1478 (pAddr
[2] == 0x5E) &&
1479 (pAddr
[3] == 0x00) &&
1482 ethSetSpecialMcastAddr(pPortCtrl
->portNo
, pAddr
[5], queue
);
1486 crcResult
= mvEthMcastCrc8Get(pAddr
);
1488 /* Check Add counter for this CRC value */
1491 if(pPortCtrl
->mcastCount
[crcResult
] == 0)
1493 mvOsPrintf("ethPort #%d: No valid Mcast for crc8=0x%02x\n",
1494 pPortCtrl
->portNo
, (unsigned)crcResult
);
1498 pPortCtrl
->mcastCount
[crcResult
]--;
1499 if(pPortCtrl
->mcastCount
[crcResult
] != 0)
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
;
1509 pPortCtrl
->mcastCount
[crcResult
]++;
1510 if(pPortCtrl
->mcastCount
[crcResult
] > 1)
1512 mvOsPrintf("ethPort #%d: Valid Mcast for crc8=0x%02x already exists\n",
1513 pPortCtrl
->portNo
, (unsigned)crcResult
);
1514 return MV_NO_CHANGE
;
1517 ethSetOtherMcastAddr(pPortCtrl
->portNo
, crcResult
, queue
);
1522 /*******************************************************************************
1523 * ethSetUcastTable - Unicast address settings.
1526 * Set all entries in the Unicast MAC Table queue==-1 means reject all
1531 *******************************************************************************/
1532 static void ethSetUcastTable(int portNo
, int queue
)
1543 regValue
= (((0x01 | (queue
<<1)) << 0) |
1544 ((0x01 | (queue
<<1)) << 8) |
1545 ((0x01 | (queue
<<1)) << 16) |
1546 ((0x01 | (queue
<<1)) << 24));
1549 for (offset
=0; offset
<=0xC; offset
+=4)
1550 MV_REG_WRITE((ETH_DA_FILTER_UCAST_BASE(portNo
) + offset
), regValue
);
1553 /*******************************************************************************
1554 * mvEthSetSpecialMcastTable - Special Multicast address settings.
1557 * Set all entries to the Special Multicast MAC Table. queue==-1 means reject all
1562 *******************************************************************************/
1563 MV_VOID
mvEthSetSpecialMcastTable(int portNo
, int queue
)
1574 regValue
= (((0x01 | (queue
<<1)) << 0) |
1575 ((0x01 | (queue
<<1)) << 8) |
1576 ((0x01 | (queue
<<1)) << 16) |
1577 ((0x01 | (queue
<<1)) << 24));
1580 for (offset
=0; offset
<=0xFC; offset
+=4)
1582 MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(portNo
) +
1587 /*******************************************************************************
1588 * mvEthSetOtherMcastTable - Other Multicast address settings.
1591 * Set all entries to the Other Multicast MAC Table. queue==-1 means reject all
1596 *******************************************************************************/
1597 MV_VOID
mvEthSetOtherMcastTable(int portNo
, int queue
)
1608 regValue
= (((0x01 | (queue
<<1)) << 0) |
1609 ((0x01 | (queue
<<1)) << 8) |
1610 ((0x01 | (queue
<<1)) << 16) |
1611 ((0x01 | (queue
<<1)) << 24));
1614 for (offset
=0; offset
<=0xFC; offset
+=4)
1616 MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(portNo
) +
1621 /*******************************************************************************
1622 * ethSetUcastAddr - This function Set the port unicast address table
1625 * This function locates the proper entry in the Unicast table for the
1626 * specified MAC nibble and sets its properties according to function
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
1636 * This function add/removes MAC addresses from the port unicast address
1640 * MV_TRUE is output succeeded.
1641 * MV_FALSE if option parameter is invalid.
1643 *******************************************************************************/
1644 static MV_BOOL
ethSetUcastAddr(int portNo
, MV_U8 lastNibble
, int queue
)
1646 unsigned int unicastReg
;
1647 unsigned int tblOffset
;
1648 unsigned int regOffset
;
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 */
1656 unicastReg
= MV_REG_READ( (ETH_DA_FILTER_UCAST_BASE(portNo
) +
1662 /* Clear accepts frame bit at specified unicast DA table entry */
1663 unicastReg
&= ~(0xFF << (8*regOffset
));
1667 unicastReg
&= ~(0xFF << (8*regOffset
));
1668 unicastReg
|= ((0x01 | (queue
<<1)) << (8*regOffset
));
1670 MV_REG_WRITE( (ETH_DA_FILTER_UCAST_BASE(portNo
) + tblOffset
),
1676 /*******************************************************************************
1677 * ethSetSpecialMcastAddr - Special Multicast address settings.
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.
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.
1698 * MV_TRUE is output succeeded.
1699 * MV_FALSE if option parameter is invalid.
1701 *******************************************************************************/
1702 static MV_BOOL
ethSetSpecialMcastAddr(int ethPortNum
, MV_U8 lastByte
, int queue
)
1704 unsigned int smcTableReg
;
1705 unsigned int tblOffset
;
1706 unsigned int regOffset
;
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 */
1712 smcTableReg
= MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum
) + tblOffset
*4));
1716 /* Clear accepts frame bit at specified Special DA table entry */
1717 smcTableReg
&= ~(0xFF << (8 * regOffset
));
1721 smcTableReg
&= ~(0xFF << (8 * regOffset
));
1722 smcTableReg
|= ((0x01 | (queue
<<1)) << (8 * regOffset
));
1724 MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum
) +
1725 tblOffset
*4), smcTableReg
);
1730 /*******************************************************************************
1731 * ethSetOtherMcastAddr - Multicast address settings.
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.
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.
1751 * MV_TRUE is output succeeded.
1752 * MV_FALSE if option parameter is invalid.
1754 *******************************************************************************/
1755 static MV_BOOL
ethSetOtherMcastAddr(int ethPortNum
, MV_U8 crc8
, int queue
)
1757 unsigned int omcTableReg
;
1758 unsigned int tblOffset
;
1759 unsigned int regOffset
;
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 */
1765 omcTableReg
= MV_REG_READ(
1766 (ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum
) + tblOffset
));
1770 /* Clear accepts frame bit at specified Other DA table entry */
1771 omcTableReg
&= ~(0xFF << (8 * regOffset
));
1775 omcTableReg
&= ~(0xFF << (8 * regOffset
));
1776 omcTableReg
|= ((0x01 | (queue
<<1)) << (8 * regOffset
));
1779 MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum
) + tblOffset
),
1786 /******************************************************************************/
1787 /* MIB Counters functions */
1788 /******************************************************************************/
1791 /*******************************************************************************
1792 * mvEthMibCounterRead - Read a MIB counter
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.
1801 * int ethPortNum - Ethernet Port number.
1802 * unsigned int mibOffset - MIB counter offset.
1805 * MV_U32* pHigh32 - pointer to place where 32 most significant bits
1806 * of the counter will be stored.
1809 * 32 low sgnificant bits of MIB counter value.
1811 *******************************************************************************/
1812 MV_U32
mvEthMibCounterRead(void* pPortHandle
, unsigned int mibOffset
,
1816 MV_U32 valLow32
, valHigh32
;
1817 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
1819 portNo
= pPortCtrl
->portNo
;
1821 valLow32
= MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo
) + mibOffset
);
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
) )
1828 valHigh32
= MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo
) + mibOffset
+ 4);
1830 *pHigh32
= valHigh32
;
1835 /*******************************************************************************
1836 * mvEthMibCountersClear - Clear all MIB counters
1839 * This function clears all MIB counters
1842 * int ethPortNum - Ethernet Port number.
1847 *******************************************************************************/
1848 void mvEthMibCountersClear(void* pPortHandle
)
1852 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
1854 portNo
= pPortCtrl
->portNo
;
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
));
1862 /******************************************************************************/
1863 /* RX Dispatching configuration routines */
1864 /******************************************************************************/
1866 int mvEthTosToRxqGet(void* pPortHandle
, int tos
)
1869 int regIdx
, regOffs
, rxq
;
1870 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
1874 mvOsPrintf("eth_%d: tos=0x%x is out of range\n", pPortCtrl
->portNo
, tos
);
1877 regIdx
= mvOsDivide(tos
>>2, 10);
1878 regOffs
= mvOsReminder(tos
>>2, 10);
1880 regValue
= MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(pPortCtrl
->portNo
, regIdx
) );
1881 rxq
= (regValue
>> (regOffs
*3));
1887 /*******************************************************************************
1888 * mvEthTosToRxqSet - Map packets with special TOS value to special RX queue
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.
1900 *******************************************************************************/
1901 MV_STATUS
mvEthTosToRxqSet(void* pPortHandle
, int tos
, int rxq
)
1904 int regIdx
, regOffs
;
1905 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
1907 if( (rxq
< 0) || (rxq
>= MV_ETH_RX_Q_NUM
) )
1909 mvOsPrintf("eth_%d: RX queue #%d is out of range\n", pPortCtrl
->portNo
, rxq
);
1910 return MV_BAD_PARAM
;
1914 mvOsPrintf("eth_%d: tos=0x%x is out of range\n", pPortCtrl
->portNo
, tos
);
1915 return MV_BAD_PARAM
;
1917 regIdx
= mvOsDivide(tos
>>2, 10);
1918 regOffs
= mvOsReminder(tos
>>2, 10);
1920 regValue
= MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(pPortCtrl
->portNo
, regIdx
) );
1921 regValue
&= ~(0x7 << (regOffs
*3));
1922 regValue
|= (rxq
<< (regOffs
*3));
1924 MV_REG_WRITE(ETH_DIFF_SERV_PRIO_REG(pPortCtrl
->portNo
, regIdx
), regValue
);
1928 /*******************************************************************************
1929 * mvEthVlanPrioRxQueue - Configure RX queue to capture VLAN tagged packets with
1930 * special priority bits [0-2]
1935 * void* pPortHandle - Pointer to port specific handler;
1936 * int bpduQueue - Special queue to capture VLAN tagged packets with special
1938 * Negative value (-1) means no special processing for these packets,
1939 * so they will be processed as regular packets.
1945 *******************************************************************************/
1946 MV_STATUS
mvEthVlanPrioRxQueue(void* pPortHandle
, int vlanPrio
, int vlanPrioQueue
)
1948 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
1951 if(vlanPrioQueue
>= MV_ETH_RX_Q_NUM
)
1953 mvOsPrintf("ethDrv: RX queue #%d is out of range\n", vlanPrioQueue
);
1954 return MV_BAD_PARAM
;
1958 mvOsPrintf("ethDrv: vlanPrio=%d is out of range\n", vlanPrio
);
1959 return MV_BAD_PARAM
;
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
);
1971 /*******************************************************************************
1972 * mvEthBpduRxQueue - Configure RX queue to capture BPDU packets.
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.
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.
1991 *******************************************************************************/
1992 MV_STATUS
mvEthBpduRxQueue(void* pPortHandle
, int bpduQueue
)
1994 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
1996 MV_U32 portCfgExtReg
;
1998 if(bpduQueue
>= MV_ETH_RX_Q_NUM
)
2000 mvOsPrintf("ethDrv: RX queue #%d is out of range\n", bpduQueue
);
2001 return MV_BAD_PARAM
;
2004 portCfgExtReg
= MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl
->portNo
));
2006 portCfgReg
= MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
));
2009 pPortCtrl
->portConfig
.rxBpduQ
= bpduQueue
;
2011 portCfgReg
&= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK
;
2012 portCfgReg
|= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl
->portConfig
.rxBpduQ
);
2014 MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
), portCfgReg
);
2016 portCfgExtReg
|= ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK
;
2020 pPortCtrl
->portConfig
.rxBpduQ
= -1;
2021 /* no special processing for BPDU packets */
2022 portCfgExtReg
&= (~ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK
);
2025 MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl
->portNo
), portCfgExtReg
);
2031 /*******************************************************************************
2032 * mvEthArpRxQueue - Configure RX queue to capture ARP packets.
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.
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
2048 *******************************************************************************/
2049 MV_STATUS
mvEthArpRxQueue(void* pPortHandle
, int arpQueue
)
2051 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2054 if(arpQueue
>= MV_ETH_RX_Q_NUM
)
2056 mvOsPrintf("ethDrv: RX queue #%d is out of range\n", arpQueue
);
2057 return MV_BAD_PARAM
;
2060 portCfgReg
= MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
));
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
);
2068 portCfgReg
&= (~ETH_REJECT_ARP_BCAST_MASK
);
2072 pPortCtrl
->portConfig
.rxArpQ
= -1;
2073 portCfgReg
|= ETH_REJECT_ARP_BCAST_MASK
;
2076 MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
), portCfgReg
);
2082 /*******************************************************************************
2083 * mvEthTcpRxQueue - Configure RX queue to capture TCP packets.
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.
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
2100 *******************************************************************************/
2101 MV_STATUS
mvEthTcpRxQueue(void* pPortHandle
, int tcpQueue
)
2103 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2106 if(tcpQueue
>= MV_ETH_RX_Q_NUM
)
2108 mvOsPrintf("ethDrv: RX queue #%d is out of range\n", tcpQueue
);
2109 return MV_BAD_PARAM
;
2111 portCfgReg
= MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
));
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
);
2119 portCfgReg
|= ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK
;
2123 pPortCtrl
->portConfig
.rxTcpQ
= -1;
2124 portCfgReg
&= (~ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK
);
2127 MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
), portCfgReg
);
2133 /*******************************************************************************
2134 * mvEthUdpRxQueue - Configure RX queue to capture UDP packets.
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.
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
2151 *******************************************************************************/
2152 MV_STATUS
mvEthUdpRxQueue(void* pPortHandle
, int udpQueue
)
2154 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2157 if(udpQueue
>= MV_ETH_RX_Q_NUM
)
2159 mvOsPrintf("ethDrv: RX queue #%d is out of range\n", udpQueue
);
2160 return MV_BAD_PARAM
;
2163 portCfgReg
= MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
));
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
);
2171 portCfgReg
|= ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK
;
2175 pPortCtrl
->portConfig
.rxUdpQ
= -1;
2176 portCfgReg
&= ~ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK
;
2179 MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl
->portNo
), portCfgReg
);
2185 /******************************************************************************/
2186 /* Speed, Duplex, FlowControl routines */
2187 /******************************************************************************/
2189 /*******************************************************************************
2190 * mvEthSpeedDuplexSet - Set Speed and Duplex of the port.
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.
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.
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)
2211 *******************************************************************************/
2212 MV_STATUS
mvEthSpeedDuplexSet(void* pPortHandle
, MV_ETH_PORT_SPEED speed
,
2213 MV_ETH_PORT_DUPLEX duplex
)
2215 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2216 int port
= pPortCtrl
->portNo
;
2217 MV_U32 portSerialCtrlReg
;
2219 if( (port
< 0) || (port
>= (int)mvCtrlEthMaxPortGet()) )
2220 return MV_OUT_OF_RANGE
;
2222 pPortCtrl
= ethPortCtrl
[port
];
2223 if(pPortCtrl
== NULL
)
2224 return MV_NOT_FOUND
;
2226 /* Check validity */
2227 if( (speed
== MV_ETH_SPEED_1000
) && (duplex
== MV_ETH_DUPLEX_HALF
) )
2228 return MV_BAD_PARAM
;
2230 portSerialCtrlReg
= MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port
));
2234 case MV_ETH_SPEED_AN
:
2235 portSerialCtrlReg
&= ~ETH_DISABLE_SPEED_AUTO_NEG_MASK
;
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
;
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
;
2250 case MV_ETH_SPEED_1000
:
2251 portSerialCtrlReg
|= ETH_DISABLE_SPEED_AUTO_NEG_MASK
;
2252 portSerialCtrlReg
|= ETH_SET_GMII_SPEED_1000_MASK
;
2256 mvOsPrintf("ethDrv: Unexpected Speed value %d\n", speed
);
2257 return MV_BAD_VALUE
;
2262 case MV_ETH_DUPLEX_AN
:
2263 portSerialCtrlReg
&= ~ETH_DISABLE_DUPLEX_AUTO_NEG_MASK
;
2266 case MV_ETH_DUPLEX_HALF
:
2267 portSerialCtrlReg
|= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK
;
2268 portSerialCtrlReg
&= ~ETH_SET_FULL_DUPLEX_MASK
;
2271 case MV_ETH_DUPLEX_FULL
:
2272 portSerialCtrlReg
|= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK
;
2273 portSerialCtrlReg
|= ETH_SET_FULL_DUPLEX_MASK
;
2277 mvOsPrintf("ethDrv: Unexpected Duplex value %d\n", duplex
);
2278 return MV_BAD_VALUE
;
2280 MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port
), portSerialCtrlReg
);
2285 /*******************************************************************************
2286 * mvEthFlowCtrlSet - Set Flow Control of the port.
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.
2295 * void* pPortHandle - Pointer to port specific handler;
2296 * MV_ETH_PORT_FC flowControl - Flow control of the port.
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
2304 *******************************************************************************/
2305 MV_STATUS
mvEthFlowCtrlSet(void* pPortHandle
, MV_ETH_PORT_FC flowControl
)
2307 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2308 int port
= pPortCtrl
->portNo
;
2309 MV_U32 portSerialCtrlReg
;
2311 if( (port
< 0) || (port
>= (int)mvCtrlEthMaxPortGet() ) )
2312 return MV_OUT_OF_RANGE
;
2314 pPortCtrl
= ethPortCtrl
[port
];
2315 if(pPortCtrl
== NULL
)
2316 return MV_NOT_FOUND
;
2318 portSerialCtrlReg
= MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port
));
2321 case MV_ETH_FC_AN_ADV_DIS
:
2322 portSerialCtrlReg
&= ~ETH_DISABLE_FC_AUTO_NEG_MASK
;
2323 portSerialCtrlReg
&= ~ETH_ADVERTISE_SYM_FC_MASK
;
2326 case MV_ETH_FC_AN_ADV_SYM
:
2327 portSerialCtrlReg
&= ~ETH_DISABLE_FC_AUTO_NEG_MASK
;
2328 portSerialCtrlReg
|= ETH_ADVERTISE_SYM_FC_MASK
;
2331 case MV_ETH_FC_DISABLE
:
2332 portSerialCtrlReg
|= ETH_DISABLE_FC_AUTO_NEG_MASK
;
2333 portSerialCtrlReg
&= ~ETH_SET_FLOW_CTRL_MASK
;
2336 case MV_ETH_FC_ENABLE
:
2337 portSerialCtrlReg
|= ETH_DISABLE_FC_AUTO_NEG_MASK
;
2338 portSerialCtrlReg
|= ETH_SET_FLOW_CTRL_MASK
;
2342 mvOsPrintf("ethDrv: Unexpected FlowControl value %d\n", flowControl
);
2343 return MV_BAD_VALUE
;
2345 MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port
), portSerialCtrlReg
);
2350 /*******************************************************************************
2351 * mvEthHeaderModeSet - Set port header mode.
2354 * This function configures the port to work in Marvell-Header mode.
2357 * void* pPortHandle - Pointer to port specific handler;
2358 * MV_ETH_HEADER_MODE headerMode - The header mode to set the port in.
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.
2367 *******************************************************************************/
2368 MV_STATUS
mvEthHeaderModeSet(void* pPortHandle
, MV_ETH_HEADER_MODE headerMode
)
2370 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2371 int port
= pPortCtrl
->portNo
;
2373 MV_U32 numRxQ
= MV_ETH_RX_Q_NUM
;
2375 if((port
< 0) || (port
>= mvCtrlEthMaxPortGet()))
2376 return MV_OUT_OF_RANGE
;
2378 pPortCtrl
= ethPortCtrl
[port
];
2379 if(pPortCtrl
== NULL
)
2380 return MV_NOT_FOUND
;
2382 mvHeaderReg
= MV_REG_READ(ETH_PORT_MARVELL_HEADER_REG(port
));
2383 /* Disable header mode. */
2384 mvHeaderReg
&= ~ETH_MVHDR_EN_MASK
;
2386 if(headerMode
!= MV_ETH_DISABLE_HEADER_MODE
)
2388 /* Enable Header mode. */
2389 mvHeaderReg
|= ETH_MVHDR_EN_MASK
;
2391 /* Clear DA-Prefix & MHMask fields.*/
2392 mvHeaderReg
&= ~(ETH_MVHDR_DAPREFIX_MASK
| ETH_MVHDR_MHMASK_MASK
);
2398 case(MV_ETH_ENABLE_HEADER_MODE_PRI_2_1
):
2399 mvHeaderReg
|= ETH_MVHDR_DAPREFIX_PRI_1_2
;
2401 case(MV_ETH_ENABLE_HEADER_MODE_PRI_DBNUM
):
2402 mvHeaderReg
|= ETH_MVHDR_DAPREFIX_DBNUM_PRI
;
2404 case(MV_ETH_ENABLE_HEADER_MODE_PRI_SPID
):
2405 mvHeaderReg
|= ETH_MVHDR_DAPREFIX_SPID_PRI
;
2414 mvHeaderReg
|= ETH_MVHDR_MHMASK_4_QUEUE
;
2417 mvHeaderReg
|= ETH_MVHDR_MHMASK_8_QUEUE
;
2425 MV_REG_WRITE(ETH_PORT_MARVELL_HEADER_REG(port
), mvHeaderReg
);
2430 #if (MV_ETH_VERSION >= 4)
2431 /*******************************************************************************
2432 * mvEthEjpModeSet - Enable / Disable EJP policy for TX.
2438 * void* pPortHandle - Pointer to port specific handler;
2439 * MV_BOOL TRUE - enable EJP mode
2440 * FALSE - disable EJP mode
2448 *******************************************************************************/
2449 MV_STATUS
mvEthEjpModeSet(void* pPortHandle
, int mode
)
2451 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2452 int port
= pPortCtrl
->portNo
;
2454 if((port
< 0) || (port
>= mvCtrlEthMaxPortGet()))
2455 return MV_OUT_OF_RANGE
;
2457 pPortCtrl
= ethPortCtrl
[port
];
2458 if(pPortCtrl
== NULL
)
2459 return MV_NOT_FOUND
;
2461 pPortCtrl
->portConfig
.ejpMode
= mode
;
2465 MV_REG_WRITE(ETH_TXQ_CMD_1_REG(port
), ETH_TX_EJP_ENABLE_MASK
);
2470 MV_REG_WRITE(ETH_TXQ_CMD_1_REG(port
), 0);
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
)));
2478 #endif /* MV_ETH_VERSION >= 4 */
2480 /*******************************************************************************
2481 * mvEthStatusGet - Get major properties of the port .
2484 * This function get major properties of the port (link, speed, duplex,
2485 * flowControl, etc) and return them using the single structure.
2488 * void* pPortHandle - Pointer to port specific handler;
2491 * MV_ETH_PORT_STATUS* pStatus - Pointer to structure, were port status
2496 *******************************************************************************/
2497 void mvEthStatusGet(void* pPortHandle
, MV_ETH_PORT_STATUS
* pStatus
)
2499 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2500 int port
= pPortCtrl
->portNo
;
2504 regValue
= MV_REG_READ( ETH_PORT_STATUS_REG(port
) );
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
;
2511 pStatus
->speed
= MV_ETH_SPEED_10
;
2513 if(regValue
& ETH_LINK_UP_MASK
)
2514 pStatus
->isLinkUp
= MV_TRUE
;
2516 pStatus
->isLinkUp
= MV_FALSE
;
2518 if(regValue
& ETH_FULL_DUPLEX_MASK
)
2519 pStatus
->duplex
= MV_ETH_DUPLEX_FULL
;
2521 pStatus
->duplex
= MV_ETH_DUPLEX_HALF
;
2524 if(regValue
& ETH_ENABLE_RCV_FLOW_CTRL_MASK
)
2525 pStatus
->flowControl
= MV_ETH_FC_ENABLE
;
2527 pStatus
->flowControl
= MV_ETH_FC_DISABLE
;
2531 /******************************************************************************/
2532 /* PHY Control Functions */
2533 /******************************************************************************/
2536 /*******************************************************************************
2537 * mvEthPhyAddrSet - Set the ethernet port PHY address.
2540 * This routine set the ethernet port PHY address according to given
2544 * void* pPortHandle - Pointer to port specific handler;
2545 * int phyAddr - PHY address
2550 *******************************************************************************/
2551 void mvEthPhyAddrSet(void* pPortHandle
, int phyAddr
)
2553 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2554 int port
= pPortCtrl
->portNo
;
2555 unsigned int regData
;
2557 regData
= MV_REG_READ(ETH_PHY_ADDR_REG(port
));
2559 regData
&= ~ETH_PHY_ADDR_MASK
;
2562 MV_REG_WRITE(ETH_PHY_ADDR_REG(port
), regData
);
2567 /*******************************************************************************
2568 * mvEthPhyAddrGet - Get the ethernet port PHY address.
2571 * This routine returns the given ethernet port PHY address.
2574 * void* pPortHandle - Pointer to port specific handler;
2577 * RETURN: int - PHY address.
2579 *******************************************************************************/
2580 int mvEthPhyAddrGet(void* pPortHandle
)
2582 ETH_PORT_CTRL
* pPortCtrl
= (ETH_PORT_CTRL
*)pPortHandle
;
2583 int port
= pPortCtrl
->portNo
;
2584 unsigned int regData
;
2586 regData
= MV_REG_READ(ETH_PHY_ADDR_REG(port
));
2588 return ((regData
>> (5 * port
)) & 0x1f);
2591 /******************************************************************************/
2592 /* Descriptor handling Functions */
2593 /******************************************************************************/
2595 /*******************************************************************************
2596 * etherInitRxDescRing - Curve a Rx chain desc list and buffer in memory.
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.
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.
2614 * The routine updates the Ethernet port control struct with information
2615 * regarding the Rx descriptors and buffers.
2619 *******************************************************************************/
2620 static void ethInitRxDescRing(ETH_PORT_CTRL
* pPortCtrl
, int queue
)
2622 ETH_RX_DESC
*pRxDescBase
, *pRxDesc
, *pRxPrevDesc
;
2623 int ix
, rxDescNum
= pPortCtrl
->rxQueueConfig
[queue
].descrNum
;
2624 ETH_QUEUE_CTRL
*pQueueCtrl
= &pPortCtrl
->rxQueue
[queue
];
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
);
2630 pRxDesc
= (ETH_RX_DESC
*)pRxDescBase
;
2631 pRxPrevDesc
= pRxDesc
;
2633 /* initialize the Rx descriptors ring */
2634 for (ix
=0; ix
<rxDescNum
; ix
++)
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))
2644 /* Closing Rx descriptors ring */
2645 pRxPrevDesc
->nextDescPtr
= (MV_U32
)ethDescVirtToPhy(pQueueCtrl
, (void*)pRxDescBase
);
2649 pRxDesc
= (ETH_RX_DESC
*)((MV_ULONG
)pRxDesc
+ ETH_RX_DESC_ALIGNED_SIZE
);
2650 pRxPrevDesc
->nextDescPtr
= (MV_U32
)ethDescVirtToPhy(pQueueCtrl
, (void*)pRxDesc
);
2652 ETH_DESCR_FLUSH_INV(pPortCtrl
, pRxPrevDesc
);
2655 pQueueCtrl
->pCurrentDescr
= pRxDescBase
;
2656 pQueueCtrl
->pUsedDescr
= pRxDescBase
;
2658 pQueueCtrl
->pFirstDescr
= pRxDescBase
;
2659 pQueueCtrl
->pLastDescr
= pRxDesc
;
2660 pQueueCtrl
->resource
= 0;
2663 void ethResetRxDescRing(void* pPortHndl
, int queue
)
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
;
2669 pQueueCtrl
->resource
= 0;
2670 if(pQueueCtrl
->pFirstDescr
!= NULL
)
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
)
2682 pRxDesc
= RX_NEXT_DESC_PTR(pRxDesc
, pQueueCtrl
);
2684 pQueueCtrl
->pCurrentDescr
= pQueueCtrl
->pFirstDescr
;
2685 pQueueCtrl
->pUsedDescr
= pQueueCtrl
->pFirstDescr
;
2687 /* Update RX Command register */
2688 pPortCtrl
->portRxQueueCmdReg
|= (1 << queue
);
2691 MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(pPortCtrl
->portNo
, queue
),
2692 (MV_U32
)ethDescVirtToPhy(pQueueCtrl
, pQueueCtrl
->pCurrentDescr
) );
2696 /* Update RX Command register */
2697 pPortCtrl
->portRxQueueCmdReg
&= ~(1 << queue
);
2700 MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(pPortCtrl
->portNo
, queue
), 0);
2704 /*******************************************************************************
2705 * etherInitTxDescRing - Curve a Tx chain desc list and buffer in memory.
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.
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.
2724 * The routine updates the Ethernet port control struct with information
2725 * regarding the Tx descriptors and buffers.
2729 *******************************************************************************/
2730 static void ethInitTxDescRing(ETH_PORT_CTRL
* pPortCtrl
, int queue
)
2732 ETH_TX_DESC
*pTxDescBase
, *pTxDesc
, *pTxPrevDesc
;
2733 int ix
, txDescNum
= pPortCtrl
->txQueueConfig
[queue
].descrNum
;
2734 ETH_QUEUE_CTRL
*pQueueCtrl
= &pPortCtrl
->txQueue
[queue
];
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
);
2740 pTxDesc
= (ETH_TX_DESC
*)pTxDescBase
;
2741 pTxPrevDesc
= pTxDesc
;
2743 /* initialize the Tx descriptors ring */
2744 for (ix
=0; ix
<txDescNum
; ix
++)
2746 pTxDesc
->byteCnt
= 0x0000;
2747 pTxDesc
->L4iChk
= 0x0000;
2748 pTxDesc
->cmdSts
= ETH_BUFFER_OWNED_BY_HOST
;
2749 pTxDesc
->bufPtr
= 0x0;
2750 pTxDesc
->returnInfo
= 0x0;
2752 pTxPrevDesc
= pTxDesc
;
2754 if(ix
== (txDescNum
-1))
2756 /* Closing Tx descriptors ring */
2757 pTxPrevDesc
->nextDescPtr
= (MV_U32
)ethDescVirtToPhy(pQueueCtrl
, (void*)pTxDescBase
);
2761 pTxDesc
= (ETH_TX_DESC
*)((MV_ULONG
)pTxDesc
+ ETH_TX_DESC_ALIGNED_SIZE
);
2762 pTxPrevDesc
->nextDescPtr
= (MV_U32
)ethDescVirtToPhy(pQueueCtrl
, (void*)pTxDesc
);
2764 ETH_DESCR_FLUSH_INV(pPortCtrl
, pTxPrevDesc
);
2767 pQueueCtrl
->pCurrentDescr
= pTxDescBase
;
2768 pQueueCtrl
->pUsedDescr
= pTxDescBase
;
2770 pQueueCtrl
->pFirstDescr
= pTxDescBase
;
2771 pQueueCtrl
->pLastDescr
= pTxDesc
;
2772 /* Leave one TX descriptor out of use */
2773 pQueueCtrl
->resource
= txDescNum
- 1;
2776 void ethResetTxDescRing(void* pPortHndl
, int queue
)
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
;
2782 pQueueCtrl
->resource
= 0;
2783 if(pQueueCtrl
->pFirstDescr
!= NULL
)
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
)
2796 pTxDesc
= TX_NEXT_DESC_PTR(pTxDesc
, pQueueCtrl
);
2798 /* Leave one TX descriptor out of use */
2799 pQueueCtrl
->resource
--;
2800 pQueueCtrl
->pCurrentDescr
= pQueueCtrl
->pFirstDescr
;
2801 pQueueCtrl
->pUsedDescr
= pQueueCtrl
->pFirstDescr
;
2803 /* Update TX Command register */
2804 pPortCtrl
->portTxQueueCmdReg
|= MV_32BIT_LE_FAST(1 << queue
);
2806 MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(pPortCtrl
->portNo
, queue
),
2807 (MV_U32
)ethDescVirtToPhy(pQueueCtrl
, pQueueCtrl
->pCurrentDescr
) );
2811 /* Update TX Command register */
2812 pPortCtrl
->portTxQueueCmdReg
&= MV_32BIT_LE_FAST(~(1 << queue
));
2814 MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(pPortCtrl
->portNo
, queue
), 0 );
2818 /*******************************************************************************
2819 * ethAllocDescrMemory - Free memory allocated for RX and TX descriptors.
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.
2827 * int size - size of memory should be allocated.
2831 *******************************************************************************/
2832 static MV_U8
* ethAllocDescrMemory(ETH_PORT_CTRL
* pPortCtrl
, int descSize
,
2833 MV_ULONG
* pPhysAddr
, MV_U32
*memHandle
)
2837 #if defined(ETH_DESCR_IN_SRAM)
2838 if(ethDescInSram
== MV_TRUE
)
2839 pVirt
= (char*)mvSramMalloc(descSize
, pPhysAddr
);
2841 #endif /* ETH_DESCR_IN_SRAM */
2843 #ifdef ETH_DESCR_UNCACHED
2844 pVirt
= (MV_U8
*)mvOsIoUncachedMalloc(pPortCtrl
->osHandle
, descSize
,
2845 pPhysAddr
,memHandle
);
2847 pVirt
= (MV_U8
*)mvOsIoCachedMalloc(pPortCtrl
->osHandle
, descSize
,
2848 pPhysAddr
, memHandle
);
2849 #endif /* ETH_DESCR_UNCACHED */
2851 memset(pVirt
, 0, descSize
);
2856 /*******************************************************************************
2857 * ethFreeDescrMemory - Free memory allocated for RX and TX descriptors.
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.
2865 * void* pVirtAddr - virtual pointer to memory allocated for RX and TX
2870 *******************************************************************************/
2871 void ethFreeDescrMemory(ETH_PORT_CTRL
* pPortCtrl
, MV_BUF_INFO
* pDescBuf
)
2873 if( (pDescBuf
== NULL
) || (pDescBuf
->bufVirtPtr
== NULL
) )
2876 #if defined(ETH_DESCR_IN_SRAM)
2879 mvSramFree(pDescBuf
->bufSize
, pDescBuf
->bufPhysAddr
, pDescBuf
->bufVirtPtr
);
2882 #endif /* ETH_DESCR_IN_SRAM */
2884 #ifdef ETH_DESCR_UNCACHED
2885 mvOsIoUncachedFree(pPortCtrl
->osHandle
, pDescBuf
->bufSize
, pDescBuf
->bufPhysAddr
,
2886 pDescBuf
->bufVirtPtr
,pDescBuf
->memHandle
);
2888 mvOsIoCachedFree(pPortCtrl
->osHandle
, pDescBuf
->bufSize
, pDescBuf
->bufPhysAddr
,
2889 pDescBuf
->bufVirtPtr
,pDescBuf
->memHandle
);
2890 #endif /* ETH_DESCR_UNCACHED */
2893 /******************************************************************************/
2894 /* Other Functions */
2895 /******************************************************************************/
2897 void mvEthPortPowerUp(int port
)
2901 /* MAC Cause register should be cleared */
2902 MV_REG_WRITE(ETH_UNIT_INTR_CAUSE_REG(port
), 0);
2904 if (mvBoardIsPortInSgmii(port
))
2905 mvEthPortSgmiiConfig(port
);
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);
2914 void mvEthPortPowerDown(int port
)
2918 /* Port must be DISABLED */
2919 regVal
= MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port
));
2920 if( (regVal
& ETH_PORT_ENABLE_MASK
) != 0)
2922 mvOsPrintf("ethPort #%d: PowerDown - port must be Disabled (PSC=0x%x)\n",
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);
2933 static void mvEthPortSgmiiConfig(int port
)
2937 regVal
= MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port
));
2939 regVal
|= (ETH_SGMII_MODE_MASK
/*| ETH_INBAND_AUTO_NEG_ENABLE_MASK */);
2940 regVal
&= (~ETH_INBAND_AUTO_NEG_BYPASS_MASK
);
2942 MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port
), regVal
);