/* * * =================================== * HARP | Host ATM Research Platform * =================================== * * * This Host ATM Research Platform ("HARP") file (the "Software") is * made available by Network Computing Services, Inc. ("NetworkCS") * "AS IS". NetworkCS does not provide maintenance, improvements or * support of any kind. * * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED, * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE. * In no event shall NetworkCS be responsible for any damages, including * but not limited to consequential damages, arising from or relating to * any use of the Software or related support. * * Copyright 1994-1998 Network Computing Services, Inc. * * Copies of this Software may be made, however, the above copyright * notice must be reproduced on all copies. * * @(#) $FreeBSD: src/sys/dev/hea/eni_if.c,v 1.5 1999/08/28 00:41:44 peter Exp $ * @(#) $DragonFly: src/sys/dev/atm/hea/eni_if.c,v 1.5 2003/08/27 10:35:15 rob Exp $ */ /* * Efficient ENI Adapter Support * ----------------------------- * * Network interface layer support * */ #include #include "eni_stats.h" #include "eni.h" #include "eni_suni.h" #include "eni_var.h" static void eni_get_stats (Eni_unit *); /* * SUNI statistics counters take one of three forms: * single byte value (0x0 - 0xff) * two byte value (0x0 - 0xffff) * two + 1/2 (three) byte value * (0x0 - 0x0fffff) */ #define READ_ONE(x) ( (eup->eu_suni[(x)] & 0xff) ) #define READ_TWO(x) ( (eup->eu_suni[(x)+1] & 0xff) << 8 | \ (eup->eu_suni[(x)] & 0xff) ) #define READ_THREE(x) ( (eup->eu_suni[(x)+2] & 0xf) << 16 | \ (eup->eu_suni[(x)+1] & 0xff) << 8 | \ (eup->eu_suni[(x)] & 0xff) ) /* * Do an initial read of the error counters without saving them. * In effect, this will "zero" our idea of the number of errors * which have occurred since the driver was loaded. * * Arguments: * eup pointer to per unit structure * * Returns: * none * */ void eni_zero_stats ( eup ) Eni_unit *eup; { int val; /* * Write the SUNI master control register which * will cause all the statistics counters to be * loaded. */ eup->eu_suni[SUNI_MASTER_REG] = eup->eu_suni[SUNI_MASTER_REG]; /* * Delay to allow for counter load time... */ DELAY ( SUNI_DELAY ); /* * Statistics counters contain the number of events * since the last time the counter was read. */ val = READ_TWO ( SUNI_SECT_BIP_REG ); /* oc3_sect_bip8 */ val = READ_TWO ( SUNI_PATH_BIP_REG ); /* oc3_path_bip8 */ val = READ_THREE ( SUNI_LINE_BIP_REG ); /* oc3_line_bip24 */ val = READ_THREE ( SUNI_LINE_FEBE_REG ); /* oc3_line_febe */ val = READ_TWO ( SUNI_PATH_FEBE_REG ); /* oc3_path_febe */ val = READ_ONE ( SUNI_HECS_REG ); /* oc3_hec_corr */ val = READ_ONE ( SUNI_UHECS_REG ); /* oc3_hec_uncorr */ } /* * Retrieve SUNI stats * * Arguments: * eup pointer to per unit structure * * Returns: * none * */ static void eni_get_stats ( eup ) Eni_unit *eup; { /* * Write the SUNI master control register which * will cause all the statistics counters to be * loaded. */ eup->eu_suni[SUNI_MASTER_REG] = eup->eu_suni[SUNI_MASTER_REG]; /* * Delay to allow for counter load time... */ DELAY ( 10 ); /* * Statistics counters contain the number of events * since the last time the counter was read. */ eup->eu_stats.eni_st_oc3.oc3_sect_bip8 += READ_TWO ( SUNI_SECT_BIP_REG ); eup->eu_stats.eni_st_oc3.oc3_path_bip8 += READ_TWO ( SUNI_PATH_BIP_REG ); eup->eu_stats.eni_st_oc3.oc3_line_bip24 += READ_THREE ( SUNI_LINE_BIP_REG ); eup->eu_stats.eni_st_oc3.oc3_line_febe += READ_THREE ( SUNI_LINE_FEBE_REG ); eup->eu_stats.eni_st_oc3.oc3_path_febe += READ_TWO ( SUNI_PATH_FEBE_REG ); eup->eu_stats.eni_st_oc3.oc3_hec_corr += READ_ONE ( SUNI_HECS_REG ); eup->eu_stats.eni_st_oc3.oc3_hec_uncorr += READ_ONE ( SUNI_UHECS_REG ); } /* * Handle netatm core service interface ioctl requests * * Called at splnet. * * Arguments: * code ioctl function (sub)code * data data to/from ioctl * arg optional code-specific argument * * Returns: * 0 request processed successfully * error request failed - reason code * */ int eni_atm_ioctl ( code, data, arg ) int code; caddr_t data; caddr_t arg; { struct atminfreq *aip = (struct atminfreq *)data; struct atm_pif *pip = (struct atm_pif *)arg; Eni_unit *eup = (Eni_unit *)pip; caddr_t buf = aip->air_buf_addr; struct air_vinfo_rsp *avr; int count, len, buf_len = aip->air_buf_len; int err = 0; char ifname[2*IFNAMSIZ]; ATM_DEBUG2("eni_atm_ioctl: code=%d, opcode=%d\n", code, aip->air_opcode ); switch ( aip->air_opcode ) { case AIOCS_INF_VST: /* * Get vendor statistics */ if ( eup == NULL ) return ( ENXIO ); snprintf ( ifname, sizeof(ifname), "%s%d", pip->pif_name, pip->pif_unit ); /* * Cast response structure onto user's buffer */ avr = (struct air_vinfo_rsp *)buf; /* * How large is the response structure */ len = sizeof(struct air_vinfo_rsp); /* * Sanity check - enough room for response structure? */ if ( buf_len < len ) return ( ENOSPC ); /* * Copy interface name into response structure */ if ((err = copyout(ifname, avr->avsp_intf, IFNAMSIZ)) != 0) break; /* * Advance the buffer address and decrement the size */ buf += len; buf_len -= len; /* * Get the vendor stats (SUNI) from the hardware */ eni_get_stats ( eup ); /* * Stick as much of it as we have room for * into the response */ count = MIN ( sizeof(Eni_stats), buf_len ); /* * Copy stats into user's buffer. Return value is * amount of data copied. */ if ((err = copyout((void *)&eup->eu_stats, buf, count)) != 0) break; buf += count; buf_len -= count; if ( count < sizeof(Eni_stats) ) err = ENOSPC; /* * Record amount we're returning as vendor info... */ if ((err = copyout(&count, &avr->avsp_len, sizeof(int))) != 0) break; /* * Update the reply pointers and length */ aip->air_buf_addr = buf; aip->air_buf_len = buf_len; break; default: err = ENOSYS; /* Operation not supported */ break; } return ( err ); }