/***************************************************************************** * * Name: skgepnmi.c * Project: GEnesis, PCI Gigabit Ethernet Adapter * Version: $Revision: 1.111 $ * Date: $Date: 2003/09/15 13:35:35 $ * Purpose: Private Network Management Interface * ****************************************************************************/ /****************************************************************************** * * (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. * ******************************************************************************/ #ifndef _lint static const char SysKonnectFileId[] = "@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell."; #endif /* !_lint */ #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/skgeinit.h" #include "h/skdrv2nd.h" #include "h/skgepnm2.h" #ifdef SK_POWER_MGMT #include "h/skgepmgt.h" #endif /* defines *******************************************************************/ #ifndef DEBUG #define PNMI_STATIC static #else /* DEBUG */ #define PNMI_STATIC #endif /* DEBUG */ /* * Public Function prototypes */ int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level); int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, unsigned int *pLen, SK_U32 NetIndex); int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, unsigned int *pLen, SK_U32 NetIndex); int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, unsigned int *pLen, SK_U32 NetIndex); int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param); int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf, unsigned int * pLen, SK_U32 NetIndex); /* * 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 int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex); PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, 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_U16 Val16; /* Multiple purpose 16 bit variable */ SK_U8 Val8; /* Mulitple purpose 8 bit variable */ SK_EVPARA EventParam; /* Event struct for timer event */ SK_PNMI_VCT *pVctBackupData; 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; } #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); } /* Initialize DSP variables for Vct() to 0xff => Never written! */ for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { pAC->GIni.GP[PortIndex].PCableLen = 0xff; pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex]; pVctBackupData->PCableLen = 0xff; } /* * Get pci bus speed */ SK_IN16(IoC, B0_CTST, &Val16); if ((Val16 & CS_BUS_CLOCK) == 0) { pAC->Pnmi.PciBusSpeed = 33; } else { pAC->Pnmi.PciBusSpeed = 66; } /* * Get pci bus width */ SK_IN16(IoC, B0_CTST, &Val16); if ((Val16 & CS_BUS_SLOT_SZ) == 0) { pAC->Pnmi.PciBusWidth = 32; } else { pAC->Pnmi.PciBusWidth = 64; } /* * 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; default: break; } /* * Get PMD and DeviceType */ SK_IN8(IoC, B2_PMD_TYP, &Val8); switch (Val8) { case 'S': pAC->Pnmi.PMD = 3; if (pAC->GIni.GIMacsFound > 1) { pAC->Pnmi.DeviceType = 0x00020002; } else { pAC->Pnmi.DeviceType = 0x00020001; } break; case 'L': pAC->Pnmi.PMD = 2; if (pAC->GIni.GIMacsFound > 1) { pAC->Pnmi.DeviceType = 0x00020004; } else { pAC->Pnmi.DeviceType = 0x00020003; } break; case 'C': pAC->Pnmi.PMD = 4; if (pAC->GIni.GIMacsFound > 1) { pAC->Pnmi.DeviceType = 0x00020006; } else { pAC->Pnmi.DeviceType = 0x00020005; } break; case 'T': pAC->Pnmi.PMD = 5; if (pAC->GIni.GIMacsFound > 1) { pAC->Pnmi.DeviceType = 0x00020008; } else { pAC->Pnmi.DeviceType = 0x00020007; } break; default : pAC->Pnmi.PMD = 1; pAC->Pnmi.DeviceType = 0; break; } /* * Get connector */ SK_IN8(IoC, B2_CONN_TYP, &Val8); switch (Val8) { 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, 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, EventParam); break; default: break; /* Nothing todo */ } 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. */ static 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 useful 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. */ static 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 useful 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 statistic */ 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 */ 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 useful 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; int Ret; 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_GEPORT *pPrt; SK_PNMI_VCT *pVctBackupData; SK_U32 RetCode; int i; SK_U32 CableLength; #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: SkPnmiEvent: 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 * 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, 28125000, 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 PhysPortIndex = (unsigned int)Param.Para64; /* * Update XMAC statistic to get fresh values */ Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); if (Ret != 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 active */ 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) { /* single net mode */ pAC->Pnmi.DualNetActiveFlag = SK_FALSE; } else { /* dual net mode */ pAC->Pnmi.DualNetActiveFlag = SK_TRUE; } break; case SK_PNMI_EVT_VCT_RESET: PhysPortIndex = Param.Para32[0]; pPrt = &pAC->GIni.GP[PhysPortIndex]; pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; 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].VctTimer, 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param); break; } pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; pAC->Pnmi.VctStatus[PhysPortIndex] |= (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); /* Copy results for later use to PNMI struct. */ for (i = 0; i < 4; i++) { if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) { pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; } } if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) { CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); } else { CableLength = 0; } pVctBackupData->PMdiPairLen[i] = CableLength; pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; } Param.Para32[0] = PhysPortIndex; Param.Para32[1] = -1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param); 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 32bit are required for OID */ if (*pLen < sizeof(SK_U32)) { /* * but 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; } /* * 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 32bit 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) { /* Dual net 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) { /* Dual net 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 += sizeof(char); 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 += sizeof(char); 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 += sizeof(char); 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; /* * 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017, SK_PNMI_ERR017MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } if ((pVpdStatus->vpd_status & VPD_VALID) == 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018, 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR021, 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR022, 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023, 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024, 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025, 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026, 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027, 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028, 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 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)) { /* * but 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 statistic */ 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_RUNT, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex); 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; Offset += sizeof(SK_U32), Index ++) { Val32 = (SK_U32)IdTable[Index].Id; SK_PNMI_STORE_U32(pBuf + Offset, Val32); } *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_ERR030, 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_ERR031, 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_ERR030, 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_ERR031, 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. */ 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: /* Oh, I love to do some string manipulation */ 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)(0x30 | ((Val8 >> 4) & 0x0F)); pBuf[3] = '.'; pBuf[4] = (char)(0x30 | (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: /* XXX 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen + pAC->Pnmi.BufPort[1].TxSwQueueLen; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax + pAC->Pnmi.BufPort[1].TxSwQueueMax; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].TxRetryCts + pAC->Pnmi.BufPort[1].TxRetryCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].RxIntrCts + pAC->Pnmi.BufPort[1].RxIntrCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].TxIntrCts + pAC->Pnmi.BufPort[1].TxIntrCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts + pAC->Pnmi.BufPort[1].RxNoBufCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts + pAC->Pnmi.BufPort[1].TxNoBufCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo + pAC->Pnmi.BufPort[1].TxUsedDescrNo; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts + pAC->Pnmi.BufPort[1].RxDeliveredCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts + pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; } /* Single net mode */ else { Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[0].RxNoBufCts + pAC->Pnmi.BufPort[1].RxNoBufCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; } /* Single net mode */ else { Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[0].TxNoBufCts + pAC->Pnmi.BufPort[1].TxNoBufCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; } /* Single net 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) { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts; } /* Single net mode */ else { Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts + pAC->Pnmi.BufPort[1].ErrRecoveryCts; } } else { /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts; } /* Single net 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; } else { Val64 = 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_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: /* 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); } /* A 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); } /* Single net mode */ PhysPortIndex = Instance - 1; /* Dual net mode */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { PhysPortIndex = NetIndex; } /* Both net modes */ Limit = PhysPortIndex + 1; } else { /* Single net mode */ PhysPortIndex = 0; Limit = PhysPortMax; /* Dual net 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; /* * 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) { /* Dual net 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: 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 += sizeof(char); break; case OID_SKGE_CONNECTOR: *pBufPtr = pAC->Pnmi.Connector; Offset += sizeof(char); break; case OID_SKGE_PHY_TYPE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ if (LogPortIndex == 0) { continue; } else { /* Get value for physical ports */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); Val32 = pAC->GIni.GP[PhysPortIndex].PhyType; SK_PNMI_STORE_U32(pBufPtr, Val32); } } else { /* DualNetMode */ Val32 = pAC->GIni.GP[NetIndex].PhyType; SK_PNMI_STORE_U32(pBufPtr, Val32); } Offset += sizeof(SK_U32); break; case OID_SKGE_LINK_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ if (LogPortIndex == 0) { /* Get value for virtual port */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical ports */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap; } } else { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap; } Offset += sizeof(char); break; case OID_SKGE_LINK_MODE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ if (LogPortIndex == 0) { /* Get value for virtual port */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical ports */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf; } } else { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf; } Offset += sizeof(char); break; case OID_SKGE_LINK_MODE_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ 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 { /* DualNetMode */ *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex); } Offset += sizeof(char); break; case OID_SKGE_LINK_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ if (LogPortIndex == 0) { /* Get value for virtual port */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical ports */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex); } } else { /* DualNetMode */ *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex); } Offset += sizeof(char); break; case OID_SKGE_FLOWCTRL_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ if (LogPortIndex == 0) { /* Get value for virtual port */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical ports */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; } } else { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap; } Offset += sizeof(char); break; case OID_SKGE_FLOWCTRL_MODE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ 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 { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode; } Offset += sizeof(char); break; case OID_SKGE_FLOWCTRL_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ 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 { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus; } Offset += sizeof(char); break; case OID_SKGE_PHY_OPERATION_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ if (LogPortIndex == 0) { /* Get value for virtual port */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical ports */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap; } } else { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap; } Offset += sizeof(char); break; case OID_SKGE_PHY_OPERATION_MODE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ 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 { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode; } Offset += sizeof(char); break; case OID_SKGE_PHY_OPERATION_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ 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 += sizeof(char); break; case OID_SKGE_SPEED_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ if (LogPortIndex == 0) { /* Get value for virtual port */ VirtualConf(pAC, IoC, Id, pBufPtr); } else { /* Get value for physical ports */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap; } } else { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap; } Offset += sizeof(char); break; case OID_SKGE_SPEED_MODE: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ 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 { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed; } Offset += sizeof(char); break; case OID_SKGE_SPEED_STATUS: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ 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 { /* DualNetMode */ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed; } Offset += sizeof(char); 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; case OID_SKGE_MTU: if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } if (*pLen != sizeof(SK_U32)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } break; default: *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } /* * Perform preset or set */ Offset = 0; for (; LogPortIndex < Limit; LogPortIndex ++) { switch (Id) { case OID_SKGE_LINK_MODE: /* Check the value range */ Val8 = *(pBuf + Offset); if (Val8 == 0) { Offset += sizeof(char); 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 (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); } } } 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); } } Offset += sizeof(char); break; case OID_SKGE_FLOWCTRL_MODE: /* Check the value range */ Val8 = *(pBuf + Offset); if (Val8 == 0) { Offset += sizeof(char); 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 (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); } } Offset += sizeof(char); break; case OID_SKGE_PHY_OPERATION_MODE : /* Check the value range */ Val8 = *(pBuf + Offset); if (Val8 == 0) { /* mode of this port remains unchanged */ Offset += sizeof(char); 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 (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); } } Offset += sizeof(char); break; case OID_SKGE_SPEED_MODE: /* Check the value range */ Val8 = *(pBuf + Offset); if (Val8 == 0) { Offset += sizeof(char); 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 (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); } } Offset += sizeof(char); break; case OID_SKGE_MTU : /* Check the value range */ Val32 = *(SK_U32*)(pBuf + Offset); 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; 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; /* * Calculate instance if wished. */ /* XXX Not yet implemented. Return always an empty table. */ Entries = 0; 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); } /* for (Offset=0; Index < Limit; Index ++) { } */ /* * XXX 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; } 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 a value that * indicates that the link mode is 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 a value * that indicates that the link mode status is * 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 a value * that indicates that the link status is * 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 a value * that indicates that the mode is 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 a * value that indicates that the status is * 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 a value * that indicates that the mode is 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 a * value that indicates that the status is * 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 flow * control mode than the first one, we return a value * that indicates that the mode is 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 flow * control status than the first one, we return a * value that indicates that the status is * 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 useful 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, (char *)&BufKeys, (int *)&BufKeysLen, (int *)pKeyNo); if (Ret > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014, SK_PNMI_ERR014MSG); 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015, 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_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016, 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) > 0) { 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) { /* Dual net mode */ PhysPortIndex = NetIndex; Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); } else { /* Single Net 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 link-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 it in * Receive Error Counter register */ if (pPrt->PhyType == SK_PHY_BCOM) { /* 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]; } 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 statistic */ 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 */ { 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_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, pBuf, pLen); break; default: RetCode = SK_PNMI_ERR_GENERAL; break; } return (RetCode); } /* * Perform preset or set */ /* POWER module does not support PRESET action */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } switch (Id) { case OID_PNP_SET_POWER: RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen); break; case OID_PNP_ADD_WAKE_UP_PATTERN: RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen); break; case OID_PNP_REMOVE_WAKE_UP_PATTERN: RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen); break; case OID_PNP_ENABLE_WAKE_UP: RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen); 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. */ /* GET value. */ if (Action == SK_PNMI_GET) { 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 * * 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_BOOL Link; SK_U32 RetCode = SK_PNMI_ERR_GENERAL; int i; SK_EVPARA Para; SK_U32 CableLength; /* * 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))) { /* Check instance range. */ if ((Instance < 2) || (Instance > LogPortMax)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { PhysPortIndex = NetIndex; } else { PhysPortIndex = Instance - 2; } Limit = PhysPortIndex + 1; } else { /* * Instance == (SK_U32) (-1), get all Instances of that OID. * * Not implemented yet. May be used in future releases. */ PhysPortIndex = 0; Limit = PhysPortMax; } pPrt = &pAC->GIni.GP[PhysPortIndex]; if (pPrt->PHWLinkUp) { Link = SK_TRUE; } else { Link = SK_FALSE; } /* Check MAC type */ if (pPrt->PhyType != SK_PHY_MARV_COPPER) { *pLen = 0; return (SK_PNMI_ERR_GENERAL); } /* Initialize backup data pointer. */ pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; /* 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: 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++) { switch (Id) { case OID_SKGE_VCT_GET: if ((Link == SK_FALSE) && (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) { RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); if (RetCode == 0) { pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; pAC->Pnmi.VctStatus[PhysPortIndex] |= (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); /* Copy results for later use to PNMI struct. */ for (i = 0; i < 4; i++) { if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) { pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; } } if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) { CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); } else { CableLength = 0; } pVctBackupData->PMdiPairLen[i] = CableLength; pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; } Para.Para32[0] = PhysPortIndex; Para.Para32[1] = -1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); SkEventDispatcher(pAC, IoC); } else { ; /* VCT test is running. */ } } /* Get all results. */ CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); Offset += sizeof(SK_U8); *(pBuf + Offset) = pPrt->PCableLen; Offset += sizeof(SK_U8); for (i = 0; i < 4; i++) { SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]); Offset += sizeof(SK_U32); } for (i = 0; i < 4; i++) { *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i]; Offset += sizeof(SK_U8); } RetCode = SK_PNMI_ERR_OK; break; case OID_SKGE_VCT_STATUS: CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); Offset += sizeof(SK_U8); 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++) { switch (Id) { case OID_SKGE_VCT_SET: /* Start VCT test. */ if (Link == SK_FALSE) { 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; pAC->Pnmi.VctStatus[PhysPortIndex] &= ~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].VctTimer, 4000000, 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 CheckVctStatus( SK_AC *pAC, SK_IOC IoC, char *pBuf, SK_U32 Offset, SK_U32 PhysPortIndex) { SK_GEPORT *pPrt; SK_PNMI_VCT *pVctData; SK_U32 RetCode; pPrt = &pAC->GIni.GP[PhysPortIndex]; pVctData = (SK_PNMI_VCT *) (pBuf + Offset); pVctData->VctStatus = SK_PNMI_VCT_NONE; if (!pPrt->PHWLinkUp) { /* Was a VCT test ever made before? */ if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { if ((pAC->Pnmi.VctStatus[PhysPortIndex] & 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 (pAC->Pnmi.VctStatus[PhysPortIndex] & 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 (pAC->Pnmi.VctStatus[PhysPortIndex] & 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 (pAC->GIni.GP[PhysPortIndex].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 */