diff options
Diffstat (limited to 'sys/dev/hea/eni_if.c')
-rw-r--r-- | sys/dev/hea/eni_if.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/sys/dev/hea/eni_if.c b/sys/dev/hea/eni_if.c new file mode 100644 index 0000000..41ffd48 --- /dev/null +++ b/sys/dev/hea/eni_if.c @@ -0,0 +1,270 @@ +/* + * + * =================================== + * 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. + * + * @(#) $Id: eni_if.c,v 1.6 1998/08/26 23:28:53 mks Exp $ + * + */ + +/* + * Efficient ENI Adapter Support + * ----------------------------- + * + * Network interface layer support + * + */ + +#ifndef lint +static char *RCSid = "@(#) $Id: eni_if.c,v 1.6 1998/08/26 23:28:53 mks Exp $"; +#endif + +#include <netatm/kern_include.h> + +#include <dev/hea/eni_stats.h> +#include <dev/hea/eni.h> +#include <dev/hea/eni_suni.h> +#include <dev/hea/eni_var.h> + +static void eni_get_stats __P((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 ); + sprintf ( 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 ) ) + 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)) + 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))) + 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 ); + +} + |