| 1 | /* |
| 2 | * |
| 3 | * =================================== |
| 4 | * HARP | Host ATM Research Platform |
| 5 | * =================================== |
| 6 | * |
| 7 | * |
| 8 | * This Host ATM Research Platform ("HARP") file (the "Software") is |
| 9 | * made available by Network Computing Services, Inc. ("NetworkCS") |
| 10 | * "AS IS". NetworkCS does not provide maintenance, improvements or |
| 11 | * support of any kind. |
| 12 | * |
| 13 | * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED, |
| 14 | * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY |
| 15 | * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE |
| 16 | * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE. |
| 17 | * In no event shall NetworkCS be responsible for any damages, including |
| 18 | * but not limited to consequential damages, arising from or relating to |
| 19 | * any use of the Software or related support. |
| 20 | * |
| 21 | * Copyright 1994-1998 Network Computing Services, Inc. |
| 22 | * |
| 23 | * Copies of this Software may be made, however, the above copyright |
| 24 | * notice must be reproduced on all copies. |
| 25 | * |
| 26 | * @(#) $FreeBSD: src/sys/dev/hea/eni_if.c,v 1.5 1999/08/28 00:41:44 peter Exp $ |
| 27 | * @(#) $DragonFly: src/sys/dev/atm/hea/eni_if.c,v 1.4 2003/08/07 21:54:28 dillon Exp $ |
| 28 | */ |
| 29 | |
| 30 | /* |
| 31 | * Efficient ENI Adapter Support |
| 32 | * ----------------------------- |
| 33 | * |
| 34 | * Network interface layer support |
| 35 | * |
| 36 | */ |
| 37 | |
| 38 | #include <netproto/atm/kern_include.h> |
| 39 | |
| 40 | #include "eni_stats.h" |
| 41 | #include "eni.h" |
| 42 | #include "eni_suni.h" |
| 43 | #include "eni_var.h" |
| 44 | |
| 45 | static void eni_get_stats __P((Eni_unit *)); |
| 46 | |
| 47 | /* |
| 48 | * SUNI statistics counters take one of three forms: |
| 49 | * single byte value (0x0 - 0xff) |
| 50 | * two byte value (0x0 - 0xffff) |
| 51 | * two + 1/2 (three) byte value |
| 52 | * (0x0 - 0x0fffff) |
| 53 | */ |
| 54 | #define READ_ONE(x) ( (eup->eu_suni[(x)] & 0xff) ) |
| 55 | |
| 56 | #define READ_TWO(x) ( (eup->eu_suni[(x)+1] & 0xff) << 8 | \ |
| 57 | (eup->eu_suni[(x)] & 0xff) ) |
| 58 | |
| 59 | #define READ_THREE(x) ( (eup->eu_suni[(x)+2] & 0xf) << 16 | \ |
| 60 | (eup->eu_suni[(x)+1] & 0xff) << 8 | \ |
| 61 | (eup->eu_suni[(x)] & 0xff) ) |
| 62 | |
| 63 | /* |
| 64 | * Do an initial read of the error counters without saving them. |
| 65 | * In effect, this will "zero" our idea of the number of errors |
| 66 | * which have occurred since the driver was loaded. |
| 67 | * |
| 68 | * Arguments: |
| 69 | * eup pointer to per unit structure |
| 70 | * |
| 71 | * Returns: |
| 72 | * none |
| 73 | * |
| 74 | */ |
| 75 | void |
| 76 | eni_zero_stats ( eup ) |
| 77 | Eni_unit *eup; |
| 78 | { |
| 79 | int val; |
| 80 | |
| 81 | /* |
| 82 | * Write the SUNI master control register which |
| 83 | * will cause all the statistics counters to be |
| 84 | * loaded. |
| 85 | */ |
| 86 | eup->eu_suni[SUNI_MASTER_REG] = eup->eu_suni[SUNI_MASTER_REG]; |
| 87 | |
| 88 | /* |
| 89 | * Delay to allow for counter load time... |
| 90 | */ |
| 91 | DELAY ( SUNI_DELAY ); |
| 92 | |
| 93 | /* |
| 94 | * Statistics counters contain the number of events |
| 95 | * since the last time the counter was read. |
| 96 | */ |
| 97 | val = READ_TWO ( SUNI_SECT_BIP_REG ); /* oc3_sect_bip8 */ |
| 98 | val = READ_TWO ( SUNI_PATH_BIP_REG ); /* oc3_path_bip8 */ |
| 99 | val = READ_THREE ( SUNI_LINE_BIP_REG ); /* oc3_line_bip24 */ |
| 100 | val = READ_THREE ( SUNI_LINE_FEBE_REG ); /* oc3_line_febe */ |
| 101 | val = READ_TWO ( SUNI_PATH_FEBE_REG ); /* oc3_path_febe */ |
| 102 | val = READ_ONE ( SUNI_HECS_REG ); /* oc3_hec_corr */ |
| 103 | val = READ_ONE ( SUNI_UHECS_REG ); /* oc3_hec_uncorr */ |
| 104 | } |
| 105 | |
| 106 | /* |
| 107 | * Retrieve SUNI stats |
| 108 | * |
| 109 | * Arguments: |
| 110 | * eup pointer to per unit structure |
| 111 | * |
| 112 | * Returns: |
| 113 | * none |
| 114 | * |
| 115 | */ |
| 116 | static void |
| 117 | eni_get_stats ( eup ) |
| 118 | Eni_unit *eup; |
| 119 | { |
| 120 | /* |
| 121 | * Write the SUNI master control register which |
| 122 | * will cause all the statistics counters to be |
| 123 | * loaded. |
| 124 | */ |
| 125 | eup->eu_suni[SUNI_MASTER_REG] = eup->eu_suni[SUNI_MASTER_REG]; |
| 126 | |
| 127 | /* |
| 128 | * Delay to allow for counter load time... |
| 129 | */ |
| 130 | DELAY ( 10 ); |
| 131 | |
| 132 | /* |
| 133 | * Statistics counters contain the number of events |
| 134 | * since the last time the counter was read. |
| 135 | */ |
| 136 | eup->eu_stats.eni_st_oc3.oc3_sect_bip8 += |
| 137 | READ_TWO ( SUNI_SECT_BIP_REG ); |
| 138 | eup->eu_stats.eni_st_oc3.oc3_path_bip8 += |
| 139 | READ_TWO ( SUNI_PATH_BIP_REG ); |
| 140 | eup->eu_stats.eni_st_oc3.oc3_line_bip24 += |
| 141 | READ_THREE ( SUNI_LINE_BIP_REG ); |
| 142 | eup->eu_stats.eni_st_oc3.oc3_line_febe += |
| 143 | READ_THREE ( SUNI_LINE_FEBE_REG ); |
| 144 | eup->eu_stats.eni_st_oc3.oc3_path_febe += |
| 145 | READ_TWO ( SUNI_PATH_FEBE_REG ); |
| 146 | eup->eu_stats.eni_st_oc3.oc3_hec_corr += |
| 147 | READ_ONE ( SUNI_HECS_REG ); |
| 148 | eup->eu_stats.eni_st_oc3.oc3_hec_uncorr += |
| 149 | READ_ONE ( SUNI_UHECS_REG ); |
| 150 | } |
| 151 | |
| 152 | /* |
| 153 | * Handle netatm core service interface ioctl requests |
| 154 | * |
| 155 | * Called at splnet. |
| 156 | * |
| 157 | * Arguments: |
| 158 | * code ioctl function (sub)code |
| 159 | * data data to/from ioctl |
| 160 | * arg optional code-specific argument |
| 161 | * |
| 162 | * Returns: |
| 163 | * 0 request processed successfully |
| 164 | * error request failed - reason code |
| 165 | * |
| 166 | */ |
| 167 | int |
| 168 | eni_atm_ioctl ( code, data, arg ) |
| 169 | int code; |
| 170 | caddr_t data; |
| 171 | caddr_t arg; |
| 172 | { |
| 173 | struct atminfreq *aip = (struct atminfreq *)data; |
| 174 | struct atm_pif *pip = (struct atm_pif *)arg; |
| 175 | Eni_unit *eup = (Eni_unit *)pip; |
| 176 | caddr_t buf = aip->air_buf_addr; |
| 177 | struct air_vinfo_rsp *avr; |
| 178 | int count, len, buf_len = aip->air_buf_len; |
| 179 | int err = 0; |
| 180 | char ifname[2*IFNAMSIZ]; |
| 181 | |
| 182 | ATM_DEBUG2("eni_atm_ioctl: code=%d, opcode=%d\n", |
| 183 | code, aip->air_opcode ); |
| 184 | |
| 185 | switch ( aip->air_opcode ) { |
| 186 | |
| 187 | case AIOCS_INF_VST: |
| 188 | /* |
| 189 | * Get vendor statistics |
| 190 | */ |
| 191 | if ( eup == NULL ) |
| 192 | return ( ENXIO ); |
| 193 | snprintf ( ifname, sizeof(ifname), |
| 194 | "%s%d", pip->pif_name, pip->pif_unit ); |
| 195 | |
| 196 | /* |
| 197 | * Cast response structure onto user's buffer |
| 198 | */ |
| 199 | avr = (struct air_vinfo_rsp *)buf; |
| 200 | |
| 201 | /* |
| 202 | * How large is the response structure |
| 203 | */ |
| 204 | len = sizeof(struct air_vinfo_rsp); |
| 205 | |
| 206 | /* |
| 207 | * Sanity check - enough room for response structure? |
| 208 | */ |
| 209 | if ( buf_len < len ) |
| 210 | return ( ENOSPC ); |
| 211 | |
| 212 | /* |
| 213 | * Copy interface name into response structure |
| 214 | */ |
| 215 | if ((err = copyout(ifname, avr->avsp_intf, IFNAMSIZ)) != 0) |
| 216 | break; |
| 217 | |
| 218 | /* |
| 219 | * Advance the buffer address and decrement the size |
| 220 | */ |
| 221 | buf += len; |
| 222 | buf_len -= len; |
| 223 | |
| 224 | /* |
| 225 | * Get the vendor stats (SUNI) from the hardware |
| 226 | */ |
| 227 | eni_get_stats ( eup ); |
| 228 | /* |
| 229 | * Stick as much of it as we have room for |
| 230 | * into the response |
| 231 | */ |
| 232 | count = MIN ( sizeof(Eni_stats), buf_len ); |
| 233 | |
| 234 | /* |
| 235 | * Copy stats into user's buffer. Return value is |
| 236 | * amount of data copied. |
| 237 | */ |
| 238 | if ((err = copyout((void *)&eup->eu_stats, buf, count)) != 0) |
| 239 | break; |
| 240 | buf += count; |
| 241 | buf_len -= count; |
| 242 | if ( count < sizeof(Eni_stats) ) |
| 243 | err = ENOSPC; |
| 244 | |
| 245 | /* |
| 246 | * Record amount we're returning as vendor info... |
| 247 | */ |
| 248 | if ((err = copyout(&count, &avr->avsp_len, sizeof(int))) != 0) |
| 249 | break; |
| 250 | |
| 251 | /* |
| 252 | * Update the reply pointers and length |
| 253 | */ |
| 254 | aip->air_buf_addr = buf; |
| 255 | aip->air_buf_len = buf_len; |
| 256 | break; |
| 257 | |
| 258 | default: |
| 259 | err = ENOSYS; /* Operation not supported */ |
| 260 | break; |
| 261 | } |
| 262 | |
| 263 | return ( err ); |
| 264 | |
| 265 | } |
| 266 | |