blob: a79cedffc7c325bd9948b995504a9c2ab39257f0 [file] [log] [blame]
/******************************************************************************
*
* Name: sky2le.h
* Project: Gigabit Ethernet Adapters, Common Modules
* Version: $Revision: 1.10 $
* Date: $Date: 2005/12/14 16:11:35 $
* Purpose: Common list element definitions and access macros.
*
******************************************************************************/
/******************************************************************************
*
* LICENSE:
* (C)Copyright 2003-2004 Marvell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* The information in this file is provided "AS IS" without warranty.
* /LICENSE
*
******************************************************************************/
#ifndef __INC_SKY2LE_H
#define __INC_SKY2LE_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* defines ********************************************************************/
#define MIN_LEN_OF_LE_TAB 128
#define MAX_LEN_OF_LE_TAB 4096
#ifdef USE_POLLING_UNIT
#define NUM_LE_POLLING_UNIT 2
#endif
#define MAX_FRAG_OVERHEAD 10
/* Macro for aligning a given value */
#define SK_ALIGN_SIZE(Value, Alignment, AlignedVal) { \
(AlignedVal) = (((Value) + (Alignment) - 1) & (~((Alignment) - 1)));\
}
/******************************************************************************
*
* LE2DWord() - Converts the given Little Endian value to machine order value
*
* Description:
* This function converts the Little Endian value received as an argument to
* the machine order value.
*
* Returns:
* The converted value
*
*/
#ifdef SK_LITTLE_ENDIAN
#ifndef SK_USE_REV_DESC
#define LE2DWord(value) (value)
#else /* SK_USE_REV_DESC */
#define LE2DWord(value) \
((((value)<<24L) & 0xff000000L) + \
(((value)<< 8L) & 0x00ff0000L) + \
(((value)>> 8L) & 0x0000ff00L) + \
(((value)>>24L) & 0x000000ffL))
#endif /* SK_USE_REV_DESC */
#else /* !SK_LITTLE_ENDIAN */
#ifndef SK_USE_REV_DESC
#define LE2DWord(value) \
((((value)<<24L) & 0xff000000L) + \
(((value)<< 8L) & 0x00ff0000L) + \
(((value)>> 8L) & 0x0000ff00L) + \
(((value)>>24L) & 0x000000ffL))
#else /* SK_USE_REV_DESC */
#define LE2DWord(value) (value)
#endif /* SK_USE_REV_DESC */
#endif /* !SK_LITTLE_ENDIAN */
/******************************************************************************
*
* DWord2LE() - Converts the given value to a Little Endian value
*
* Description:
* This function converts the value received as an argument to a Little Endian
* value on Big Endian machines. If the machine running the code is Little
* Endian, then no conversion is done.
*
* Returns:
* The converted value
*
*/
#ifdef SK_LITTLE_ENDIAN
#ifndef SK_USE_REV_DESC
#define DWord2LE(value) (value)
#else /* SK_USE_REV_DESC */
#define DWord2LE(value) \
((((value)<<24L) & 0xff000000L) + \
(((value)<< 8L) & 0x00ff0000L) + \
(((value)>> 8L) & 0x0000ff00L) + \
(((value)>>24L) & 0x000000ffL))
#endif /* SK_USE_REV_DESC */
#else /* !SK_LITTLE_ENDIAN */
#ifndef SK_USE_REV_DESC
#define DWord2LE(value) \
((((value)<<24L) & 0xff000000L) + \
(((value)<< 8L) & 0x00ff0000L) + \
(((value)>> 8L) & 0x0000ff00L) + \
(((value)>>24L) & 0x000000ffL))
#else /* SK_USE_REV_DESC */
#define DWord2LE(value) (value)
#endif /* SK_USE_REV_DESC */
#endif /* !SK_LITTLE_ENDIAN */
/******************************************************************************
*
* LE2Word() - Converts the given Little Endian value to machine order value
*
* Description:
* This function converts the Little Endian value received as an argument to
* the machine order value.
*
* Returns:
* The converted value
*
*/
#ifdef SK_LITTLE_ENDIAN
#ifndef SK_USE_REV_DESC
#define LE2Word(value) (value)
#else /* SK_USE_REV_DESC */
#define LE2Word(value) \
((((value)<< 8L) & 0xff00) + \
(((value)>> 8L) & 0x00ff))
#endif /* SK_USE_REV_DESC */
#else /* !SK_LITTLE_ENDIAN */
#ifndef SK_USE_REV_DESC
#define LE2Word(value) \
((((value)<< 8L) & 0xff00) + \
(((value)>> 8L) & 0x00ff))
#else /* SK_USE_REV_DESC */
#define LE2Word(value) (value)
#endif /* SK_USE_REV_DESC */
#endif /* !SK_LITTLE_ENDIAN */
/******************************************************************************
*
* Word2LE() - Converts the given value to a Little Endian value
*
* Description:
* This function converts the value received as an argument to a Little Endian
* value on Big Endian machines. If the machine running the code is Little
* Endian, then no conversion is done.
*
* Returns:
* The converted value
*
*/
#ifdef SK_LITTLE_ENDIAN
#ifndef SK_USE_REV_DESC
#define Word2LE(value) (value)
#else /* SK_USE_REV_DESC */
#define Word2LE(value) \
((((value)<< 8L) & 0xff00) + \
(((value)>> 8L) & 0x00ff))
#endif /* SK_USE_REV_DESC */
#else /* !SK_LITTLE_ENDIAN */
#ifndef SK_USE_REV_DESC
#define Word2LE(value) \
((((value)<< 8L) & 0xff00) + \
(((value)>> 8L) & 0x00ff))
#else /* SK_USE_REV_DESC */
#define Word2LE(value) (value)
#endif /* SK_USE_REV_DESC */
#endif /* !SK_LITTLE_ENDIAN */
/******************************************************************************
*
* Transmit list element macros
*
*/
#define TXLE_SET_ADDR(pLE, Addr) \
((pLE)->Tx.TxUn.BufAddr = DWord2LE(Addr))
#define TXLE_SET_LSLEN(pLE, Len) \
((pLE)->Tx.TxUn.LargeSend.Length = Word2LE(Len))
#define TXLE_SET_STACS(pLE, Start) \
((pLE)->Tx.TxUn.ChkSum.TxTcpSp = Word2LE(Start))
#define TXLE_SET_WRICS(pLE, Write) \
((pLE)->Tx.TxUn.ChkSum.TxTcpWp = Word2LE(Write))
#define TXLE_SET_INICS(pLE, Ini) ((pLE)->Tx.Send.InitCsum = Word2LE(Ini))
#define TXLE_SET_LEN(pLE, Len) ((pLE)->Tx.Send.BufLen = Word2LE(Len))
#define TXLE_SET_VLAN(pLE, Vlan) ((pLE)->Tx.Send.VlanTag = Word2LE(Vlan))
#define TXLE_SET_LCKCS(pLE, Lock) ((pLE)->Tx.ControlFlags = (Lock))
#define TXLE_SET_CTRL(pLE, Ctrl) ((pLE)->Tx.ControlFlags = (Ctrl))
#define TXLE_SET_OPC(pLE, Opc) ((pLE)->Tx.Opcode = (Opc))
#define TXLE_GET_ADDR(pLE) LE2DWord((pLE)->Tx.TxUn.BufAddr)
#define TXLE_GET_LSLEN(pLE) LE2Word((pLE)->Tx.TxUn.LargeSend.Length)
#define TXLE_GET_STACS(pLE) LE2Word((pLE)->Tx.TxUn.ChkSum.TxTcpSp)
#define TXLE_GET_WRICS(pLE) LE2Word((pLE)->Tx.TxUn.ChkSum.TxTcpWp)
#define TXLE_GET_INICS(pLE) LE2Word((pLE)->Tx.Send.InitCsum)
#define TXLE_GET_LEN(pLE) LE2Word((pLE)->Tx.Send.BufLen)
#define TXLE_GET_VLAN(pLE) LE2Word((pLE)->Tx.Send.VlanTag)
#define TXLE_GET_LCKCS(pLE) ((pLE)->Tx.ControlFlags)
#define TXLE_GET_CTRL(pLE) ((pLE)->Tx.ControlFlags)
#define TXLE_GET_OPC(pLE) ((pLE)->Tx.Opcode)
/******************************************************************************
*
* Receive list element macros
*
*/
#define RXLE_SET_ADDR(pLE, Addr) \
((pLE)->Rx.RxUn.BufAddr = (SK_U32) DWord2LE(Addr))
#define RXLE_SET_STACS2(pLE, Offs) \
((pLE)->Rx.RxUn.ChkSum.RxTcpSp2 = Word2LE(Offs))
#define RXLE_SET_STACS1(pLE, Offs) \
((pLE)->Rx.RxUn.ChkSum.RxTcpSp1 = Word2LE(Offs))
#define RXLE_SET_LEN(pLE, Len) ((pLE)->Rx.BufferLength = Word2LE(Len))
#define RXLE_SET_CTRL(pLE, Ctrl) ((pLE)->Rx.ControlFlags = (Ctrl))
#define RXLE_SET_OPC(pLE, Opc) ((pLE)->Rx.Opcode = (Opc))
#define RXLE_GET_ADDR(pLE) LE2DWord((pLE)->Rx.RxUn.BufAddr)
#define RXLE_GET_STACS2(pLE) LE2Word((pLE)->Rx.RxUn.ChkSum.RxTcpSp2)
#define RXLE_GET_STACS1(pLE) LE2Word((pLE)->Rx.RxUn.ChkSum.RxTcpSp1)
#define RXLE_GET_LEN(pLE) LE2Word((pLE)->Rx.BufferLength)
#define RXLE_GET_CTRL(pLE) ((pLE)->Rx.ControlFlags)
#define RXLE_GET_OPC(pLE) ((pLE)->Rx.Opcode)
/******************************************************************************
*
* Status list element macros
*
*/
#define STLE_SET_OPC(pLE, Opc) ((pLE)->St.Opcode = (Opc))
#define STLE_GET_FRSTATUS(pLE) LE2DWord((pLE)->St.StUn.StRxStatWord)
#define STLE_GET_TIST(pLE) LE2DWord((pLE)->St.StUn.StRxTimeStamp)
#define STLE_GET_TCP1(pLE) LE2Word((pLE)->St.StUn.StRxTCPCSum.RxTCPSum1)
#define STLE_GET_TCP2(pLE) LE2Word((pLE)->St.StUn.StRxTCPCSum.RxTCPSum2)
#define STLE_GET_LEN(pLE) LE2Word((pLE)->St.Stat.BufLen)
#define STLE_GET_VLAN(pLE) LE2Word((pLE)->St.Stat.VlanTag)
#define STLE_GET_LINK(pLE) ((pLE)->St.Link)
#define STLE_GET_OPC(pLE) ((pLE)->St.Opcode)
#define STLE_GET_DONE_IDX(pLE,LowVal,HighVal) { \
(LowVal) = LE2DWord((pLE)->St.StUn.StTxStatLow); \
(HighVal) = LE2Word((pLE)->St.Stat.StTxStatHi); \
}
#define STLE_GET_RSS(pLE) LE2DWord((pLE)->St.StUn.StRxRssValue)
#define STLE_GET_IPBIT(pLE) ((pLE)->St.Stat.Rss.FlagField & RSS_IP_FLAG)
#define STLE_GET_TCPBIT(pLE) ((pLE)->St.Stat.Rss.FlagField & RSS_TCP_FLAG)
/* I always take both values as a paramter to avoid typos */
#define STLE_GET_DONE_IDX_TXA1(LowVal,HighVal) \
(((LowVal) & STLE_TXA1_MSKL) >> STLE_TXA1_SHIFTL)
#define STLE_GET_DONE_IDX_TXS1(LowVal,HighVal) \
((LowVal & STLE_TXS1_MSKL) >> STLE_TXS1_SHIFTL)
#define STLE_GET_DONE_IDX_TXA2(LowVal,HighVal) \
(((LowVal & STLE_TXA2_MSKL) >> STLE_TXA2_SHIFTL) + \
((HighVal & STLE_TXA2_MSKH) << STLE_TXA2_SHIFTH))
#define STLE_GET_DONE_IDX_TXS2(LowVal,HighVal) \
((HighVal & STLE_TXS2_MSKH) >> STLE_TXS2_SHIFTH)
#define SK_Y2_RXSTAT_CHECK_PKT(Len, RxStat, IsOk) { \
(IsOk) = (((RxStat) & GMR_FS_RX_OK) != 0) && \
(((RxStat) & GMR_FS_ANY_ERR) == 0); \
\
if ((IsOk) && ((SK_U16)(((RxStat) & GMR_FS_LEN_MSK) >> \
GMR_FS_LEN_SHIFT) != (Len))) { \
/* length in MAC status differs from length in LE */\
(IsOk) = SK_FALSE; \
} \
}
/******************************************************************************
*
* Polling unit list element macros
*
* NOTE: the Idx must be <= 0xfff and PU_PUTIDX_VALID makes them valid
*
*/
#ifdef USE_POLLING_UNIT
#define POLE_SET_OPC(pLE, Opc) ((pLE)->Sa.Opcode = (Opc))
#define POLE_SET_LINK(pLE, Port) ((pLE)->Sa.Link = (Port))
#define POLE_SET_RXIDX(pLE, Idx) ((pLE)->Sa.RxIdxVld = Word2LE(Idx))
#define POLE_SET_TXAIDX(pLE, Idx) ((pLE)->Sa.TxAIdxVld = Word2LE(Idx))
#define POLE_SET_TXSIDX(pLE, Idx) ((pLE)->Sa.TxSIdxVld = Word2LE(Idx))
#define POLE_GET_OPC(pLE) ((pLE)->Sa.Opcode)
#define POLE_GET_LINK(pLE) ((pLE)->Sa.Link)
#define POLE_GET_RXIDX(pLE) LE2Word((pLE)->Sa.RxIdxVld)
#define POLE_GET_TXAIDX(pLE) LE2Word((pLE)->Sa.TxAIdxVld)
#define POLE_GET_TXSIDX(pLE) LE2Word((pLE)->Sa.TxSIdxVld)
#endif /* USE_POLLING_UNIT */
/******************************************************************************
*
* Debug macros for list elements
*
*/
#ifdef DEBUG
#define SK_DBG_DUMP_RX_LE(pLE) { \
SK_U8 Opcode; \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("=== RX_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n", \
pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \
((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\t (16bit) %04x %04x %04x %04x\n", \
((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \
((SK_U16 *) pLE)[3])); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\t (32bit) %08x %08x\n", \
((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \
Opcode = RXLE_GET_OPC(pLE); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ? \
"Hardware" : "Software")); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOpc: 0x%x ",Opcode)); \
switch (Opcode & (~HW_OWNER)) { \
case OP_BUFFER: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_BUFFER\n")); \
break; \
case OP_PACKET: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_PACKET\n")); \
break; \
case OP_ADDR64: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_ADDR64\n")); \
break; \
case OP_TCPSTART: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_TCPPAR\n")); \
break; \
case SW_OWNER: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tunused LE\n")); \
break; \
default: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tunknown Opcode!!!\n")); \
break; \
} \
if ((Opcode & OP_BUFFER) == OP_BUFFER) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tControl: 0x%x\n", RXLE_GET_CTRL(pLE))); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tBufLen: 0x%x\n", RXLE_GET_LEN(pLE))); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tLowAddr: 0x%x\n", RXLE_GET_ADDR(pLE))); \
} \
if ((Opcode & OP_ADDR64) == OP_ADDR64) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tHighAddr: 0x%x\n", RXLE_GET_ADDR(pLE))); \
} \
if ((Opcode & OP_TCPSTART) == OP_TCPSTART) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTCP Sum Start 1 : 0x%x\n", RXLE_GET_STACS1(pLE))); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTCP Sum Start 2 : 0x%x\n", RXLE_GET_STACS2(pLE))); \
} \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("=====================\n")); \
}
#define SK_DBG_DUMP_TX_LE(pLE) { \
SK_U8 Opcode; \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("=== TX_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n", \
pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \
((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\t (16bit) %04x %04x %04x %04x\n", \
((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \
((SK_U16 *) pLE)[3])); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\t (32bit) %08x %08x\n", \
((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \
Opcode = TXLE_GET_OPC(pLE); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ? \
"Hardware" : "Software")); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOpc: 0x%x ",Opcode)); \
switch (Opcode & (~HW_OWNER)) { \
case OP_TCPCHKSUM: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_TCPCHKSUM\n")); \
break; \
case OP_TCPIS: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_TCPIS\n")); \
break; \
case OP_TCPLCK: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_TCPLCK\n")); \
break; \
case OP_TCPLW: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_TCPLW\n")); \
break; \
case OP_TCPLSW: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_TCPLSW\n")); \
break; \
case OP_TCPLISW: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_TCPLISW\n")); \
break; \
case OP_ADDR64: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_ADDR64\n")); \
break; \
case OP_VLAN: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_VLAN\n")); \
break; \
case OP_ADDR64VLAN: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_ADDR64VLAN\n")); \
break; \
case OP_LRGLEN: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_LRGLEN\n")); \
break; \
case OP_LRGLENVLAN: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_LRGLENVLAN\n")); \
break; \
case OP_BUFFER: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_BUFFER\n")); \
break; \
case OP_PACKET: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_PACKET\n")); \
break; \
case OP_LARGESEND: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_LARGESEND\n")); \
break; \
case SW_OWNER: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tunused LE\n")); \
break; \
default: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tunknown Opcode!!!\n")); \
break; \
} \
if ((Opcode & OP_BUFFER) == OP_BUFFER) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tControl: 0x%x\n", TXLE_GET_CTRL(pLE))); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tBufLen: 0x%x\n", TXLE_GET_LEN(pLE))); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tLowAddr: 0x%x\n", TXLE_GET_ADDR(pLE))); \
} \
if ((Opcode & OP_ADDR64) == OP_ADDR64) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tHighAddr: 0x%x\n", TXLE_GET_ADDR(pLE))); \
} \
if ((Opcode & OP_VLAN) == OP_VLAN) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tVLAN Id: 0x%x\n", TXLE_GET_VLAN(pLE))); \
} \
if ((Opcode & OP_LRGLEN) == OP_LRGLEN) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tLarge send length: 0x%x\n", TXLE_GET_LSLEN(pLE))); \
} \
if ((Opcode &(~HW_OWNER)) <= OP_ADDR64) { \
if ((Opcode & OP_TCPWRITE) == OP_TCPWRITE) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTCP Sum Write: 0x%x\n", TXLE_GET_WRICS(pLE))); \
} \
if ((Opcode & OP_TCPSTART) == OP_TCPSTART) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTCP Sum Start: 0x%x\n", TXLE_GET_STACS(pLE))); \
} \
if ((Opcode & OP_TCPINIT) == OP_TCPINIT) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTCP Sum Init: 0x%x\n", TXLE_GET_INICS(pLE))); \
} \
if ((Opcode & OP_TCPLCK) == OP_TCPLCK) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTCP Sum Lock: 0x%x\n", TXLE_GET_LCKCS(pLE))); \
} \
} \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("=====================\n")); \
}
#define SK_DBG_DUMP_ST_LE(pLE) { \
SK_U8 Opcode; \
SK_U16 HighVal; \
SK_U32 LowVal; \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("=== ST_LIST_ELEMENT @addr: %p contains: %02x %02x %02x %02x %02x %02x %02x %02x\n",\
pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \
((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\t (16bit) %04x %04x %04x %04x\n", \
((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \
((SK_U16 *) pLE)[3])); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\t (32bit) %08x %08x\n", \
((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \
Opcode = STLE_GET_OPC(pLE); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == SW_OWNER) ? \
"Hardware" : "Software")); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOpc: 0x%x", Opcode)); \
Opcode &= (~HW_OWNER); \
switch (Opcode) { \
case OP_RXSTAT: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_RXSTAT\n")); \
break; \
case OP_RXTIMESTAMP: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_RXTIMESTAMP\n")); \
break; \
case OP_RXVLAN: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_RXVLAN\n")); \
break; \
case OP_RXCHKS: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_RXCHKS\n")); \
break; \
case OP_RXCHKSVLAN: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_RXCHKSVLAN\n")); \
break; \
case OP_RXTIMEVLAN: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_RXTIMEVLAN\n")); \
break; \
case OP_RSS_HASH: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_RSS_HASH\n")); \
break; \
case OP_TXINDEXLE: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_TXINDEXLE\n")); \
break; \
case HW_OWNER: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tunused LE\n")); \
break; \
default: \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tunknown status list element!!!\n")); \
break; \
} \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tPort: %c\n", 'A' + STLE_GET_LINK(pLE))); \
if (Opcode == OP_RXSTAT) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tFrameLen: 0x%x\n", STLE_GET_LEN(pLE))); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tFrameStat: 0x%x\n", STLE_GET_FRSTATUS(pLE))); \
} \
if ((Opcode & OP_RXVLAN) == OP_RXVLAN) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tVLAN Id: 0x%x\n", STLE_GET_VLAN(pLE))); \
} \
if ((Opcode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTimestamp: 0x%x\n", STLE_GET_TIST(pLE))); \
} \
if ((Opcode & OP_RXCHKS) == OP_RXCHKS) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTCP: 0x%x 0x%x\n", STLE_GET_TCP1(pLE), \
STLE_GET_TCP2(pLE))); \
} \
if (Opcode == OP_TXINDEXLE) { \
STLE_GET_DONE_IDX(pLE, LowVal, HighVal); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTx Index TxA1: 0x%x\n", \
STLE_GET_DONE_IDX_TXA1(LowVal,HighVal))); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTx Index TxS1: 0x%x\n", \
STLE_GET_DONE_IDX_TXS1(LowVal,HighVal))); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTx Index TxA2: 0x%x\n", \
STLE_GET_DONE_IDX_TXA2(LowVal,HighVal))); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTx Index TxS2: 0x%x\n", \
STLE_GET_DONE_IDX_TXS2(LowVal,HighVal))); \
} \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("=====================\n")); \
}
#ifdef USE_POLLING_UNIT
#define SK_DBG_DUMP_PO_LE(pLE) { \
SK_U8 Opcode; \
SK_U16 Idx; \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("=== PO_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n", \
pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \
((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\t (16bit) %04x %04x %04x %04x\n", \
((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \
((SK_U16 *) pLE)[3])); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\t (32bit) %08x %08x\n", \
((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \
Opcode = POLE_GET_OPC(pLE); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ? \
"Hardware" : "Software")); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOpc: 0x%x ",Opcode)); \
if ((Opcode & ~HW_OWNER) == OP_PUTIDX) { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tOP_PUTIDX\n")); \
} \
else { \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tunknown Opcode!!!\n")); \
} \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tPort %c\n", 'A' + POLE_GET_LINK(pLE))); \
Idx = POLE_GET_TXAIDX(pLE); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTxA Index is 0x%X and %svalid\n", Idx, \
(Idx & PU_PUTIDX_VALID) ? "" : "not ")); \
Idx = POLE_GET_TXSIDX(pLE); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tTxS Index is 0x%X and %svalid\n", Idx, \
(Idx & PU_PUTIDX_VALID) ? "" : "not ")); \
Idx = POLE_GET_RXIDX(pLE); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("\tRx Index is 0x%X and %svalid\n", Idx, \
(Idx & PU_PUTIDX_VALID) ? "" : "not ")); \
SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
("=====================\n")); \
}
#endif /* USE_POLLING_UNIT */
#else /* !DEBUG */
#define SK_DBG_DUMP_RX_LE(pLE)
#define SK_DBG_DUMP_TX_LE(pLE)
#define SK_DBG_DUMP_ST_LE(pLE)
#define SK_DBG_DUMP_PO_LE(pLE)
#endif /* !DEBUG */
/******************************************************************************
*
* Macros for listelement tables
*
*
*/
#define LE_SIZE sizeof(SK_HWLE)
#define LE_TAB_SIZE(NumElements) ((NumElements) * LE_SIZE)
/* Number of unused list elements in table
* this macro always returns the number of free listelements - 1
* this way we want to guarantee that always one LE remains unused
*/
#define NUM_FREE_LE_IN_TABLE(pTable) \
( ((pTable)->Put >= (pTable)->Done) ? \
(NUM_LE_IN_TABLE(pTable) - (pTable)->Put + (pTable)->Done - 1) :\
((pTable)->Done - (pTable)->Put - 1) )
/* total number of list elements in table */
#define NUM_LE_IN_TABLE(pTable) ((pTable)->Num)
/* get next unused Rx list element */
#define GET_RX_LE(pLE, pTable) { \
pLE = &(pTable)->pLETab[(pTable)->Put]; \
(pTable)->Put = ((pTable)->Put + 1) & (NUM_LE_IN_TABLE(pTable) - 1);\
}
/* get next unused Tx list element */
#define GET_TX_LE(pLE, pTable) GET_RX_LE(pLE, pTable)
/* get next status list element expected to be finished by hw */
#define GET_ST_LE(pLE, pTable) { \
pLE = &(pTable)->pLETab[(pTable)->Done]; \
(pTable)->Done = ((pTable)->Done +1) & (NUM_LE_IN_TABLE(pTable) - 1);\
}
#ifdef USE_POLLING_UNIT
/* get next polling unit list element for port */
#define GET_PO_LE(pLE, pTable, Port) { \
pLE = &(pTable)->pLETab[(Port)]; \
}
#endif /* USE_POLLING_UNIT */
#define GET_PUT_IDX(pTable) ((pTable)->Put)
#define UPDATE_HWPUT_IDX(pTable) {(pTable)->HwPut = (pTable)->Put; }
/*
* get own bit of next status LE
* if the result is != 0 there has been at least one status LE finished
*/
#define OWN_OF_FIRST_LE(pTable) \
(STLE_GET_OPC(&(pTable)->pLETab[(pTable)->Done]) & HW_OWNER)
#define SET_DONE_INDEX(pTable, Idx) (pTable)->Done = (Idx);
#define GET_DONE_INDEX(pTable) ((pTable)->Done)
#ifdef SAFE_BUT_SLOW
/* check own bit of LE before current done idx */
#define CHECK_STLE_OVERFLOW(pTable, IsOk) { \
unsigned i; \
if ((i = (pTable)->Done) == 0) { \
i = NUM_LE_IN_TABLE(pTable); \
} \
else { \
i = i - 1; \
} \
if (STLE_GET_OPC(&(pTable)->pLETab[i]) == HW_OWNER) { \
(IsOk) = SK_TRUE; \
} \
else { \
(IsOk) = SK_FALSE; \
} \
}
/*
* for Yukon-2 the hardware is not polling the list elements, so it
* is not necessary to change the own-bit of Rx or Tx LEs before
* reusing them
* but it might make debugging easier if one simply can see whether
* a LE has been worked on
*/
#define CLEAR_LE_OWN(pTable, Idx) \
STLE_SET_OPC(&(pTable)->pLETab[(Idx)], SW_OWNER)
/*
* clear all own bits starting from old done index up to the LE before
* the new done index
*/
#define CLEAR_LE_OWN_FROM_DONE_TO(pTable, To) { \
int i; \
i = (pTable)->Done; \
while (i != To) { \
CLEAR_LE_OWN(pTable, i); \
i = (i + 1) & (NUM_LE_IN_TABLE(pTable) - 1); \
} \
}
#else /* !SAFE_BUT_SLOW */
#define CHECK_STLE_OVERFLOW(pTable, IsOk)
#define CLEAR_LE_OWN(pTable, Idx)
#define CLEAR_LE_OWN_FROM_DONE_TO(pTable, To)
#endif /* !SAFE_BUT_SLOW */
/* typedefs *******************************************************************/
typedef struct s_LetRxTx {
SK_U16 VlanId; /* VLAN Id given down last time */
SK_U16 TcpWp; /* TCP Checksum Write Position */
SK_U16 TcpSp1; /* TCP Checksum Calculation Start Position 1 */
SK_U16 TcpSp2; /* TCP Checksum Calculation Start Position 2 */
SK_U16 MssValue; /* Maximum Segment Size */
SK_U16 Reserved1; /* reserved word for furture extensions */
SK_U16 Reserved2; /* reserved word for furture extensions */
SK_U16 Reserved3; /* reserved word for furture extensions */
} SK_LET_RX_TX;
typedef struct s_LetStat {
SK_U32 RxTimeStamp; /* Receive Timestamp */
SK_U32 RssHashValue; /* RSS Hash Value */
SK_BOOL RssIsIp; /* RSS Hash Value: IP packet detected */
SK_BOOL RssIsTcp; /* RSS Hash Value: IP+TCP packet detected */
SK_U16 VlanId; /* VLAN Id given received by Status BMU */
SK_U16 TcpSum1; /* TCP checksum 1 (status BMU) */
SK_U16 TcpSum2; /* TCP checksum 2 (status BMU) */
} SK_LET_STAT;
typedef union s_LetBmuSpec {
SK_LET_RX_TX RxTx; /* Rx/Tx BMU specific variables */
SK_LET_STAT Stat; /* Status BMU specific variables */
} SK_LET_BMU_S;
typedef struct s_le_table {
/* all LE's between Done and HWPut are owned by the hardware */
/* all LE's between Put and Done can be used from Software */
/* all LE's between HWPut and Put are currently processed in DriverSend */
unsigned Done; /* done index - consumed from HW and available */
unsigned Put; /* put index - to be given to hardware */
unsigned HwPut; /* put index actually given to hardware */
unsigned Num; /* total number of list elements */
SK_HWLE *pLETab; /* virtual address of list element table */
SK_U32 pPhyLETABLow; /* physical address of list element table */
SK_U32 pPhyLETABHigh; /* physical address of list element table */
/* values to remember in order to save some LEs */
SK_U32 BufHighAddr; /* high addr given down last time */
SK_LET_BMU_S Bmu; /* contains BMU specific information */
SK_U32 private; /* driver private variable free usable */
SK_U16 TcpInitCsum; /* Init. Checksum */
} SK_LE_TABLE;
/* function prototypes ********************************************************/
#ifndef SK_KR_PROTO
/*
* public functions in sky2le.c
*/
extern void SkGeY2SetPutIndex(
SK_AC *pAC,
SK_IOC IoC,
SK_U32 StartAddrPrefetchUnit,
SK_LE_TABLE *pLETab);
extern void SkGeY2InitPrefetchUnit(
SK_AC *pAC,
SK_IOC IoC,
unsigned int Queue,
SK_LE_TABLE *pLETab);
extern void SkGeY2InitStatBmu(
SK_AC *pAC,
SK_IOC IoC,
SK_LE_TABLE *pLETab);
extern void SkGeY2InitPollUnit(
SK_AC *pAC,
SK_IOC IoC,
SK_LE_TABLE *pLETab);
extern void SkGeY2InitSingleLETable(
SK_AC *pAC,
SK_LE_TABLE *pLETab,
unsigned int NumLE,
void *pVMem,
SK_U32 PMemLowAddr,
SK_U32 PMemHighAddr);
#else /* SK_KR_PROTO */
extern void SkGeY2SetPutIndex();
extern void SkGeY2InitPrefetchUnit();
extern void SkGeY2InitStatBmu();
extern void SkGeY2InitPollUnit();
extern void SkGeY2InitSingleLETable();
#endif /* SK_KR_PROTO */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __INC_SKY2LE_H */