/****************************************************************************** * * Name: sky2le.h * Project: Gigabit Ethernet Adapters, Common Modules * Version: $Revision: 1.9 $ * Date: $Date: 2005/01/26 10:53:34 $ * Purpose: Common list element definitions and access macros. * ******************************************************************************/ /****************************************************************************** * * (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. * ******************************************************************************/ #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 */