/***************************************************************************** * * Name: skgepnmi.c * Project: Gigabit Ethernet Adapters, PNMI-Module * Version: $Revision: 2.26 $ * Date: $Date: 2005/12/21 09:53:21 $ * Purpose: Private Network Management Interface * ****************************************************************************/ /****************************************************************************** * * LICENSE: * (C)Copyright 1998-2002 SysKonnect GmbH. * (C)Copyright 2002-2003 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 * ******************************************************************************/ #include #ifdef CONFIG_SK98 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = "@(#) $Id: skgepnmi.c,v 2.26 2005/12/21 09:53:21 tschilli Exp $ (C) Marvell."; #endif #include "h/skdrv1st.h" #include "h/sktypes.h" #include "h/xmac_ii.h" #include "h/skdebug.h" #include "h/skqueue.h" #include "h/skgepnmi.h" #include "h/skgesirq.h" #include "h/skcsum.h" #include "h/skvpd.h" #include "h/skgehw.h" #include "h/sky2le.h" #include "h/skgeinit.h" #include "h/skdrv2nd.h" #include "h/skgepnm2.h" #ifdef SK_POWER_MGMT #include "h/skgepmgt.h" #endif /* SK_POWER_MGMT */ /* defines *******************************************************************/ #ifndef DEBUG #define PNMI_STATIC static #else /* DEBUG */ #define PNMI_STATIC #endif /* DEBUG */ /* * Private Function prototypes */ PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int PhysPortIndex); PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int PhysPortIndex); PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac); PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf); PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int PhysPortIndex, unsigned int StatIndex); PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex, unsigned int StatIndex, SK_U32 NetIndex); PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size); PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen, unsigned int *pEntries); PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr, unsigned int KeyArrLen, unsigned int *pKeyNo); PNMI_STATIC int LookupId(SK_U32 Id); PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac, unsigned int LastMac); PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf, unsigned int *pLen, SK_U32 NetIndex); PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac); PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId, unsigned int PortIndex); PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId, unsigned int SensorIndex); PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId); PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC); PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf); PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32); PNMI_STATIC void VctGetResults(SK_AC *, SK_IOC, SK_U32); /* * Table to correlate OID with handler function and index to * hardware register stored in StatAddress if applicable. */ #include "skgemib.c" /* global variables **********************************************************/ /* * Overflow status register bit table and corresponding counter * dependent on MAC type - the number relates to the size of overflow * mask returned by the pFnMacOverflow function */ PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = { /* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST}, /* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST}, /* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC}, /* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST}, /* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW}, /* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH}, /* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64}, /* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127}, /* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255}, /* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511}, /* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023}, /* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX}, /* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES}, /* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED}, /* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL}, /* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL}, /* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL}, /* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL}, /* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL}, /* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN}, /* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED}, /* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED}, /* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED}, /* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED}, /* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED}, /* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED}, /* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, /* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, /* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, /* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, /* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, /* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, /* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST}, /* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST}, /* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC}, /* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST}, /* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS}, /* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED}, /* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW}, /* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH}, /* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW}, /* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH}, /* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE}, /* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT}, /* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64}, /* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127}, /* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255}, /* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511}, /* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023}, /* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX}, /* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES}, /* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG}, /* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER}, /* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED}, /* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW}, /* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED}, /* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED}, /* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED}, /* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED}, /* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED}, /* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED}, /* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED}, /* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED}, /* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED} }; /* * Table for hardware register saving on resets and port switches */ PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = { /* SK_PNMI_HTX */ {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_OCTETHIGH */ {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}}, /* SK_PNMI_HTX_OCTETLOW */ {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}}, /* SK_PNMI_HTX_BROADCAST */ {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}}, /* SK_PNMI_HTX_MULTICAST */ {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}}, /* SK_PNMI_HTX_UNICAST */ {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}}, /* SK_PNMI_HTX_BURST */ {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_PMACC */ {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}}, /* SK_PNMI_HTX_MACC */ {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_COL */ {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}}, /* SK_PNMI_HTX_SINGLE_COL */ {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}}, /* SK_PNMI_HTX_MULTI_COL */ {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}}, /* SK_PNMI_HTX_EXCESS_COL */ {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}}, /* SK_PNMI_HTX_LATE_COL */ {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}}, /* SK_PNMI_HTX_DEFFERAL */ {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_EXCESS_DEF */ {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_UNDERRUN */ {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}}, /* SK_PNMI_HTX_CARRIER */ {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_UTILUNDER */ {{0, SK_FALSE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_UTILOVER */ {{0, SK_FALSE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_64 */ {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}}, /* SK_PNMI_HTX_127 */ {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}}, /* SK_PNMI_HTX_255 */ {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}}, /* SK_PNMI_HTX_511 */ {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}}, /* SK_PNMI_HTX_1023 */ {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}}, /* SK_PNMI_HTX_MAX */ {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}}, /* SK_PNMI_HTX_LONGFRAMES */ {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}}, /* SK_PNMI_HTX_SYNC */ {{0, SK_FALSE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_SYNC_OCTET */ {{0, SK_FALSE}, {0, SK_FALSE}}, /* SK_PNMI_HTX_RESERVED */ {{0, SK_FALSE}, {0, SK_FALSE}}, /* SK_PNMI_HRX */ {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_OCTETHIGH */ {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}}, /* SK_PNMI_HRX_OCTETLOW */ {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}}, /* SK_PNMI_HRX_BADOCTETHIGH */ {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}}, /* SK_PNMI_HRX_BADOCTETLOW */ {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}}, /* SK_PNMI_HRX_BROADCAST */ {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}}, /* SK_PNMI_HRX_MULTICAST */ {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}}, /* SK_PNMI_HRX_UNICAST */ {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}}, /* SK_PNMI_HRX_PMACC */ {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}}, /* SK_PNMI_HRX_MACC */ {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_PMACC_ERR */ {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_MACC_UNKWN */ {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_BURST */ {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_MISSED */ {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_FRAMING */ {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_UNDERSIZE */ {{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}}, /* SK_PNMI_HRX_OVERFLOW */ {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}}, /* SK_PNMI_HRX_JABBER */ {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}}, /* SK_PNMI_HRX_CARRIER */ {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_IRLENGTH */ {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_SYMBOL */ {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_SHORTS */ {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_RUNT */ {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}}, /* SK_PNMI_HRX_TOO_LONG */ {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}}, /* SK_PNMI_HRX_FCS */ {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}}, /* SK_PNMI_HRX_CEXT */ {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_UTILUNDER */ {{0, SK_FALSE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_UTILOVER */ {{0, SK_FALSE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_64 */ {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}}, /* SK_PNMI_HRX_127 */ {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}}, /* SK_PNMI_HRX_255 */ {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}}, /* SK_PNMI_HRX_511 */ {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}}, /* SK_PNMI_HRX_1023 */ {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}}, /* SK_PNMI_HRX_MAX */ {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}}, /* SK_PNMI_HRX_LONGFRAMES */ {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}}, /* SK_PNMI_HRX_RESERVED */ {{0, SK_FALSE}, {0, SK_FALSE}} }; /***************************************************************************** * * Public functions * */ /***************************************************************************** * * SkPnmiInit - Init function of PNMI * * Description: * SK_INIT_DATA: Initialises the data structures * SK_INIT_IO: Resets the XMAC statistics, determines the device and * connector type. * SK_INIT_RUN: Starts a timer event for port switch per hour * calculation. * * Returns: * Always 0 */ int SkPnmiInit( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Level) /* Initialization level */ { unsigned int PortMax; /* Number of ports */ unsigned int PortIndex; /* Current port index in loop */ SK_EVPARA EventParam; /* Event struct for timer event */ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiInit: Called, level=%d\n", Level)); switch (Level) { case SK_INIT_DATA: SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi)); pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN; pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES; for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) { pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE; pAC->Pnmi.DualNetActiveFlag = SK_FALSE; /* Initialize DSP variables for Vct() to 0xff => Never written! */ pAC->GIni.GP[PortIndex].PCableLen = 0xff; pAC->Pnmi.VctBackup[PortIndex].CableLen = 0xff; } #ifdef SK_PNMI_CHECK if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG); SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, ("CounterOffset struct size (%d) differs from" "SK_PNMI_MAX_IDX (%d)\n", SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX)); } if (SK_PNMI_MAX_IDX != (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG); SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, ("StatAddr table size (%d) differs from " "SK_PNMI_MAX_IDX (%d)\n", (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)), SK_PNMI_MAX_IDX)); } #endif /* SK_PNMI_CHECK */ break; case SK_INIT_IO: /* Reset MAC counters. */ PortMax = pAC->GIni.GIMacsFound; for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex); } /* Get PCI bus speed. */ if (pAC->GIni.GIPciClock66) { pAC->Pnmi.PciBusSpeed = 66; } else { pAC->Pnmi.PciBusSpeed = 33; } /* Get PCI bus width. */ if (pAC->GIni.GIPciSlot64) { pAC->Pnmi.PciBusWidth = 64; } else { pAC->Pnmi.PciBusWidth = 32; } /* Get chipset. */ switch (pAC->GIni.GIChipId) { case CHIP_ID_GENESIS: pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC; break; case CHIP_ID_YUKON: pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON; break; case CHIP_ID_YUKON_LITE: pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_LITE; break; case CHIP_ID_YUKON_LP: pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_LP; break; case CHIP_ID_YUKON_XL: pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_XL; break; case CHIP_ID_YUKON_EC: pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_EC; break; case CHIP_ID_YUKON_FE: pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_FE; break; default: break; } /* Get PMD and Device Type. */ switch (pAC->GIni.GIPmdTyp) { case 'S': pAC->Pnmi.PMD = 3; pAC->Pnmi.DeviceType = 0x00020001; break; case 'L': pAC->Pnmi.PMD = 2; pAC->Pnmi.DeviceType = 0x00020003; break; case 'C': pAC->Pnmi.PMD = 4; pAC->Pnmi.DeviceType = 0x00020005; break; case 'T': pAC->Pnmi.PMD = 5; pAC->Pnmi.DeviceType = 0x00020007; break; default : pAC->Pnmi.PMD = 1; pAC->Pnmi.DeviceType = 0; break; } if (pAC->GIni.GIMacsFound > 1) { pAC->Pnmi.DeviceType++; } /* Get connector type. */ switch (pAC->GIni.GIConTyp) { case 'C': pAC->Pnmi.Connector = 2; break; case 'D': pAC->Pnmi.Connector = 3; break; case 'F': pAC->Pnmi.Connector = 4; break; case 'J': pAC->Pnmi.Connector = 5; break; case 'V': pAC->Pnmi.Connector = 6; break; default: pAC->Pnmi.Connector = 1; break; } break; case SK_INIT_RUN: /* Start timer for RLMT change counter. */ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, SK_PNMI_EVT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, EventParam); break; default: break; /* Nothing to do. */ } return (0); } /***************************************************************************** * * SkPnmiGetVar - Retrieves the value of a single OID * * Description: * Calls a general sub-function for all this stuff. If the instance * -1 is passed, the values of all instances are returned in an * array of values. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed * SK_PNMI_ERR_GENERAL A general severe internal error occured * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take * the data. * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ int SkPnmiGetVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ void *pBuf, /* Buffer to which the management data will be copied */ unsigned int *pLen, /* On call: buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", Id, *pLen, Instance, NetIndex)); return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen, Instance, NetIndex)); } /***************************************************************************** * * SkPnmiPreSetVar - Presets the value of a single OID * * Description: * Calls a general sub-function for all this stuff. The preset does * the same as a set, but returns just before finally setting the * new value. This is usefull to check if a set might be successfull. * If the instance -1 is passed, an array of values is supposed and * all instances of the OID will be set. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ int SkPnmiPreSetVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ void *pBuf, /* Buffer to which the management data will be copied */ unsigned int *pLen, /* Total length of management data */ SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", Id, *pLen, Instance, NetIndex)); return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen, Instance, NetIndex)); } /***************************************************************************** * * SkPnmiSetVar - Sets the value of a single OID * * Description: * Calls a general sub-function for all this stuff. The preset does * the same as a set, but returns just before finally setting the * new value. This is usefull to check if a set might be successfull. * If the instance -1 is passed, an array of values is supposed and * all instances of the OID will be set. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ int SkPnmiSetVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ void *pBuf, /* Buffer to which the management data will be copied */ unsigned int *pLen, /* Total length of management data */ SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", Id, *pLen, Instance, NetIndex)); return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen, Instance, NetIndex)); } /***************************************************************************** * * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA * * Description: * Runs through the IdTable, queries the single OIDs and stores the * returned data into the management database structure * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure * is stored in the IdTable. The return value of the function will also * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the * minimum size of SK_PNMI_MIN_STRUCT_SIZE. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed * SK_PNMI_ERR_GENERAL A general severe internal error occured * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take * the data. * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist */ int SkPnmiGetStruct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ void *pBuf, /* Buffer to which the management data will be copied. */ unsigned int *pLen, /* Length of buffer */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int TableIndex; unsigned int DstOffset; unsigned int InstanceNo; unsigned int InstanceCnt; SK_U32 Instance; unsigned int TmpLen; char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n", *pLen, NetIndex)); if (*pLen < SK_PNMI_STRUCT_SIZE) { if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, (SK_U32)(-1)); } *pLen = SK_PNMI_STRUCT_SIZE; return (SK_PNMI_ERR_TOO_SHORT); } /* Check NetIndex. */ if (NetIndex >= pAC->Rlmt.NumNets) { return (SK_PNMI_ERR_UNKNOWN_NET); } /* Update statistics. */ SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call"); if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) != SK_PNMI_ERR_OK) { SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (Ret); } if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (Ret); } if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (Ret); } /* Increment semaphores to indicate that an update was already done. */ pAC->Pnmi.MacUpdatedFlag ++; pAC->Pnmi.RlmtUpdatedFlag ++; pAC->Pnmi.SirqUpdatedFlag ++; /* * Get VPD keys for instance calculation. * Please read comment in Vpd(). */ if (pAC->Pnmi.VpdKeyReadError == SK_FALSE) { Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen); if (Ret != SK_PNMI_ERR_OK) { pAC->Pnmi.MacUpdatedFlag --; pAC->Pnmi.RlmtUpdatedFlag --; pAC->Pnmi.SirqUpdatedFlag --; SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (SK_PNMI_ERR_GENERAL); } } /* Retrieve values. */ SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE); for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { InstanceNo = IdTable[TableIndex].InstanceNo; for (InstanceCnt = 1; InstanceCnt <= InstanceNo; InstanceCnt ++) { DstOffset = IdTable[TableIndex].Offset + (InstanceCnt - 1) * IdTable[TableIndex].StructSize; /* * For the VPD the instance is not an index number * but the key itself. Determin with the instance * counter the VPD key to be used. */ if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY || IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE || IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS || IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) { SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4); } else { Instance = (SK_U32)InstanceCnt; } TmpLen = *pLen - DstOffset; Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET, IdTable[TableIndex].Id, (char *)pBuf + DstOffset, &TmpLen, Instance, TableIndex, NetIndex); /* * An unknown instance error means that we reached * the last instance of that variable. Proceed with * the next OID in the table and ignore the return * code. */ if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { break; } if (Ret != SK_PNMI_ERR_OK) { pAC->Pnmi.MacUpdatedFlag --; pAC->Pnmi.RlmtUpdatedFlag --; pAC->Pnmi.SirqUpdatedFlag --; SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); SK_PNMI_SET_STAT(pBuf, Ret, DstOffset); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (Ret); } } } pAC->Pnmi.MacUpdatedFlag --; pAC->Pnmi.RlmtUpdatedFlag --; pAC->Pnmi.SirqUpdatedFlag --; *pLen = SK_PNMI_STRUCT_SIZE; SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); return (SK_PNMI_ERR_OK); } /***************************************************************************** * * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA * * Description: * Calls a general sub-function for all this set stuff. The preset does * the same as a set, but returns just before finally setting the * new value. This is usefull to check if a set might be successfull. * The sub-function runs through the IdTable, checks which OIDs are able * to set, and calls the handler function of the OID to perform the * preset. The return value of the function will also be stored in * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of * SK_PNMI_MIN_STRUCT_SIZE. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. */ int SkPnmiPreSetStruct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ void *pBuf, /* Buffer which contains the data to be set */ unsigned int *pLen, /* Length of buffer */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n", *pLen, NetIndex)); return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf, pLen, NetIndex)); } /***************************************************************************** * * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA * * Description: * Calls a general sub-function for all this set stuff. The return value * of the function will also be stored in SK_PNMI_STRUCT_DATA if the * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE. * The sub-function runs through the IdTable, checks which OIDs are able * to set, and calls the handler function of the OID to perform the * set. The return value of the function will also be stored in * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of * SK_PNMI_MIN_STRUCT_SIZE. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. */ int SkPnmiSetStruct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ void *pBuf, /* Buffer which contains the data to be set */ unsigned int *pLen, /* Length of buffer */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n", *pLen, NetIndex)); return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf, pLen, NetIndex)); } /***************************************************************************** * * SkPnmiEvent - Event handler * * Description: * Handles the following events: * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an * interrupt will be generated which is * first handled by SIRQ which generates a * this event. The event increments the * upper 32 bit of the 64 bit counter. * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module * when a sensor reports a warning or * error. The event will store a trap * message in the trap buffer. * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this * module and is used to calculate the * port switches per hour. * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and * timestamps. * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver * before a hard reset of the XMAC is * performed. All counters will be saved * and added to the hardware counter * values after reset to grant continuous * counter values. * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port * went logically up. A trap message will * be stored to the trap buffer. * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port * went logically down. A trap message will * be stored to the trap buffer. * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two * spanning tree root bridges were * detected. A trap message will be stored * to the trap buffer. * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went * down. PNMI will not further add the * statistic values to the virtual port. * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and * is now an active port. PNMI will now * add the statistic data of this port to * the virtual port. * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first parameter * contains the number of nets. 1 means single net, 2 means * dual net. The second parameter is -1 * * Returns: * Always 0 */ int SkPnmiEvent( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Event, /* Event-Id */ SK_EVPARA Param) /* Event dependent parameter */ { unsigned int PhysPortIndex; unsigned int MaxNetNumber; int CounterIndex; SK_U16 MacStatus; SK_U64 OverflowStatus; SK_U64 Mask; int MacType; SK_U64 Value; SK_U32 Val32; SK_U16 Register; SK_EVPARA EventParam; SK_U64 NewestValue; SK_U64 OldestValue; SK_U64 Delta; SK_PNMI_ESTIMATE *pEst; SK_U32 NetIndex; SK_U32 RetCode; #ifdef DEBUG if (Event != SK_PNMI_EVT_XMAC_RESET) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n", (unsigned int)Event, (unsigned int)Param.Para64)); } #endif /* DEBUG */ SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call"); MacType = pAC->GIni.GIMacType; switch (Event) { case SK_PNMI_EVT_SIRQ_OVERFLOW: PhysPortIndex = (int)Param.Para32[0]; MacStatus = (SK_U16)Param.Para32[1]; #ifdef DEBUG if (PhysPortIndex >= SK_MAX_MACS) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter" " wrong, PhysPortIndex=0x%x\n", PhysPortIndex)); return (0); } #endif /* DEBUG */ OverflowStatus = 0; /* Check which source caused an overflow interrupt. */ if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex, MacStatus, &OverflowStatus) != 0) || (OverflowStatus == 0)) { SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); return (0); } /* * Check the overflow status register and increment * the upper dword of corresponding counter. */ for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8; CounterIndex ++) { Mask = (SK_U64)1 << CounterIndex; if ((OverflowStatus & Mask) == 0) { continue; } switch (StatOvrflwBit[CounterIndex][MacType]) { case SK_PNMI_HTX_UTILUNDER: case SK_PNMI_HTX_UTILOVER: if (MacType == SK_MAC_XMAC) { XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register); Register |= XM_TX_SAM_LINE; XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register); } break; case SK_PNMI_HRX_UTILUNDER: case SK_PNMI_HRX_UTILOVER: if (MacType == SK_MAC_XMAC) { XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register); Register |= XM_RX_SAM_LINE; XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register); } break; case SK_PNMI_HTX_OCTETHIGH: case SK_PNMI_HTX_OCTETLOW: case SK_PNMI_HTX_RESERVED: case SK_PNMI_HRX_OCTETHIGH: case SK_PNMI_HRX_OCTETLOW: case SK_PNMI_HRX_IRLENGTH: case SK_PNMI_HRX_RESERVED: /* The following counters aren't be handled (id > 63). */ case SK_PNMI_HTX_SYNC: case SK_PNMI_HTX_SYNC_OCTET: break; case SK_PNMI_HRX_LONGFRAMES: if (MacType == SK_MAC_GMAC) { pAC->Pnmi.Port[PhysPortIndex]. CounterHigh[CounterIndex] ++; } break; default: pAC->Pnmi.Port[PhysPortIndex]. CounterHigh[CounterIndex] ++; } } break; case SK_PNMI_EVT_SEN_WAR_LOW: #ifdef DEBUG if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n", (unsigned int)Param.Para64)); return (0); } #endif /* DEBUG */ /* * Store a trap message in the trap buffer and generate * an event for user space applications with the * SK_DRIVER_SENDEVENT macro. */ QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW, (unsigned int)Param.Para64); (void)SK_DRIVER_SENDEVENT(pAC, IoC); break; case SK_PNMI_EVT_SEN_WAR_UPP: #ifdef DEBUG if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n", (unsigned int)Param.Para64)); return (0); } #endif /* DEBUG */ /* * Store a trap message in the trap buffer and generate * an event for user space applications with the * SK_DRIVER_SENDEVENT macro. */ QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP, (unsigned int)Param.Para64); (void)SK_DRIVER_SENDEVENT(pAC, IoC); break; case SK_PNMI_EVT_SEN_ERR_LOW: #ifdef DEBUG if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n", (unsigned int)Param.Para64)); return (0); } #endif /* DEBUG */ /* * Store a trap message in the trap buffer and generate * an event for user space applications with the * SK_DRIVER_SENDEVENT macro. */ QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW, (unsigned int)Param.Para64); (void)SK_DRIVER_SENDEVENT(pAC, IoC); break; case SK_PNMI_EVT_SEN_ERR_UPP: #ifdef DEBUG if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n", (unsigned int)Param.Para64)); return (0); } #endif /* DEBUG */ /* * Store a trap message in the trap buffer and generate * an event for user space applications with the * SK_DRIVER_SENDEVENT macro. */ QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP, (unsigned int)Param.Para64); (void)SK_DRIVER_SENDEVENT(pAC, IoC); break; case SK_PNMI_EVT_CHG_EST_TIMER: /* * Calculate port switch average on a per hour basis * Time interval for check : 28125 ms (SK_PNMI_EVT_TIMER_CHECK) * Number of values for average : 8 * * Be careful in changing these values, on change check * - typedef of SK_PNMI_ESTIMATE (Size of EstValue * array one less than value number) * - Timer initialization SkTimerStart() in SkPnmiInit * - Delta value below must be multiplicated with power of 2 */ pEst = &pAC->Pnmi.RlmtChangeEstimate; CounterIndex = pEst->EstValueIndex + 1; if (CounterIndex == 7) { CounterIndex = 0; } pEst->EstValueIndex = CounterIndex; NewestValue = pAC->Pnmi.RlmtChangeCts; OldestValue = pEst->EstValue[CounterIndex]; pEst->EstValue[CounterIndex] = NewestValue; /* * Calculate average. Delta stores the number of * port switches per 28125 * 8 = 225000 ms */ if (NewestValue >= OldestValue) { Delta = NewestValue - OldestValue; } else { /* Overflow situation. */ Delta = (SK_U64)(0 - OldestValue) + NewestValue; } /* * Extrapolate delta to port switches per hour. * Estimate = Delta * (3600000 / 225000) * = Delta * 16 * = Delta << 4 */ pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4; /* * Check if threshold is exceeded. If the threshold is * permanently exceeded every 28125 ms an event will be * generated to remind the user of this condition. */ if ((pAC->Pnmi.RlmtChangeThreshold != 0) && (pAC->Pnmi.RlmtChangeEstimate.Estimate >= pAC->Pnmi.RlmtChangeThreshold)) { QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES); (void)SK_DRIVER_SENDEVENT(pAC, IoC); } SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, SK_PNMI_EVT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, EventParam); break; case SK_PNMI_EVT_CLEAR_COUNTER: /* * Param.Para32[0] contains the NetIndex (0 ..1). * Param.Para32[1] is reserved, contains -1. */ NetIndex = (SK_U32)Param.Para32[0]; #ifdef DEBUG if (NetIndex >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n", NetIndex)); return (0); } #endif /* DEBUG */ /* * Set all counters and timestamps to zero. * The according NetIndex is required as a * parameter of the event. */ ResetCounter(pAC, IoC, NetIndex); break; case SK_PNMI_EVT_XMAC_RESET: /* * To grant continuous counter values store the current * XMAC statistic values to the entries 1..n of the * CounterOffset array. XMAC Errata #2 */ #ifdef DEBUG if ((unsigned int)Param.Para64 >= SK_MAX_MACS) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n", (unsigned int)Param.Para64)); return (0); } #endif /* DEBUG */ PhysPortIndex = (unsigned int)Param.Para64; /* Update XMAC statistic to get fresh values. */ if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != SK_PNMI_ERR_OK) { SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); return (0); } /* Increment semaphore to indicate that an update was already done. */ pAC->Pnmi.MacUpdatedFlag ++; for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; CounterIndex ++) { if (!StatAddr[CounterIndex][MacType].GetOffset) { continue; } pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0; } pAC->Pnmi.MacUpdatedFlag --; break; case SK_PNMI_EVT_RLMT_PORT_UP: PhysPortIndex = (unsigned int)Param.Para32[0]; #ifdef DEBUG if (PhysPortIndex >= SK_MAX_MACS) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter" " wrong, PhysPortIndex=%d\n", PhysPortIndex)); return (0); } #endif /* DEBUG */ /* * Store a trap message in the trap buffer and generate an event for * user space applications with the SK_DRIVER_SENDEVENT macro. */ QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex); (void)SK_DRIVER_SENDEVENT(pAC, IoC); /* Bugfix for XMAC errata (#10620). */ if (MacType == SK_MAC_XMAC) { /* Add incremental difference to offset (#10620). */ (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, XM_RXE_SHT_ERR, &Val32); Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] += Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark; } /* Tell VctStatus() that a link was up meanwhile. */ pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK; break; case SK_PNMI_EVT_RLMT_PORT_DOWN: PhysPortIndex = (unsigned int)Param.Para32[0]; #ifdef DEBUG if (PhysPortIndex >= SK_MAX_MACS) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter" " wrong, PhysPortIndex=%d\n", PhysPortIndex)); return (0); } #endif /* DEBUG */ /* * Store a trap message in the trap buffer and generate an event for * user space applications with the SK_DRIVER_SENDEVENT macro. */ QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex); (void)SK_DRIVER_SENDEVENT(pAC, IoC); /* Bugfix #10620 - get zero level for incremental difference. */ if (MacType == SK_MAC_XMAC) { (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, XM_RXE_SHT_ERR, &Val32); pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); } break; case SK_PNMI_EVT_RLMT_ACTIVE_DOWN: PhysPortIndex = (unsigned int)Param.Para32[0]; NetIndex = (SK_U32)Param.Para32[1]; #ifdef DEBUG if (PhysPortIndex >= SK_MAX_MACS) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n", PhysPortIndex)); } if (NetIndex >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n", NetIndex)); } #endif /* DEBUG */ /* For now, ignore event if NetIndex != 0. */ if (Param.Para32[1] != 0) { return (0); } /* Nothing to do if port is already inactive. */ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { return (0); } /* * Update statistic counters to calculate new offset for the virtual * port and increment semaphore to indicate that an update was already * done. */ if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != SK_PNMI_ERR_OK) { SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); return (0); } pAC->Pnmi.MacUpdatedFlag ++; /* * Calculate new counter offset for virtual port to grant continous * counting on port switches. The virtual port consists of all currently * active ports. The port down event indicates that a port is removed * from the virtual port. Therefore add the counter value of the removed * port to the CounterOffset for the virtual port to grant the same * counter value. */ for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; CounterIndex ++) { if (!StatAddr[CounterIndex][MacType].GetOffset) { continue; } Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value; } /* Set port to inactive. */ pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE; pAC->Pnmi.MacUpdatedFlag --; break; case SK_PNMI_EVT_RLMT_ACTIVE_UP: PhysPortIndex = (unsigned int)Param.Para32[0]; NetIndex = (SK_U32)Param.Para32[1]; #ifdef DEBUG if (PhysPortIndex >= SK_MAX_MACS) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n", PhysPortIndex)); } if (NetIndex >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n", NetIndex)); } #endif /* DEBUG */ /* For now, ignore event if NetIndex != 0. */ if (Param.Para32[1] != 0) { return (0); } /* Nothing to do if port is already inactive. */ if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { return (0); } /* Statistic maintenance. */ pAC->Pnmi.RlmtChangeCts ++; pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); /* * Store a trap message in the trap buffer and generate an event for * user space applications with the SK_DRIVER_SENDEVENT macro. */ QueueRlmtNewMacTrap(pAC, PhysPortIndex); (void)SK_DRIVER_SENDEVENT(pAC, IoC); /* * Update statistic counters to calculate new offset for the virtual * port and increment semaphore to indicate that an update was * already done. */ if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != SK_PNMI_ERR_OK) { SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); return (0); } pAC->Pnmi.MacUpdatedFlag ++; /* * Calculate new counter offset for virtual port to grant continous * counting on port switches. A new port is added to the virtual port. * Therefore substract the counter value of the new port from the * CounterOffset for the virtual port to grant the same value. */ for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; CounterIndex ++) { if (!StatAddr[CounterIndex][MacType].GetOffset) { continue; } Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value; } /* Set port to active. */ pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE; pAC->Pnmi.MacUpdatedFlag --; break; case SK_PNMI_EVT_RLMT_SEGMENTATION: /* Para.Para32[0] contains the NetIndex. */ /* * Store a trap message in the trap buffer and generate an event for * user space applications with the SK_DRIVER_SENDEVENT macro. */ QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION); (void)SK_DRIVER_SENDEVENT(pAC, IoC); break; case SK_PNMI_EVT_RLMT_SET_NETS: /* * Param.Para32[0] contains the number of Nets. * Param.Para32[1] is reserved, contains -1. */ /* Check number of nets. */ MaxNetNumber = pAC->GIni.GIMacsFound; if (((unsigned int)Param.Para32[0] < 1) || ((unsigned int)Param.Para32[0] > MaxNetNumber)) { return (SK_PNMI_ERR_UNKNOWN_NET); } if ((unsigned int)Param.Para32[0] == 1) { /* SingleNet mode. */ pAC->Pnmi.DualNetActiveFlag = SK_FALSE; } else { /* DualNet mode. */ pAC->Pnmi.DualNetActiveFlag = SK_TRUE; } break; case SK_PNMI_EVT_VCT_RESET: PhysPortIndex = Param.Para32[0]; if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); if (RetCode == 2) { /* * VCT test is still running. * Start VCT timer counter again. */ SK_MEMSET((char *)&Param, 0, sizeof(Param)); Param.Para32[0] = PhysPortIndex; Param.Para32[1] = -1; SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex], SK_PNMI_VCT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param); break; } VctGetResults(pAC, IoC, PhysPortIndex); EventParam.Para32[0] = PhysPortIndex; EventParam.Para32[1] = -1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, EventParam); /* SkEventDispatcher(pAC, IoC); */ } break; default: break; } SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); return (0); } /****************************************************************************** * * Private functions * */ /***************************************************************************** * * PnmiVar - Gets, presets, and sets single OIDs * * Description: * Looks up the requested OID, calls the corresponding handler * function, and passes the parameters with the get, preset, or * set command. The function is called by SkGePnmiGetVar, * SkGePnmiPreSetVar, or SkGePnmiSetVar. * * Returns: * SK_PNMI_ERR_XXX. For details have a look at the description of the * calling functions. * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist */ PNMI_STATIC int PnmiVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* Total length of pBuf management data */ SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int TableIndex; int Ret; if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_OID); } /* Check NetIndex. */ if (NetIndex >= pAC->Rlmt.NumNets) { return (SK_PNMI_ERR_UNKNOWN_NET); } SK_PNMI_CHECKFLAGS("PnmiVar: On call"); Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen, Instance, TableIndex, NetIndex); SK_PNMI_CHECKFLAGS("PnmiVar: On return"); return (Ret); } /***************************************************************************** * * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA * * Description: * The return value of the function will also be stored in * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable, * checks which OIDs are able to set, and calls the handler function of * the OID to perform the set. The return value of the function will * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called * by SkGePnmiPreSetStruct and SkGePnmiSetStruct. * * Returns: * SK_PNMI_ERR_XXX. The codes are described in the calling functions. * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist */ PNMI_STATIC int PnmiStruct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* PRESET/SET action to be performed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* Length of pBuf management data buffer */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int TableIndex; unsigned int DstOffset; unsigned int Len; unsigned int InstanceNo; unsigned int InstanceCnt; SK_U32 Instance; SK_U32 Id; /* Check if the passed buffer has the right size. */ if (*pLen < SK_PNMI_STRUCT_SIZE) { /* Check if we can return the error within the buffer. */ if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, (SK_U32)(-1)); } *pLen = SK_PNMI_STRUCT_SIZE; return (SK_PNMI_ERR_TOO_SHORT); } /* Check NetIndex. */ if (NetIndex >= pAC->Rlmt.NumNets) { return (SK_PNMI_ERR_UNKNOWN_NET); } SK_PNMI_CHECKFLAGS("PnmiStruct: On call"); /* * Update the values of RLMT and SIRQ and increment semaphores to * indicate that an update was already done. */ if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (Ret); } if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (Ret); } pAC->Pnmi.RlmtUpdatedFlag ++; pAC->Pnmi.SirqUpdatedFlag ++; /* PRESET/SET values. */ for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { if ((IdTable[TableIndex].Access != SK_PNMI_RW) && (IdTable[TableIndex].Access != SK_PNMI_WO)) { continue; } InstanceNo = IdTable[TableIndex].InstanceNo; Id = IdTable[TableIndex].Id; for (InstanceCnt = 1; InstanceCnt <= InstanceNo; InstanceCnt ++) { DstOffset = IdTable[TableIndex].Offset + (InstanceCnt - 1) * IdTable[TableIndex].StructSize; /* * Because VPD multiple instance variables are * not setable we do not need to evaluate VPD * instances. Have a look to VPD instance * calculation in SkPnmiGetStruct(). */ Instance = (SK_U32)InstanceCnt; /* Evaluate needed buffer length. */ Len = 0; Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET, IdTable[TableIndex].Id, NULL, &Len, Instance, TableIndex, NetIndex); if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { break; } if (Ret != SK_PNMI_ERR_TOO_SHORT) { pAC->Pnmi.RlmtUpdatedFlag --; pAC->Pnmi.SirqUpdatedFlag --; SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_GENERAL, DstOffset); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (SK_PNMI_ERR_GENERAL); } if (Id == OID_SKGE_VPD_ACTION) { switch (*(pBuf + DstOffset)) { case SK_PNMI_VPD_CREATE: Len = 3 + *(pBuf + DstOffset + 3); break; case SK_PNMI_VPD_DELETE: Len = 3; break; default: Len = 1; break; } } /* Call the OID handler function. */ Ret = IdTable[TableIndex].Func(pAC, IoC, Action, IdTable[TableIndex].Id, pBuf + DstOffset, &Len, Instance, TableIndex, NetIndex); if (Ret != SK_PNMI_ERR_OK) { pAC->Pnmi.RlmtUpdatedFlag --; pAC->Pnmi.SirqUpdatedFlag --; SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE, DstOffset); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (SK_PNMI_ERR_BAD_VALUE); } } } pAC->Pnmi.RlmtUpdatedFlag --; pAC->Pnmi.SirqUpdatedFlag --; SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); return (SK_PNMI_ERR_OK); } /***************************************************************************** * * LookupId - Lookup an OID in the IdTable * * Description: * Scans the IdTable to find the table entry of an OID. * * Returns: * The table index or -1 if not found. */ PNMI_STATIC int LookupId( SK_U32 Id) /* Object identifier to be searched */ { int i; for (i = 0; i < ID_TABLE_SIZE; i++) { if (IdTable[i].Id == Id) { return (i); } } return (-1); } /***************************************************************************** * * OidStruct - Handler of OID_SKGE_ALL_DATA * * Description: * This OID performs a Get/Preset/SetStruct call and returns all data * in a SK_PNMI_STRUCT_DATA structure. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int OidStruct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { if (Id != OID_SKGE_ALL_DATA) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003, SK_PNMI_ERR003MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* Check instance. We only handle single instance variables. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } switch (Action) { case SK_PNMI_GET: return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex)); case SK_PNMI_PRESET: return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); case SK_PNMI_SET: return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); } SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /***************************************************************************** * * Perform - OID handler of OID_SKGE_ACTION * * Description: * None. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Perform( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; SK_U32 ActionOp; /* Check instance. We only handle single instance variables. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } /* Check if a GET should be performed. */ if (Action == SK_PNMI_GET) { /* A GET is easy. We always return the same value. */ ActionOp = (SK_U32)SK_PNMI_ACT_IDLE; SK_PNMI_STORE_U32(pBuf, ActionOp); *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_OK); } /* Continue with PRESET/SET action. */ if (*pLen > sizeof(SK_U32)) { return (SK_PNMI_ERR_BAD_VALUE); } /* Check if the command is a known one. */ SK_PNMI_READ_U32(pBuf, ActionOp); if (*pLen > sizeof(SK_U32) || (ActionOp != SK_PNMI_ACT_IDLE && ActionOp != SK_PNMI_ACT_RESET && ActionOp != SK_PNMI_ACT_SELFTEST && ActionOp != SK_PNMI_ACT_RESETCNT)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* A PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } switch (ActionOp) { case SK_PNMI_ACT_IDLE: /* Nothing to do. */ break; case SK_PNMI_ACT_RESET: /* Perform a driver reset or something that comes near to this. */ Ret = SK_DRIVER_RESET(pAC, IoC); if (Ret != 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005, SK_PNMI_ERR005MSG); return (SK_PNMI_ERR_GENERAL); } break; case SK_PNMI_ACT_SELFTEST: /* * Perform a driver selftest or something similar to this. * Currently this feature is not used and will probably * implemented in another way. */ Ret = SK_DRIVER_SELFTEST(pAC, IoC); pAC->Pnmi.TestResult = Ret; break; case SK_PNMI_ACT_RESETCNT: /* Set all counters and timestamps to zero. */ ResetCounter(pAC, IoC, NetIndex); break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006, SK_PNMI_ERR006MSG); return (SK_PNMI_ERR_GENERAL); } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX * * Description: * Retrieves the statistic values of the virtual port (logical * index 0). Only special OIDs of NDIS are handled which consist * of a 32 bit instead of a 64 bit value. The OIDs are public * because perhaps some other platform can use them too. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Mac8023Stat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; SK_U64 StatVal; SK_U32 StatVal32; SK_BOOL Is64BitReq = SK_FALSE; /* Only the active MAC is returned. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } /* Check action type. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } /* Check length. */ switch (Id) { case OID_802_3_PERMANENT_ADDRESS: case OID_802_3_CURRENT_ADDRESS: if (*pLen < sizeof(SK_MAC_ADDR)) { *pLen = sizeof(SK_MAC_ADDR); return (SK_PNMI_ERR_TOO_SHORT); } break; default: #ifndef SK_NDIS_64BIT_CTR if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } #else /* SK_NDIS_64BIT_CTR */ /* For compatibility, at least 32 bits are required for OID. */ if (*pLen < sizeof(SK_U32)) { /* * Indicate handling for 64 bit values, * if insufficient space is provided. */ *pLen = sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; #endif /* SK_NDIS_64BIT_CTR */ break; } /* * Update all statistics, because we retrieve virtual MAC, which * consists of multiple physical statistics and increment semaphore * to indicate that an update was already done. */ Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); if (Ret != SK_PNMI_ERR_OK) { *pLen = 0; return (Ret); } pAC->Pnmi.MacUpdatedFlag ++; /* Get value (MAC index 0 identifies the virtual MAC). */ switch (Id) { case OID_802_3_PERMANENT_ADDRESS: CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress); *pLen = sizeof(SK_MAC_ADDR); break; case OID_802_3_CURRENT_ADDRESS: CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress); *pLen = sizeof(SK_MAC_ADDR); break; default: StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex); /* By default 32 bit values are evaluated. */ if (!Is64BitReq) { StatVal32 = (SK_U32)StatVal; SK_PNMI_STORE_U32(pBuf, StatVal32); *pLen = sizeof(SK_U32); } else { SK_PNMI_STORE_U64(pBuf, StatVal); *pLen = sizeof(SK_U64); } break; } pAC->Pnmi.MacUpdatedFlag --; return (SK_PNMI_ERR_OK); } /***************************************************************************** * * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX * * Description: * Retrieves the MAC statistic data. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int MacPrivateStat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int LogPortMax; unsigned int LogPortIndex; unsigned int PhysPortMax; unsigned int Limit; unsigned int Offset; int MacType; int Ret; SK_U64 StatVal; /* Calculate instance if wished. MAC index 0 is the virtual MAC. */ PhysPortMax = pAC->GIni.GIMacsFound; LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); MacType = pAC->GIni.GIMacType; if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */ LogPortMax--; } if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */ /* Check instance range. */ if ((Instance < 1) || (Instance > LogPortMax)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); Limit = LogPortIndex + 1; } else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */ LogPortIndex = 0; Limit = LogPortMax; } /* Check action. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } /* Check length. */ if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) { *pLen = (Limit - LogPortIndex) * sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } /* * Update MAC statistic and increment semaphore to indicate that * an update was already done. */ Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); if (Ret != SK_PNMI_ERR_OK) { *pLen = 0; return (Ret); } pAC->Pnmi.MacUpdatedFlag ++; /* Get value. */ Offset = 0; for (; LogPortIndex < Limit; LogPortIndex ++) { switch (Id) { /* XXX not yet implemented due to XMAC problems case OID_SKGE_STAT_TX_UTIL: return (SK_PNMI_ERR_GENERAL); */ /* XXX not yet implemented due to XMAC problems case OID_SKGE_STAT_RX_UTIL: return (SK_PNMI_ERR_GENERAL); */ case OID_SKGE_STAT_RX: if (MacType == SK_MAC_GMAC) { StatVal = GetStatVal(pAC, IoC, LogPortIndex, SK_PNMI_HRX_BROADCAST, NetIndex) + GetStatVal(pAC, IoC, LogPortIndex, SK_PNMI_HRX_MULTICAST, NetIndex) + GetStatVal(pAC, IoC, LogPortIndex, SK_PNMI_HRX_UNICAST, NetIndex) + GetStatVal(pAC, IoC, LogPortIndex, SK_PNMI_HRX_UNDERSIZE, NetIndex); } else { StatVal = GetStatVal(pAC, IoC, LogPortIndex, IdTable[TableIndex].Param, NetIndex); } break; case OID_SKGE_STAT_TX: if (MacType == SK_MAC_GMAC) { StatVal = GetStatVal(pAC, IoC, LogPortIndex, SK_PNMI_HTX_BROADCAST, NetIndex) + GetStatVal(pAC, IoC, LogPortIndex, SK_PNMI_HTX_MULTICAST, NetIndex) + GetStatVal(pAC, IoC, LogPortIndex, SK_PNMI_HTX_UNICAST, NetIndex); } else { StatVal = GetStatVal(pAC, IoC, LogPortIndex, IdTable[TableIndex].Param, NetIndex); } break; default: StatVal = GetStatVal(pAC, IoC, LogPortIndex, IdTable[TableIndex].Param, NetIndex); } SK_PNMI_STORE_U64(pBuf + Offset, StatVal); Offset += sizeof(SK_U64); } *pLen = Offset; pAC->Pnmi.MacUpdatedFlag --; return (SK_PNMI_ERR_OK); } /***************************************************************************** * * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR * * Description: * Get/Presets/Sets the current and factory MAC address. The MAC * address of the virtual port, which is reported to the OS, may * not be changed, but the physical ones. A set to the virtual port * will be ignored. No error should be reported because otherwise * a multiple instance set (-1) would always fail. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Addr( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int LogPortMax; unsigned int PhysPortMax; unsigned int LogPortIndex; unsigned int PhysPortIndex; unsigned int Limit; unsigned int Offset = 0; /* Calculate instance if wished. MAC index 0 is the virtual MAC. */ PhysPortMax = pAC->GIni.GIMacsFound; LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */ LogPortMax--; } if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */ /* Check instance range. */ if ((Instance < 1) || (Instance > LogPortMax)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); Limit = LogPortIndex + 1; } else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */ LogPortIndex = 0; Limit = LogPortMax; } /* Perform action. */ if (Action == SK_PNMI_GET) { /* Check length. */ if (*pLen < (Limit - LogPortIndex) * 6) { *pLen = (Limit - LogPortIndex) * 6; return (SK_PNMI_ERR_TOO_SHORT); } /* Get value. */ for (; LogPortIndex < Limit; LogPortIndex ++) { switch (Id) { case OID_SKGE_PHYS_CUR_ADDR: if (LogPortIndex == 0) { CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress); } else { PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); CopyMac(pBuf + Offset, &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress); } Offset += 6; break; case OID_SKGE_PHYS_FAC_ADDR: if (LogPortIndex == 0) { CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].PermanentMacAddress); } else { PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); CopyMac(pBuf + Offset, &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress); } Offset += 6; break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, SK_PNMI_ERR008MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } *pLen = Offset; } else { /* * The logical MAC address may not be changed, * only the physical ones. */ if (Id == OID_SKGE_PHYS_FAC_ADDR) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } /* Only the current address may be changed. */ if (Id != OID_SKGE_PHYS_CUR_ADDR) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, SK_PNMI_ERR009MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* Check length. */ if (*pLen < (Limit - LogPortIndex) * 6) { *pLen = (Limit - LogPortIndex) * 6; return (SK_PNMI_ERR_TOO_SHORT); } if (*pLen > (Limit - LogPortIndex) * 6) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* Check action. */ if (Action == SK_PNMI_PRESET) { *pLen = 0; return (SK_PNMI_ERR_OK); } /* Set OID_SKGE_MAC_CUR_ADDR. */ for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) { /* * A set to virtual port and set of broadcast * address will be ignored. */ if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset, "\xff\xff\xff\xff\xff\xff", 6) == 0) { continue; } PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); Ret = SkAddrOverride(pAC, IoC, PhysPortIndex, (SK_MAC_ADDR *)(pBuf + Offset), (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS : SK_ADDR_PHYSICAL_ADDRESS)); if (Ret != SK_ADDR_OVERRIDE_SUCCESS) { return (SK_PNMI_ERR_GENERAL); } } *pLen = Offset; } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX * * Description: * Retrieves the statistic values of the CSUM module. The CSUM data * structure must be available in the SK_AC even if the CSUM module * is not included, because PNMI reads the statistic data from the * CSUM part of SK_AC directly. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int CsumStat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int Index; unsigned int Limit; unsigned int Offset = 0; SK_U64 StatVal; /* Calculate instance if wished. */ if (Instance != (SK_U32)(-1)) { if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } Index = (unsigned int)Instance - 1; Limit = Index + 1; } else { Index = 0; Limit = SKCS_NUM_PROTOCOLS; } /* Check action. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } /* Check length. */ if (*pLen < (Limit - Index) * sizeof(SK_U64)) { *pLen = (Limit - Index) * sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } /* Get value. */ for (; Index < Limit; Index ++) { switch (Id) { case OID_SKGE_CHKSM_RX_OK_CTS: StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts; break; case OID_SKGE_CHKSM_RX_UNABLE_CTS: StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts; break; case OID_SKGE_CHKSM_RX_ERR_CTS: StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts; break; case OID_SKGE_CHKSM_TX_OK_CTS: StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts; break; case OID_SKGE_CHKSM_TX_UNABLE_CTS: StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts; break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, SK_PNMI_ERR010MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } SK_PNMI_STORE_U64(pBuf + Offset, StatVal); Offset += sizeof(SK_U64); } /* Store used buffer space. */ *pLen = Offset; return (SK_PNMI_ERR_OK); } /***************************************************************************** * * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX * * Description: * Retrieves the statistic values of the I2C module, which handles * the temperature and voltage sensors. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int SensorStat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int i; unsigned int Index; unsigned int Limit; unsigned int Offset; unsigned int Len; SK_U32 Val32; SK_U64 Val64; /* Calculate instance if wished. */ if ((Instance != (SK_U32)(-1))) { if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } Index = (unsigned int)Instance -1; Limit = (unsigned int)Instance; } else { Index = 0; Limit = (unsigned int) pAC->I2c.MaxSens; } /* Check action. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } /* Check length. */ switch (Id) { case OID_SKGE_SENSOR_VALUE: case OID_SKGE_SENSOR_WAR_THRES_LOW: case OID_SKGE_SENSOR_WAR_THRES_UPP: case OID_SKGE_SENSOR_ERR_THRES_LOW: case OID_SKGE_SENSOR_ERR_THRES_UPP: if (*pLen < (Limit - Index) * sizeof(SK_U32)) { *pLen = (Limit - Index) * sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_SENSOR_DESCR: for (Offset = 0, i = Index; i < Limit; i ++) { Len = (unsigned int) SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1; if (Len >= SK_PNMI_STRINGLEN2) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011, SK_PNMI_ERR011MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } Offset += Len; } if (*pLen < Offset) { *pLen = Offset; return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_SENSOR_INDEX: case OID_SKGE_SENSOR_TYPE: case OID_SKGE_SENSOR_STATUS: if (*pLen < Limit - Index) { *pLen = Limit - Index; return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_SENSOR_WAR_CTS: case OID_SKGE_SENSOR_WAR_TIME: case OID_SKGE_SENSOR_ERR_CTS: case OID_SKGE_SENSOR_ERR_TIME: if (*pLen < (Limit - Index) * sizeof(SK_U64)) { *pLen = (Limit - Index) * sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, SK_PNMI_ERR012MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* Get value. */ for (Offset = 0; Index < Limit; Index ++) { switch (Id) { case OID_SKGE_SENSOR_INDEX: *(pBuf + Offset) = (char)Index; Offset ++; break; case OID_SKGE_SENSOR_DESCR: Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc); SK_MEMCPY(pBuf + Offset + 1, pAC->I2c.SenTable[Index].SenDesc, Len); *(pBuf + Offset) = (char)Len; Offset += Len + 1; break; case OID_SKGE_SENSOR_TYPE: *(pBuf + Offset) = (char)pAC->I2c.SenTable[Index].SenType; Offset ++; break; case OID_SKGE_SENSOR_VALUE: Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue; SK_PNMI_STORE_U32(pBuf + Offset, Val32); Offset += sizeof(SK_U32); break; case OID_SKGE_SENSOR_WAR_THRES_LOW: Val32 = (SK_U32)pAC->I2c.SenTable[Index]. SenThreWarnLow; SK_PNMI_STORE_U32(pBuf + Offset, Val32); Offset += sizeof(SK_U32); break; case OID_SKGE_SENSOR_WAR_THRES_UPP: Val32 = (SK_U32)pAC->I2c.SenTable[Index]. SenThreWarnHigh; SK_PNMI_STORE_U32(pBuf + Offset, Val32); Offset += sizeof(SK_U32); break; case OID_SKGE_SENSOR_ERR_THRES_LOW: Val32 = (SK_U32)pAC->I2c.SenTable[Index]. SenThreErrLow; SK_PNMI_STORE_U32(pBuf + Offset, Val32); Offset += sizeof(SK_U32); break; case OID_SKGE_SENSOR_ERR_THRES_UPP: Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh; SK_PNMI_STORE_U32(pBuf + Offset, Val32); Offset += sizeof(SK_U32); break; case OID_SKGE_SENSOR_STATUS: *(pBuf + Offset) = (char)pAC->I2c.SenTable[Index].SenErrFlag; Offset ++; break; case OID_SKGE_SENSOR_WAR_CTS: Val64 = pAC->I2c.SenTable[Index].SenWarnCts; SK_PNMI_STORE_U64(pBuf + Offset, Val64); Offset += sizeof(SK_U64); break; case OID_SKGE_SENSOR_ERR_CTS: Val64 = pAC->I2c.SenTable[Index].SenErrCts; SK_PNMI_STORE_U64(pBuf + Offset, Val64); Offset += sizeof(SK_U64); break; case OID_SKGE_SENSOR_WAR_TIME: Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. SenBegWarnTS); SK_PNMI_STORE_U64(pBuf + Offset, Val64); Offset += sizeof(SK_U64); break; case OID_SKGE_SENSOR_ERR_TIME: Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. SenBegErrTS); SK_PNMI_STORE_U64(pBuf + Offset, Val64); Offset += sizeof(SK_U64); break; default: SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, ("SensorStat: Unknown OID should be handled before")); return (SK_PNMI_ERR_GENERAL); } } /* Store used buffer space. */ *pLen = Offset; return (SK_PNMI_ERR_OK); } /***************************************************************************** * * Vpd - OID handler function of OID_SKGE_VPD_XXX * * Description: * Get/preset/set of VPD data. As instance the name of a VPD key * can be passed. The Instance parameter is a SK_U32 and can be * used as a string buffer for the VPD key, because their maximum * length is 4 byte. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Vpd( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_VPD_STATUS *pVpdStatus; unsigned int BufLen; char Buf[256]; char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; char KeyStr[SK_PNMI_VPD_KEY_SIZE]; unsigned int KeyNo; unsigned int Offset; unsigned int Index; unsigned int FirstIndex; unsigned int LastIndex; unsigned int Len; int Ret; SK_U32 Val32; /* * VpdKeyReadError will be set in GetVpdKeyArr() if an error occurs. * Due to the fact that some drivers use SkPnmiGetStruct() to retrieve * all statistical data, an error in GetVpdKeyArr() will generate a PNMI * error and terminate SkPnmiGetStruct() without filling in statistical * data into the PNMI struct. In this case the driver will get no values * for statistical purposes (netstat, ifconfig etc.). GetVpdKeyArr() is * the first function to be called in SkPnmiGetStruct(), so any error * will terminate SkPnmiGetStruct() immediately. Hence, VpdKeyReadError will * be set during the first call to GetVpdKeyArr() to make successful calls * to SkPnmiGetStruct() possible. But there is another point to consider: * When filling in the statistical data into the PNMI struct, the VPD * handler Vpd() will also be called. If GetVpdKeyArr() in Vpd() would * return with SK_PNMI_ERR_GENERAL, SkPnmiGetStruct() would fail again. * For this reason VpdKeyReadError is checked here and, if set, Vpd() * will return without doing anything and the return value SK_PNMI_ERR_OK. * Therefore SkPnmiGetStruct() is able to continue and fill in all other * statistical data. */ if (pAC->Pnmi.VpdKeyReadError == SK_TRUE) { return (SK_PNMI_ERR_OK); } /* Get array of all currently stored VPD keys. */ Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo); if (Ret != SK_PNMI_ERR_OK) { *pLen = 0; return (Ret); } /* * If instance is not -1, try to find the requested VPD key for * the multiple instance variables. The other OIDs as for example * OID VPD_ACTION are single instance variables and must be * handled separatly. */ FirstIndex = 0; LastIndex = KeyNo; if ((Instance != (SK_U32)(-1))) { if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE || Id == OID_SKGE_VPD_ACCESS) { SK_STRNCPY(KeyStr, (char *)&Instance, 4); KeyStr[4] = 0; for (Index = 0; Index < KeyNo; Index ++) { if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { FirstIndex = Index; LastIndex = Index+1; break; } } if (Index == KeyNo) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } } else if (Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } } /* Get value, if a query should be performed. */ if (Action == SK_PNMI_GET) { switch (Id) { case OID_SKGE_VPD_FREE_BYTES: /* Check length of buffer. */ if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } /* Get number of free bytes. */ pVpdStatus = VpdStat(pAC, IoC); if (pVpdStatus == NULL) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR017MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } if ((pVpdStatus->vpd_status & VPD_VALID) == 0) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR018MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } Val32 = (SK_U32)pVpdStatus->vpd_free_rw; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_VPD_ENTRIES_LIST: /* Check length. */ for (Len = 0, Index = 0; Index < KeyNo; Index ++) { Len += SK_STRLEN(KeyArr[Index]) + 1; } if (*pLen < Len) { *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } /* Get value. */ *(pBuf) = (char)Len - 1; for (Offset = 1, Index = 0; Index < KeyNo; Index ++) { Len = SK_STRLEN(KeyArr[Index]); SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len); Offset += Len; if (Index < KeyNo - 1) { *(pBuf + Offset) = ' '; Offset ++; } } *pLen = Offset; break; case OID_SKGE_VPD_ENTRIES_NUMBER: /* Check length. */ if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } Val32 = (SK_U32)KeyNo; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_VPD_KEY: /* Check buffer length, if it is large enough. */ for (Len = 0, Index = FirstIndex; Index < LastIndex; Index ++) { Len += SK_STRLEN(KeyArr[Index]) + 1; } if (*pLen < Len) { *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } /* * Get the key to an intermediate buffer, because * we have to prepend a length byte. */ for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) { Len = SK_STRLEN(KeyArr[Index]); *(pBuf + Offset) = (char)Len; SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], Len); Offset += Len + 1; } *pLen = Offset; break; case OID_SKGE_VPD_VALUE: /* Check the buffer length if it is large enough. */ for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) { BufLen = 256; if (VpdRead(pAC, IoC, KeyArr[Index], Buf, (int *)&BufLen) > 0 || BufLen >= SK_PNMI_VPD_DATALEN) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR021MSG)); return (SK_PNMI_ERR_GENERAL); } Offset += BufLen + 1; } if (*pLen < Offset) { *pLen = Offset; return (SK_PNMI_ERR_TOO_SHORT); } /* * Get the value to an intermediate buffer, because * we have to prepend a length byte. */ for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) { BufLen = 256; if (VpdRead(pAC, IoC, KeyArr[Index], Buf, (int *)&BufLen) > 0 || BufLen >= SK_PNMI_VPD_DATALEN) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR022MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } *(pBuf + Offset) = (char)BufLen; SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen); Offset += BufLen + 1; } *pLen = Offset; break; case OID_SKGE_VPD_ACCESS: if (*pLen < LastIndex - FirstIndex) { *pLen = LastIndex - FirstIndex; return (SK_PNMI_ERR_TOO_SHORT); } for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) { if (VpdMayWrite(KeyArr[Index])) { *(pBuf + Offset) = SK_PNMI_VPD_RW; } else { *(pBuf + Offset) = SK_PNMI_VPD_RO; } Offset ++; } *pLen = Offset; break; case OID_SKGE_VPD_ACTION: Offset = LastIndex - FirstIndex; if (*pLen < Offset) { *pLen = Offset; return (SK_PNMI_ERR_TOO_SHORT); } SK_MEMSET(pBuf, 0, Offset); *pLen = Offset; break; default: SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR023MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } else { /* The only OID which can be set is VPD_ACTION. */ if (Id != OID_SKGE_VPD_ACTION) { if (Id == OID_SKGE_VPD_FREE_BYTES || Id == OID_SKGE_VPD_ENTRIES_LIST || Id == OID_SKGE_VPD_ENTRIES_NUMBER || Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE || Id == OID_SKGE_VPD_ACCESS) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR024MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* * From this point we handle VPD_ACTION. Check the buffer * length. It should at least have the size of one byte. */ if (*pLen < 1) { *pLen = 1; return (SK_PNMI_ERR_TOO_SHORT); } /* The first byte contains the VPD action type we should perform. */ switch (*pBuf) { case SK_PNMI_VPD_IGNORE: /* Nothing to do. */ break; case SK_PNMI_VPD_CREATE: /* * We have to create a new VPD entry or we modify * an existing one. Check first the buffer length. */ if (*pLen < 4) { *pLen = 4; return (SK_PNMI_ERR_TOO_SHORT); } KeyStr[0] = pBuf[1]; KeyStr[1] = pBuf[2]; KeyStr[2] = 0; /* * Is the entry writable or does it belong to the * read-only area? */ if (!VpdMayWrite(KeyStr)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } Offset = (int)pBuf[3] & 0xFF; SK_MEMCPY(Buf, pBuf + 4, Offset); Buf[Offset] = 0; /* A PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } /* Write the new entry or modify an existing one .*/ Ret = VpdWrite(pAC, IoC, KeyStr, Buf); if (Ret == SK_PNMI_VPD_NOWRITE ) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } else if (Ret != SK_PNMI_VPD_OK) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR025MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* * Perform an update of the VPD data. This is * not mandantory, but just to be sure. */ Ret = VpdUpdate(pAC, IoC); if (Ret != SK_PNMI_VPD_OK) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR026MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } break; case SK_PNMI_VPD_DELETE: /* Check if the buffer size is plausible. */ if (*pLen < 3) { *pLen = 3; return (SK_PNMI_ERR_TOO_SHORT); } if (*pLen > 3) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } KeyStr[0] = pBuf[1]; KeyStr[1] = pBuf[2]; KeyStr[2] = 0; /* Find the passed key in the array. */ for (Index = 0; Index < KeyNo; Index ++) { if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { break; } } /* * If we cannot find the key it is wrong, so we * return an appropriate error value. */ if (Index == KeyNo) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } /* Ok, you wanted it and you will get it. */ Ret = VpdDelete(pAC, IoC, KeyStr); if (Ret != SK_PNMI_VPD_OK) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR027MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* * Perform an update of the VPD data. This is * not mandantory, but just to be sure. */ Ret = VpdUpdate(pAC, IoC); if (Ret != SK_PNMI_VPD_OK) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR028MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } break; default: *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * General - OID handler function of various single instance OIDs * * Description: * The code is simple. No description necessary. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int General( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int Index; unsigned int Len; unsigned int Offset; unsigned int Val; SK_U8 Val8; SK_U16 Val16; SK_U32 Val32; SK_U64 Val64; SK_U64 Val64RxHwErrs = 0; SK_U64 Val64RxRunt = 0; SK_U64 Val64RxFcs = 0; SK_U64 Val64TxHwErrs = 0; SK_BOOL Is64BitReq = SK_FALSE; char Buf[256]; int MacType; /* Check instance. We only handle single instance variables. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } /* Check action. We only allow get requests. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } MacType = pAC->GIni.GIMacType; /* Check length for the various supported OIDs. */ switch (Id) { case OID_GEN_XMIT_ERROR: case OID_GEN_RCV_ERROR: case OID_GEN_RCV_NO_BUFFER: #ifndef SK_NDIS_64BIT_CTR if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } #else /* SK_NDIS_64BIT_CTR */ /* For compatibility, at least 32bit are required for OID. */ if (*pLen < sizeof(SK_U32)) { /* * Indicate handling for 64bit values, * if insufficient space is provided. */ *pLen = sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; #endif /* SK_NDIS_64BIT_CTR */ break; case OID_SKGE_PORT_NUMBER: case OID_SKGE_DEVICE_TYPE: case OID_SKGE_RESULT: case OID_SKGE_RLMT_MONITOR_NUMBER: case OID_GEN_TRANSMIT_QUEUE_LENGTH: case OID_SKGE_TRAP_NUMBER: case OID_SKGE_MDB_VERSION: case OID_SKGE_BOARDLEVEL: case OID_SKGE_CHIPID: case OID_SKGE_RAMSIZE: if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_CHIPSET: if (*pLen < sizeof(SK_U16)) { *pLen = sizeof(SK_U16); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_BUS_TYPE: case OID_SKGE_BUS_SPEED: case OID_SKGE_BUS_WIDTH: case OID_SKGE_SENSOR_NUMBER: case OID_SKGE_CHKSM_NUMBER: case OID_SKGE_VAUXAVAIL: if (*pLen < sizeof(SK_U8)) { *pLen = sizeof(SK_U8); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_TX_SW_QUEUE_LEN: case OID_SKGE_TX_SW_QUEUE_MAX: case OID_SKGE_TX_RETRY: case OID_SKGE_RX_INTR_CTS: case OID_SKGE_TX_INTR_CTS: case OID_SKGE_RX_NO_BUF_CTS: case OID_SKGE_TX_NO_BUF_CTS: case OID_SKGE_TX_USED_DESCR_NO: case OID_SKGE_RX_DELIVERED_CTS: case OID_SKGE_RX_OCTETS_DELIV_CTS: case OID_SKGE_RX_HW_ERROR_CTS: case OID_SKGE_TX_HW_ERROR_CTS: case OID_SKGE_IN_ERRORS_CTS: case OID_SKGE_OUT_ERROR_CTS: case OID_SKGE_ERR_RECOVERY_CTS: case OID_SKGE_SYSUPTIME: if (*pLen < sizeof(SK_U64)) { *pLen = sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } break; default: /* Checked later. */ break; } /* Update statistics. */ if (Id == OID_SKGE_RX_HW_ERROR_CTS || Id == OID_SKGE_TX_HW_ERROR_CTS || Id == OID_SKGE_IN_ERRORS_CTS || Id == OID_SKGE_OUT_ERROR_CTS || Id == OID_GEN_XMIT_ERROR || Id == OID_GEN_RCV_ERROR) { /* * Force the XMAC to update its statistic counters and * Increment semaphore to indicate that an update was * already done. */ Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); if (Ret != SK_PNMI_ERR_OK) { *pLen = 0; return (Ret); } pAC->Pnmi.MacUpdatedFlag ++; /* * Some OIDs consist of multiple hardware counters. Those * values which are contained in all of them will be added * now. */ switch (Id) { case OID_SKGE_RX_HW_ERROR_CTS: case OID_SKGE_IN_ERRORS_CTS: case OID_GEN_RCV_ERROR: Val64RxHwErrs = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex); /* * In some cases the runt and fcs counters are incremented when collisions * occur. We have to correct those counters here. */ Val64RxRunt = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex); Val64RxFcs = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex); if (Val64RxRunt > Val64RxFcs) { Val64RxRunt -= Val64RxFcs; Val64RxHwErrs += Val64RxRunt; } else { Val64RxFcs -= Val64RxRunt; Val64RxHwErrs += Val64RxFcs; } break; case OID_SKGE_TX_HW_ERROR_CTS: case OID_SKGE_OUT_ERROR_CTS: case OID_GEN_XMIT_ERROR: Val64TxHwErrs = GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex); break; } } /* Retrieve value. */ switch (Id) { case OID_SKGE_SUPPORTED_LIST: Len = ID_TABLE_SIZE * sizeof(SK_U32); if (*pLen < Len) { *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } for (Offset = 0, Index = 0; Offset < Len; Index ++) { Val32 = (SK_U32)IdTable[Index].Id; SK_PNMI_STORE_U32(pBuf + Offset, Val32); Offset += sizeof(SK_U32); } *pLen = Len; break; case OID_SKGE_BOARDLEVEL: Val32 = (SK_U32)pAC->GIni.GILevel; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_PORT_NUMBER: Val32 = (SK_U32)pAC->GIni.GIMacsFound; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_DEVICE_TYPE: Val32 = (SK_U32)pAC->Pnmi.DeviceType; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_DRIVER_DESCR: if (pAC->Pnmi.pDriverDescription == NULL) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, SK_PNMI_ERR007MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1; if (Len > SK_PNMI_STRINGLEN1) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, SK_PNMI_ERR029MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } if (*pLen < Len) { *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } *pBuf = (char)(Len - 1); SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1); *pLen = Len; break; case OID_SKGE_DRIVER_VERSION: if (pAC->Pnmi.pDriverVersion == NULL) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, SK_PNMI_ERR030MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1; if (Len > SK_PNMI_STRINGLEN1) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, SK_PNMI_ERR031MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } if (*pLen < Len) { *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } *pBuf = (char)(Len - 1); SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1); *pLen = Len; break; case OID_SKGE_DRIVER_RELDATE: if (pAC->Pnmi.pDriverReleaseDate == NULL) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR053, SK_PNMI_ERR053MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1; if (Len > SK_PNMI_STRINGLEN1) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR054, SK_PNMI_ERR054MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } if (*pLen < Len) { *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } *pBuf = (char)(Len - 1); SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1); *pLen = Len; break; case OID_SKGE_DRIVER_FILENAME: if (pAC->Pnmi.pDriverFileName == NULL) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR055, SK_PNMI_ERR055MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1; if (Len > SK_PNMI_STRINGLEN1) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR056, SK_PNMI_ERR056MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } if (*pLen < Len) { *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } *pBuf = (char)(Len - 1); SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1); *pLen = Len; break; case OID_SKGE_HW_DESCR: /* * The hardware description is located in the VPD. This * query may move to the initialisation routine. But * the VPD data is cached and therefore a call here * will not make much difference. * Please read comment in Vpd(). */ if (pAC->Pnmi.VpdKeyReadError == SK_TRUE) { return (SK_PNMI_ERR_OK); } Len = 256; if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, SK_PNMI_ERR032MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } Len ++; if (Len > SK_PNMI_STRINGLEN1) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, SK_PNMI_ERR033MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } if (*pLen < Len) { *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } *pBuf = (char)(Len - 1); SK_MEMCPY(pBuf + 1, Buf, Len - 1); *pLen = Len; break; case OID_SKGE_HW_VERSION: if (*pLen < 5) { *pLen = 5; return (SK_PNMI_ERR_TOO_SHORT); } Val8 = (SK_U8)pAC->GIni.GIPciHwRev; pBuf[0] = 4; pBuf[1] = 'v'; pBuf[2] = (char)('0' | ((Val8 >> 4) & 0x0f)); pBuf[3] = '.'; pBuf[4] = (char)('0' | (Val8 & 0x0f)); *pLen = 5; break; case OID_SKGE_CHIPSET: Val16 = pAC->Pnmi.Chipset; SK_PNMI_STORE_U16(pBuf, Val16); *pLen = sizeof(SK_U16); break; case OID_SKGE_CHIPID: Val32 = pAC->GIni.GIChipId; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_RAMSIZE: Val32 = pAC->GIni.GIRamSize; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_VAUXAVAIL: *pBuf = (char)pAC->GIni.GIVauxAvail; *pLen = sizeof(char); break; case OID_SKGE_BUS_TYPE: *pBuf = (char)SK_PNMI_BUS_PCI; *pLen = sizeof(char); break; case OID_SKGE_BUS_SPEED: *pBuf = pAC->Pnmi.PciBusSpeed; *pLen = sizeof(char); break; case OID_SKGE_BUS_WIDTH: *pBuf = pAC->Pnmi.PciBusWidth; *pLen = sizeof(char); break; case OID_SKGE_RESULT: Val32 = pAC->Pnmi.TestResult; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_SENSOR_NUMBER: *pBuf = (char)pAC->I2c.MaxSens; *pLen = sizeof(char); break; case OID_SKGE_CHKSM_NUMBER: *pBuf = SKCS_NUM_PROTOCOLS; *pLen = sizeof(char); break; case OID_SKGE_TRAP_NUMBER: GetTrapQueueLen(pAC, &Len, &Val); Val32 = (SK_U32)Val; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_TRAP: GetTrapQueueLen(pAC, &Len, &Val); if (*pLen < Len) { *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } CopyTrapQueue(pAC, pBuf); *pLen = Len; break; case OID_SKGE_RLMT_MONITOR_NUMBER: /* Not yet implemented by RLMT, therefore we return zero elements. */ Val32 = 0; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_TX_SW_QUEUE_LEN: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen + pAC->Pnmi.BufPort[1].TxSwQueueLen; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxSwQueueLen + pAC->Pnmi.Port[1].TxSwQueueLen; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_TX_SW_QUEUE_MAX: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax + pAC->Pnmi.BufPort[1].TxSwQueueMax; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxSwQueueMax + pAC->Pnmi.Port[1].TxSwQueueMax; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_TX_RETRY: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxRetryCts + pAC->Pnmi.BufPort[1].TxRetryCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxRetryCts + pAC->Pnmi.Port[1].TxRetryCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_RX_INTR_CTS: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].RxIntrCts + pAC->Pnmi.BufPort[1].RxIntrCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].RxIntrCts + pAC->Pnmi.Port[1].RxIntrCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_TX_INTR_CTS: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxIntrCts + pAC->Pnmi.BufPort[1].TxIntrCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxIntrCts + pAC->Pnmi.Port[1].TxIntrCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_RX_NO_BUF_CTS: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts + pAC->Pnmi.BufPort[1].RxNoBufCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].RxNoBufCts + pAC->Pnmi.Port[1].RxNoBufCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_TX_NO_BUF_CTS: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts + pAC->Pnmi.BufPort[1].TxNoBufCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxNoBufCts + pAC->Pnmi.Port[1].TxNoBufCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_TX_USED_DESCR_NO: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo + pAC->Pnmi.BufPort[1].TxUsedDescrNo; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo + pAC->Pnmi.Port[1].TxUsedDescrNo; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_RX_DELIVERED_CTS: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts + pAC->Pnmi.BufPort[1].RxDeliveredCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].RxDeliveredCts + pAC->Pnmi.Port[1].RxDeliveredCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_RX_OCTETS_DELIV_CTS: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts + pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts + pAC->Pnmi.Port[1].RxOctetsDeliveredCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_RX_HW_ERROR_CTS: SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs); *pLen = sizeof(SK_U64); break; case OID_SKGE_TX_HW_ERROR_CTS: SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs); *pLen = sizeof(SK_U64); break; case OID_SKGE_IN_ERRORS_CTS: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; } /* SingleNet mode. */ else { Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[0].RxNoBufCts + pAC->Pnmi.BufPort[1].RxNoBufCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; } /* SingleNet mode. */ else { Val64 = Val64RxHwErrs + pAC->Pnmi.Port[0].RxNoBufCts + pAC->Pnmi.Port[1].RxNoBufCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_OUT_ERROR_CTS: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; } /* SingleNet mode. */ else { Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[0].TxNoBufCts + pAC->Pnmi.BufPort[1].TxNoBufCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; } /* SingleNet mode. */ else { Val64 = Val64TxHwErrs + pAC->Pnmi.Port[0].TxNoBufCts + pAC->Pnmi.Port[1].TxNoBufCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_ERR_RECOVERY_CTS: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts + pAC->Pnmi.BufPort[1].ErrRecoveryCts; } } else { /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts; } /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts + pAC->Pnmi.Port[1].ErrRecoveryCts; } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_SYSUPTIME: Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); Val64 -= pAC->Pnmi.StartUpTime; SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_MDB_VERSION: Val32 = SK_PNMI_MDB_VERSION; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_GEN_RCV_ERROR: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; } else { Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; } /* * By default 32bit values are evaluated. */ if (!Is64BitReq) { Val32 = (SK_U32)Val64; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); } else { SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); } break; case OID_GEN_XMIT_ERROR: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; } else { Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; } /* * By default 32bit values are evaluated. */ if (!Is64BitReq) { Val32 = (SK_U32)Val64; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); } else { SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); } break; case OID_GEN_RCV_NO_BUFFER: /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex); } else { Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex); } /* * By default 32bit values are evaluated. */ if (!Is64BitReq) { Val32 = (SK_U32)Val64; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); } else { SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); } break; case OID_GEN_TRANSMIT_QUEUE_LENGTH: Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, SK_PNMI_ERR034MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } if (Id == OID_SKGE_RX_HW_ERROR_CTS || Id == OID_SKGE_TX_HW_ERROR_CTS || Id == OID_SKGE_IN_ERRORS_CTS || Id == OID_SKGE_OUT_ERROR_CTS || Id == OID_GEN_XMIT_ERROR || Id == OID_GEN_RCV_ERROR) { pAC->Pnmi.MacUpdatedFlag --; } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance. * * Description: * Get/Presets/Sets the RLMT OIDs. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Rlmt( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int PhysPortIndex; unsigned int PhysPortMax; SK_EVPARA EventParam; SK_U32 Val32; SK_U64 Val64; /* Check instance. Only single instance OIDs are allowed here. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } /* Perform the requested action. */ if (Action == SK_PNMI_GET) { /* Check if the buffer length is large enough. */ switch (Id) { case OID_SKGE_RLMT_MODE: case OID_SKGE_RLMT_PORT_ACTIVE: case OID_SKGE_RLMT_PORT_PREFERRED: if (*pLen < sizeof(SK_U8)) { *pLen = sizeof(SK_U8); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_RLMT_PORT_NUMBER: if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_RLMT_CHANGE_CTS: case OID_SKGE_RLMT_CHANGE_TIME: case OID_SKGE_RLMT_CHANGE_ESTIM: case OID_SKGE_RLMT_CHANGE_THRES: if (*pLen < sizeof(SK_U64)) { *pLen = sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, SK_PNMI_ERR035MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* * Update RLMT statistic and increment semaphores to indicate * that an update was already done. Maybe RLMT will hold its * statistic always up to date some time. Then we can * remove this type of call. */ if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { *pLen = 0; return (Ret); } pAC->Pnmi.RlmtUpdatedFlag ++; /* Retrieve value. */ switch (Id) { case OID_SKGE_RLMT_MODE: *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode; *pLen = sizeof(char); break; case OID_SKGE_RLMT_PORT_NUMBER: Val32 = (SK_U32)pAC->GIni.GIMacsFound; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_RLMT_PORT_ACTIVE: *pBuf = 0; /* * If multiple ports may become active this OID * doesn't make sense any more. A new variable in * the port structure should be created. However, * for this variable the first active port is * returned. */ PhysPortMax = pAC->GIni.GIMacsFound; for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) { if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex); break; } } *pLen = sizeof(char); break; case OID_SKGE_RLMT_PORT_PREFERRED: *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference); *pLen = sizeof(char); break; case OID_SKGE_RLMT_CHANGE_CTS: Val64 = pAC->Pnmi.RlmtChangeCts; SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_RLMT_CHANGE_TIME: Val64 = pAC->Pnmi.RlmtChangeTime; SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_RLMT_CHANGE_ESTIM: Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate; SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; case OID_SKGE_RLMT_CHANGE_THRES: Val64 = pAC->Pnmi.RlmtChangeThreshold; SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); break; default: SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, ("Rlmt: Unknown OID should be handled before")); pAC->Pnmi.RlmtUpdatedFlag --; *pLen = 0; return (SK_PNMI_ERR_GENERAL); } pAC->Pnmi.RlmtUpdatedFlag --; } else { /* Perform a PRESET or SET. */ switch (Id) { case OID_SKGE_RLMT_MODE: /* Check if the buffer length is plausible. */ if (*pLen < sizeof(char)) { *pLen = sizeof(char); return (SK_PNMI_ERR_TOO_SHORT); } /* Check if the value range is correct. */ if (*pLen != sizeof(char) || (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 || *(SK_U8 *)pBuf > 15) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { *pLen = 0; return (SK_PNMI_ERR_OK); } /* Send an event to RLMT to change the mode. */ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); EventParam.Para32[0] |= (SK_U32)(*pBuf); EventParam.Para32[1] = 0; if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, SK_PNMI_ERR037MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } break; case OID_SKGE_RLMT_PORT_PREFERRED: /* PRESET/SET action makes no sense in Dual Net mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { break; } /* Check if the buffer length is plausible. */ if (*pLen < sizeof(char)) { *pLen = sizeof(char); return (SK_PNMI_ERR_TOO_SHORT); } /* Check if the value range is correct. */ if (*pLen != sizeof(char) || *(SK_U8 *)pBuf > (SK_U8)pAC->GIni.GIMacsFound) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { *pLen = 0; return (SK_PNMI_ERR_OK); } /* * Send an event to RLMT change the preferred port. * A param of -1 means automatic mode. RLMT will * make the decision which is the preferred port. */ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); EventParam.Para32[0] = (SK_U32)(*pBuf) - 1; EventParam.Para32[1] = NetIndex; if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, SK_PNMI_ERR038MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } break; case OID_SKGE_RLMT_CHANGE_THRES: /* Check if the buffer length is plausible. */ if (*pLen < sizeof(SK_U64)) { *pLen = sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } /* There are not many restrictions to the value range. */ if (*pLen != sizeof(SK_U64)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { *pLen = 0; return (SK_PNMI_ERR_OK); } /* * Store the new threshold, which will be taken * on the next timer event. */ SK_PNMI_READ_U64(pBuf, Val64); pAC->Pnmi.RlmtChangeThreshold = Val64; break; default: /* The other OIDs are not be able for set. */ *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance. * * Description: * Performs get requests on multiple instance variables. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int RlmtStat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int PhysPortMax; unsigned int PhysPortIndex; unsigned int Limit; unsigned int Offset; int Ret; SK_U32 Val32; SK_U64 Val64; /* Calculate the port indexes from the instance. */ PhysPortMax = pAC->GIni.GIMacsFound; if ((Instance != (SK_U32)(-1))) { /* Check instance range. */ if ((Instance < 1) || (Instance > PhysPortMax)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } /* SingleNet mode. */ PhysPortIndex = Instance - 1; /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { PhysPortIndex = NetIndex; } /* Both net modes. */ Limit = PhysPortIndex + 1; } else { /* SingleNet mode. */ PhysPortIndex = 0; Limit = PhysPortMax; /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { PhysPortIndex = NetIndex; Limit = PhysPortIndex + 1; } } /* Currently only GET requests are allowed. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } /* Check if the buffer length is large enough. */ switch (Id) { case OID_SKGE_RLMT_PORT_INDEX: case OID_SKGE_RLMT_STATUS: if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_RLMT_TX_HELLO_CTS: case OID_SKGE_RLMT_RX_HELLO_CTS: case OID_SKGE_RLMT_TX_SP_REQ_CTS: case OID_SKGE_RLMT_RX_SP_CTS: if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) { *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, SK_PNMI_ERR039MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* * Update statistic and increment semaphores to indicate that * an update was already done. */ if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { *pLen = 0; return (Ret); } pAC->Pnmi.RlmtUpdatedFlag ++; /* Get value. */ Offset = 0; for (; PhysPortIndex < Limit; PhysPortIndex ++) { switch (Id) { case OID_SKGE_RLMT_PORT_INDEX: Val32 = PhysPortIndex; SK_PNMI_STORE_U32(pBuf + Offset, Val32); Offset += sizeof(SK_U32); break; case OID_SKGE_RLMT_STATUS: if (pAC->Rlmt.Port[PhysPortIndex].PortState == SK_RLMT_PS_INIT || pAC->Rlmt.Port[PhysPortIndex].PortState == SK_RLMT_PS_DOWN) { Val32 = SK_PNMI_RLMT_STATUS_ERROR; } else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { Val32 = SK_PNMI_RLMT_STATUS_ACTIVE; } else { Val32 = SK_PNMI_RLMT_STATUS_STANDBY; } SK_PNMI_STORE_U32(pBuf + Offset, Val32); Offset += sizeof(SK_U32); break; case OID_SKGE_RLMT_TX_HELLO_CTS: Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts; SK_PNMI_STORE_U64(pBuf + Offset, Val64); Offset += sizeof(SK_U64); break; case OID_SKGE_RLMT_RX_HELLO_CTS: Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts; SK_PNMI_STORE_U64(pBuf + Offset, Val64); Offset += sizeof(SK_U64); break; case OID_SKGE_RLMT_TX_SP_REQ_CTS: Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts; SK_PNMI_STORE_U64(pBuf + Offset, Val64); Offset += sizeof(SK_U64); break; case OID_SKGE_RLMT_RX_SP_CTS: Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts; SK_PNMI_STORE_U64(pBuf + Offset, Val64); Offset += sizeof(SK_U64); break; default: SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, ("RlmtStat: Unknown OID should be errored before")); pAC->Pnmi.RlmtUpdatedFlag --; *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } *pLen = Offset; pAC->Pnmi.RlmtUpdatedFlag --; return (SK_PNMI_ERR_OK); } /***************************************************************************** * * MacPrivateConf - OID handler function of OIDs concerning the configuration * * Description: * Get/Presets/Sets the OIDs concerning the configuration. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int MacPrivateConf( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int PhysPortMax; unsigned int PhysPortIndex; unsigned int LogPortMax; unsigned int LogPortIndex; unsigned int Limit; unsigned int Offset; char Val8; char *pBufPtr; int Ret; SK_EVPARA EventParam; SK_U32 Val32; #ifdef SK_PHY_LP_MODE SK_U8 CurrentPhyPowerState; #endif /* SK_PHY_LP_MODE */ /* Calculate instance if wished. MAC index 0 is the virtual MAC. */ PhysPortMax = pAC->GIni.GIMacsFound; LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */ LogPortMax--; } if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */ /* Check instance range. */ if ((Instance < 1) || (Instance > LogPortMax)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); Limit = LogPortIndex + 1; } else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */ LogPortIndex = 0; Limit = LogPortMax; } /* Perform action. */ if (Action == SK_PNMI_GET) { /* Check length. */ switch (Id) { case OID_SKGE_PMD: case OID_SKGE_CONNECTOR: case OID_SKGE_LINK_CAP: case OID_SKGE_LINK_MODE: case OID_SKGE_LINK_MODE_STATUS: case OID_SKGE_LINK_STATUS: case OID_SKGE_FLOWCTRL_CAP: case OID_SKGE_FLOWCTRL_MODE: case OID_SKGE_FLOWCTRL_STATUS: case OID_SKGE_PHY_OPERATION_CAP: case OID_SKGE_PHY_OPERATION_MODE: case OID_SKGE_PHY_OPERATION_STATUS: case OID_SKGE_SPEED_CAP: case OID_SKGE_SPEED_MODE: case OID_SKGE_SPEED_STATUS: #ifdef SK_PHY_LP_MODE case OID_SKGE_PHY_LP_MODE: #endif if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) { *pLen = (Limit - LogPortIndex) * sizeof(SK_U8); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_MTU: case OID_SKGE_PHY_TYPE: if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) { *pLen = (Limit - LogPortIndex) * sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, SK_PNMI_ERR041MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* * Update statistic and increment semaphore to indicate * that an update was already done. */ if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { *pLen = 0; return (Ret); } pAC->Pnmi.SirqUpdatedFlag ++; /* Get value. */ Offset = 0; for (; LogPortIndex < Limit; LogPortIndex ++) { pBufPtr = pBuf + Offset; switch (Id) { case OID_SKGE_PMD: *pBufPtr = pAC->Pnmi.PMD; Offset ++; break; case OID_SKGE_CONNECTOR: *pBufPtr = pAC->Pnmi.Connector; Offset ++; break; case OID_SKGE_PHY_TYPE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { continue; } /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); Val32 = pAC->GIni.GP[PhysPortIndex].PhyType; } else { /* DualNet mode. */ Val32 = pAC->GIni.GP[NetIndex].PhyType; } SK_PNMI_STORE_U32(pBufPtr, Val32); Offset += sizeof(SK_U32); break; #ifdef SK_PHY_LP_MODE case OID_SKGE_PHY_LP_MODE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { continue; } /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); *pBufPtr = (SK_U8)pAC->GIni.GP[PhysPortIndex].PPhyPowerState; } else { /* DualNet mode. */ *pBufPtr = (SK_U8)pAC->GIni.GP[NetIndex].PPhyPowerState; } Offset += sizeof(SK_U8); break; #endif case OID_SKGE_LINK_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap; } Offset ++; break; case OID_SKGE_LINK_MODE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf; } Offset ++; break; case OID_SKGE_LINK_MODE_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); } } else { /* DualNet mode. */ *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex); } Offset ++; break; case OID_SKGE_LINK_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex); } } else { /* DualNet mode. */ *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex); } Offset ++; break; case OID_SKGE_FLOWCTRL_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap; } Offset ++; break; case OID_SKGE_FLOWCTRL_MODE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode; } Offset ++; break; case OID_SKGE_FLOWCTRL_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus; } Offset ++; break; case OID_SKGE_PHY_OPERATION_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet Mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap; } Offset ++; break; case OID_SKGE_PHY_OPERATION_MODE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode; } Offset ++; break; case OID_SKGE_PHY_OPERATION_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus; } } else { *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus; } Offset ++; break; case OID_SKGE_SPEED_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap; } Offset ++; break; case OID_SKGE_SPEED_MODE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed; } Offset ++; break; case OID_SKGE_SPEED_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* Get value for virtual port. */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; } } else { /* DualNet mode. */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed; } Offset ++; break; case OID_SKGE_MTU: Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex); SK_PNMI_STORE_U32(pBufPtr, Val32); Offset += sizeof(SK_U32); break; default: SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, ("MacPrivateConf: Unknown OID should be handled before")); pAC->Pnmi.SirqUpdatedFlag --; return (SK_PNMI_ERR_GENERAL); } } *pLen = Offset; pAC->Pnmi.SirqUpdatedFlag --; return (SK_PNMI_ERR_OK); } /* * From here SET or PRESET action. Check if the passed * buffer length is plausible. */ switch (Id) { case OID_SKGE_LINK_MODE: case OID_SKGE_FLOWCTRL_MODE: case OID_SKGE_PHY_OPERATION_MODE: case OID_SKGE_SPEED_MODE: if (*pLen < Limit - LogPortIndex) { *pLen = Limit - LogPortIndex; return (SK_PNMI_ERR_TOO_SHORT); } if (*pLen != Limit - LogPortIndex) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } break; #ifdef SK_PHY_LP_MODE case OID_SKGE_PHY_LP_MODE: if (*pLen < Limit - LogPortIndex) { *pLen = Limit - LogPortIndex; return (SK_PNMI_ERR_TOO_SHORT); } break; #endif /* SK_PHY_LP_MODE */ case OID_SKGE_MTU: if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) { *pLen = (Limit - LogPortIndex) * sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; default: *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } /* Perform PRESET or SET. */ Offset = 0; for (; LogPortIndex < Limit; LogPortIndex ++) { Val8 = *(pBuf + Offset); switch (Id) { case OID_SKGE_LINK_MODE: /* Check the value range. */ if (Val8 == 0) { Offset++; break; } if (Val8 < SK_LMODE_HALF || (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) || (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* * The virtual port consists of all currently * active ports. Find them and send an event * with the new link mode to SIRQ. */ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) { if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { continue; } EventParam.Para32[0] = PhysPortIndex; EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR043, SK_PNMI_ERR043MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } /* for */ } else { /* * Send an event with the new link mode to * the SIRQ module. */ EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR043, SK_PNMI_ERR043MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } } else { /* DualNet mode. */ /* * Send an event with the new link mode to * the SIRQ module. */ EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR043, SK_PNMI_ERR043MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } Offset++; break; case OID_SKGE_FLOWCTRL_MODE: /* Check the value range. */ if (Val8 == 0) { Offset++; break; } if (Val8 < SK_FLOW_MODE_NONE || (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) || (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* * The virtual port consists of all currently * active ports. Find them and send an event * with the new flow control mode to SIRQ. */ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) { if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { continue; } EventParam.Para32[0] = PhysPortIndex; EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_FLOWMODE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR044, SK_PNMI_ERR044MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } } else { /* * Send an event with the new flow control * mode to the SIRQ module. */ EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_FLOWMODE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR044, SK_PNMI_ERR044MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } } else { /* DualNet mode. */ /* * Send an event with the new link mode to * the SIRQ module. */ EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_FLOWMODE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR044, SK_PNMI_ERR044MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } Offset++; break; case OID_SKGE_PHY_OPERATION_MODE : /* Check the value range. */ if (Val8 == 0) { /* Mode of this port remains unchanged. */ Offset++; break; } if (Val8 < SK_MS_MODE_AUTO || (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) || (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* * The virtual port consists of all currently * active ports. Find them and send an event * with new master/slave (role) mode to SIRQ. */ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) { if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { continue; } EventParam.Para32[0] = PhysPortIndex; EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_ROLE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR042, SK_PNMI_ERR042MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } } else { /* * Send an event with the new master/slave * (role) mode to the SIRQ module. */ EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_ROLE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR042, SK_PNMI_ERR042MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } } else { /* DualNet mode. */ /* * Send an event with the new link mode to * the SIRQ module. */ EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_ROLE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR042, SK_PNMI_ERR042MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } Offset++; break; case OID_SKGE_SPEED_MODE: /* Check the value range. */ if (Val8 == 0) { Offset++; break; } if (Val8 < (SK_LSPEED_AUTO) || (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) || (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { /* * The virtual port consists of all currently * active ports. Find them and send an event * with the new flow control mode to SIRQ. */ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) { if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { continue; } EventParam.Para32[0] = PhysPortIndex; EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_SPEED, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR045, SK_PNMI_ERR045MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } } else { /* * Send an event with the new flow control * mode to the SIRQ module. */ EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_SPEED, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR045, SK_PNMI_ERR045MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } } else { /* DualNet mode. */ /* * Send an event with the new link mode to * the SIRQ module. */ EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_SPEED, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR045, SK_PNMI_ERR045MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } Offset++; break; case OID_SKGE_MTU: /* Check the value range. */ SK_PNMI_READ_U32((pBuf + Offset), Val32); if (Val32 == 0) { /* MTU of this port remains unchanged. */ Offset += sizeof(SK_U32); break; } if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) { return (SK_PNMI_ERR_GENERAL); } Offset += sizeof(SK_U32); break; #ifdef SK_PHY_LP_MODE case OID_SKGE_PHY_LP_MODE: /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { Offset = 0; continue; } } /* Set value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); CurrentPhyPowerState = pAC->GIni.GP[PhysPortIndex].PPhyPowerState; switch (Val8) { case PHY_PM_OPERATIONAL_MODE: /* If LowPowerMode is active, we can leave it. */ if (CurrentPhyPowerState) { Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex); if ((CurrentPhyPowerState == PHY_PM_DEEP_SLEEP) || (CurrentPhyPowerState == PHY_PM_IEEE_POWER_DOWN)) { SkDrvInitAdapter(pAC); } break; } else { *pLen = 0; return (SK_PNMI_ERR_GENERAL); } case PHY_PM_DEEP_SLEEP: case PHY_PM_IEEE_POWER_DOWN: /* If no LowPowerMode is active, we can enter it. */ if (!CurrentPhyPowerState) { SkDrvDeInitAdapter(pAC); } case PHY_PM_ENERGY_DETECT: case PHY_PM_ENERGY_DETECT_PLUS: /* If no LowPowerMode is active, we can enter it. */ if (!CurrentPhyPowerState) { Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf); break; } else { *pLen = 0; return (SK_PNMI_ERR_GENERAL); } default: *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } Offset++; break; #endif /* SK_PHY_LP_MODE */ default: SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, ("MacPrivateConf: Unknown OID should be handled before set")); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * Monitor - OID handler function for RLMT_MONITOR_XXX * * Description: * Because RLMT currently does not support the monitoring of * remote adapter cards, we return always an empty table. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Monitor( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int Index; unsigned int Limit; unsigned int Offset; unsigned int Entries; /* Not implemented yet. Return always an empty table. */ Entries = 0; /* Calculate instance if wished. */ if ((Instance != (SK_U32)(-1))) { if ((Instance < 1) || (Instance > Entries)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } Index = (unsigned int)Instance - 1; Limit = (unsigned int)Instance; } else { Index = 0; Limit = Entries; } /* GET/SET value. */ if (Action == SK_PNMI_GET) { for (Offset = 0; Index < Limit; Index ++) { switch (Id) { case OID_SKGE_RLMT_MONITOR_INDEX: case OID_SKGE_RLMT_MONITOR_ADDR: case OID_SKGE_RLMT_MONITOR_ERRS: case OID_SKGE_RLMT_MONITOR_TIMESTAMP: case OID_SKGE_RLMT_MONITOR_ADMIN: break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046, SK_PNMI_ERR046MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } *pLen = Offset; } else { /* Only MONITOR_ADMIN can be set. */ if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } /* Check if the length is plausible. */ if (*pLen < (Limit - Index)) { return (SK_PNMI_ERR_TOO_SHORT); } /* Okay, we have a wide value range. */ if (*pLen != (Limit - Index)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } /* * Not yet implemented. Return always BAD_VALUE, * because the table is empty. */ *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * VirtualConf - Calculates the values of configuration OIDs for virtual port * * Description: * We handle here the get of the configuration group OIDs, which are * a little bit complicated. The virtual port consists of all currently * active physical ports. If multiple ports are active and configured * differently we get in some trouble to return a single value. So we * get the value of the first active port and compare it with that of * the other active ports. If they are not the same, we return a value * that indicates that the state is indeterminated. * * Returns: * Nothing */ PNMI_STATIC void VirtualConf( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf) /* Buffer used for the management data transfer */ { unsigned int PhysPortMax; unsigned int PhysPortIndex; SK_U8 Val8; SK_U32 Val32; SK_BOOL PortActiveFlag; SK_GEPORT *pPrt; *pBuf = 0; PortActiveFlag = SK_FALSE; PhysPortMax = pAC->GIni.GIMacsFound; for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) { pPrt = &pAC->GIni.GP[PhysPortIndex]; /* Check if the physical port is active. */ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { continue; } PortActiveFlag = SK_TRUE; switch (Id) { case OID_SKGE_PHY_TYPE: /* Check if it is the first active port. */ if (*pBuf == 0) { Val32 = pPrt->PhyType; SK_PNMI_STORE_U32(pBuf, Val32); continue; } break; case OID_SKGE_LINK_CAP: /* * Different capabilities should not happen, but * in the case of the cases OR them all together. * From a curious point of view the virtual port * is capable of all found capabilities. */ *pBuf |= pPrt->PLinkCap; break; case OID_SKGE_LINK_MODE: /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = pPrt->PLinkModeConf; continue; } /* * If we find an active port with a different link mode * than the first one we return indeterminated. */ if (*pBuf != pPrt->PLinkModeConf) { *pBuf = SK_LMODE_INDETERMINATED; } break; case OID_SKGE_LINK_MODE_STATUS: /* Get the link mode of the physical port. */ Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = Val8; continue; } /* * If we find an active port with a different link mode status * than the first one we return indeterminated. */ if (*pBuf != Val8) { *pBuf = SK_LMODE_STAT_INDETERMINATED; } break; case OID_SKGE_LINK_STATUS: /* Get the link status of the physical port. */ Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex); /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = Val8; continue; } /* * If we find an active port with a different link status * than the first one we return indeterminated. */ if (*pBuf != Val8) { *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; } break; case OID_SKGE_FLOWCTRL_CAP: /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = pPrt->PFlowCtrlCap; continue; } /* * From a curious point of view the virtual port * is capable of all found capabilities. */ *pBuf |= pPrt->PFlowCtrlCap; break; case OID_SKGE_FLOWCTRL_MODE: /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = pPrt->PFlowCtrlMode; continue; } /* * If we find an active port with a different flow-control mode * than the first one we return indeterminated. */ if (*pBuf != pPrt->PFlowCtrlMode) { *pBuf = SK_FLOW_MODE_INDETERMINATED; } break; case OID_SKGE_FLOWCTRL_STATUS: /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = pPrt->PFlowCtrlStatus; continue; } /* * If we find an active port with a different flow-control status * than the first one we return indeterminated. */ if (*pBuf != pPrt->PFlowCtrlStatus) { *pBuf = SK_FLOW_STAT_INDETERMINATED; } break; case OID_SKGE_PHY_OPERATION_CAP: /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = pPrt->PMSCap; continue; } /* * From a curious point of view the virtual port * is capable of all found capabilities. */ *pBuf |= pPrt->PMSCap; break; case OID_SKGE_PHY_OPERATION_MODE: /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = pPrt->PMSMode; continue; } /* * If we find an active port with a different master/slave mode * than the first one we return indeterminated. */ if (*pBuf != pPrt->PMSMode) { *pBuf = SK_MS_MODE_INDETERMINATED; } break; case OID_SKGE_PHY_OPERATION_STATUS: /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = pPrt->PMSStatus; continue; } /* * If we find an active port with a different master/slave status * than the first one we return indeterminated. */ if (*pBuf != pPrt->PMSStatus) { *pBuf = SK_MS_STAT_INDETERMINATED; } break; case OID_SKGE_SPEED_MODE: /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = pPrt->PLinkSpeed; continue; } /* * If we find an active port with a different link speed * than the first one we return indeterminated. */ if (*pBuf != pPrt->PLinkSpeed) { *pBuf = SK_LSPEED_INDETERMINATED; } break; case OID_SKGE_SPEED_STATUS: /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = pPrt->PLinkSpeedUsed; continue; } /* * If we find an active port with a different link speed used * than the first one we return indeterminated. */ if (*pBuf != pPrt->PLinkSpeedUsed) { *pBuf = SK_LSPEED_STAT_INDETERMINATED; } break; } } /* If no port is active return an indeterminated answer. */ if (!PortActiveFlag) { switch (Id) { case OID_SKGE_LINK_CAP: *pBuf = SK_LMODE_CAP_INDETERMINATED; break; case OID_SKGE_LINK_MODE: *pBuf = SK_LMODE_INDETERMINATED; break; case OID_SKGE_LINK_MODE_STATUS: *pBuf = SK_LMODE_STAT_INDETERMINATED; break; case OID_SKGE_LINK_STATUS: *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; break; case OID_SKGE_FLOWCTRL_CAP: case OID_SKGE_FLOWCTRL_MODE: *pBuf = SK_FLOW_MODE_INDETERMINATED; break; case OID_SKGE_FLOWCTRL_STATUS: *pBuf = SK_FLOW_STAT_INDETERMINATED; break; case OID_SKGE_PHY_OPERATION_CAP: *pBuf = SK_MS_CAP_INDETERMINATED; break; case OID_SKGE_PHY_OPERATION_MODE: *pBuf = SK_MS_MODE_INDETERMINATED; break; case OID_SKGE_PHY_OPERATION_STATUS: *pBuf = SK_MS_STAT_INDETERMINATED; break; case OID_SKGE_SPEED_CAP: *pBuf = SK_LSPEED_CAP_INDETERMINATED; break; case OID_SKGE_SPEED_MODE: *pBuf = SK_LSPEED_INDETERMINATED; break; case OID_SKGE_SPEED_STATUS: *pBuf = SK_LSPEED_STAT_INDETERMINATED; break; } } } /***************************************************************************** * * CalculateLinkStatus - Determins the link status of a physical port * * Description: * Determins the link status the following way: * LSTAT_PHY_DOWN: Link is down * LSTAT_AUTONEG: Auto-negotiation failed * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port * logically up. * LSTAT_LOG_UP: RLMT marked the port as up * * Returns: * Link status of physical port */ PNMI_STATIC SK_U8 CalculateLinkStatus( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ unsigned int PhysPortIndex) /* Physical port index */ { SK_U8 Result; if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) { Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN; } else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) { Result = SK_PNMI_RLMT_LSTAT_AUTONEG; } else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) { Result = SK_PNMI_RLMT_LSTAT_LOG_UP; } else { Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN; } return (Result); } /***************************************************************************** * * CalculateLinkModeStatus - Determins the link mode status of a phys. port * * Description: * The COMMON module only tells us if the mode is half or full duplex. * But in the decade of auto sensing it is usefull for the user to * know if the mode was negotiated or forced. Therefore we have a * look to the mode, which was last used by the negotiation process. * * Returns: * The link mode status */ PNMI_STATIC SK_U8 CalculateLinkModeStatus( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ unsigned int PhysPortIndex) /* Physical port index */ { SK_U8 Result; /* Get the current mode, which can be full or half duplex. */ Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus; /* Check if no valid mode could be found (link is down). */ if (Result < SK_LMODE_STAT_HALF) { Result = SK_LMODE_STAT_UNKNOWN; } else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) { /* * Auto-negotiation was used to bring up the link. Change * the already found duplex status that it indicates * auto-negotiation was involved. */ if (Result == SK_LMODE_STAT_HALF) { Result = SK_LMODE_STAT_AUTOHALF; } else if (Result == SK_LMODE_STAT_FULL) { Result = SK_LMODE_STAT_AUTOFULL; } } return (Result); } /***************************************************************************** * * GetVpdKeyArr - Obtain an array of VPD keys * * Description: * Read the VPD keys and build an array of VPD keys, which are * easy to access. * * Returns: * SK_PNMI_ERR_OK Task successfully performed. * SK_PNMI_ERR_GENERAL Something went wrong. */ PNMI_STATIC int GetVpdKeyArr( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ char *pKeyArr, /* Ptr KeyArray */ unsigned int KeyArrLen, /* Length of array in bytes */ unsigned int *pKeyNo) /* Number of keys */ { unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE; char BufKeys[SK_PNMI_VPD_BUFSIZE]; unsigned int StartOffset; unsigned int Offset; int Index; int Ret; SK_MEMSET(pKeyArr, 0, KeyArrLen); /* Get VPD key list. */ Ret = VpdKeys(pAC, IoC, BufKeys, (int *)&BufKeysLen, (int *)pKeyNo); if (Ret > 0) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR014MSG)); /* Please read comment in Vpd(). */ pAC->Pnmi.VpdKeyReadError = SK_TRUE; return (SK_PNMI_ERR_GENERAL); } /* If no keys are available return now. */ if (*pKeyNo == 0 || BufKeysLen == 0) { return (SK_PNMI_ERR_OK); } /* * If the key list is too long for us trunc it and give a * errorlog notification. This case should not happen because * the maximum number of keys is limited due to RAM limitations. */ if (*pKeyNo > SK_PNMI_VPD_ENTRIES) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR015MSG)); *pKeyNo = SK_PNMI_VPD_ENTRIES; } /* * Now build an array of fixed string length size and copy * the keys together. */ for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen; Offset ++) { if (BufKeys[Offset] != 0) { continue; } if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, (SK_PNMI_ERR016MSG)); return (SK_PNMI_ERR_GENERAL); } SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); Index ++; StartOffset = Offset + 1; } /* Last key not zero terminated? Get it anyway. */ if (StartOffset < Offset) { SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * SirqUpdate - Let the SIRQ update its internal values * * Description: * Just to be sure that the SIRQ module holds its internal data * structures up to date, we send an update event before we make * any access. * * Returns: * SK_PNMI_ERR_OK Task successfully performed. * SK_PNMI_ERR_GENERAL Something went wrong. */ PNMI_STATIC int SirqUpdate( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC) /* IO context handle */ { SK_EVPARA EventParam; /* Was the module already updated during the current PNMI call? */ if (pAC->Pnmi.SirqUpdatedFlag > 0) { return (SK_PNMI_ERR_OK); } /* Send an synchronuous update event to the module. */ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam)) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, SK_PNMI_ERR047MSG); return (SK_PNMI_ERR_GENERAL); } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * RlmtUpdate - Let the RLMT update its internal values * * Description: * Just to be sure that the RLMT module holds its internal data * structures up to date, we send an update event before we make * any access. * * Returns: * SK_PNMI_ERR_OK Task successfully performed. * SK_PNMI_ERR_GENERAL Something went wrong. */ PNMI_STATIC int RlmtUpdate( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ { SK_EVPARA EventParam; /* Was the module already updated during the current PNMI call? */ if (pAC->Pnmi.RlmtUpdatedFlag > 0) { return (SK_PNMI_ERR_OK); } /* Send an synchronuous update event to the module. */ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)-1; if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, SK_PNMI_ERR048MSG); return (SK_PNMI_ERR_GENERAL); } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * MacUpdate - Force the XMAC to output the current statistic * * Description: * The XMAC holds its statistic internally. To obtain the current * values we must send a command so that the statistic data will * be written to a predefined memory area on the adapter. * * Returns: * SK_PNMI_ERR_OK Task successfully performed. * SK_PNMI_ERR_GENERAL Something went wrong. */ PNMI_STATIC int MacUpdate( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ unsigned int FirstMac, /* Index of the first Mac to be updated */ unsigned int LastMac) /* Index of the last Mac to be updated */ { unsigned int MacIndex; /* * Were the statistics already updated during the * current PNMI call? */ if (pAC->Pnmi.MacUpdatedFlag > 0) { return (SK_PNMI_ERR_OK); } /* Send an update command to all MACs specified. */ for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) { /* * 2002-09-13 pweber: Freeze the current SW counters. * (That should be done as close as * possible to the update of the * HW counters). */ if (pAC->GIni.GIMacType == SK_MAC_XMAC) { pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex]; } /* 2002-09-13 pweber: Update the HW counter. */ if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) { return (SK_PNMI_ERR_GENERAL); } } return (SK_PNMI_ERR_OK); } /***************************************************************************** * * GetStatVal - Retrieve an XMAC statistic counter * * Description: * Retrieves the statistic counter of a virtual or physical port. The * virtual port is identified by the index 0. It consists of all * currently active ports. To obtain the counter value for this port * we must add the statistic counter of all active ports. To grant * continuous counter values for the virtual port even when port * switches occur we must additionally add a delta value, which was * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event. * * Returns: * Requested statistic value */ PNMI_STATIC SK_U64 GetStatVal( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ unsigned int LogPortIndex, /* Index of the logical Port to be processed */ unsigned int StatIndex, /* Index to statistic value */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ { unsigned int PhysPortIndex; unsigned int PhysPortMax; SK_U64 Val = 0; if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */ PhysPortIndex = NetIndex; Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); } else { /* SingleNet mode. */ if (LogPortIndex == 0) { PhysPortMax = pAC->GIni.GIMacsFound; /* Add counter of all active ports. */ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) { if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); } } /* Correct value because of port switches. */ Val += pAC->Pnmi.VirtualCounterOffset[StatIndex]; } else { /* Get counter value of physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); } } return (Val); } /***************************************************************************** * * GetPhysStatVal - Get counter value for physical port * * Description: * Builds a 64bit counter value. Except for the octet counters * the lower 32bit are counted in hardware and the upper 32bit * in software by monitoring counter overflow interrupts in the * event handler. To grant continous counter values during XMAC * resets (caused by a workaround) we must add a delta value. * The delta was calculated in the event handler when a * SK_PNMI_EVT_XMAC_RESET was received. * * Returns: * Counter value */ PNMI_STATIC SK_U64 GetPhysStatVal( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ unsigned int PhysPortIndex, /* Index of the logical Port to be processed */ unsigned int StatIndex) /* Index to statistic value */ { SK_U64 Val = 0; SK_U32 LowVal = 0; SK_U32 HighVal = 0; SK_U16 Word; int MacType; unsigned int HelpIndex; SK_GEPORT *pPrt; SK_PNMI_PORT *pPnmiPrt; SK_GEMACFUNC *pFnMac; pPrt = &pAC->GIni.GP[PhysPortIndex]; MacType = pAC->GIni.GIMacType; /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex]; } else { pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex]; } pFnMac = &pAC->GIni.GIFunc; switch (StatIndex) { case SK_PNMI_HTX: if (MacType == SK_MAC_GMAC) { (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg, &LowVal); (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg, &HighVal); LowVal += HighVal; (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg, &HighVal); LowVal += HighVal; } else { (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); } HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; case SK_PNMI_HRX: if (MacType == SK_MAC_GMAC) { (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg, &LowVal); (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg, &HighVal); LowVal += HighVal; (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg, &HighVal); LowVal += HighVal; } else { (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); } HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; case SK_PNMI_HTX_OCTET: case SK_PNMI_HRX_OCTET: (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &HighVal); (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex + 1][MacType].Reg, &LowVal); break; case SK_PNMI_HTX_BURST: case SK_PNMI_HTX_EXCESS_DEF: case SK_PNMI_HTX_CARRIER: /* Not supported by GMAC. */ if (MacType == SK_MAC_GMAC) { return (Val); } (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; case SK_PNMI_HTX_MACC: /* GMAC only supports PAUSE MAC control frames. */ if (MacType == SK_MAC_GMAC) { HelpIndex = SK_PNMI_HTX_PMACC; } else { HelpIndex = StatIndex; } (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[HelpIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; case SK_PNMI_HTX_COL: case SK_PNMI_HRX_UNDERSIZE: /* Not supported by XMAC. */ if (MacType == SK_MAC_XMAC) { return (Val); } (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; case SK_PNMI_HTX_DEFFERAL: /* Not supported by GMAC. */ if (MacType == SK_MAC_GMAC) { return (Val); } /* * XMAC counts frames with deferred transmission * even in full-duplex mode. * * In full-duplex mode the counter remains constant! */ if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) || (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) { LowVal = 0; HighVal = 0; } else { /* Otherwise get contents of hardware register. */ (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; } break; case SK_PNMI_HRX_BADOCTET: /* Not supported by XMAC. */ if (MacType == SK_MAC_XMAC) { return (Val); } (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &HighVal); (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex + 1][MacType].Reg, &LowVal); break; case SK_PNMI_HTX_OCTETLOW: case SK_PNMI_HRX_OCTETLOW: case SK_PNMI_HRX_BADOCTETLOW: return (Val); case SK_PNMI_HRX_LONGFRAMES: /* For XMAC the SW counter is managed by PNMI. */ if (MacType == SK_MAC_XMAC) { return (pPnmiPrt->StatRxLongFrameCts); } (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; case SK_PNMI_HRX_TOO_LONG: (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); if (MacType == SK_MAC_GMAC) { /* For GMAC the SW counter is additionally managed by PNMI. */ Val += pPnmiPrt->StatRxFrameTooLongCts; } else { /* * Frames longer than IEEE 802.3 frame max size are counted * by XMAC in frame_too_long counter even reception of long * frames was enabled and the frame was correct. * So correct the value by subtracting RxLongFrame counter. */ Val -= pPnmiPrt->StatRxLongFrameCts; } LowVal = (SK_U32)Val; HighVal = (SK_U32)(Val >> 32); break; case SK_PNMI_HRX_SHORTS: /* Not supported by GMAC. */ if (MacType == SK_MAC_GMAC) { /* GM_RXE_FRAG?? */ return (Val); } /* * XMAC counts short frame errors even if link down (#10620). * If the link is down, the counter remains constant. */ if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) { /* Otherwise get incremental difference. */ (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); Val -= pPnmiPrt->RxShortZeroMark; LowVal = (SK_U32)Val; HighVal = (SK_U32)(Val >> 32); } break; case SK_PNMI_HRX_MACC: case SK_PNMI_HRX_MACC_UNKWN: case SK_PNMI_HRX_BURST: case SK_PNMI_HRX_MISSED: case SK_PNMI_HRX_FRAMING: case SK_PNMI_HRX_CARRIER: case SK_PNMI_HRX_IRLENGTH: case SK_PNMI_HRX_SYMBOL: case SK_PNMI_HRX_CEXT: /* Not supported by GMAC. */ if (MacType == SK_MAC_GMAC) { return (Val); } (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; case SK_PNMI_HRX_PMACC_ERR: /* For GMAC the SW counter is managed by PNMI. */ if (MacType == SK_MAC_GMAC) { return (pPnmiPrt->StatRxPMaccErr); } (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; /* SW counter managed by PNMI. */ case SK_PNMI_HTX_SYNC: LowVal = (SK_U32)pPnmiPrt->StatSyncCts; HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32); break; /* SW counter managed by PNMI. */ case SK_PNMI_HTX_SYNC_OCTET: LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts; HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32); break; case SK_PNMI_HRX_FCS: /* * Broadcom filters FCS errors and counts them in * Receive Error Counter register. */ if (pPrt->PhyType == SK_PHY_BCOM) { #ifdef GENESIS /* Do not read while not initialized (PHY_READ hangs!). */ if (pPrt->PState != SK_PRT_RESET) { SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word); LowVal = Word; } HighVal = pPnmiPrt->CounterHigh[StatIndex]; #endif /* GENESIS */ } else { (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; } break; default: (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; } Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); /* Correct value because of possible XMAC reset (XMAC Errata #2). */ Val += pPnmiPrt->CounterOffset[StatIndex]; return (Val); } /***************************************************************************** * * ResetCounter - Set all counters and timestamps to zero * * Description: * Notifies other common modules which store statistic data to * reset their counters and finally reset our own counters. * * Returns: * Nothing */ PNMI_STATIC void ResetCounter( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 NetIndex) { unsigned int PhysPortIndex; SK_EVPARA EventParam; SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); /* Notify sensor module. */ SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam); /* Notify RLMT module. */ EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)-1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam); EventParam.Para32[1] = 0; /* Notify SIRQ module. */ SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam); /* Notify CSUM module. */ #ifdef SK_USE_CSUM EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)-1; SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS, EventParam); #endif /* SK_USE_CSUM */ /* Clear XMAC statistics. */ for (PhysPortIndex = 0; PhysPortIndex < (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) { (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex); SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh, 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh)); SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. CounterOffset, 0, sizeof(pAC->Pnmi.Port[ PhysPortIndex].CounterOffset)); SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts, 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts)); SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[ PhysPortIndex].StatSyncOctetsCts)); SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[ PhysPortIndex].StatRxLongFrameCts)); SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[ PhysPortIndex].StatRxFrameTooLongCts)); SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[ PhysPortIndex].StatRxPMaccErr)); } /* Clear local statistics. */ SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0, sizeof(pAC->Pnmi.VirtualCounterOffset)); pAC->Pnmi.RlmtChangeCts = 0; pAC->Pnmi.RlmtChangeTime = 0; SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0, sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue)); pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0; pAC->Pnmi.RlmtChangeEstimate.Estimate = 0; pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0; pAC->Pnmi.Port[NetIndex].TxRetryCts = 0; pAC->Pnmi.Port[NetIndex].RxIntrCts = 0; pAC->Pnmi.Port[NetIndex].TxIntrCts = 0; pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0; pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0; pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0; pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0; pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0; pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0; } /***************************************************************************** * * GetTrapEntry - Get an entry in the trap buffer * * Description: * The trap buffer stores various events. A user application somehow * gets notified that an event occured and retrieves the trap buffer * contens (or simply polls the buffer). The buffer is organized as * a ring which stores the newest traps at the beginning. The oldest * traps are overwritten by the newest ones. Each trap entry has a * unique number, so that applications may detect new trap entries. * * Returns: * A pointer to the trap entry */ PNMI_STATIC char* GetTrapEntry( SK_AC *pAC, /* Pointer to adapter context */ SK_U32 TrapId, /* SNMP ID of the trap */ unsigned int Size) /* Space needed for trap entry */ { unsigned int BufPad = pAC->Pnmi.TrapBufPad; unsigned int BufFree = pAC->Pnmi.TrapBufFree; unsigned int Beg = pAC->Pnmi.TrapQueueBeg; unsigned int End = pAC->Pnmi.TrapQueueEnd; char *pBuf = &pAC->Pnmi.TrapBuf[0]; int Wrap; unsigned int NeededSpace; unsigned int EntrySize; SK_U32 Val32; SK_U64 Val64; /* Last byte of entry will get a copy of the entry length. */ Size ++; /* Calculate needed buffer space. */ if (Beg >= Size) { NeededSpace = Size; Wrap = SK_FALSE; } else { NeededSpace = Beg + Size; Wrap = SK_TRUE; } /* * Check if enough buffer space is provided. Otherwise * free some entries. Leave one byte space between begin * and end of buffer to make it possible to detect whether * the buffer is full or empty. */ while (BufFree < NeededSpace + 1) { if (End == 0) { End = SK_PNMI_TRAP_QUEUE_LEN; } EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1); BufFree += EntrySize; End -= EntrySize; #ifdef DEBUG SK_MEMSET(pBuf + End, (char)(-1), EntrySize); #endif /* DEBUG */ if (End == BufPad) { #ifdef DEBUG SK_MEMSET(pBuf, (char)(-1), End); #endif /* DEBUG */ BufFree += End; End = 0; BufPad = 0; } } /* * Insert new entry as first entry. Newest entries are * stored at the beginning of the queue. */ if (Wrap) { BufPad = Beg; Beg = SK_PNMI_TRAP_QUEUE_LEN - Size; } else { Beg = Beg - Size; } BufFree -= NeededSpace; /* Save the current offsets. */ pAC->Pnmi.TrapQueueBeg = Beg; pAC->Pnmi.TrapQueueEnd = End; pAC->Pnmi.TrapBufPad = BufPad; pAC->Pnmi.TrapBufFree = BufFree; /* Initialize the trap entry. */ *(pBuf + Beg + Size - 1) = (char)Size; *(pBuf + Beg) = (char)Size; Val32 = (pAC->Pnmi.TrapUnique) ++; SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32); SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId); Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64); return (pBuf + Beg); } /***************************************************************************** * * CopyTrapQueue - Copies the trap buffer for the TRAP OID * * Description: * On a query of the TRAP OID the trap buffer contents will be * copied continuously to the request buffer, which must be large * enough. No length check is performed. * * Returns: * Nothing */ PNMI_STATIC void CopyTrapQueue( SK_AC *pAC, /* Pointer to adapter context */ char *pDstBuf) /* Buffer to which the queued traps will be copied */ { unsigned int BufPad = pAC->Pnmi.TrapBufPad; unsigned int Trap = pAC->Pnmi.TrapQueueBeg; unsigned int End = pAC->Pnmi.TrapQueueEnd; char *pBuf = &pAC->Pnmi.TrapBuf[0]; unsigned int Len; unsigned int DstOff = 0; while (Trap != End) { Len = (unsigned int)*(pBuf + Trap); /* * Last byte containing a copy of the length will * not be copied. */ *(pDstBuf + DstOff) = (char)(Len - 1); SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2); DstOff += Len - 1; Trap += Len; if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { Trap = BufPad; } } } /***************************************************************************** * * GetTrapQueueLen - Get the length of the trap buffer * * Description: * Evaluates the number of currently stored traps and the needed * buffer size to retrieve them. * * Returns: * Nothing */ PNMI_STATIC void GetTrapQueueLen( SK_AC *pAC, /* Pointer to adapter context */ unsigned int *pLen, /* Length in Bytes of all queued traps */ unsigned int *pEntries) /* Returns number of trapes stored in queue */ { unsigned int BufPad = pAC->Pnmi.TrapBufPad; unsigned int Trap = pAC->Pnmi.TrapQueueBeg; unsigned int End = pAC->Pnmi.TrapQueueEnd; char *pBuf = &pAC->Pnmi.TrapBuf[0]; unsigned int Len; unsigned int Entries = 0; unsigned int TotalLen = 0; while (Trap != End) { Len = (unsigned int)*(pBuf + Trap); TotalLen += Len - 1; Entries ++; Trap += Len; if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { Trap = BufPad; } } *pEntries = Entries; *pLen = TotalLen; } /***************************************************************************** * * QueueSimpleTrap - Store a simple trap to the trap buffer * * Description: * A simple trap is a trap with now additional data. It consists * simply of a trap code. * * Returns: * Nothing */ PNMI_STATIC void QueueSimpleTrap( SK_AC *pAC, /* Pointer to adapter context */ SK_U32 TrapId) /* Type of sensor trap */ { GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN); } /***************************************************************************** * * QueueSensorTrap - Stores a sensor trap in the trap buffer * * Description: * Gets an entry in the trap buffer and fills it with sensor related * data. * * Returns: * Nothing */ PNMI_STATIC void QueueSensorTrap( SK_AC *pAC, /* Pointer to adapter context */ SK_U32 TrapId, /* Type of sensor trap */ unsigned int SensorIndex) /* Index of sensor which caused the trap */ { char *pBuf; unsigned int Offset; unsigned int DescrLen; SK_U32 Val32; /* Get trap buffer entry. */ DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc); pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen); Offset = SK_PNMI_TRAP_SIMPLE_LEN; /* Store additionally sensor trap related data. */ Val32 = OID_SKGE_SENSOR_INDEX; SK_PNMI_STORE_U32(pBuf + Offset, Val32); *(pBuf + Offset + 4) = 4; Val32 = (SK_U32)SensorIndex; SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); Offset += 9; Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR; SK_PNMI_STORE_U32(pBuf + Offset, Val32); *(pBuf + Offset + 4) = (char)DescrLen; SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc, DescrLen); Offset += DescrLen + 5; Val32 = OID_SKGE_SENSOR_TYPE; SK_PNMI_STORE_U32(pBuf + Offset, Val32); *(pBuf + Offset + 4) = 1; *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType; Offset += 6; Val32 = OID_SKGE_SENSOR_VALUE; SK_PNMI_STORE_U32(pBuf + Offset, Val32); *(pBuf + Offset + 4) = 4; Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue; SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); } /***************************************************************************** * * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer * * Description: * Nothing further to explain. * * Returns: * Nothing */ PNMI_STATIC void QueueRlmtNewMacTrap( SK_AC *pAC, /* Pointer to adapter context */ unsigned int ActiveMac) /* Index (0..n) of the currently active port */ { char *pBuf; SK_U32 Val32; pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT, SK_PNMI_TRAP_RLMT_CHANGE_LEN); Val32 = OID_SKGE_RLMT_PORT_ACTIVE; SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac; } /***************************************************************************** * * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer * * Description: * Nothing further to explain. * * Returns: * Nothing */ PNMI_STATIC void QueueRlmtPortTrap( SK_AC *pAC, /* Pointer to adapter context */ SK_U32 TrapId, /* Type of RLMT port trap */ unsigned int PortIndex) /* Index of the port, which changed its state */ { char *pBuf; SK_U32 Val32; pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN); Val32 = OID_SKGE_RLMT_PORT_INDEX; SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex; } /***************************************************************************** * * CopyMac - Copies a MAC address * * Description: * Nothing further to explain. * * Returns: * Nothing */ PNMI_STATIC void CopyMac( char *pDst, /* Pointer to destination buffer */ SK_MAC_ADDR *pMac) /* Pointer of Source */ { int i; for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) { *(pDst + i) = pMac->a[i]; } } #ifdef SK_POWER_MGMT /***************************************************************************** * * PowerManagement - OID handler function of PowerManagement OIDs * * Description: * The code is simple. No description necessary. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int PowerManagement( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* Get/PreSet/Set action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer to which to mgmt data will be retrieved */ unsigned int *pLen, /* On call: buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ { int i; unsigned int HwPortIndex; SK_U32 RetCode = SK_PNMI_ERR_GENERAL; /* Check instance. We only handle single instance variables. */ if ((Instance != (SK_U32)(-1))) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } /* Get hardware port index */ HwPortIndex = NetIndex; /* Check length. */ switch (Id) { case OID_PNP_CAPABILITIES: if (*pLen < sizeof(SK_PNP_CAPABILITIES)) { *pLen = sizeof(SK_PNP_CAPABILITIES); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_PNP_SET_POWER: case OID_PNP_QUERY_POWER: if (*pLen < sizeof(SK_DEVICE_POWER_STATE)) { *pLen = sizeof(SK_DEVICE_POWER_STATE); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_PNP_ADD_WAKE_UP_PATTERN: case OID_PNP_REMOVE_WAKE_UP_PATTERN: if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) { *pLen = sizeof(SK_PM_PACKET_PATTERN); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_PNP_ENABLE_WAKE_UP: if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; } /* Perform action. */ if (Action == SK_PNMI_GET) { /* Get value. */ switch (Id) { case OID_PNP_CAPABILITIES: RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen); break; case OID_PNP_QUERY_POWER: /* * The Windows DDK describes: An OID_PNP_QUERY_POWER requests * the miniport to indicate whether it can transition its NIC * to the low-power state. * A miniport driver must always return NDIS_STATUS_SUCCESS * to a query of OID_PNP_QUERY_POWER. */ *pLen = sizeof(SK_DEVICE_POWER_STATE); RetCode = SK_PNMI_ERR_OK; break; /* * NDIS handles these OIDs as write-only. * So in case of get action the buffer with written length = 0 * is returned. */ case OID_PNP_SET_POWER: case OID_PNP_ADD_WAKE_UP_PATTERN: case OID_PNP_REMOVE_WAKE_UP_PATTERN: *pLen = 0; RetCode = SK_PNMI_ERR_NOT_SUPPORTED; break; case OID_PNP_ENABLE_WAKE_UP: RetCode = SkPowerGetEnableWakeUp(pAC, IoC, HwPortIndex, pBuf, pLen); break; default: RetCode = SK_PNMI_ERR_GENERAL; break; } return (RetCode); } /* Perform PRESET or SET. */ /* The POWER module does not support PRESET action. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } /* */ i= HwPortIndex; switch (Id) { case OID_PNP_SET_POWER: /* Dual net mode? */ for (i = 0; i < pAC->GIni.GIMacsFound; i++) { if (RetCode = SkPowerSetPower(pAC, IoC, i, pBuf, pLen)) { break; } } break; case OID_PNP_ADD_WAKE_UP_PATTERN: for (i = 0; i < pAC->GIni.GIMacsFound; i++) { if (RetCode = SkPowerAddWakeUpPattern(pAC, IoC, i, pBuf, pLen)) { break; } } break; case OID_PNP_REMOVE_WAKE_UP_PATTERN: for (i = 0; i < pAC->GIni.GIMacsFound; i++) { if (RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, i, pBuf, pLen)) { break; } } break; case OID_PNP_ENABLE_WAKE_UP: for (i = 0; i < pAC->GIni.GIMacsFound; i++) { if (RetCode = SkPowerSetEnableWakeUp(pAC, IoC, i, pBuf, pLen)) { break; } } break; default: RetCode = SK_PNMI_ERR_READ_ONLY; } return (RetCode); } #endif /* SK_POWER_MGMT */ #ifdef SK_DIAG_SUPPORT /***************************************************************************** * * DiagActions - OID handler function of Diagnostic driver * * Description: * The code is simple. No description necessary. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int DiagActions( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_U32 DiagStatus; SK_U32 RetCode = SK_PNMI_ERR_GENERAL; /* Check instance. We only handle single instance variables. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } /* Check length. */ switch (Id) { case OID_SKGE_DIAG_MODE: if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* Perform action. */ if (Action == SK_PNMI_GET) { /* Get value. */ switch (Id) { case OID_SKGE_DIAG_MODE: DiagStatus = pAC->Pnmi.DiagAttached; SK_PNMI_STORE_U32(pBuf, DiagStatus); *pLen = sizeof(SK_U32); RetCode = SK_PNMI_ERR_OK; break; default: *pLen = 0; RetCode = SK_PNMI_ERR_GENERAL; break; } return (RetCode); } /* From here SET or PRESET value. */ /* PRESET value is not supported. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } /* SET value. */ switch (Id) { case OID_SKGE_DIAG_MODE: /* Handle the SET. */ switch (*pBuf) { /* Attach the DIAG to this adapter. */ case SK_DIAG_ATTACHED: /* Check if we come from running. */ if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { RetCode = SkDrvLeaveDiagMode(pAC); } else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) { RetCode = SK_PNMI_ERR_OK; } else { RetCode = SK_PNMI_ERR_GENERAL; } if (RetCode == SK_PNMI_ERR_OK) { pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED; } break; /* Enter the DIAG mode in the driver. */ case SK_DIAG_RUNNING: RetCode = SK_PNMI_ERR_OK; /* * If DiagAttached is set, we can tell the driver * to enter the DIAG mode. */ if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { /* If DiagMode is not active, we can enter it. */ if (!pAC->DiagModeActive) { RetCode = SkDrvEnterDiagMode(pAC); } else { RetCode = SK_PNMI_ERR_GENERAL; } } else { RetCode = SK_PNMI_ERR_GENERAL; } if (RetCode == SK_PNMI_ERR_OK) { pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING; } break; case SK_DIAG_IDLE: /* Check if we come from running. */ if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { RetCode = SkDrvLeaveDiagMode(pAC); } else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { RetCode = SK_PNMI_ERR_OK; } else { RetCode = SK_PNMI_ERR_GENERAL; } if (RetCode == SK_PNMI_ERR_OK) { pAC->Pnmi.DiagAttached = SK_DIAG_IDLE; } break; default: RetCode = SK_PNMI_ERR_BAD_VALUE; break; } break; default: RetCode = SK_PNMI_ERR_GENERAL; } if (RetCode == SK_PNMI_ERR_OK) { *pLen = sizeof(SK_U32); } else { *pLen = 0; } return (RetCode); } #endif /* SK_DIAG_SUPPORT */ /***************************************************************************** * * Vct - OID handler function of OIDs for Virtual Cable Tester (VCT) * * Description: * The code is simple. No description necessary. * * Returns: * SK_PNMI_ERR_OK The request was performed successfully. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter). * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed. * */ PNMI_STATIC int Vct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_GEPORT *pPrt; SK_PNMI_VCT *pVctBackupData; SK_U32 LogPortMax; SK_U32 PhysPortMax; SK_U32 PhysPortIndex; SK_U32 Limit; SK_U32 Offset; SK_U32 RetCode; int i; SK_EVPARA Para; RetCode = SK_PNMI_ERR_GENERAL; /* Calculate the port indexes from the instance. */ PhysPortMax = pAC->GIni.GIMacsFound; LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); /* Dual net mode? */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { LogPortMax--; } if ((Instance != (SK_U32) (-1))) { /* * Get one instance of that OID, so check the instance range: * There is no virtual port with an Instance == 1, so we get * the values from one physical port only. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { PhysPortIndex = NetIndex; } else { if ((Instance < 2) || (Instance > LogPortMax)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } PhysPortIndex = Instance - 2; } Limit = PhysPortIndex + 1; } else { /* * Instance == (SK_U32) (-1), so get all instances of that OID. * There is no virtual port with an Instance == 1, so we get * the values from all physical ports. */ PhysPortIndex = 0; Limit = PhysPortMax; } /* Check MAC type. */ if ((Id != OID_SKGE_VCT_CAPABILITIES) && (pAC->GIni.GP[PhysPortIndex].PhyType != SK_PHY_MARV_COPPER)) { *pLen = 0; return (SK_PNMI_ERR_NOT_SUPPORTED); } /* Check action type. */ if (Action == SK_PNMI_GET) { /* Check length. */ switch (Id) { case OID_SKGE_VCT_GET: if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) { *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT); return (SK_PNMI_ERR_TOO_SHORT); } break; case OID_SKGE_VCT_STATUS: case OID_SKGE_VCT_CAPABILITIES: if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) { *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8); return (SK_PNMI_ERR_TOO_SHORT); } break; default: *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* Get value. */ Offset = 0; for (; PhysPortIndex < Limit; PhysPortIndex++) { pPrt = &pAC->GIni.GP[PhysPortIndex]; switch (Id) { case OID_SKGE_VCT_GET: if (!pPrt->PHWLinkUp && (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) { RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); if (RetCode == 0) { /* VCT test is finished, so save the data. */ VctGetResults(pAC, IoC, PhysPortIndex); Para.Para32[0] = PhysPortIndex; Para.Para32[1] = -1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); /* SkEventDispatcher(pAC, IoC); */ } } /* Initialize backup data pointer. */ pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; /* Get all results. */ CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); Offset++; *(pBuf + Offset) = pPrt->PCableLen; Offset++; for (i = 0; i < 4; i++) { SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->MdiPairLen[i]); Offset += sizeof(SK_U32); } for (i = 0; i < 4; i++) { *(pBuf + Offset) = pVctBackupData->MdiPairSts[i]; Offset++; } RetCode = SK_PNMI_ERR_OK; break; case OID_SKGE_VCT_STATUS: CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); Offset++; RetCode = SK_PNMI_ERR_OK; break; case OID_SKGE_VCT_CAPABILITIES: if (pPrt->PhyType != SK_PHY_MARV_COPPER) { *(pBuf + Offset) = SK_PNMI_VCT_NOT_SUPPORTED; } else { *(pBuf + Offset) = SK_PNMI_VCT_SUPPORTED; } Offset++; RetCode = SK_PNMI_ERR_OK; break; default: *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } /* for */ *pLen = Offset; return (RetCode); } /* if SK_PNMI_GET */ /* * From here SET or PRESET action. Check if the passed * buffer length is plausible. */ /* Check length. */ switch (Id) { case OID_SKGE_VCT_SET: if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; default: *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* Perform PRESET or SET. */ /* VCT does not support PRESET action. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } Offset = 0; for (; PhysPortIndex < Limit; PhysPortIndex++) { pPrt = &pAC->GIni.GP[PhysPortIndex]; switch (Id) { case OID_SKGE_VCT_SET: /* Start VCT test. */ if (!pPrt->PHWLinkUp) { SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST); RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE); if (RetCode == 0) { /* RetCode: 0 => Start! */ pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING; pAC->Pnmi.VctStatus[PhysPortIndex] &= ~(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_LINK); /* Start VCT timer counter. */ SK_MEMSET((char *)&Para, 0, sizeof(Para)); Para.Para32[0] = PhysPortIndex; Para.Para32[1] = -1; SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex], SK_PNMI_VCT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para); SK_PNMI_STORE_U32((pBuf + Offset), RetCode); RetCode = SK_PNMI_ERR_OK; } else { /* RetCode: 2 => Running! */ SK_PNMI_STORE_U32((pBuf + Offset), RetCode); RetCode = SK_PNMI_ERR_OK; } } else { /* RetCode: 4 => Link! */ RetCode = 4; SK_PNMI_STORE_U32((pBuf + Offset), RetCode); RetCode = SK_PNMI_ERR_OK; } Offset += sizeof(SK_U32); break; default: *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } /* for */ *pLen = Offset; return (RetCode); } /* Vct */ PNMI_STATIC void VctGetResults( SK_AC *pAC, SK_IOC IoC, SK_U32 Port) { SK_GEPORT *pPrt; int i; SK_U8 PairLen; SK_U8 PairSts; SK_U32 MinLength; SK_U32 CableLength; pPrt = &pAC->GIni.GP[Port]; if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) { MinLength = 25; } else { MinLength = 35; } /* Copy results for later use to PNMI struct. */ for (i = 0; i < 4; i++) { PairLen = pPrt->PMdiPairLen[i]; if (((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) == 0) && (i > 1)) { PairSts = SK_PNMI_VCT_NOT_PRESENT; } else { PairSts = pPrt->PMdiPairSts[i]; } if ((PairSts == SK_PNMI_VCT_NORMAL_CABLE) && (PairLen > 28) && (PairLen < 0xff)) { PairSts = SK_PNMI_VCT_IMPEDANCE_MISMATCH; } /* Ignore values <= MinLength, the linear factor is 4/5. */ if ((PairLen > MinLength) && (PairLen < 0xff)) { CableLength = 1000UL * (PairLen - MinLength) * 4 / 5; } else { /* No cable or short cable. */ CableLength = 0; } pAC->Pnmi.VctBackup[Port].MdiPairLen[i] = CableLength; pAC->Pnmi.VctBackup[Port].MdiPairSts[i] = PairSts; } pAC->Pnmi.VctStatus[Port] &= ~SK_PNMI_VCT_PENDING; pAC->Pnmi.VctStatus[Port] |= (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); } /* GetVctResults */ PNMI_STATIC void CheckVctStatus( SK_AC *pAC, SK_IOC IoC, char *pBuf, SK_U32 Offset, SK_U32 PhysPortIndex) { SK_GEPORT *pPrt; SK_PNMI_VCT *pVctData; SK_U8 VctStatus; SK_U32 RetCode; pPrt = &pAC->GIni.GP[PhysPortIndex]; pVctData = (SK_PNMI_VCT *) (pBuf + Offset); pVctData->VctStatus = SK_PNMI_VCT_NONE; VctStatus = pAC->Pnmi.VctStatus[PhysPortIndex]; if (!pPrt->PHWLinkUp) { /* Was a VCT test ever made before? */ if (VctStatus & SK_PNMI_VCT_TEST_DONE) { if (VctStatus & SK_PNMI_VCT_LINK) { pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; } else { pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; } } /* Check VCT test status. */ RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE); if (RetCode == 2) { /* VCT test is running. */ pVctData->VctStatus |= SK_PNMI_VCT_RUNNING; } else { /* VCT data was copied to pAC here. Check PENDING state. */ if (VctStatus & SK_PNMI_VCT_PENDING) { pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; } } if (pPrt->PCableLen != 0xff) { /* Old DSP value. */ pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA; } } else { /* Was a VCT test ever made before? */ if (VctStatus & SK_PNMI_VCT_TEST_DONE) { pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA; pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; } /* DSP only valid in 100/1000 modes. */ if (pPrt->PLinkSpeedUsed != SK_LSPEED_STAT_10MBPS) { pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA; } } } /* CheckVctStatus */ /***************************************************************************** * * SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed * PNMI function depending on the subcommand and * returns all data belonging to the complete database * or OID request. * * Description: * Looks up the requested subcommand, calls the corresponding handler * function and passes all required parameters to it. * The function is called by the driver. It is needed to handle the new * generic PNMI IOCTL. This IOCTL is given to the driver and contains both * the OID and a subcommand to decide what kind of request has to be done. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed * SK_PNMI_ERR_GENERAL A general severe internal error occured * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take * the data. * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ int SkPnmiGenIoctl( SK_AC *pAC, /* Pointer to adapter context struct */ SK_IOC IoC, /* I/O context */ void *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* Length of buffer */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_I32 Mode; /* Store value of subcommand. */ SK_U32 Oid; /* Store value of OID. */ int ReturnCode; /* Store return value to show status of PNMI action. */ int HeaderLength; /* Length of desired action plus OID. */ ReturnCode = SK_PNMI_ERR_GENERAL; SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32)); SK_MEMCPY(&Oid, (char *)pBuf + sizeof(SK_I32), sizeof(SK_U32)); HeaderLength = sizeof(SK_I32) + sizeof(SK_U32); *pLen = *pLen - HeaderLength; SK_MEMCPY((char *)pBuf + sizeof(SK_I32), (char *)pBuf + HeaderLength, *pLen); switch(Mode) { case SK_GET_SINGLE_VAR: ReturnCode = SkPnmiGetVar(pAC, IoC, Oid, (char *)pBuf + sizeof(SK_I32), pLen, ((SK_U32) (-1)), NetIndex); SK_PNMI_STORE_U32(pBuf, ReturnCode); *pLen = *pLen + sizeof(SK_I32); break; case SK_PRESET_SINGLE_VAR: ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid, (char *)pBuf + sizeof(SK_I32), pLen, ((SK_U32) (-1)), NetIndex); SK_PNMI_STORE_U32(pBuf, ReturnCode); *pLen = *pLen + sizeof(SK_I32); break; case SK_SET_SINGLE_VAR: ReturnCode = SkPnmiSetVar(pAC, IoC, Oid, (char *)pBuf + sizeof(SK_I32), pLen, ((SK_U32) (-1)), NetIndex); SK_PNMI_STORE_U32(pBuf, ReturnCode); *pLen = *pLen + sizeof(SK_I32); break; case SK_GET_FULL_MIB: ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex); break; case SK_PRESET_FULL_MIB: ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex); break; case SK_SET_FULL_MIB: ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex); break; default: break; } return (ReturnCode); } /* SkGeIocGen */ #ifdef SK_ASF /***************************************************************************** * * Asf * * Description: * The code is simple. No description necessary. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. * SK_PNMI_ERR_GENERAL A general severe internal error occured. * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Asf( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_U32 RetCode = SK_PNMI_ERR_GENERAL; /* * Check instance. We only handle single instance variables. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } /* Perform action. */ /* GET value. */ if (Action == SK_PNMI_GET) { switch (Id) { case OID_SKGE_ASF: RetCode = SkAsfGet(pAC, IoC, (SK_U8 *) pBuf, pLen); break; default: RetCode = SkAsfGetOid( pAC, IoC, Id, Instance, (SK_U8 *) pBuf, pLen ); break; } return (RetCode); } /* PRESET value. */ if (Action == SK_PNMI_PRESET) { switch (Id) { case OID_SKGE_ASF: RetCode = SkAsfPreSet(pAC, IoC, (SK_U8 *) pBuf, pLen); break; default: RetCode = SkAsfPreSetOid( pAC, IoC, Id, Instance, (SK_U8 *) pBuf, pLen ); break; } } /* SET value. */ if (Action == SK_PNMI_SET) { switch (Id) { case OID_SKGE_ASF: RetCode = SkAsfSet(pAC, IoC, (SK_U8 *) pBuf, pLen); break; default: RetCode = SkAsfSetOid( pAC, IoC, Id, Instance, (SK_U8 *) pBuf, pLen ); break; } } return (RetCode); } #endif /* SK_ASF */ #endif