Index: head/tools/regression/lib/msun/test-cexp.c =================================================================== --- head/tools/regression/lib/msun/test-cexp.c (revision 287296) +++ head/tools/regression/lib/msun/test-cexp.c (revision 287297) @@ -1,322 +1,322 @@ /*- * Copyright (c) 2008-2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for corner cases in cexp*(). */ #include __FBSDID("$FreeBSD$"); +#include + #include #include #include #include #include #include #include "test-utils.h" -#define N(i) (sizeof(i) / sizeof((i)[0])) - #pragma STDC FENV_ACCESS ON #pragma STDC CX_LIMITED_RANGE OFF /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several * reasons, but mainly because on some architectures it's impossible * to raise FE_OVERFLOW without raising FE_INEXACT. In some cases, * whether cexp() raises an invalid exception is unspecified. * * These are macros instead of functions so that assert provides more * meaningful error messages. * * XXX The volatile here is to avoid gcc's bogus constant folding and work * around the lack of support for the FENV_ACCESS pragma. */ #define test(func, z, result, exceptmask, excepts, checksign) do { \ volatile long double complex _d = z; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(cfpequal_cs((func)(_d), (result), (checksign))); \ assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* Test within a given tolerance. */ #define test_tol(func, z, result, tol) do { \ volatile long double complex _d = z; \ assert(cfpequal_tol((func)(_d), (result), (tol), \ FPE_ABS_ZERO | CS_BOTH)); \ } while (0) /* Test all the functions that compute cexp(x). */ #define testall(x, result, exceptmask, excepts, checksign) do { \ test(cexp, x, result, exceptmask, excepts, checksign); \ test(cexpf, x, result, exceptmask, excepts, checksign); \ } while (0) /* * Test all the functions that compute cexp(x), within a given tolerance. * The tolerance is specified in ulps. */ #define testall_tol(x, result, tol) do { \ test_tol(cexp, x, result, tol * DBL_ULP()); \ test_tol(cexpf, x, result, tol * FLT_ULP()); \ } while (0) /* Various finite non-zero numbers to test. */ static const float finites[] = { -42.0e20, -1.0, -1.0e-10, -0.0, 0.0, 1.0e-10, 1.0, 42.0e20 }; /* Tests for 0 */ void test_zero(void) { /* cexp(0) = 1, no exceptions raised */ testall(0.0, 1.0, ALL_STD_EXCEPT, 0, 1); testall(-0.0, 1.0, ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(0.0, -0.0), CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(-0.0, -0.0), CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); } /* * Tests for NaN. The signs of the results are indeterminate unless the * imaginary part is 0. */ void test_nan() { int i; /* cexp(x + NaNi) = NaN + NaNi and optionally raises invalid */ /* cexp(NaN + yi) = NaN + NaNi and optionally raises invalid (|y|>0) */ - for (i = 0; i < N(finites); i++) { + for (i = 0; i < nitems(finites); i++) { printf("# Run %d..\n", i); testall(CMPLXL(finites[i], NAN), CMPLXL(NAN, NAN), ALL_STD_EXCEPT & ~FE_INVALID, 0, 0); if (finites[i] == 0.0) continue; /* XXX FE_INEXACT shouldn't be raised here */ testall(CMPLXL(NAN, finites[i]), CMPLXL(NAN, NAN), ALL_STD_EXCEPT & ~(FE_INVALID | FE_INEXACT), 0, 0); } /* cexp(NaN +- 0i) = NaN +- 0i */ testall(CMPLXL(NAN, 0.0), CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(NAN, -0.0), CMPLXL(NAN, -0.0), ALL_STD_EXCEPT, 0, 1); /* cexp(inf + NaN i) = inf + nan i */ testall(CMPLXL(INFINITY, NAN), CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); /* cexp(-inf + NaN i) = 0 */ testall(CMPLXL(-INFINITY, NAN), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT, 0, 0); /* cexp(NaN + NaN i) = NaN + NaN i */ testall(CMPLXL(NAN, NAN), CMPLXL(NAN, NAN), ALL_STD_EXCEPT, 0, 0); } void test_inf(void) { int i; /* cexp(x + inf i) = NaN + NaNi and raises invalid */ - for (i = 0; i < N(finites); i++) { + for (i = 0; i < nitems(finites); i++) { printf("# Run %d..\n", i); testall(CMPLXL(finites[i], INFINITY), CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 1); } /* cexp(-inf + yi) = 0 * (cos(y) + sin(y)i) */ /* XXX shouldn't raise an inexact exception */ testall(CMPLXL(-INFINITY, M_PI_4), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(-INFINITY, 3 * M_PI_4), CMPLXL(-0.0, 0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(-INFINITY, 5 * M_PI_4), CMPLXL(-0.0, -0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(-INFINITY, 7 * M_PI_4), CMPLXL(0.0, -0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(-INFINITY, 0.0), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(-INFINITY, -0.0), CMPLXL(0.0, -0.0), ALL_STD_EXCEPT, 0, 1); /* cexp(inf + yi) = inf * (cos(y) + sin(y)i) (except y=0) */ /* XXX shouldn't raise an inexact exception */ testall(CMPLXL(INFINITY, M_PI_4), CMPLXL(INFINITY, INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(INFINITY, 3 * M_PI_4), CMPLXL(-INFINITY, INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(INFINITY, 5 * M_PI_4), CMPLXL(-INFINITY, -INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(INFINITY, 7 * M_PI_4), CMPLXL(INFINITY, -INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); /* cexp(inf + 0i) = inf + 0i */ testall(CMPLXL(INFINITY, 0.0), CMPLXL(INFINITY, 0.0), ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(INFINITY, -0.0), CMPLXL(INFINITY, -0.0), ALL_STD_EXCEPT, 0, 1); } void test_reals(void) { int i; - for (i = 0; i < N(finites); i++) { + for (i = 0; i < nitems(finites); i++) { /* XXX could check exceptions more meticulously */ printf("# Run %d..\n", i); test(cexp, CMPLXL(finites[i], 0.0), CMPLXL(exp(finites[i]), 0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); test(cexp, CMPLXL(finites[i], -0.0), CMPLXL(exp(finites[i]), -0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); test(cexpf, CMPLXL(finites[i], 0.0), CMPLXL(expf(finites[i]), 0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); test(cexpf, CMPLXL(finites[i], -0.0), CMPLXL(expf(finites[i]), -0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); } } void test_imaginaries(void) { int i; - for (i = 0; i < N(finites); i++) { + for (i = 0; i < nitems(finites); i++) { printf("# Run %d..\n", i); test(cexp, CMPLXL(0.0, finites[i]), CMPLXL(cos(finites[i]), sin(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); test(cexp, CMPLXL(-0.0, finites[i]), CMPLXL(cos(finites[i]), sin(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); test(cexpf, CMPLXL(0.0, finites[i]), CMPLXL(cosf(finites[i]), sinf(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); test(cexpf, CMPLXL(-0.0, finites[i]), CMPLXL(cosf(finites[i]), sinf(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); } } void test_small(void) { static const double tests[] = { /* csqrt(a + bI) = x + yI */ /* a b x y */ 1.0, M_PI_4, M_SQRT2 * 0.5 * M_E, M_SQRT2 * 0.5 * M_E, -1.0, M_PI_4, M_SQRT2 * 0.5 / M_E, M_SQRT2 * 0.5 / M_E, 2.0, M_PI_2, 0.0, M_E * M_E, M_LN2, M_PI, -2.0, 0.0, }; double a, b; double x, y; int i; - for (i = 0; i < N(tests); i += 4) { + for (i = 0; i < nitems(tests); i += 4) { printf("# Run %d..\n", i); a = tests[i]; b = tests[i + 1]; x = tests[i + 2]; y = tests[i + 3]; test_tol(cexp, CMPLXL(a, b), CMPLXL(x, y), 3 * DBL_ULP()); /* float doesn't have enough precision to pass these tests */ if (x == 0 || y == 0) continue; test_tol(cexpf, CMPLXL(a, b), CMPLXL(x, y), 1 * FLT_ULP()); } } /* Test inputs with a real part r that would overflow exp(r). */ void test_large(void) { test_tol(cexp, CMPLXL(709.79, 0x1p-1074), CMPLXL(INFINITY, 8.94674309915433533273e-16), DBL_ULP()); test_tol(cexp, CMPLXL(1000, 0x1p-1074), CMPLXL(INFINITY, 9.73344457300016401328e+110), DBL_ULP()); test_tol(cexp, CMPLXL(1400, 0x1p-1074), CMPLXL(INFINITY, 5.08228858149196559681e+284), DBL_ULP()); test_tol(cexp, CMPLXL(900, 0x1.23456789abcdep-1020), CMPLXL(INFINITY, 7.42156649354218408074e+83), DBL_ULP()); test_tol(cexp, CMPLXL(1300, 0x1.23456789abcdep-1020), CMPLXL(INFINITY, 3.87514844965996756704e+257), DBL_ULP()); test_tol(cexpf, CMPLXL(88.73, 0x1p-149), CMPLXL(INFINITY, 4.80265603e-07), 2 * FLT_ULP()); test_tol(cexpf, CMPLXL(90, 0x1p-149), CMPLXL(INFINITY, 1.7101492622e-06f), 2 * FLT_ULP()); test_tol(cexpf, CMPLXL(192, 0x1p-149), CMPLXL(INFINITY, 3.396809344e+38f), 2 * FLT_ULP()); test_tol(cexpf, CMPLXL(120, 0x1.234568p-120), CMPLXL(INFINITY, 1.1163382522e+16f), 2 * FLT_ULP()); test_tol(cexpf, CMPLXL(170, 0x1.234568p-120), CMPLXL(INFINITY, 5.7878851079e+37f), 2 * FLT_ULP()); } int main(int argc, char *argv[]) { printf("1..7\n"); test_zero(); printf("ok 1 - cexp zero\n"); test_nan(); printf("ok 2 - cexp nan\n"); test_inf(); printf("ok 3 - cexp inf\n"); #if defined(__i386__) printf("not ok 4 - cexp reals # TODO: PR # 191676 fails assertion on i386\n"); #else test_reals(); printf("ok 4 - cexp reals\n"); #endif test_imaginaries(); printf("ok 5 - cexp imaginaries\n"); test_small(); printf("ok 6 - cexp small\n"); test_large(); printf("ok 7 - cexp large\n"); return (0); } Index: head/tools/regression/lib/msun/test-csqrt.c =================================================================== --- head/tools/regression/lib/msun/test-csqrt.c (revision 287296) +++ head/tools/regression/lib/msun/test-csqrt.c (revision 287297) @@ -1,295 +1,295 @@ /*- * Copyright (c) 2007 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for csqrt{,f}() */ #include __FBSDID("$FreeBSD$"); +#include + #include #include #include #include #include #include "test-utils.h" -#define N(i) (sizeof(i) / sizeof((i)[0])) - /* * This is a test hook that can point to csqrtl(), _csqrt(), or to _csqrtf(). * The latter two convert to float or double, respectively, and test csqrtf() * and csqrt() with the same arguments. */ long double complex (*t_csqrt)(long double complex); static long double complex _csqrtf(long double complex d) { return (csqrtf((float complex)d)); } static long double complex _csqrt(long double complex d) { return (csqrt((double complex)d)); } #pragma STDC CX_LIMITED_RANGE OFF /* * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. * Fail an assertion if they differ. */ static void assert_equal(long double complex d1, long double complex d2) { assert(cfpequal(d1, d2)); } /* * Test csqrt for some finite arguments where the answer is exact. * (We do not test if it produces correctly rounded answers when the * result is inexact, nor do we check whether it throws spurious * exceptions.) */ static void test_finite() { static const double tests[] = { /* csqrt(a + bI) = x + yI */ /* a b x y */ 0, 8, 2, 2, 0, -8, 2, -2, 4, 0, 2, 0, -4, 0, 0, 2, 3, 4, 2, 1, 3, -4, 2, -1, -3, 4, 1, 2, -3, -4, 1, -2, 5, 12, 3, 2, 7, 24, 4, 3, 9, 40, 5, 4, 11, 60, 6, 5, 13, 84, 7, 6, 33, 56, 7, 4, 39, 80, 8, 5, 65, 72, 9, 4, 987, 9916, 74, 67, 5289, 6640, 83, 40, 460766389075.0, 16762287900.0, 678910, 12345 }; /* * We also test some multiples of the above arguments. This * array defines which multiples we use. Note that these have * to be small enough to not cause overflow for float precision * with all of the constants in the above table. */ static const double mults[] = { 1, 2, 3, 13, 16, 0x1.p30, 0x1.p-30, }; double a, b; double x, y; int i, j; - for (i = 0; i < N(tests); i += 4) { - for (j = 0; j < N(mults); j++) { + for (i = 0; i < nitems(tests); i += 4) { + for (j = 0; j < nitems(mults); j++) { a = tests[i] * mults[j] * mults[j]; b = tests[i + 1] * mults[j] * mults[j]; x = tests[i + 2] * mults[j]; y = tests[i + 3] * mults[j]; assert(t_csqrt(CMPLXL(a, b)) == CMPLXL(x, y)); } } } /* * Test the handling of +/- 0. */ static void test_zeros() { assert_equal(t_csqrt(CMPLXL(0.0, 0.0)), CMPLXL(0.0, 0.0)); assert_equal(t_csqrt(CMPLXL(-0.0, 0.0)), CMPLXL(0.0, 0.0)); assert_equal(t_csqrt(CMPLXL(0.0, -0.0)), CMPLXL(0.0, -0.0)); assert_equal(t_csqrt(CMPLXL(-0.0, -0.0)), CMPLXL(0.0, -0.0)); } /* * Test the handling of infinities when the other argument is not NaN. */ static void test_infinities() { static const double vals[] = { 0.0, -0.0, 42.0, -42.0, INFINITY, -INFINITY, }; int i; - for (i = 0; i < N(vals); i++) { + for (i = 0; i < nitems(vals); i++) { if (isfinite(vals[i])) { assert_equal(t_csqrt(CMPLXL(-INFINITY, vals[i])), CMPLXL(0.0, copysignl(INFINITY, vals[i]))); assert_equal(t_csqrt(CMPLXL(INFINITY, vals[i])), CMPLXL(INFINITY, copysignl(0.0, vals[i]))); } assert_equal(t_csqrt(CMPLXL(vals[i], INFINITY)), CMPLXL(INFINITY, INFINITY)); assert_equal(t_csqrt(CMPLXL(vals[i], -INFINITY)), CMPLXL(INFINITY, -INFINITY)); } } /* * Test the handling of NaNs. */ static void test_nans() { assert(creall(t_csqrt(CMPLXL(INFINITY, NAN))) == INFINITY); assert(isnan(cimagl(t_csqrt(CMPLXL(INFINITY, NAN))))); assert(isnan(creall(t_csqrt(CMPLXL(-INFINITY, NAN))))); assert(isinf(cimagl(t_csqrt(CMPLXL(-INFINITY, NAN))))); assert_equal(t_csqrt(CMPLXL(NAN, INFINITY)), CMPLXL(INFINITY, INFINITY)); assert_equal(t_csqrt(CMPLXL(NAN, -INFINITY)), CMPLXL(INFINITY, -INFINITY)); assert_equal(t_csqrt(CMPLXL(0.0, NAN)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(-0.0, NAN)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(42.0, NAN)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(-42.0, NAN)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, 0.0)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, -0.0)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, 42.0)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, -42.0)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, NAN)), CMPLXL(NAN, NAN)); } /* * Test whether csqrt(a + bi) works for inputs that are large enough to * cause overflow in hypot(a, b) + a. In this case we are using * csqrt(115 + 252*I) == 14 + 9*I * scaled up to near MAX_EXP. */ static void test_overflow(int maxexp) { long double a, b; long double complex result; a = ldexpl(115 * 0x1p-8, maxexp); b = ldexpl(252 * 0x1p-8, maxexp); result = t_csqrt(CMPLXL(a, b)); assert(creall(result) == ldexpl(14 * 0x1p-4, maxexp / 2)); assert(cimagl(result) == ldexpl(9 * 0x1p-4, maxexp / 2)); } int main(int argc, char *argv[]) { printf("1..15\n"); /* Test csqrt() */ t_csqrt = _csqrt; test_finite(); printf("ok 1 - csqrt\n"); test_zeros(); printf("ok 2 - csqrt\n"); test_infinities(); printf("ok 3 - csqrt\n"); test_nans(); printf("ok 4 - csqrt\n"); test_overflow(DBL_MAX_EXP); printf("ok 5 - csqrt\n"); /* Now test csqrtf() */ t_csqrt = _csqrtf; test_finite(); printf("ok 6 - csqrt\n"); test_zeros(); printf("ok 7 - csqrt\n"); test_infinities(); printf("ok 8 - csqrt\n"); test_nans(); printf("ok 9 - csqrt\n"); test_overflow(FLT_MAX_EXP); printf("ok 10 - csqrt\n"); /* Now test csqrtl() */ t_csqrt = csqrtl; test_finite(); printf("ok 11 - csqrt\n"); test_zeros(); printf("ok 12 - csqrt\n"); test_infinities(); printf("ok 13 - csqrt\n"); test_nans(); printf("ok 14 - csqrt\n"); test_overflow(LDBL_MAX_EXP); printf("ok 15 - csqrt\n"); return (0); } Index: head/tools/regression/lib/msun/test-invtrig.c =================================================================== --- head/tools/regression/lib/msun/test-invtrig.c (revision 287296) +++ head/tools/regression/lib/msun/test-invtrig.c (revision 287297) @@ -1,458 +1,456 @@ /*- * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for corner cases in the inverse trigonometric functions. Some * accuracy tests are included as well, but these are very basic * sanity checks, not intended to be comprehensive. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "test-utils.h" -#define LEN(a) (sizeof(a) / sizeof((a)[0])) - #pragma STDC FENV_ACCESS ON /* * Test that a function returns the correct value and sets the * exception flags correctly. A tolerance specifying the maximum * relative error allowed may be specified. For the 'testall' * functions, the tolerance is specified in ulps. * * These are macros instead of functions so that assert provides more * meaningful error messages. */ #define test_tol(func, x, result, tol, excepts) do { \ volatile long double _in = (x), _out = (result); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal_tol(func(_in), _out, (tol), CS_BOTH)); \ assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ } while (0) #define test(func, x, result, excepts) \ test_tol(func, (x), (result), 0, (excepts)) #define testall_tol(prefix, x, result, tol, excepts) do { \ test_tol(prefix, (double)(x), (double)(result), \ (tol) * ldexp(1.0, 1 - DBL_MANT_DIG), (excepts)); \ test_tol(prefix##f, (float)(x), (float)(result), \ (tol) * ldexpf(1.0, 1 - FLT_MANT_DIG), (excepts)); \ test_tol(prefix##l, (x), (result), \ (tol) * ldexpl(1.0, 1 - LDBL_MANT_DIG), (excepts)); \ } while (0) #define testall(prefix, x, result, excepts) \ testall_tol(prefix, (x), (result), 0, (excepts)) #define test2_tol(func, y, x, result, tol, excepts) do { \ volatile long double _iny = (y), _inx = (x), _out = (result); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal_tol(func(_iny, _inx), _out, (tol), CS_BOTH)); \ assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ } while (0) #define test2(func, y, x, result, excepts) \ test2_tol(func, (y), (x), (result), 0, (excepts)) #define testall2_tol(prefix, y, x, result, tol, excepts) do { \ test2_tol(prefix, (double)(y), (double)(x), (double)(result), \ (tol) * ldexp(1.0, 1 - DBL_MANT_DIG), (excepts)); \ test2_tol(prefix##f, (float)(y), (float)(x), (float)(result), \ (tol) * ldexpf(1.0, 1 - FLT_MANT_DIG), (excepts)); \ test2_tol(prefix##l, (y), (x), (result), \ (tol) * ldexpl(1.0, 1 - LDBL_MANT_DIG), (excepts)); \ } while (0) #define testall2(prefix, y, x, result, excepts) \ testall2_tol(prefix, (y), (x), (result), 0, (excepts)) long double pi = 3.14159265358979323846264338327950280e+00L, pio3 = 1.04719755119659774615421446109316766e+00L, c3pi = 9.42477796076937971538793014983850839e+00L, c5pi = 1.57079632679489661923132169163975140e+01L, c7pi = 2.19911485751285526692385036829565196e+01L, c5pio3 = 5.23598775598298873077107230546583851e+00L, sqrt2m1 = 4.14213562373095048801688724209698081e-01L; /* * Test special case inputs in asin(), acos() and atan(): signed * zeroes, infinities, and NaNs. */ static void test_special(void) { testall(asin, 0.0, 0.0, 0); testall(acos, 0.0, pi / 2, FE_INEXACT); testall(atan, 0.0, 0.0, 0); testall(asin, -0.0, -0.0, 0); testall(acos, -0.0, pi / 2, FE_INEXACT); testall(atan, -0.0, -0.0, 0); testall(asin, INFINITY, NAN, FE_INVALID); testall(acos, INFINITY, NAN, FE_INVALID); testall(atan, INFINITY, pi / 2, FE_INEXACT); testall(asin, -INFINITY, NAN, FE_INVALID); testall(acos, -INFINITY, NAN, FE_INVALID); testall(atan, -INFINITY, -pi / 2, FE_INEXACT); testall(asin, NAN, NAN, 0); testall(acos, NAN, NAN, 0); testall(atan, NAN, NAN, 0); } /* * Test special case inputs in atan2(), where the exact value of y/x is * zero or non-finite. */ static void test_special_atan2(void) { long double z; int e; testall2(atan2, 0.0, -0.0, pi, FE_INEXACT); testall2(atan2, -0.0, -0.0, -pi, FE_INEXACT); testall2(atan2, 0.0, 0.0, 0.0, 0); testall2(atan2, -0.0, 0.0, -0.0, 0); testall2(atan2, INFINITY, -INFINITY, c3pi / 4, FE_INEXACT); testall2(atan2, -INFINITY, -INFINITY, -c3pi / 4, FE_INEXACT); testall2(atan2, INFINITY, INFINITY, pi / 4, FE_INEXACT); testall2(atan2, -INFINITY, INFINITY, -pi / 4, FE_INEXACT); /* Tests with one input in the range (0, Inf]. */ z = 1.23456789L; for (e = FLT_MIN_EXP - FLT_MANT_DIG; e <= FLT_MAX_EXP; e++) { test2(atan2f, 0.0, ldexpf(z, e), 0.0, 0); test2(atan2f, -0.0, ldexpf(z, e), -0.0, 0); test2(atan2f, 0.0, ldexpf(-z, e), (float)pi, FE_INEXACT); test2(atan2f, -0.0, ldexpf(-z, e), (float)-pi, FE_INEXACT); test2(atan2f, ldexpf(z, e), 0.0, (float)pi / 2, FE_INEXACT); test2(atan2f, ldexpf(z, e), -0.0, (float)pi / 2, FE_INEXACT); test2(atan2f, ldexpf(-z, e), 0.0, (float)-pi / 2, FE_INEXACT); test2(atan2f, ldexpf(-z, e), -0.0, (float)-pi / 2, FE_INEXACT); } for (e = DBL_MIN_EXP - DBL_MANT_DIG; e <= DBL_MAX_EXP; e++) { test2(atan2, 0.0, ldexp(z, e), 0.0, 0); test2(atan2, -0.0, ldexp(z, e), -0.0, 0); test2(atan2, 0.0, ldexp(-z, e), (double)pi, FE_INEXACT); test2(atan2, -0.0, ldexp(-z, e), (double)-pi, FE_INEXACT); test2(atan2, ldexp(z, e), 0.0, (double)pi / 2, FE_INEXACT); test2(atan2, ldexp(z, e), -0.0, (double)pi / 2, FE_INEXACT); test2(atan2, ldexp(-z, e), 0.0, (double)-pi / 2, FE_INEXACT); test2(atan2, ldexp(-z, e), -0.0, (double)-pi / 2, FE_INEXACT); } for (e = LDBL_MIN_EXP - LDBL_MANT_DIG; e <= LDBL_MAX_EXP; e++) { test2(atan2l, 0.0, ldexpl(z, e), 0.0, 0); test2(atan2l, -0.0, ldexpl(z, e), -0.0, 0); test2(atan2l, 0.0, ldexpl(-z, e), pi, FE_INEXACT); test2(atan2l, -0.0, ldexpl(-z, e), -pi, FE_INEXACT); test2(atan2l, ldexpl(z, e), 0.0, pi / 2, FE_INEXACT); test2(atan2l, ldexpl(z, e), -0.0, pi / 2, FE_INEXACT); test2(atan2l, ldexpl(-z, e), 0.0, -pi / 2, FE_INEXACT); test2(atan2l, ldexpl(-z, e), -0.0, -pi / 2, FE_INEXACT); } /* Tests with one input in the range (0, Inf). */ for (e = FLT_MIN_EXP - FLT_MANT_DIG; e <= FLT_MAX_EXP - 1; e++) { test2(atan2f, ldexpf(z, e), INFINITY, 0.0, 0); test2(atan2f, ldexpf(-z,e), INFINITY, -0.0, 0); test2(atan2f, ldexpf(z, e), -INFINITY, (float)pi, FE_INEXACT); test2(atan2f, ldexpf(-z,e), -INFINITY, (float)-pi, FE_INEXACT); test2(atan2f, INFINITY, ldexpf(z,e), (float)pi/2, FE_INEXACT); test2(atan2f, INFINITY, ldexpf(-z,e), (float)pi/2, FE_INEXACT); test2(atan2f, -INFINITY, ldexpf(z,e), (float)-pi/2,FE_INEXACT); test2(atan2f, -INFINITY, ldexpf(-z,e),(float)-pi/2,FE_INEXACT); } for (e = DBL_MIN_EXP - DBL_MANT_DIG; e <= DBL_MAX_EXP - 1; e++) { test2(atan2, ldexp(z, e), INFINITY, 0.0, 0); test2(atan2, ldexp(-z,e), INFINITY, -0.0, 0); test2(atan2, ldexp(z, e), -INFINITY, (double)pi, FE_INEXACT); test2(atan2, ldexp(-z,e), -INFINITY, (double)-pi, FE_INEXACT); test2(atan2, INFINITY, ldexp(z,e), (double)pi/2, FE_INEXACT); test2(atan2, INFINITY, ldexp(-z,e), (double)pi/2, FE_INEXACT); test2(atan2, -INFINITY, ldexp(z,e), (double)-pi/2,FE_INEXACT); test2(atan2, -INFINITY, ldexp(-z,e),(double)-pi/2,FE_INEXACT); } for (e = LDBL_MIN_EXP - LDBL_MANT_DIG; e <= LDBL_MAX_EXP - 1; e++) { test2(atan2l, ldexpl(z, e), INFINITY, 0.0, 0); test2(atan2l, ldexpl(-z,e), INFINITY, -0.0, 0); test2(atan2l, ldexpl(z, e), -INFINITY, pi, FE_INEXACT); test2(atan2l, ldexpl(-z,e), -INFINITY, -pi, FE_INEXACT); test2(atan2l, INFINITY, ldexpl(z, e), pi / 2, FE_INEXACT); test2(atan2l, INFINITY, ldexpl(-z, e), pi / 2, FE_INEXACT); test2(atan2l, -INFINITY, ldexpl(z, e), -pi / 2, FE_INEXACT); test2(atan2l, -INFINITY, ldexpl(-z, e), -pi / 2, FE_INEXACT); } } /* * Test various inputs to asin(), acos() and atan() and verify that the * results are accurate to within 1 ulp. */ static void test_accuracy(void) { /* We expect correctly rounded results for these basic cases. */ testall(asin, 1.0, pi / 2, FE_INEXACT); testall(acos, 1.0, 0, 0); testall(atan, 1.0, pi / 4, FE_INEXACT); testall(asin, -1.0, -pi / 2, FE_INEXACT); testall(acos, -1.0, pi, FE_INEXACT); testall(atan, -1.0, -pi / 4, FE_INEXACT); /* * Here we expect answers to be within 1 ulp, although inexactness * in the input, combined with double rounding, could cause larger * errors. */ testall_tol(asin, sqrtl(2) / 2, pi / 4, 1, FE_INEXACT); testall_tol(acos, sqrtl(2) / 2, pi / 4, 1, FE_INEXACT); testall_tol(asin, -sqrtl(2) / 2, -pi / 4, 1, FE_INEXACT); testall_tol(acos, -sqrtl(2) / 2, c3pi / 4, 1, FE_INEXACT); testall_tol(asin, sqrtl(3) / 2, pio3, 1, FE_INEXACT); testall_tol(acos, sqrtl(3) / 2, pio3 / 2, 1, FE_INEXACT); testall_tol(atan, sqrtl(3), pio3, 1, FE_INEXACT); testall_tol(asin, -sqrtl(3) / 2, -pio3, 1, FE_INEXACT); testall_tol(acos, -sqrtl(3) / 2, c5pio3 / 2, 1, FE_INEXACT); testall_tol(atan, -sqrtl(3), -pio3, 1, FE_INEXACT); testall_tol(atan, sqrt2m1, pi / 8, 1, FE_INEXACT); testall_tol(atan, -sqrt2m1, -pi / 8, 1, FE_INEXACT); } /* * Test inputs to atan2() where x is a power of 2. These are easy cases * because y/x is exact. */ static void test_p2x_atan2(void) { testall2(atan2, 1.0, 1.0, pi / 4, FE_INEXACT); testall2(atan2, 1.0, -1.0, c3pi / 4, FE_INEXACT); testall2(atan2, -1.0, 1.0, -pi / 4, FE_INEXACT); testall2(atan2, -1.0, -1.0, -c3pi / 4, FE_INEXACT); testall2_tol(atan2, sqrt2m1 * 2, 2.0, pi / 8, 1, FE_INEXACT); testall2_tol(atan2, sqrt2m1 * 2, -2.0, c7pi / 8, 1, FE_INEXACT); testall2_tol(atan2, -sqrt2m1 * 2, 2.0, -pi / 8, 1, FE_INEXACT); testall2_tol(atan2, -sqrt2m1 * 2, -2.0, -c7pi / 8, 1, FE_INEXACT); testall2_tol(atan2, sqrtl(3) * 0.5, 0.5, pio3, 1, FE_INEXACT); testall2_tol(atan2, sqrtl(3) * 0.5, -0.5, pio3 * 2, 1, FE_INEXACT); testall2_tol(atan2, -sqrtl(3) * 0.5, 0.5, -pio3, 1, FE_INEXACT); testall2_tol(atan2, -sqrtl(3) * 0.5, -0.5, -pio3 * 2, 1, FE_INEXACT); } /* * Test inputs very close to 0. */ static void test_tiny(void) { float tiny = 0x1.23456p-120f; testall(asin, tiny, tiny, FE_INEXACT); testall(acos, tiny, pi / 2, FE_INEXACT); testall(atan, tiny, tiny, FE_INEXACT); testall(asin, -tiny, -tiny, FE_INEXACT); testall(acos, -tiny, pi / 2, FE_INEXACT); testall(atan, -tiny, -tiny, FE_INEXACT); /* Test inputs to atan2() that would cause y/x to underflow. */ test2(atan2f, 0x1.0p-100, 0x1.0p100, 0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2, 0x1.0p-1000, 0x1.0p1000, 0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2l, ldexpl(1.0, 100 - LDBL_MAX_EXP), ldexpl(1.0, LDBL_MAX_EXP - 100), 0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2f, -0x1.0p-100, 0x1.0p100, -0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2, -0x1.0p-1000, 0x1.0p1000, -0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2l, -ldexpl(1.0, 100 - LDBL_MAX_EXP), ldexpl(1.0, LDBL_MAX_EXP - 100), -0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2f, 0x1.0p-100, -0x1.0p100, (float)pi, FE_INEXACT); test2(atan2, 0x1.0p-1000, -0x1.0p1000, (double)pi, FE_INEXACT); test2(atan2l, ldexpl(1.0, 100 - LDBL_MAX_EXP), -ldexpl(1.0, LDBL_MAX_EXP - 100), pi, FE_INEXACT); test2(atan2f, -0x1.0p-100, -0x1.0p100, (float)-pi, FE_INEXACT); test2(atan2, -0x1.0p-1000, -0x1.0p1000, (double)-pi, FE_INEXACT); test2(atan2l, -ldexpl(1.0, 100 - LDBL_MAX_EXP), -ldexpl(1.0, LDBL_MAX_EXP - 100), -pi, FE_INEXACT); } /* * Test very large inputs to atan(). */ static void test_atan_huge(void) { float huge = 0x1.23456p120; testall(atan, huge, pi / 2, FE_INEXACT); testall(atan, -huge, -pi / 2, FE_INEXACT); /* Test inputs to atan2() that would cause y/x to overflow. */ test2(atan2f, 0x1.0p100, 0x1.0p-100, (float)pi / 2, FE_INEXACT); test2(atan2, 0x1.0p1000, 0x1.0p-1000, (double)pi / 2, FE_INEXACT); test2(atan2l, ldexpl(1.0, LDBL_MAX_EXP - 100), ldexpl(1.0, 100 - LDBL_MAX_EXP), pi / 2, FE_INEXACT); test2(atan2f, -0x1.0p100, 0x1.0p-100, (float)-pi / 2, FE_INEXACT); test2(atan2, -0x1.0p1000, 0x1.0p-1000, (double)-pi / 2, FE_INEXACT); test2(atan2l, -ldexpl(1.0, LDBL_MAX_EXP - 100), ldexpl(1.0, 100 - LDBL_MAX_EXP), -pi / 2, FE_INEXACT); test2(atan2f, 0x1.0p100, -0x1.0p-100, (float)pi / 2, FE_INEXACT); test2(atan2, 0x1.0p1000, -0x1.0p-1000, (double)pi / 2, FE_INEXACT); test2(atan2l, ldexpl(1.0, LDBL_MAX_EXP - 100), -ldexpl(1.0, 100 - LDBL_MAX_EXP), pi / 2, FE_INEXACT); test2(atan2f, -0x1.0p100, -0x1.0p-100, (float)-pi / 2, FE_INEXACT); test2(atan2, -0x1.0p1000, -0x1.0p-1000, (double)-pi / 2, FE_INEXACT); test2(atan2l, -ldexpl(1.0, LDBL_MAX_EXP - 100), -ldexpl(1.0, 100 - LDBL_MAX_EXP), -pi / 2, FE_INEXACT); } /* * Test that sin(asin(x)) == x, and similarly for acos() and atan(). * You need to have a working sinl(), cosl(), and tanl() for these * tests to pass. */ static long double sinasinf(float x) { return (sinl(asinf(x))); } static long double sinasin(double x) { return (sinl(asin(x))); } static long double sinasinl(long double x) { return (sinl(asinl(x))); } static long double cosacosf(float x) { return (cosl(acosf(x))); } static long double cosacos(double x) { return (cosl(acos(x))); } static long double cosacosl(long double x) { return (cosl(acosl(x))); } static long double tanatanf(float x) { return (tanl(atanf(x))); } static long double tanatan(double x) { return (tanl(atan(x))); } static long double tanatanl(long double x) { return (tanl(atanl(x))); } static void test_inverse(void) { float i; for (i = -1; i <= 1; i += 0x1.0p-12f) { testall_tol(sinasin, i, i, 2, i == 0 ? 0 : FE_INEXACT); /* The relative error for cosacos is very large near x=0. */ if (fabsf(i) > 0x1.0p-4f) testall_tol(cosacos, i, i, 16, i == 1 ? 0 : FE_INEXACT); testall_tol(tanatan, i, i, 2, i == 0 ? 0 : FE_INEXACT); } } int main(int argc, char *argv[]) { printf("1..7\n"); test_special(); printf("ok 1 - special\n"); test_special_atan2(); printf("ok 2 - atan2 special\n"); test_accuracy(); printf("ok 3 - accuracy\n"); test_p2x_atan2(); printf("ok 4 - atan2 p2x\n"); test_tiny(); printf("ok 5 - tiny inputs\n"); test_atan_huge(); printf("ok 6 - atan huge inputs\n"); test_inverse(); printf("ok 7 - inverse\n"); return (0); } Index: head/tools/regression/lib/msun/test-trig.c =================================================================== --- head/tools/regression/lib/msun/test-trig.c (revision 287296) +++ head/tools/regression/lib/msun/test-trig.c (revision 287297) @@ -1,280 +1,280 @@ /*- * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for corner cases in trigonometric functions. Some accuracy tests * are included as well, but these are very basic sanity checks, not * intended to be comprehensive. * * The program for generating representable numbers near multiples of pi is * available at http://www.cs.berkeley.edu/~wkahan/testpi/ . */ #include __FBSDID("$FreeBSD$"); +#include + #include #include #include #include #include #include "test-utils.h" -#define LEN(a) (sizeof(a) / sizeof((a)[0])) - #pragma STDC FENV_ACCESS ON /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several * reasons, but mainly because on some architectures it's impossible * to raise FE_OVERFLOW without raising FE_INEXACT. * * These are macros instead of functions so that assert provides more * meaningful error messages. * * XXX The volatile here is to avoid gcc's bogus constant folding and work * around the lack of support for the FENV_ACCESS pragma. */ #define test(func, x, result, exceptmask, excepts) do { \ volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) #define testall(prefix, x, result, exceptmask, excepts) do { \ test(prefix, x, (double)result, exceptmask, excepts); \ test(prefix##f, x, (float)result, exceptmask, excepts); \ test(prefix##l, x, result, exceptmask, excepts); \ } while (0) #define testdf(prefix, x, result, exceptmask, excepts) do { \ test(prefix, x, (double)result, exceptmask, excepts); \ test(prefix##f, x, (float)result, exceptmask, excepts); \ } while (0) /* * Test special cases in sin(), cos(), and tan(). */ static void run_special_tests(void) { /* Values at 0 should be exact. */ testall(tan, 0.0, 0.0, ALL_STD_EXCEPT, 0); testall(tan, -0.0, -0.0, ALL_STD_EXCEPT, 0); testall(cos, 0.0, 1.0, ALL_STD_EXCEPT, 0); testall(cos, -0.0, 1.0, ALL_STD_EXCEPT, 0); testall(sin, 0.0, 0.0, ALL_STD_EXCEPT, 0); testall(sin, -0.0, -0.0, ALL_STD_EXCEPT, 0); /* func(+-Inf) == NaN */ testall(tan, INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(sin, INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(cos, INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(tan, -INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(sin, -INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(cos, -INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); /* func(NaN) == NaN */ testall(tan, NAN, NAN, ALL_STD_EXCEPT, 0); testall(sin, NAN, NAN, ALL_STD_EXCEPT, 0); testall(cos, NAN, NAN, ALL_STD_EXCEPT, 0); } /* * Tests to ensure argument reduction for large arguments is accurate. */ static void run_reduction_tests(void) { /* floats very close to odd multiples of pi */ static const float f_pi_odd[] = { 85563208.0f, 43998769152.0f, 9.2763667655669323e+25f, 1.5458357838905804e+29f, }; /* doubles very close to odd multiples of pi */ static const double d_pi_odd[] = { 3.1415926535897931, 91.106186954104004, 642615.9188844458, 3397346.5699258847, 6134899525417045.0, 3.0213551960457761e+43, 1.2646209897993783e+295, 6.2083625380677099e+307, }; /* long doubles very close to odd multiples of pi */ #if LDBL_MANT_DIG == 64 static const long double ld_pi_odd[] = { 1.1891886960373841596e+101L, 1.07999475322710967206e+2087L, 6.522151627890431836e+2147L, 8.9368974898260328229e+2484L, 9.2961044110572205863e+2555L, 4.90208421886578286e+3189L, 1.5275546401232615884e+3317L, 1.7227465626338900093e+3565L, 2.4160090594000745334e+3808L, 9.8477555741888350649e+4314L, 1.6061597222105160737e+4326L, }; #elif LDBL_MANT_DIG == 113 static const long double ld_pi_odd[] = { /* XXX */ }; #endif int i; - for (i = 0; i < LEN(f_pi_odd); i++) { + for (i = 0; i < nitems(f_pi_odd); i++) { assert(fabs(sinf(f_pi_odd[i])) < FLT_EPSILON); assert(cosf(f_pi_odd[i]) == -1.0); assert(fabs(tan(f_pi_odd[i])) < FLT_EPSILON); assert(fabs(sinf(-f_pi_odd[i])) < FLT_EPSILON); assert(cosf(-f_pi_odd[i]) == -1.0); assert(fabs(tanf(-f_pi_odd[i])) < FLT_EPSILON); assert(fabs(sinf(f_pi_odd[i] * 2)) < FLT_EPSILON); assert(cosf(f_pi_odd[i] * 2) == 1.0); assert(fabs(tanf(f_pi_odd[i] * 2)) < FLT_EPSILON); assert(fabs(sinf(-f_pi_odd[i] * 2)) < FLT_EPSILON); assert(cosf(-f_pi_odd[i] * 2) == 1.0); assert(fabs(tanf(-f_pi_odd[i] * 2)) < FLT_EPSILON); } - for (i = 0; i < LEN(d_pi_odd); i++) { + for (i = 0; i < nitems(d_pi_odd); i++) { assert(fabs(sin(d_pi_odd[i])) < 2 * DBL_EPSILON); assert(cos(d_pi_odd[i]) == -1.0); assert(fabs(tan(d_pi_odd[i])) < 2 * DBL_EPSILON); assert(fabs(sin(-d_pi_odd[i])) < 2 * DBL_EPSILON); assert(cos(-d_pi_odd[i]) == -1.0); assert(fabs(tan(-d_pi_odd[i])) < 2 * DBL_EPSILON); assert(fabs(sin(d_pi_odd[i] * 2)) < 2 * DBL_EPSILON); assert(cos(d_pi_odd[i] * 2) == 1.0); assert(fabs(tan(d_pi_odd[i] * 2)) < 2 * DBL_EPSILON); assert(fabs(sin(-d_pi_odd[i] * 2)) < 2 * DBL_EPSILON); assert(cos(-d_pi_odd[i] * 2) == 1.0); assert(fabs(tan(-d_pi_odd[i] * 2)) < 2 * DBL_EPSILON); } #if LDBL_MANT_DIG > 53 - for (i = 0; i < LEN(ld_pi_odd); i++) { + for (i = 0; i < nitems(ld_pi_odd); i++) { assert(fabsl(sinl(ld_pi_odd[i])) < LDBL_EPSILON); assert(cosl(ld_pi_odd[i]) == -1.0); assert(fabsl(tanl(ld_pi_odd[i])) < LDBL_EPSILON); assert(fabsl(sinl(-ld_pi_odd[i])) < LDBL_EPSILON); assert(cosl(-ld_pi_odd[i]) == -1.0); assert(fabsl(tanl(-ld_pi_odd[i])) < LDBL_EPSILON); assert(fabsl(sinl(ld_pi_odd[i] * 2)) < LDBL_EPSILON); assert(cosl(ld_pi_odd[i] * 2) == 1.0); assert(fabsl(tanl(ld_pi_odd[i] * 2)) < LDBL_EPSILON); assert(fabsl(sinl(-ld_pi_odd[i] * 2)) < LDBL_EPSILON); assert(cosl(-ld_pi_odd[i] * 2) == 1.0); assert(fabsl(tanl(-ld_pi_odd[i] * 2)) < LDBL_EPSILON); } #endif } /* * Tests the accuracy of these functions over the primary range. */ static void run_accuracy_tests(void) { /* For small args, sin(x) = tan(x) = x, and cos(x) = 1. */ testall(sin, 0xd.50ee515fe4aea16p-114L, 0xd.50ee515fe4aea16p-114L, ALL_STD_EXCEPT, FE_INEXACT); testall(tan, 0xd.50ee515fe4aea16p-114L, 0xd.50ee515fe4aea16p-114L, ALL_STD_EXCEPT, FE_INEXACT); testall(cos, 0xd.50ee515fe4aea16p-114L, 1.0, ALL_STD_EXCEPT, FE_INEXACT); /* * These tests should pass for f32, d64, and ld80 as long as * the error is <= 0.75 ulp (round to nearest) */ #if LDBL_MANT_DIG <= 64 #define testacc testall #else #define testacc testdf #endif testacc(sin, 0.17255452780841205174L, 0.17169949801444412683L, ALL_STD_EXCEPT, FE_INEXACT); testacc(sin, -0.75431944555904520893L, -0.68479288156557286353L, ALL_STD_EXCEPT, FE_INEXACT); testacc(cos, 0.70556358769838947292L, 0.76124620693117771850L, ALL_STD_EXCEPT, FE_INEXACT); testacc(cos, -0.34061437849088045332L, 0.94254960031831729956L, ALL_STD_EXCEPT, FE_INEXACT); testacc(tan, -0.15862817413325692897L, -0.15997221861309522115L, ALL_STD_EXCEPT, FE_INEXACT); testacc(tan, 0.38374784931303813530L, 0.40376500259976759951L, ALL_STD_EXCEPT, FE_INEXACT); /* * XXX missing: * - tests for ld128 * - tests for other rounding modes (probably won't pass for now) * - tests for large numbers that get reduced to hi+lo with lo!=0 */ } int main(int argc, char *argv[]) { printf("1..3\n"); run_special_tests(); printf("ok 1 - trig\n"); #ifndef __i386__ run_reduction_tests(); #endif printf("ok 2 - trig\n"); #ifndef __i386__ run_accuracy_tests(); #endif printf("ok 3 - trig\n"); return (0); } Index: head/tools/regression/p1003_1b/main.c =================================================================== --- head/tools/regression/p1003_1b/main.c (revision 287296) +++ head/tools/regression/p1003_1b/main.c (revision 287297) @@ -1,79 +1,80 @@ /* $FreeBSD$ */ + +#include + #include #include int fifo(int argc, char *argv[]); int memlock(int argc, char *argv[]); int p26(int argc, char *argv[]); int sched(int argc, char *argv[]); int yield(int argc, char *argv[]); static struct { const char *t; int (*f)(int, char *[]); int works; } tab[] = { { "fifo", fifo, 1 }, { "memlock", memlock, 0 }, { "p26", p26, 1 }, { "sched", sched, 1 }, { "yield", yield, 1 }, }; -#define N(T) (sizeof (T)/ sizeof(T[0])) - static int usage(int argc, char *argv[]) { int i; if (argc > 1) fprintf(stderr, "%s is unknown\n", argv[1]); fprintf(stderr, "usage: %s [-a] or one of [", argv[0]); for (i = 0; i < (sizeof(tab) / sizeof(tab[0])); i++) fprintf(stderr, "%s%s", (i)? " | " : "", tab[i].t); fprintf(stderr, "]\n"); return -1; } int main(int argc, char *argv[]) { int i; if (argc == 2 && strcmp(argv[1], "-a") == 0) { #if 1 fprintf(stderr, "-a should but doesn't really work" " (my notes say \"because things detach\");\n" "meanwhile do these individual tests and look" " for a non-zero exit code:\n"); - for (i = 0; i < N(tab); i++) + for (i = 0; i < nitems(tab); i++) if (tab[i].works) fprintf(stderr, "p1003_1b %s\n", tab[i].t); return -1; #else { int r; - for (i = 0; i < N(tab); i++) { + for (i = 0; i < nitems(tab); i++) { if (tab[i].works) { if ( (r = (*tab[i].f)(argc - 1, argv + 1)) ) { fprintf(stderr, "%s failed\n", tab[i].t); return r; } } } return 0; } #endif } if (argc > 1) { - for (i = 0; i < N(tab); i++) + for (i = 0; i < nitems(tab); i++) if (strcmp(tab[i].t, argv[1]) == 0) return (*tab[i].f)(argc - 1, argv + 1); } return usage(argc, argv); } Index: head/tools/tools/ath/athaggrstats/athaggrstats.c =================================================================== --- head/tools/tools/ath/athaggrstats/athaggrstats.c (revision 287296) +++ head/tools/tools/ath/athaggrstats/athaggrstats.c (revision 287297) @@ -1,404 +1,404 @@ /*- * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ +#include + #include "opt_ah.h" /* * ath statistics class. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ah.h" #include "ah_desc.h" #include "net80211/ieee80211_ioctl.h" #include "net80211/ieee80211_radiotap.h" #include "if_athioctl.h" #include "athaggrstats.h" #define NOTPRESENT { 0, "", "" } #define AFTER(prev) ((prev)+1) static const struct fmt athaggrstats[] = { #define S_SINGLE_PKT 0 { 4, "singlepkt", "spkt", "single frames scheduled" }, #define S_NONBAW_PKT AFTER(S_SINGLE_PKT) { 5, "nonbawpkt", "nbpkt", "frames outside of the BAW" }, #define S_AGGR_PKT AFTER(S_NONBAW_PKT) { 6, "aggrpkt", "aggpkt", "aggregate frames scheduled" }, #define S_BAW_CLOSED_SINGLE_PKT AFTER(S_AGGR_PKT) { 8, "bawclosedpkt", "bawclpkt", "single frames due to closed BAW" }, #define S_LOW_HWQ_SINGLE_PKT AFTER(S_BAW_CLOSED_SINGLE_PKT) { 6, "lhsinglepkt", "lhspkt", "single frames scheduled due to low HWQ depth" }, #define S_SCHED_NOPKT AFTER(S_LOW_HWQ_SINGLE_PKT) { 6, "schednopkt", "snopkt", "sched called with no frames" }, #define S_RTS_AGGR_LIMITED AFTER(S_SCHED_NOPKT) { 8, "rtsaggrlimit", "rtslimit", "RTS limited aggregates" }, #define S_PKT0 AFTER(S_RTS_AGGR_LIMITED) { 2, "p0", "p0", "" }, #define S_PKT1 AFTER(S_PKT0) { 2, "p1", "p1", "" }, #define S_PKT2 AFTER(S_PKT1) { 2, "p2", "p2", "" }, #define S_PKT3 AFTER(S_PKT2) { 2, "p3", "p3", "" }, #define S_PKT4 AFTER(S_PKT3) { 2, "p4", "p4", "" }, #define S_PKT5 AFTER(S_PKT4) { 2, "p5", "p5", "" }, #define S_PKT6 AFTER(S_PKT5) { 2, "p6", "p6", "" }, #define S_PKT7 AFTER(S_PKT6) { 2, "p7", "p7", "" }, #define S_PKT8 AFTER(S_PKT7) { 2, "p8", "p8", "" }, #define S_PKT9 AFTER(S_PKT8) { 2, "p9", "p9", "" }, #define S_PKT10 AFTER(S_PKT9) { 3, "p10", "p10", "" }, #define S_PKT11 AFTER(S_PKT10) { 3, "p11", "p11", "" }, #define S_PKT12 AFTER(S_PKT11) { 3, "p12", "p12", "" }, #define S_PKT13 AFTER(S_PKT12) { 3, "p13", "p13", "" }, #define S_PKT14 AFTER(S_PKT13) { 3, "p14", "p14", "" }, #define S_PKT15 AFTER(S_PKT14) { 3, "p15", "p15", "" }, #define S_PKT16 AFTER(S_PKT15) { 3, "p16", "p16", "" }, #define S_PKT17 AFTER(S_PKT16) { 3, "p17", "p17", "" }, #define S_PKT18 AFTER(S_PKT17) { 3, "p18", "p18", "" }, #define S_PKT19 AFTER(S_PKT18) { 3, "p19", "p19", "" }, #define S_PKT20 AFTER(S_PKT19) { 3, "p20", "p20", "" }, #define S_PKT21 AFTER(S_PKT20) { 3, "p21", "p21", "" }, #define S_PKT22 AFTER(S_PKT21) { 3, "p22", "p22", "" }, #define S_PKT23 AFTER(S_PKT22) { 3, "p23", "p23", "" }, #define S_PKT24 AFTER(S_PKT23) { 3, "p24", "p24", "" }, #define S_PKT25 AFTER(S_PKT24) { 3, "p25", "p25", "" }, #define S_PKT26 AFTER(S_PKT25) { 3, "p26", "p26", "" }, #define S_PKT27 AFTER(S_PKT26) { 3, "p27", "p27", "" }, #define S_PKT28 AFTER(S_PKT27) { 3, "p28", "p28", "" }, #define S_PKT29 AFTER(S_PKT28) { 3, "p29", "p29", "" }, #define S_PKT30 AFTER(S_PKT29) { 3, "p30", "p30", "" }, #define S_PKT31 AFTER(S_PKT30) { 3, "p31", "p31", "" }, }; #define S_LAST S_RTS_AGGR_LIMITED #define S_MAX (S_PKT31 + 1) struct athaggrstatfoo_p { struct athaggrstatfoo base; int s; int optstats; struct ifreq ifr; struct ath_diag atd; struct ath_tx_aggr_stats cur; struct ath_tx_aggr_stats total; }; static void ath_setifname(struct athaggrstatfoo *wf0, const char *ifname) { struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) wf0; strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name)); } static void ath_zerostats(struct athaggrstatfoo *wf0) { #if 0 struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) wf0; if (ioctl(wf->s, SIOCZATHSTATS, &wf->ifr) < 0) err(-1, wf->ifr.ifr_name); #endif } static void ath_collect(struct athaggrstatfoo_p *wf, struct ath_tx_aggr_stats *stats) { wf->ifr.ifr_data = (caddr_t) stats; if (ioctl(wf->s, SIOCGATHAGSTATS, &wf->ifr) < 0) err(1, "%s: ioctl: %s", __func__, wf->ifr.ifr_name); } static void ath_collect_cur(struct bsdstat *sf) { struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf; ath_collect(wf, &wf->cur); } static void ath_collect_tot(struct bsdstat *sf) { struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf; ath_collect(wf, &wf->total); } static void ath_update_tot(struct bsdstat *sf) { struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf; wf->total = wf->cur; } static void snprintrate(char b[], size_t bs, int rate) { if (rate & IEEE80211_RATE_MCS) snprintf(b, bs, "MCS%u", rate &~ IEEE80211_RATE_MCS); else if (rate & 1) snprintf(b, bs, "%u.5M", rate / 2); else snprintf(b, bs, "%uM", rate / 2); } static int ath_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->cur.aggr_##x - wf->total.aggr_##x); return 1 #define PKT(x) \ snprintf(b, bs, "%u", wf->cur.aggr_pkts[x] - wf->total.aggr_pkts[x]); return 1 switch (s) { case S_SINGLE_PKT: STAT(single_pkt); case S_NONBAW_PKT: STAT(nonbaw_pkt); case S_AGGR_PKT: STAT(aggr_pkt); case S_BAW_CLOSED_SINGLE_PKT: STAT(baw_closed_single_pkt); case S_LOW_HWQ_SINGLE_PKT: STAT(low_hwq_single_pkt); case S_SCHED_NOPKT: STAT(sched_nopkt); case S_RTS_AGGR_LIMITED: STAT(rts_aggr_limited); case S_PKT0: PKT(0); case S_PKT1: PKT(1); case S_PKT2: PKT(2); case S_PKT3: PKT(3); case S_PKT4: PKT(4); case S_PKT5: PKT(5); case S_PKT6: PKT(6); case S_PKT7: PKT(7); case S_PKT8: PKT(8); case S_PKT9: PKT(9); case S_PKT10: PKT(10); case S_PKT11: PKT(11); case S_PKT12: PKT(12); case S_PKT13: PKT(13); case S_PKT14: PKT(14); case S_PKT15: PKT(15); case S_PKT16: PKT(16); case S_PKT17: PKT(17); case S_PKT18: PKT(18); case S_PKT19: PKT(19); case S_PKT20: PKT(20); case S_PKT21: PKT(21); case S_PKT22: PKT(22); case S_PKT23: PKT(23); case S_PKT24: PKT(24); case S_PKT25: PKT(25); case S_PKT26: PKT(26); case S_PKT27: PKT(27); case S_PKT28: PKT(28); case S_PKT29: PKT(29); case S_PKT30: PKT(30); case S_PKT31: PKT(31); } b[0] = '\0'; return 0; #undef PKT #undef STAT } static int ath_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->total.aggr_##x); return 1 #define PKT(x) \ snprintf(b, bs, "%u", wf->total.aggr_pkts[x]); return 1 switch (s) { case S_SINGLE_PKT: STAT(single_pkt); case S_NONBAW_PKT: STAT(nonbaw_pkt); case S_AGGR_PKT: STAT(aggr_pkt); case S_BAW_CLOSED_SINGLE_PKT: STAT(baw_closed_single_pkt); case S_LOW_HWQ_SINGLE_PKT: STAT(low_hwq_single_pkt); case S_SCHED_NOPKT: STAT(sched_nopkt); case S_RTS_AGGR_LIMITED: STAT(rts_aggr_limited); case S_PKT0: PKT(0); case S_PKT1: PKT(1); case S_PKT2: PKT(2); case S_PKT3: PKT(3); case S_PKT4: PKT(4); case S_PKT5: PKT(5); case S_PKT6: PKT(6); case S_PKT7: PKT(7); case S_PKT8: PKT(8); case S_PKT9: PKT(9); case S_PKT10: PKT(10); case S_PKT11: PKT(11); case S_PKT12: PKT(12); case S_PKT13: PKT(13); case S_PKT14: PKT(14); case S_PKT15: PKT(15); case S_PKT16: PKT(16); case S_PKT17: PKT(17); case S_PKT18: PKT(18); case S_PKT19: PKT(19); case S_PKT20: PKT(20); case S_PKT21: PKT(21); case S_PKT22: PKT(22); case S_PKT23: PKT(23); case S_PKT24: PKT(24); case S_PKT25: PKT(25); case S_PKT26: PKT(26); case S_PKT27: PKT(27); case S_PKT28: PKT(28); case S_PKT29: PKT(29); case S_PKT30: PKT(30); case S_PKT31: PKT(31); } b[0] = '\0'; return 0; #undef PKT #undef STAT } static void ath_print_verbose(struct bsdstat *sf, FILE *fd) { struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf; const struct fmt *f; char s[32]; const char *indent; int i, width; width = 0; for (i = 0; i < S_LAST; i++) { f = &sf->stats[i]; if (f->width > width) width = f->width; } for (i = 0; i < S_LAST; i++) { if (ath_get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) { indent = ""; fprintf(fd, "%s%-*s %s\n", indent, width, s, athaggrstats[i].desc); } } fprintf(fd, "\nAggregate size profile:\n\n"); for (i = 0; i < 64; i++) { fprintf(fd, "%2d: %12u%s", i, wf->total.aggr_pkts[i], (i % 4 == 3) ? "\n" : " "); } fprintf(fd, "\n"); } BSDSTAT_DEFINE_BOUNCE(athaggrstatfoo) struct athaggrstatfoo * athaggrstats_new(const char *ifname, const char *fmtstring) { -#define N(a) (sizeof(a) / sizeof(a[0])) struct athaggrstatfoo_p *wf; wf = calloc(1, sizeof(struct athaggrstatfoo_p)); if (wf != NULL) { bsdstat_init(&wf->base.base, "athaggrstats", - athaggrstats, N(athaggrstats)); + athaggrstats, nitems(athaggrstats)); /* override base methods */ wf->base.base.collect_cur = ath_collect_cur; wf->base.base.collect_tot = ath_collect_tot; wf->base.base.get_curstat = ath_get_curstat; wf->base.base.get_totstat = ath_get_totstat; wf->base.base.update_tot = ath_update_tot; wf->base.base.print_verbose = ath_print_verbose; /* setup bounce functions for public methods */ BSDSTAT_BOUNCE(wf, athaggrstatfoo); /* setup our public methods */ wf->base.setifname = ath_setifname; #if 0 wf->base.setstamac = wlan_setstamac; #endif wf->base.zerostats = ath_zerostats; wf->s = socket(AF_INET, SOCK_DGRAM, 0); if (wf->s < 0) err(1, "socket"); ath_setifname(&wf->base, ifname); wf->base.setfmt(&wf->base, fmtstring); } return &wf->base; -#undef N } Index: head/tools/tools/ath/athaggrstats/main.c =================================================================== --- head/tools/tools/ath/athaggrstats/main.c (revision 287296) +++ head/tools/tools/ath/athaggrstats/main.c (revision 287297) @@ -1,159 +1,159 @@ /*- * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * 2012, Adrian Chadd * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * Simple Atheros-specific tool to inspect and monitor software queue * and aggregate statistics. * * athaggrstats [-i interface] [-bz] [-l] [-o fmtstring] [interval] * * (default interface is ath0). If interval is specified a rolling output * a la netstat -i is displayed every interval seconds. The format of * the rolling display can be controlled a la ps. The -l option will * print a list of all possible statistics for use with the -o option. */ +#include + +#include +#include #include #include -#include -#include #include -#include +#include #include "athaggrstats.h" static struct { const char *tag; const char *fmt; } tags[] = { { "default", "singlepkt,nonbawpkt,aggrpkt,bawclosedpkt,lhsinglepkt,schednopkt,rtsaggrlimit" }, }; static const char * getfmt(const char *tag) { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; - for (i = 0; i < N(tags); i++) + for (i = 0; i < nitems(tags); i++) if (strcasecmp(tags[i].tag, tag) == 0) return tags[i].fmt; return tag; -#undef N } static int signalled; static void catchalarm(int signo __unused) { signalled = 1; } int main(int argc, char *argv[]) { struct athaggrstatfoo *wf; const char *ifname; int c, banner = 1; ifname = getenv("ATH"); if (ifname == NULL) ifname = "ath0"; wf = athaggrstats_new(ifname, getfmt("default")); while ((c = getopt(argc, argv, "bi:lo:z")) != -1) { switch (c) { case 'b': banner = 0; break; case 'i': wf->setifname(wf, optarg); break; case 'l': wf->print_fields(wf, stdout); return 0; case 'o': wf->setfmt(wf, getfmt(optarg)); break; case 'z': wf->zerostats(wf); break; default: errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] [-z] [interval]\n", argv[0]); /*NOTREACHED*/ } } argc -= optind; argv += optind; if (argc > 0) { u_long interval = strtoul(argv[0], NULL, 0); int line, omask; if (interval < 1) interval = 1; signal(SIGALRM, catchalarm); signalled = 0; alarm(interval); banner: if (banner) wf->print_header(wf, stdout); line = 0; loop: if (line != 0) { wf->collect_cur(wf); wf->print_current(wf, stdout); wf->update_tot(wf); } else { wf->collect_tot(wf); wf->print_total(wf, stdout); } fflush(stdout); omask = sigblock(sigmask(SIGALRM)); if (!signalled) sigpause(0); sigsetmask(omask); signalled = 0; alarm(interval); line++; if (line == 21) /* XXX tty line count */ goto banner; else goto loop; /*NOTREACHED*/ } else { wf->collect_tot(wf); wf->print_verbose(wf, stdout); } return 0; } Index: head/tools/tools/ath/athdebug/athdebug.c =================================================================== --- head/tools/tools/ath/athdebug/athdebug.c (revision 287296) +++ head/tools/tools/ath/athdebug/athdebug.c (revision 287297) @@ -1,231 +1,230 @@ /*- * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * athdebug [-i interface] flags * (default interface is ath0). */ -#include + +#include #include #include #include #include -#include #include +#include #include +#include #include #include #include -#include -#define N(a) (sizeof(a)/sizeof(a[0])) - const char *progname; /* XXX TODO: include if_ath_debug.h */ enum { ATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ ATH_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */ ATH_DEBUG_RECV = 0x00000004, /* basic recv operation */ ATH_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */ ATH_DEBUG_RATE = 0x00000010, /* rate control */ ATH_DEBUG_RESET = 0x00000020, /* reset processing */ ATH_DEBUG_MODE = 0x00000040, /* mode init/setup */ ATH_DEBUG_BEACON = 0x00000080, /* beacon handling */ ATH_DEBUG_WATCHDOG = 0x00000100, /* watchdog timeout */ ATH_DEBUG_INTR = 0x00001000, /* ISR */ ATH_DEBUG_TX_PROC = 0x00002000, /* tx ISR proc */ ATH_DEBUG_RX_PROC = 0x00004000, /* rx ISR proc */ ATH_DEBUG_BEACON_PROC = 0x00008000, /* beacon ISR proc */ ATH_DEBUG_CALIBRATE = 0x00010000, /* periodic calibration */ ATH_DEBUG_KEYCACHE = 0x00020000, /* key cache management */ ATH_DEBUG_STATE = 0x00040000, /* 802.11 state transitions */ ATH_DEBUG_NODE = 0x00080000, /* node management */ ATH_DEBUG_LED = 0x00100000, /* led management */ ATH_DEBUG_FF = 0x00200000, /* fast frames */ ATH_DEBUG_DFS = 0x00400000, /* DFS processing */ ATH_DEBUG_TDMA = 0x00800000, /* TDMA processing */ ATH_DEBUG_TDMA_TIMER = 0x01000000, /* TDMA timer processing */ ATH_DEBUG_REGDOMAIN = 0x02000000, /* regulatory processing */ ATH_DEBUG_FATAL = 0x80000000, /* fatal errors */ ATH_DEBUG_ANY = 0xffffffff }; static struct { const char *name; uint64_t bit; } flags[] = { { "xmit", ATH_DEBUG_XMIT }, { "xmit_desc", ATH_DEBUG_XMIT_DESC }, { "recv", ATH_DEBUG_RECV }, { "recv_desc", ATH_DEBUG_RECV_DESC }, { "rate", ATH_DEBUG_RATE }, { "reset", ATH_DEBUG_RESET }, { "mode", ATH_DEBUG_MODE }, { "beacon", ATH_DEBUG_BEACON }, { "watchdog", ATH_DEBUG_WATCHDOG }, { "intr", ATH_DEBUG_INTR }, { "xmit_proc", ATH_DEBUG_TX_PROC }, { "recv_proc", ATH_DEBUG_RX_PROC }, { "beacon_proc",ATH_DEBUG_BEACON_PROC }, { "calibrate", ATH_DEBUG_CALIBRATE }, { "keycache", ATH_DEBUG_KEYCACHE }, { "state", ATH_DEBUG_STATE }, { "node", ATH_DEBUG_NODE }, { "led", ATH_DEBUG_LED }, { "ff", ATH_DEBUG_FF }, { "dfs", ATH_DEBUG_DFS }, { "tdma", ATH_DEBUG_TDMA }, { "tdma_timer", ATH_DEBUG_TDMA_TIMER }, { "regdomain", ATH_DEBUG_REGDOMAIN }, { "fatal", ATH_DEBUG_FATAL }, }; static uint64_t getflag(const char *name, int len) { int i; - for (i = 0; i < N(flags); i++) + for (i = 0; i < nitems(flags); i++) if (strncasecmp(flags[i].name, name, len) == 0) return flags[i].bit; return 0; } static const char * getflagname(u_int flag) { int i; - for (i = 0; i < N(flags); i++) + for (i = 0; i < nitems(flags); i++) if (flags[i].bit == flag) return flags[i].name; return "???"; } static void usage(void) { int i; fprintf(stderr, "usage: %s [-i device] [flags]\n", progname); fprintf(stderr, "where flags are:\n"); - for (i = 0; i < N(flags); i++) + for (i = 0; i < nitems(flags); i++) printf("%s\n", flags[i].name); exit(-1); } int main(int argc, char *argv[]) { const char *ifname; const char *cp, *tp; const char *sep; int c, op, i; uint64_t debug, ndebug; size_t debuglen; char oid[256]; ifname = getenv("ATH"); if (ifname == NULL) ifname = "ath0"; progname = argv[0]; if (argc > 1) { if (strcmp(argv[1], "-i") == 0) { if (argc < 2) errx(1, "missing interface name for -i option"); ifname = argv[2]; if (strncmp(ifname, "ath", 3) != 0) errx(2, "huh, this is for ath devices?"); argc -= 2, argv += 2; } else if (strcmp(argv[1], "-?") == 0) usage(); } #ifdef __linux__ snprintf(oid, sizeof(oid), "dev.%s.debug", ifname); #else snprintf(oid, sizeof(oid), "dev.ath.%s.debug", ifname+3); #endif debuglen = sizeof(debug); if (sysctlbyname(oid, &debug, &debuglen, NULL, 0) < 0) err(1, "sysctl-get(%s)", oid); ndebug = debug; for (; argc > 1; argc--, argv++) { cp = argv[1]; do { u_int bit; if (*cp == '-') { cp++; op = -1; } else if (*cp == '+') { cp++; op = 1; } else op = 0; for (tp = cp; *tp != '\0' && *tp != '+' && *tp != '-';) tp++; bit = getflag(cp, tp-cp); if (op < 0) ndebug &= ~bit; else if (op > 0) ndebug |= bit; else { if (bit == 0) { if (isdigit(*cp)) bit = strtoul(cp, NULL, 0); else errx(1, "unknown flag %.*s", (int) (tp-cp), cp); } ndebug = bit; } } while (*(cp = tp) != '\0'); } if (debug != ndebug) { printf("%s: 0x%llx => ", oid, (long long) debug); if (sysctlbyname(oid, NULL, NULL, &ndebug, sizeof(ndebug)) < 0) err(1, "sysctl-set(%s)", oid); printf("0x%llx", (long long) ndebug); debug = ndebug; } else printf("%s: 0x%llx", oid, (long long) debug); sep = "<"; - for (i = 0; i < N(flags); i++) + for (i = 0; i < nitems(flags); i++) if (debug & flags[i].bit) { printf("%s%s", sep, flags[i].name); sep = ","; } printf("%s\n", *sep != '<' ? ">" : ""); return 0; } Index: head/tools/tools/ath/athrd/athrd.c =================================================================== --- head/tools/tools/ath/athrd/athrd.c (revision 287296) +++ head/tools/tools/ath/athrd/athrd.c (revision 287297) @@ -1,1673 +1,1661 @@ /*- * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ #include "opt_ah.h" #include "ah.h" +#include + #include #include #include "ah_internal.h" #include "ah_eeprom_v3.h" /* XXX */ +#include +#include #include #include -#include #include #include -#include int ath_hal_debug = 0; HAL_CTRY_CODE cc = CTRY_DEFAULT; HAL_REG_DOMAIN rd = 169; /* FCC */ HAL_BOOL Amode = 1; HAL_BOOL Bmode = 1; HAL_BOOL Gmode = 1; HAL_BOOL HT20mode = 1; HAL_BOOL HT40mode = 1; HAL_BOOL turbo5Disable = AH_FALSE; HAL_BOOL turbo2Disable = AH_FALSE; u_int16_t _numCtls = 8; u_int16_t _ctl[32] = { 0x10, 0x13, 0x40, 0x30, 0x11, 0x31, 0x12, 0x32 }; RD_EDGES_POWER _rdEdgesPower[NUM_EDGES*NUM_CTLS] = { { 5180, 28, 0 }, /* 0x10 */ { 5240, 60, 0 }, { 5260, 36, 0 }, { 5320, 27, 0 }, { 5745, 36, 0 }, { 5765, 36, 0 }, { 5805, 36, 0 }, { 5825, 36, 0 }, { 5210, 28, 0 }, /* 0x13 */ { 5250, 28, 0 }, { 5290, 30, 0 }, { 5760, 36, 0 }, { 5800, 36, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 5170, 60, 0 }, /* 0x40 */ { 5230, 60, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 5180, 33, 0 }, /* 0x30 */ { 5320, 33, 0 }, { 5500, 34, 0 }, { 5700, 34, 0 }, { 5745, 35, 0 }, { 5765, 35, 0 }, { 5785, 35, 0 }, { 5825, 35, 0 }, { 2412, 36, 0 }, /* 0x11 */ { 2417, 36, 0 }, { 2422, 36, 0 }, { 2432, 36, 0 }, { 2442, 36, 0 }, { 2457, 36, 0 }, { 2467, 36, 0 }, { 2472, 36, 0 }, { 2412, 36, 0 }, /* 0x31 */ { 2417, 36, 0 }, { 2422, 36, 0 }, { 2432, 36, 0 }, { 2442, 36, 0 }, { 2457, 36, 0 }, { 2467, 36, 0 }, { 2472, 36, 0 }, { 2412, 36, 0 }, /* 0x12 */ { 2417, 36, 0 }, { 2422, 36, 0 }, { 2432, 36, 0 }, { 2442, 36, 0 }, { 2457, 36, 0 }, { 2467, 36, 0 }, { 2472, 36, 0 }, { 2412, 28, 0 }, /* 0x32 */ { 2417, 28, 0 }, { 2422, 28, 0 }, { 2432, 28, 0 }, { 2442, 28, 0 }, { 2457, 28, 0 }, { 2467, 28, 0 }, { 2472, 28, 0 }, }; u_int16_t turbo2WMaxPower5 = 32; u_int16_t turbo2WMaxPower2; int8_t antennaGainMax[2] = { 0, 0 }; /* XXX */ int eeversion = AR_EEPROM_VER3_1; TRGT_POWER_ALL_MODES tpow = { 8, { { 22, 24, 28, 32, 5180 }, { 22, 24, 28, 32, 5200 }, { 22, 24, 28, 32, 5320 }, { 26, 30, 34, 34, 5500 }, { 26, 30, 34, 34, 5700 }, { 20, 30, 34, 36, 5745 }, { 20, 30, 34, 36, 5825 }, { 20, 30, 34, 36, 5850 }, }, 2, { { 23, 27, 31, 34, 2412 }, { 23, 27, 31, 34, 2447 }, }, 2, { { 36, 36, 36, 36, 2412 }, { 36, 36, 36, 36, 2484 }, } }; #define numTargetPwr_11a tpow.numTargetPwr_11a #define trgtPwr_11a tpow.trgtPwr_11a #define numTargetPwr_11g tpow.numTargetPwr_11g #define trgtPwr_11g tpow.trgtPwr_11g #define numTargetPwr_11b tpow.numTargetPwr_11b #define trgtPwr_11b tpow.trgtPwr_11b static HAL_BOOL getChannelEdges(struct ath_hal *ah, u_int16_t flags, u_int16_t *low, u_int16_t *high) { struct ath_hal_private *ahp = AH_PRIVATE(ah); HAL_CAPABILITIES *pCap = &ahp->ah_caps; if (flags & IEEE80211_CHAN_5GHZ) { *low = pCap->halLow5GhzChan; *high = pCap->halHigh5GhzChan; return AH_TRUE; } if (flags & IEEE80211_CHAN_2GHZ) { *low = pCap->halLow2GhzChan; *high = pCap->halHigh2GhzChan; return AH_TRUE; } return AH_FALSE; } static u_int getWirelessModes(struct ath_hal *ah) { u_int mode = 0; if (Amode) { mode = HAL_MODE_11A; if (!turbo5Disable) mode |= HAL_MODE_TURBO; } if (Bmode) mode |= HAL_MODE_11B; if (Gmode) { mode |= HAL_MODE_11G; if (!turbo2Disable) mode |= HAL_MODE_108G; } if (HT20mode) mode |= HAL_MODE_11NG_HT20|HAL_MODE_11NA_HT20; if (HT40mode) mode |= HAL_MODE_11NG_HT40PLUS|HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NG_HT40MINUS|HAL_MODE_11NA_HT40MINUS ; return mode; } /* Enumerated Regulatory Domain Information 8 bit values indicate that * the regdomain is really a pair of unitary regdomains. 12 bit values * are the real unitary regdomains and are the only ones which have the * frequency bitmasks and flags set. */ enum EnumRd { /* * The following regulatory domain definitions are * found in the EEPROM. Each regulatory domain * can operate in either a 5GHz or 2.4GHz wireless mode or * both 5GHz and 2.4GHz wireless modes. * In general, the value holds no special * meaning and is used to decode into either specific * 2.4GHz or 5GHz wireless mode for that particular * regulatory domain. */ NO_ENUMRD = 0x00, NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */ NULL1_ETSIB = 0x07, /* Israel */ NULL1_ETSIC = 0x08, FCC1_FCCA = 0x10, /* USA */ FCC1_WORLD = 0x11, /* Hong Kong */ FCC4_FCCA = 0x12, /* USA - Public Safety */ FCC2_FCCA = 0x20, /* Canada */ FCC2_WORLD = 0x21, /* Australia & HK */ FCC2_ETSIC = 0x22, FRANCE_RES = 0x31, /* Legacy France for OEM */ FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ ETSI1_WORLD = 0x37, ETSI3_ETSIA = 0x32, /* France (optional) */ ETSI2_WORLD = 0x35, /* Hungary & others */ ETSI3_WORLD = 0x36, /* France & others */ ETSI4_WORLD = 0x30, ETSI4_ETSIC = 0x38, ETSI5_WORLD = 0x39, ETSI6_WORLD = 0x34, /* Bulgaria */ ETSI_RESERVED = 0x33, /* Reserved (Do not used) */ MKK1_MKKA = 0x40, /* Japan (JP1) */ MKK1_MKKB = 0x41, /* Japan (JP0) */ APL4_WORLD = 0x42, /* Singapore */ MKK2_MKKA = 0x43, /* Japan with 4.9G channels */ APL_RESERVED = 0x44, /* Reserved (Do not used) */ APL2_WORLD = 0x45, /* Korea */ APL2_APLC = 0x46, APL3_WORLD = 0x47, MKK1_FCCA = 0x48, /* Japan (JP1-1) */ APL2_APLD = 0x49, /* Korea with 2.3G channels */ MKK1_MKKA1 = 0x4A, /* Japan (JE1) */ MKK1_MKKA2 = 0x4B, /* Japan (JE2) */ MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */ APL3_FCCA = 0x50, APL1_WORLD = 0x52, /* Latin America */ APL1_FCCA = 0x53, APL1_APLA = 0x54, APL1_ETSIC = 0x55, APL2_ETSIC = 0x56, /* Venezuela */ APL5_WORLD = 0x58, /* Chile */ APL6_WORLD = 0x5B, /* Singapore */ APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */ APL8_WORLD = 0x5D, /* Malaysia 5GHz */ APL9_WORLD = 0x5E, /* Korea 5GHz */ /* * World mode SKUs */ WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */ WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */ WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */ WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */ WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */ WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */ WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */ WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */ EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */ WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */ WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */ MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */ MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */ MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */ MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */ MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */ MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */ MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */ MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */ MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ MKK7_MKKA2 = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ /* Following definitions are used only by s/w to map old * Japan SKUs. */ MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */ MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */ MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */ MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */ MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */ MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */ MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */ MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */ /* * Regulator domains ending in a number (e.g. APL1, * MK1, ETSI4, etc) apply to 5GHz channel and power * information. Regulator domains ending in a letter * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and * power information. */ APL1 = 0x0150, /* LAT & Asia */ APL2 = 0x0250, /* LAT & Asia */ APL3 = 0x0350, /* Taiwan */ APL4 = 0x0450, /* Jordan */ APL5 = 0x0550, /* Chile */ APL6 = 0x0650, /* Singapore */ APL8 = 0x0850, /* Malaysia */ APL9 = 0x0950, /* Korea (South) ROC 3 */ ETSI1 = 0x0130, /* Europe & others */ ETSI2 = 0x0230, /* Europe & others */ ETSI3 = 0x0330, /* Europe & others */ ETSI4 = 0x0430, /* Europe & others */ ETSI5 = 0x0530, /* Europe & others */ ETSI6 = 0x0630, /* Europe & others */ ETSIA = 0x0A30, /* France */ ETSIB = 0x0B30, /* Israel */ ETSIC = 0x0C30, /* Latin America */ FCC1 = 0x0110, /* US & others */ FCC2 = 0x0120, /* Canada, Australia & New Zealand */ FCC3 = 0x0160, /* US w/new middle band & DFS */ FCC4 = 0x0165, /* US Public Safety */ FCCA = 0x0A10, APLD = 0x0D50, /* South Korea */ MKK1 = 0x0140, /* Japan (UNI-1 odd)*/ MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */ MKK3 = 0x0340, /* Japan (UNI-1 even) */ MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */ MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */ MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */ MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */ MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ MKKA = 0x0A40, /* Japan */ MKKC = 0x0A50, NULL1 = 0x0198, WORLD = 0x0199, DEBUG_REG_DMN = 0x01ff, }; #define DEF_REGDMN FCC1_FCCA static struct { const char *name; HAL_REG_DOMAIN rd; } domains[] = { #define D(_x) { #_x, _x } D(NO_ENUMRD), D(NULL1_WORLD), /* For 11b-only countries (no 11a allowed) */ D(NULL1_ETSIB), /* Israel */ D(NULL1_ETSIC), D(FCC1_FCCA), /* USA */ D(FCC1_WORLD), /* Hong Kong */ D(FCC4_FCCA), /* USA - Public Safety */ D(FCC2_FCCA), /* Canada */ D(FCC2_WORLD), /* Australia & HK */ D(FCC2_ETSIC), D(FRANCE_RES), /* Legacy France for OEM */ D(FCC3_FCCA), D(FCC3_WORLD), D(ETSI1_WORLD), D(ETSI3_ETSIA), /* France (optional) */ D(ETSI2_WORLD), /* Hungary & others */ D(ETSI3_WORLD), /* France & others */ D(ETSI4_WORLD), D(ETSI4_ETSIC), D(ETSI5_WORLD), D(ETSI6_WORLD), /* Bulgaria */ D(ETSI_RESERVED), /* Reserved (Do not used) */ D(MKK1_MKKA), /* Japan (JP1) */ D(MKK1_MKKB), /* Japan (JP0) */ D(APL4_WORLD), /* Singapore */ D(MKK2_MKKA), /* Japan with 4.9G channels */ D(APL_RESERVED), /* Reserved (Do not used) */ D(APL2_WORLD), /* Korea */ D(APL2_APLC), D(APL3_WORLD), D(MKK1_FCCA), /* Japan (JP1-1) */ D(APL2_APLD), /* Korea with 2.3G channels */ D(MKK1_MKKA1), /* Japan (JE1) */ D(MKK1_MKKA2), /* Japan (JE2) */ D(MKK1_MKKC), D(APL3_FCCA), D(APL1_WORLD), /* Latin America */ D(APL1_FCCA), D(APL1_APLA), D(APL1_ETSIC), D(APL2_ETSIC), /* Venezuela */ D(APL5_WORLD), /* Chile */ D(APL6_WORLD), /* Singapore */ D(APL7_FCCA), /* Taiwan 5.47 Band */ D(APL8_WORLD), /* Malaysia 5GHz */ D(APL9_WORLD), /* Korea 5GHz */ D(WOR0_WORLD), /* World0 (WO0 SKU) */ D(WOR1_WORLD), /* World1 (WO1 SKU) */ D(WOR2_WORLD), /* World2 (WO2 SKU) */ D(WOR3_WORLD), /* World3 (WO3 SKU) */ D(WOR4_WORLD), /* World4 (WO4 SKU) */ D(WOR5_ETSIC), /* World5 (WO5 SKU) */ D(WOR01_WORLD), /* World0-1 (WW0-1 SKU) */ D(WOR02_WORLD), /* World0-2 (WW0-2 SKU) */ D(EU1_WORLD), D(WOR9_WORLD), /* World9 (WO9 SKU) */ D(WORA_WORLD), /* WorldA (WOA SKU) */ D(MKK3_MKKB), /* Japan UNI-1 even + MKKB */ D(MKK3_MKKA2), /* Japan UNI-1 even + MKKA2 */ D(MKK3_MKKC), /* Japan UNI-1 even + MKKC */ D(MKK4_MKKB), /* Japan UNI-1 even + UNI-2 + MKKB */ D(MKK4_MKKA2), /* Japan UNI-1 even + UNI-2 + MKKA2 */ D(MKK4_MKKC), /* Japan UNI-1 even + UNI-2 + MKKC */ D(MKK5_MKKB), /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ D(MKK5_MKKA2), /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ D(MKK5_MKKC), /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ D(MKK6_MKKB), /* Japan UNI-1 even + UNI-1 odd MKKB */ D(MKK6_MKKA2), /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ D(MKK6_MKKC), /* Japan UNI-1 even + UNI-1 odd + MKKC */ D(MKK7_MKKB), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ D(MKK7_MKKA2), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ D(MKK7_MKKC), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ D(MKK8_MKKB), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ D(MKK8_MKKA2), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ D(MKK8_MKKC), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ D(MKK3_MKKA), /* Japan UNI-1 even + MKKA */ D(MKK3_MKKA1), /* Japan UNI-1 even + MKKA1 */ D(MKK3_FCCA), /* Japan UNI-1 even + FCCA */ D(MKK4_MKKA), /* Japan UNI-1 even + UNI-2 + MKKA */ D(MKK4_MKKA1), /* Japan UNI-1 even + UNI-2 + MKKA1 */ D(MKK4_FCCA), /* Japan UNI-1 even + UNI-2 + FCCA */ D(MKK9_MKKA), /* Japan UNI-1 even + 4.9GHz */ D(MKK10_MKKA), /* Japan UNI-1 even + UNI-2 + 4.9GHz */ D(APL1), /* LAT & Asia */ D(APL2), /* LAT & Asia */ D(APL3), /* Taiwan */ D(APL4), /* Jordan */ D(APL5), /* Chile */ D(APL6), /* Singapore */ D(APL8), /* Malaysia */ D(APL9), /* Korea (South) ROC 3 */ D(ETSI1), /* Europe & others */ D(ETSI2), /* Europe & others */ D(ETSI3), /* Europe & others */ D(ETSI4), /* Europe & others */ D(ETSI5), /* Europe & others */ D(ETSI6), /* Europe & others */ D(ETSIA), /* France */ D(ETSIB), /* Israel */ D(ETSIC), /* Latin America */ D(FCC1), /* US & others */ D(FCC2), D(FCC3), /* US w/new middle band & DFS */ D(FCC4), /* US Public Safety */ D(FCCA), D(APLD), /* South Korea */ D(MKK1), /* Japan (UNI-1 odd)*/ D(MKK2), /* Japan (4.9 GHz + UNI-1 odd) */ D(MKK3), /* Japan (UNI-1 even) */ D(MKK4), /* Japan (UNI-1 even + UNI-2) */ D(MKK5), /* Japan (UNI-1 even + UNI-2 + mid-band) */ D(MKK6), /* Japan (UNI-1 odd + UNI-1 even) */ D(MKK7), /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ D(MKK8), /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ D(MKK9), /* Japan (UNI-1 even + 4.9 GHZ) */ D(MKK10), /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ D(MKKA), /* Japan */ D(MKKC), D(NULL1), D(WORLD), D(DEBUG_REG_DMN), #undef D }; static HAL_BOOL rdlookup(const char *name, HAL_REG_DOMAIN *rd) { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; - for (i = 0; i < N(domains); i++) + for (i = 0; i < nitems(domains); i++) if (strcasecmp(domains[i].name, name) == 0) { *rd = domains[i].rd; return AH_TRUE; } return AH_FALSE; -#undef N } static const char * getrdname(HAL_REG_DOMAIN rd) { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; - for (i = 0; i < N(domains); i++) + for (i = 0; i < nitems(domains); i++) if (domains[i].rd == rd) return domains[i].name; return NULL; -#undef N } static void rdlist() { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; printf("\nRegulatory domains:\n\n"); - for (i = 0; i < N(domains); i++) + for (i = 0; i < nitems(domains); i++) printf("%-15s%s", domains[i].name, ((i+1)%5) == 0 ? "\n" : ""); printf("\n"); -#undef N } typedef struct { HAL_CTRY_CODE countryCode; HAL_REG_DOMAIN regDmnEnum; const char* isoName; const char* name; } COUNTRY_CODE_TO_ENUM_RD; /* * Country Code Table to Enumerated RD */ static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG" }, {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET" }, {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA" }, {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA" }, {CTRY_ARGENTINA, APL3_WORLD, "AR", "ARGENTINA" }, {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA" }, {CTRY_AUSTRALIA, FCC2_WORLD, "AU", "AUSTRALIA" }, {CTRY_AUSTRIA, ETSI1_WORLD, "AT", "AUSTRIA" }, {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN" }, {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN" }, {CTRY_BELARUS, NULL1_WORLD, "BY", "BELARUS" }, {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM" }, {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE" }, {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLVIA" }, {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL" }, {CTRY_BRUNEI_DARUSSALAM,APL1_WORLD,"BN", "BRUNEI DARUSSALAM" }, {CTRY_BULGARIA, ETSI6_WORLD, "BG", "BULGARIA" }, {CTRY_CANADA, FCC2_FCCA, "CA", "CANADA" }, {CTRY_CHILE, APL6_WORLD, "CL", "CHILE" }, {CTRY_CHINA, APL1_WORLD, "CN", "CHINA" }, {CTRY_COLOMBIA, FCC1_FCCA, "CO", "COLOMBIA" }, {CTRY_COSTA_RICA, NULL1_WORLD, "CR", "COSTA RICA" }, {CTRY_CROATIA, ETSI3_WORLD, "HR", "CROATIA" }, {CTRY_CYPRUS, ETSI1_WORLD, "CY", "CYPRUS" }, {CTRY_CZECH, ETSI3_WORLD, "CZ", "CZECH REPUBLIC" }, {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK" }, {CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA,"DO", "DOMINICAN REPUBLIC" }, {CTRY_ECUADOR, NULL1_WORLD, "EC", "ECUADOR" }, {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT" }, {CTRY_EL_SALVADOR, NULL1_WORLD, "SV", "EL SALVADOR" }, {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA" }, {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND" }, {CTRY_FRANCE, ETSI3_WORLD, "FR", "FRANCE" }, {CTRY_FRANCE2, ETSI3_WORLD, "F2", "FRANCE_RES" }, {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA" }, {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY" }, {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE" }, {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA" }, {CTRY_HONDURAS, NULL1_WORLD, "HN", "HONDURAS" }, {CTRY_HONG_KONG, FCC2_WORLD, "HK", "HONG KONG" }, {CTRY_HUNGARY, ETSI1_WORLD, "HU", "HUNGARY" }, {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND" }, {CTRY_INDIA, APL6_WORLD, "IN", "INDIA" }, {CTRY_INDONESIA, APL1_WORLD, "ID", "INDONESIA" }, {CTRY_IRAN, APL1_WORLD, "IR", "IRAN" }, {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND" }, {CTRY_ISRAEL, NULL1_WORLD, "IL", "ISRAEL" }, {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY" }, {CTRY_JAPAN, MKK1_MKKA, "JP", "JAPAN" }, {CTRY_JAPAN1, MKK1_MKKB, "JP", "JAPAN1" }, {CTRY_JAPAN2, MKK1_FCCA, "JP", "JAPAN2" }, {CTRY_JAPAN3, MKK2_MKKA, "JP", "JAPAN3" }, {CTRY_JAPAN4, MKK1_MKKA1, "JP", "JAPAN4" }, {CTRY_JAPAN5, MKK1_MKKA2, "JP", "JAPAN5" }, {CTRY_JAPAN6, MKK1_MKKC, "JP", "JAPAN6" }, {CTRY_JAPAN7, MKK3_MKKB, "JP", "JAPAN7" }, {CTRY_JAPAN8, MKK3_MKKA2, "JP", "JAPAN8" }, {CTRY_JAPAN9, MKK3_MKKC, "JP", "JAPAN9" }, {CTRY_JAPAN10, MKK4_MKKB, "JP", "JAPAN10" }, {CTRY_JAPAN11, MKK4_MKKA2, "JP", "JAPAN11" }, {CTRY_JAPAN12, MKK4_MKKC, "JP", "JAPAN12" }, {CTRY_JAPAN13, MKK5_MKKB, "JP", "JAPAN13" }, {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN14" }, {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN15" }, {CTRY_JAPAN16, MKK6_MKKB, "JP", "JAPAN16" }, {CTRY_JAPAN17, MKK6_MKKA2, "JP", "JAPAN17" }, {CTRY_JAPAN18, MKK6_MKKC, "JP", "JAPAN18" }, {CTRY_JAPAN19, MKK7_MKKB, "JP", "JAPAN19" }, {CTRY_JAPAN20, MKK7_MKKA2, "JP", "JAPAN20" }, {CTRY_JAPAN21, MKK7_MKKC, "JP", "JAPAN21" }, {CTRY_JAPAN22, MKK8_MKKB, "JP", "JAPAN22" }, {CTRY_JAPAN23, MKK8_MKKA2, "JP", "JAPAN23" }, {CTRY_JAPAN24, MKK8_MKKC, "JP", "JAPAN24" }, {CTRY_JORDAN, APL4_WORLD, "JO", "JORDAN" }, {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN" }, {CTRY_KOREA_NORTH, APL2_WORLD, "KP", "NORTH KOREA" }, {CTRY_KOREA_ROC, APL2_WORLD, "KR", "KOREA REPUBLIC" }, {CTRY_KOREA_ROC2, APL2_WORLD, "K2", "KOREA REPUBLIC2" }, {CTRY_KOREA_ROC3, APL9_WORLD, "K3", "KOREA REPUBLIC3" }, {CTRY_KUWAIT, NULL1_WORLD, "KW", "KUWAIT" }, {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA" }, {CTRY_LEBANON, NULL1_WORLD, "LB", "LEBANON" }, {CTRY_LIECHTENSTEIN,ETSI1_WORLD, "LI", "LIECHTENSTEIN" }, {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA" }, {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG" }, {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU" }, {CTRY_MACEDONIA, NULL1_WORLD, "MK", "MACEDONIA" }, {CTRY_MALAYSIA, APL8_WORLD, "MY", "MALAYSIA" }, {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA" }, {CTRY_MEXICO, FCC1_FCCA, "MX", "MEXICO" }, {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO" }, {CTRY_MOROCCO, NULL1_WORLD, "MA", "MOROCCO" }, {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS" }, {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ", "NEW ZEALAND" }, {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY" }, {CTRY_OMAN, APL6_WORLD, "OM", "OMAN" }, {CTRY_PAKISTAN, NULL1_WORLD, "PK", "PAKISTAN" }, {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA" }, {CTRY_PERU, APL1_WORLD, "PE", "PERU" }, {CTRY_PHILIPPINES, APL1_WORLD, "PH", "PHILIPPINES" }, {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND" }, {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL" }, {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO" }, {CTRY_QATAR, NULL1_WORLD, "QA", "QATAR" }, {CTRY_ROMANIA, NULL1_WORLD, "RO", "ROMANIA" }, {CTRY_RUSSIA, NULL1_WORLD, "RU", "RUSSIA" }, {CTRY_SAUDI_ARABIA,NULL1_WORLD, "SA", "SAUDI ARABIA" }, {CTRY_SINGAPORE, APL6_WORLD, "SG", "SINGAPORE" }, {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAK REPUBLIC" }, {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA" }, {CTRY_SOUTH_AFRICA,FCC3_WORLD, "ZA", "SOUTH AFRICA" }, {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN" }, {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN" }, {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND" }, {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIA" }, {CTRY_TAIWAN, APL3_FCCA, "TW", "TAIWAN" }, {CTRY_THAILAND, NULL1_WORLD, "TH", "THAILAND" }, {CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD,"TT", "TRINIDAD & TOBAGO" }, {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA" }, {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY" }, {CTRY_UKRAINE, NULL1_WORLD, "UA", "UKRAINE" }, {CTRY_UAE, NULL1_WORLD, "AE", "UNITED ARAB EMIRATES" }, {CTRY_UNITED_KINGDOM, ETSI1_WORLD,"GB", "UNITED KINGDOM" }, {CTRY_UNITED_STATES, FCC1_FCCA, "US", "UNITED STATES" }, {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS", "UNITED STATES (PUBLIC SAFETY)" }, {CTRY_URUGUAY, APL2_WORLD, "UY", "URUGUAY" }, {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN" }, {CTRY_VENEZUELA, APL2_ETSIC, "VE", "VENEZUELA" }, {CTRY_VIET_NAM, NULL1_WORLD, "VN", "VIET NAM" }, {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN" }, {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE" } }; static HAL_BOOL cclookup(const char *name, HAL_REG_DOMAIN *rd, HAL_CTRY_CODE *cc) { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; - for (i = 0; i < N(allCountries); i++) + for (i = 0; i < nitems(allCountries); i++) if (strcasecmp(allCountries[i].isoName, name) == 0 || strcasecmp(allCountries[i].name, name) == 0) { *rd = allCountries[i].regDmnEnum; *cc = allCountries[i].countryCode; return AH_TRUE; } return AH_FALSE; -#undef N } static const char * getccname(HAL_CTRY_CODE cc) { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; - for (i = 0; i < N(allCountries); i++) + for (i = 0; i < nitems(allCountries); i++) if (allCountries[i].countryCode == cc) return allCountries[i].name; return NULL; -#undef N } static const char * getccisoname(HAL_CTRY_CODE cc) { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; - for (i = 0; i < N(allCountries); i++) + for (i = 0; i < nitems(allCountries); i++) if (allCountries[i].countryCode == cc) return allCountries[i].isoName; return NULL; -#undef N } static void cclist() { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; printf("\nCountry codes:\n"); - for (i = 0; i < N(allCountries); i++) + for (i = 0; i < nitems(allCountries); i++) printf("%2s %-15.15s%s", allCountries[i].isoName, allCountries[i].name, ((i+1)%4) == 0 ? "\n" : " "); printf("\n"); -#undef N } static HAL_BOOL setRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan, int16_t tpcScaleReduction, int16_t powerLimit, int16_t *pMinPower, int16_t *pMaxPower); static void calctxpower(struct ath_hal *ah, int nchan, const struct ieee80211_channel *chans, int16_t tpcScaleReduction, int16_t powerLimit, int16_t *txpow) { int16_t minpow; int i; for (i = 0; i < nchan; i++) if (!setRateTable(ah, &chans[i], tpcScaleReduction, powerLimit, &minpow, &txpow[i])) { printf("unable to set rate table\n"); exit(-1); } } int n = 1; const char *sep = ""; int dopassive = 0; int showchannels = 0; int isdfs = 0; int is4ms = 0; static int anychan(const struct ieee80211_channel *chans, int nc, int flag) { int i; for (i = 0; i < nc; i++) if ((chans[i].ic_flags & flag) != 0) return 1; return 0; } static __inline int mapgsm(u_int freq, u_int flags) { freq *= 10; if (flags & IEEE80211_CHAN_QUARTER) freq += 5; else if (flags & IEEE80211_CHAN_HALF) freq += 10; else freq += 20; return (freq - 24220) / 5; } static __inline int mappsb(u_int freq, u_int flags) { return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5; } /* * Convert GHz frequency to IEEE channel number. */ int ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags) { if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ if (freq == 2484) return 14; if (freq < 2484) return ((int)freq - 2407) / 5; else return 15 + ((freq - 2512) / 20); } else if (flags & IEEE80211_CHAN_5GHZ) {/* 5Ghz band */ if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) return mappsb(freq, flags); else if ((flags & IEEE80211_CHAN_A) && (freq <= 5000)) return (freq - 4000) / 5; else return (freq - 5000) / 5; } else { /* either, guess */ if (freq == 2484) return 14; if (freq < 2484) return ((int)freq - 2407) / 5; if (freq < 5000) { if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) return mappsb(freq, flags); else if (freq > 4900) return (freq - 4000) / 5; else return 15 + ((freq - 2512) / 20); } return (freq - 5000) / 5; } } #define IEEE80211_IS_CHAN_4MS(_c) \ (((_c)->ic_flags & IEEE80211_CHAN_4MSXMIT) != 0) static void dumpchannels(struct ath_hal *ah, int nc, const struct ieee80211_channel *chans, int16_t *txpow) { int i; for (i = 0; i < nc; i++) { const struct ieee80211_channel *c = &chans[i]; int type; if (showchannels) printf("%s%3d", sep, ath_hal_mhz2ieee(ah, c->ic_freq, c->ic_flags)); else printf("%s%u", sep, c->ic_freq); if (IEEE80211_IS_CHAN_HALF(c)) type = 'H'; else if (IEEE80211_IS_CHAN_QUARTER(c)) type = 'Q'; else if (IEEE80211_IS_CHAN_TURBO(c)) type = 'T'; else if (IEEE80211_IS_CHAN_HT(c)) type = 'N'; else if (IEEE80211_IS_CHAN_A(c)) type = 'A'; else if (IEEE80211_IS_CHAN_108G(c)) type = 'T'; else if (IEEE80211_IS_CHAN_G(c)) type = 'G'; else type = 'B'; if (dopassive && IEEE80211_IS_CHAN_PASSIVE(c)) type = tolower(type); if (isdfs && is4ms) printf("%c%c%c %d.%d", type, IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ', IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ', txpow[i]/2, (txpow[i]%2)*5); else if (isdfs) printf("%c%c %d.%d", type, IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ', txpow[i]/2, (txpow[i]%2)*5); else if (is4ms) printf("%c%c %d.%d", type, IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ', txpow[i]/2, (txpow[i]%2)*5); else printf("%c %d.%d", type, txpow[i]/2, (txpow[i]%2)*5); if ((n++ % (showchannels ? 7 : 6)) == 0) sep = "\n"; else sep = " "; } } static void intersect(struct ieee80211_channel *dst, int16_t *dtxpow, int *nd, const struct ieee80211_channel *src, int16_t *stxpow, int ns) { int i = 0, j, k, l; while (i < *nd) { for (j = 0; j < ns && dst[i].ic_freq != src[j].ic_freq; j++) ; if (j < ns && dtxpow[i] == stxpow[j]) { for (k = i+1, l = i; k < *nd; k++, l++) dst[l] = dst[k]; (*nd)--; } else i++; } } static void usage(const char *progname) { printf("usage: %s [-acdefoilpr4ABGT] [-m opmode] [cc | rd]\n", progname); exit(-1); } static HAL_BOOL getChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan) { } static HAL_BOOL eepromRead(struct ath_hal *ah, u_int off, u_int16_t *data) { /* emulate enough stuff to handle japan channel shift */ switch (off) { case AR_EEPROM_VERSION: *data = eeversion; return AH_TRUE; case AR_EEPROM_REG_CAPABILITIES_OFFSET: *data = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A; return AH_TRUE; case AR_EEPROM_REG_CAPABILITIES_OFFSET_PRE4_0: *data = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0; return AH_TRUE; } return AH_FALSE; } HAL_STATUS getCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result) { const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; switch (type) { case HAL_CAP_REG_DMN: /* regulatory domain */ *result = AH_PRIVATE(ah)->ah_currentRD; return HAL_OK; default: return HAL_EINVAL; } } #define HAL_MODE_HT20 \ (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20) #define HAL_MODE_HT40 \ (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \ HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUS) #define HAL_MODE_HT (HAL_MODE_HT20 | HAL_MODE_HT40) int main(int argc, char *argv[]) { static const u_int16_t tpcScaleReductionTable[5] = { 0, 3, 6, 9, MAX_RATE_POWER }; struct ath_hal_private ahp; struct ieee80211_channel achans[IEEE80211_CHAN_MAX]; int16_t atxpow[IEEE80211_CHAN_MAX]; struct ieee80211_channel bchans[IEEE80211_CHAN_MAX]; int16_t btxpow[IEEE80211_CHAN_MAX]; struct ieee80211_channel gchans[IEEE80211_CHAN_MAX]; int16_t gtxpow[IEEE80211_CHAN_MAX]; struct ieee80211_channel tchans[IEEE80211_CHAN_MAX]; int16_t ttxpow[IEEE80211_CHAN_MAX]; struct ieee80211_channel tgchans[IEEE80211_CHAN_MAX]; int16_t tgtxpow[IEEE80211_CHAN_MAX]; struct ieee80211_channel nchans[IEEE80211_CHAN_MAX]; int16_t ntxpow[IEEE80211_CHAN_MAX]; int i, na, nb, ng, nt, ntg, nn; HAL_BOOL showall = AH_FALSE; HAL_BOOL extendedChanMode = AH_TRUE; int modes = 0; int16_t tpcReduction, powerLimit; int showdfs = 0; int show4ms = 0; memset(&ahp, 0, sizeof(ahp)); ahp.ah_getChannelEdges = getChannelEdges; ahp.ah_getWirelessModes = getWirelessModes; ahp.ah_eepromRead = eepromRead; ahp.ah_getChipPowerLimits = getChipPowerLimits; ahp.ah_caps.halWirelessModes = HAL_MODE_ALL; ahp.ah_caps.halLow5GhzChan = 4920; ahp.ah_caps.halHigh5GhzChan = 6100; ahp.ah_caps.halLow2GhzChan = 2312; ahp.ah_caps.halHigh2GhzChan = 2732; ahp.ah_caps.halChanHalfRate = AH_TRUE; ahp.ah_caps.halChanQuarterRate = AH_TRUE; ahp.h.ah_getCapability = getCapability; ahp.ah_opmode = HAL_M_STA; tpcReduction = tpcScaleReductionTable[0]; powerLimit = MAX_RATE_POWER; while ((i = getopt(argc, argv, "acdeflm:pr4ABGhHNT")) != -1) switch (i) { case 'a': showall = AH_TRUE; break; case 'c': showchannels = AH_TRUE; break; case 'd': ath_hal_debug = HAL_DEBUG_ANY; break; case 'e': extendedChanMode = AH_FALSE; break; case 'f': showchannels = AH_FALSE; break; case 'l': cclist(); rdlist(); exit(0); case 'm': if (strncasecmp(optarg, "sta", 2) == 0) ahp.ah_opmode = HAL_M_STA; else if (strncasecmp(optarg, "ibss", 2) == 0) ahp.ah_opmode = HAL_M_IBSS; else if (strncasecmp(optarg, "adhoc", 2) == 0) ahp.ah_opmode = HAL_M_IBSS; else if (strncasecmp(optarg, "ap", 2) == 0) ahp.ah_opmode = HAL_M_HOSTAP; else if (strncasecmp(optarg, "hostap", 2) == 0) ahp.ah_opmode = HAL_M_HOSTAP; else if (strncasecmp(optarg, "monitor", 2) == 0) ahp.ah_opmode = HAL_M_MONITOR; else usage(argv[0]); break; case 'p': dopassive = 1; break; case 'A': modes |= HAL_MODE_11A; break; case 'B': modes |= HAL_MODE_11B; break; case 'G': modes |= HAL_MODE_11G; break; case 'h': modes |= HAL_MODE_HT20; break; case 'H': modes |= HAL_MODE_HT40; break; case 'N': modes |= HAL_MODE_HT; break; case 'T': modes |= HAL_MODE_TURBO | HAL_MODE_108G; break; case 'r': showdfs = 1; break; case '4': show4ms = 1; break; default: usage(argv[0]); } switch (argc - optind) { case 0: if (!cclookup("US", &rd, &cc)) { printf("%s: unknown country code\n", "US"); exit(-1); } break; case 1: /* cc/regdomain */ if (!cclookup(argv[optind], &rd, &cc)) { if (!rdlookup(argv[optind], &rd)) { const char* rdname; rd = strtoul(argv[optind], NULL, 0); rdname = getrdname(rd); if (rdname == NULL) { printf("%s: unknown country/regulatory " "domain code\n", argv[optind]); exit(-1); } } cc = CTRY_DEFAULT; } break; default: /* regdomain cc */ if (!rdlookup(argv[optind], &rd)) { const char* rdname; rd = strtoul(argv[optind], NULL, 0); rdname = getrdname(rd); if (rdname == NULL) { printf("%s: unknown country/regulatory " "domain code\n", argv[optind]); exit(-1); } } if (!cclookup(argv[optind+1], &rd, &cc)) cc = strtoul(argv[optind+1], NULL, 0); break; } if (cc != CTRY_DEFAULT) printf("\n%s (%s, 0x%x, %u) %s (0x%x, %u)\n", getccname(cc), getccisoname(cc), cc, cc, getrdname(rd), rd, rd); else printf("\n%s (0x%x, %u)\n", getrdname(rd), rd, rd); if (modes == 0) { /* NB: no HAL_MODE_HT */ modes = HAL_MODE_11A | HAL_MODE_11B | HAL_MODE_11G | HAL_MODE_TURBO | HAL_MODE_108G; } na = nb = ng = nt = ntg = nn = 0; if (modes & HAL_MODE_11G) { ahp.ah_currentRD = rd; if (ath_hal_getchannels(&ahp.h, gchans, IEEE80211_CHAN_MAX, &ng, HAL_MODE_11G, cc, rd, extendedChanMode) == HAL_OK) { calctxpower(&ahp.h, ng, gchans, tpcReduction, powerLimit, gtxpow); if (showdfs) isdfs |= anychan(gchans, ng, IEEE80211_CHAN_DFS); if (show4ms) is4ms |= anychan(gchans, ng, IEEE80211_CHAN_4MSXMIT); } } if (modes & HAL_MODE_11B) { ahp.ah_currentRD = rd; if (ath_hal_getchannels(&ahp.h, bchans, IEEE80211_CHAN_MAX, &nb, HAL_MODE_11B, cc, rd, extendedChanMode) == HAL_OK) { calctxpower(&ahp.h, nb, bchans, tpcReduction, powerLimit, btxpow); if (showdfs) isdfs |= anychan(bchans, nb, IEEE80211_CHAN_DFS); if (show4ms) is4ms |= anychan(bchans, nb, IEEE80211_CHAN_4MSXMIT); } } if (modes & HAL_MODE_11A) { ahp.ah_currentRD = rd; if (ath_hal_getchannels(&ahp.h, achans, IEEE80211_CHAN_MAX, &na, HAL_MODE_11A, cc, rd, extendedChanMode) == HAL_OK) { calctxpower(&ahp.h, na, achans, tpcReduction, powerLimit, atxpow); if (showdfs) isdfs |= anychan(achans, na, IEEE80211_CHAN_DFS); if (show4ms) is4ms |= anychan(achans, na, IEEE80211_CHAN_4MSXMIT); } } if (modes & HAL_MODE_TURBO) { ahp.ah_currentRD = rd; if (ath_hal_getchannels(&ahp.h, tchans, IEEE80211_CHAN_MAX, &nt, HAL_MODE_TURBO, cc, rd, extendedChanMode) == HAL_OK) { calctxpower(&ahp.h, nt, tchans, tpcReduction, powerLimit, ttxpow); if (showdfs) isdfs |= anychan(tchans, nt, IEEE80211_CHAN_DFS); if (show4ms) is4ms |= anychan(tchans, nt, IEEE80211_CHAN_4MSXMIT); } } if (modes & HAL_MODE_108G) { ahp.ah_currentRD = rd; if (ath_hal_getchannels(&ahp.h, tgchans, IEEE80211_CHAN_MAX, &ntg, HAL_MODE_108G, cc, rd, extendedChanMode) == HAL_OK) { calctxpower(&ahp.h, ntg, tgchans, tpcReduction, powerLimit, tgtxpow); if (showdfs) isdfs |= anychan(tgchans, ntg, IEEE80211_CHAN_DFS); if (show4ms) is4ms |= anychan(tgchans, ntg, IEEE80211_CHAN_4MSXMIT); } } if (modes & HAL_MODE_HT) { ahp.ah_currentRD = rd; if (ath_hal_getchannels(&ahp.h, nchans, IEEE80211_CHAN_MAX, &nn, modes & HAL_MODE_HT, cc, rd, extendedChanMode) == HAL_OK) { calctxpower(&ahp.h, nn, nchans, tpcReduction, powerLimit, ntxpow); if (showdfs) isdfs |= anychan(nchans, nn, IEEE80211_CHAN_DFS); if (show4ms) is4ms |= anychan(nchans, nn, IEEE80211_CHAN_4MSXMIT); } } if (!showall) { #define CHECKMODES(_modes, _m) ((_modes & (_m)) == (_m)) if (CHECKMODES(modes, HAL_MODE_11B|HAL_MODE_11G)) { /* b ^= g */ intersect(bchans, btxpow, &nb, gchans, gtxpow, ng); } if (CHECKMODES(modes, HAL_MODE_11A|HAL_MODE_TURBO)) { /* t ^= a */ intersect(tchans, ttxpow, &nt, achans, atxpow, na); } if (CHECKMODES(modes, HAL_MODE_11G|HAL_MODE_108G)) { /* tg ^= g */ intersect(tgchans, tgtxpow, &ntg, gchans, gtxpow, ng); } if (CHECKMODES(modes, HAL_MODE_11G|HAL_MODE_HT)) { /* g ^= n */ intersect(gchans, gtxpow, &ng, nchans, ntxpow, nn); } if (CHECKMODES(modes, HAL_MODE_11A|HAL_MODE_HT)) { /* a ^= n */ intersect(achans, atxpow, &na, nchans, ntxpow, nn); } #undef CHECKMODES } if (modes & HAL_MODE_11G) dumpchannels(&ahp.h, ng, gchans, gtxpow); if (modes & HAL_MODE_11B) dumpchannels(&ahp.h, nb, bchans, btxpow); if (modes & HAL_MODE_11A) dumpchannels(&ahp.h, na, achans, atxpow); if (modes & HAL_MODE_108G) dumpchannels(&ahp.h, ntg, tgchans, tgtxpow); if (modes & HAL_MODE_TURBO) dumpchannels(&ahp.h, nt, tchans, ttxpow); if (modes & HAL_MODE_HT) dumpchannels(&ahp.h, nn, nchans, ntxpow); printf("\n"); return (0); } /* * Search a list for a specified value v that is within * EEP_DELTA of the search values. Return the closest * values in the list above and below the desired value. * EEP_DELTA is a factional value; everything is scaled * so only integer arithmetic is used. * * NB: the input list is assumed to be sorted in ascending order */ static void ar5212GetLowerUpperValues(u_int16_t v, u_int16_t *lp, u_int16_t listSize, u_int16_t *vlo, u_int16_t *vhi) { u_int32_t target = v * EEP_SCALE; u_int16_t *ep = lp+listSize; /* * Check first and last elements for out-of-bounds conditions. */ if (target < (u_int32_t)(lp[0] * EEP_SCALE - EEP_DELTA)) { *vlo = *vhi = lp[0]; return; } if (target > (u_int32_t)(ep[-1] * EEP_SCALE + EEP_DELTA)) { *vlo = *vhi = ep[-1]; return; } /* look for value being near or between 2 values in list */ for (; lp < ep; lp++) { /* * If value is close to the current value of the list * then target is not between values, it is one of the values */ if (abs(lp[0] * EEP_SCALE - target) < EEP_DELTA) { *vlo = *vhi = lp[0]; return; } /* * Look for value being between current value and next value * if so return these 2 values */ if (target < (u_int32_t)(lp[1] * EEP_SCALE - EEP_DELTA)) { *vlo = lp[0]; *vhi = lp[1]; return; } } } /* * Find the maximum conformance test limit for the given channel and CTL info */ static u_int16_t ar5212GetMaxEdgePower(u_int16_t channel, RD_EDGES_POWER *pRdEdgesPower) { /* temp array for holding edge channels */ u_int16_t tempChannelList[NUM_EDGES]; u_int16_t clo, chi, twiceMaxEdgePower; int i, numEdges; /* Get the edge power */ for (i = 0; i < NUM_EDGES; i++) { if (pRdEdgesPower[i].rdEdge == 0) break; tempChannelList[i] = pRdEdgesPower[i].rdEdge; } numEdges = i; ar5212GetLowerUpperValues(channel, tempChannelList, numEdges, &clo, &chi); /* Get the index for the lower channel */ for (i = 0; i < numEdges && clo != tempChannelList[i]; i++) ; /* Is lower channel ever outside the rdEdge? */ HALASSERT(i != numEdges); if ((clo == chi && clo == channel) || (pRdEdgesPower[i].flag)) { /* * If there's an exact channel match or an inband flag set * on the lower channel use the given rdEdgePower */ twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower; HALASSERT(twiceMaxEdgePower > 0); } else twiceMaxEdgePower = MAX_RATE_POWER; return twiceMaxEdgePower; } /* * Returns interpolated or the scaled up interpolated value */ static u_int16_t interpolate(u_int16_t target, u_int16_t srcLeft, u_int16_t srcRight, u_int16_t targetLeft, u_int16_t targetRight) { u_int16_t rv; int16_t lRatio; /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ if ((targetLeft * targetRight) == 0) return 0; if (srcRight != srcLeft) { /* * Note the ratio always need to be scaled, * since it will be a fraction. */ lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); if (lRatio < 0) { /* Return as Left target if value would be negative */ rv = targetLeft; } else if (lRatio > EEP_SCALE) { /* Return as Right target if Ratio is greater than 100% (SCALE) */ rv = targetRight; } else { rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * targetLeft) / EEP_SCALE; } } else { rv = targetLeft; } return rv; } /* * Return the four rates of target power for the given target power table * channel, and number of channels */ static void ar5212GetTargetPowers(struct ath_hal *ah, const struct ieee80211_channel *chan, TRGT_POWER_INFO *powInfo, u_int16_t numChannels, TRGT_POWER_INFO *pNewPower) { /* temp array for holding target power channels */ u_int16_t tempChannelList[NUM_TEST_FREQUENCIES]; u_int16_t clo, chi, ixlo, ixhi; int i; /* Copy the target powers into the temp channel list */ for (i = 0; i < numChannels; i++) tempChannelList[i] = powInfo[i].testChannel; ar5212GetLowerUpperValues(chan->ic_freq, tempChannelList, numChannels, &clo, &chi); /* Get the indices for the channel */ ixlo = ixhi = 0; for (i = 0; i < numChannels; i++) { if (clo == tempChannelList[i]) { ixlo = i; } if (chi == tempChannelList[i]) { ixhi = i; break; } } /* * Get the lower and upper channels, target powers, * and interpolate between them. */ pNewPower->twicePwr6_24 = interpolate(chan->ic_freq, clo, chi, powInfo[ixlo].twicePwr6_24, powInfo[ixhi].twicePwr6_24); pNewPower->twicePwr36 = interpolate(chan->ic_freq, clo, chi, powInfo[ixlo].twicePwr36, powInfo[ixhi].twicePwr36); pNewPower->twicePwr48 = interpolate(chan->ic_freq, clo, chi, powInfo[ixlo].twicePwr48, powInfo[ixhi].twicePwr48); pNewPower->twicePwr54 = interpolate(chan->ic_freq, clo, chi, powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54); } static RD_EDGES_POWER* findEdgePower(struct ath_hal *ah, u_int ctl) { int i; for (i = 0; i < _numCtls; i++) if (_ctl[i] == ctl) return &_rdEdgesPower[i * NUM_EDGES]; return AH_NULL; } /* * Sets the transmit power in the baseband for the given * operating channel and mode. */ static HAL_BOOL setRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan, int16_t tpcScaleReduction, int16_t powerLimit, int16_t *pMinPower, int16_t *pMaxPower) { u_int16_t ratesArray[16]; u_int16_t *rpow = ratesArray; u_int16_t twiceMaxRDPower, twiceMaxEdgePower, twiceMaxEdgePowerCck; int8_t twiceAntennaGain, twiceAntennaReduction; TRGT_POWER_INFO targetPowerOfdm, targetPowerCck; RD_EDGES_POWER *rep; int16_t scaledPower; u_int8_t cfgCtl; twiceMaxRDPower = chan->ic_maxregpower * 2; *pMaxPower = -MAX_RATE_POWER; *pMinPower = MAX_RATE_POWER; /* Get conformance test limit maximum for this channel */ cfgCtl = ath_hal_getctl(ah, chan); rep = findEdgePower(ah, cfgCtl); if (rep != AH_NULL) twiceMaxEdgePower = ar5212GetMaxEdgePower(chan->ic_freq, rep); else twiceMaxEdgePower = MAX_RATE_POWER; if (IEEE80211_IS_CHAN_G(chan)) { /* Check for a CCK CTL for 11G CCK powers */ cfgCtl = (cfgCtl & 0xFC) | 0x01; rep = findEdgePower(ah, cfgCtl); if (rep != AH_NULL) twiceMaxEdgePowerCck = ar5212GetMaxEdgePower(chan->ic_freq, rep); else twiceMaxEdgePowerCck = MAX_RATE_POWER; } else { /* Set the 11B cck edge power to the one found before */ twiceMaxEdgePowerCck = twiceMaxEdgePower; } /* Get Antenna Gain reduction */ if (IEEE80211_IS_CHAN_5GHZ(chan)) { twiceAntennaGain = antennaGainMax[0]; } else { twiceAntennaGain = antennaGainMax[1]; } twiceAntennaReduction = ath_hal_getantennareduction(ah, chan, twiceAntennaGain); if (IEEE80211_IS_CHAN_OFDM(chan)) { /* Get final OFDM target powers */ if (IEEE80211_IS_CHAN_G(chan)) { /* TODO - add Turbo 2.4 to this mode check */ ar5212GetTargetPowers(ah, chan, trgtPwr_11g, numTargetPwr_11g, &targetPowerOfdm); } else { ar5212GetTargetPowers(ah, chan, trgtPwr_11a, numTargetPwr_11a, &targetPowerOfdm); } /* Get Maximum OFDM power */ /* Minimum of target and edge powers */ scaledPower = AH_MIN(twiceMaxEdgePower, twiceMaxRDPower - twiceAntennaReduction); /* * If turbo is set, reduce power to keep power * consumption under 2 Watts. Note that we always do * this unless specially configured. Then we limit * power only for non-AP operation. */ if (IEEE80211_IS_CHAN_TURBO(chan) #ifdef AH_ENABLE_AP_SUPPORT && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP #endif ) { /* * If turbo is set, reduce power to keep power * consumption under 2 Watts */ if (eeversion >= AR_EEPROM_VER3_1) scaledPower = AH_MIN(scaledPower, turbo2WMaxPower5); /* * EEPROM version 4.0 added an additional * constraint on 2.4GHz channels. */ if (eeversion >= AR_EEPROM_VER4_0 && IEEE80211_IS_CHAN_2GHZ(chan)) scaledPower = AH_MIN(scaledPower, turbo2WMaxPower2); } /* Reduce power by max regulatory domain allowed restrictions */ scaledPower -= (tpcScaleReduction * 2); scaledPower = (scaledPower < 0) ? 0 : scaledPower; scaledPower = AH_MIN(scaledPower, powerLimit); scaledPower = AH_MIN(scaledPower, targetPowerOfdm.twicePwr6_24); /* Set OFDM rates 9, 12, 18, 24, 36, 48, 54, XR */ rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower; rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36); rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48); rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54); #ifdef notyet if (eeversion >= AR_EEPROM_VER4_0) { /* Setup XR target power from EEPROM */ rpow[15] = AH_MIN(scaledPower, IS_CHAN_2GHZ(chan) ? xrTargetPower2 : xrTargetPower5); } else { /* XR uses 6mb power */ rpow[15] = rpow[0]; } #else rpow[15] = rpow[0]; #endif *pMinPower = rpow[7]; *pMaxPower = rpow[0]; #if 0 ahp->ah_ofdmTxPower = rpow[0]; #endif HALDEBUG(ah, HAL_DEBUG_ANY, "%s: MaxRD: %d TurboMax: %d MaxCTL: %d " "TPC_Reduction %d\n", __func__, twiceMaxRDPower, turbo2WMaxPower5, twiceMaxEdgePower, tpcScaleReduction * 2); } if (IEEE80211_IS_CHAN_CCK(chan)) { /* Get final CCK target powers */ ar5212GetTargetPowers(ah, chan, trgtPwr_11b, numTargetPwr_11b, &targetPowerCck); /* Reduce power by max regulatory domain allowed restrictions */ scaledPower = AH_MIN(twiceMaxEdgePowerCck, twiceMaxRDPower - twiceAntennaReduction); scaledPower -= (tpcScaleReduction * 2); scaledPower = (scaledPower < 0) ? 0 : scaledPower; scaledPower = AH_MIN(scaledPower, powerLimit); rpow[8] = (scaledPower < 1) ? 1 : scaledPower; /* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */ rpow[8] = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24); rpow[9] = AH_MIN(scaledPower, targetPowerCck.twicePwr36); rpow[10] = rpow[9]; rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48); rpow[12] = rpow[11]; rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54); rpow[14] = rpow[13]; /* Set min/max power based off OFDM values or initialization */ if (rpow[13] < *pMinPower) *pMinPower = rpow[13]; if (rpow[9] > *pMaxPower) *pMaxPower = rpow[9]; } #if 0 ahp->ah_tx6PowerInHalfDbm = *pMaxPower; #endif return AH_TRUE; } void* ath_hal_malloc(size_t size) { return calloc(1, size); } void ath_hal_free(void* p) { return free(p); } void ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap) { vprintf(fmt, ap); } void ath_hal_printf(struct ath_hal *ah, const char* fmt, ...) { va_list ap; va_start(ap, fmt); ath_hal_vprintf(ah, fmt, ap); va_end(ap); } void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) { __va_list ap; va_start(ap, fmt); ath_hal_vprintf(ah, fmt, ap); va_end(ap); } Index: head/tools/tools/ath/athstats/athstats.c =================================================================== --- head/tools/tools/ath/athstats/athstats.c (revision 287296) +++ head/tools/tools/ath/athstats/athstats.c (revision 287297) @@ -1,1093 +1,1094 @@ /*- * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ #include "opt_ah.h" /* * ath statistics class. */ -#include + +#include #include #include #include + #include #include #include +#include +#include #include #include -#include #include #include -#include #include "ah.h" #include "ah_desc.h" #include "ah_diagcodes.h" #include "net80211/ieee80211_ioctl.h" #include "net80211/ieee80211_radiotap.h" #include "if_athioctl.h" #include "athstats.h" #ifdef ATH_SUPPORT_ANI #define HAL_EP_RND(x,mul) \ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) #define HAL_RSSI(x) HAL_EP_RND(x, HAL_RSSI_EP_MULTIPLIER) #endif #define NOTPRESENT { 0, "", "" } #define AFTER(prev) ((prev)+1) static const struct fmt athstats[] = { #define S_INPUT 0 { 8, "input", "input", "data frames received" }, #define S_OUTPUT AFTER(S_INPUT) { 8, "output", "output", "data frames transmit" }, #define S_TX_ALTRATE AFTER(S_OUTPUT) { 7, "altrate", "altrate", "tx frames with an alternate rate" }, #define S_TX_SHORTRETRY AFTER(S_TX_ALTRATE) { 7, "short", "short", "short on-chip tx retries" }, #define S_TX_LONGRETRY AFTER(S_TX_SHORTRETRY) { 7, "long", "long", "long on-chip tx retries" }, #define S_TX_XRETRIES AFTER(S_TX_LONGRETRY) { 6, "xretry", "xretry", "tx failed 'cuz too many retries" }, #define S_MIB AFTER(S_TX_XRETRIES) { 5, "mib", "mib", "mib overflow interrupts" }, #ifndef __linux__ #define S_TX_LINEAR AFTER(S_MIB) { 5, "txlinear", "txlinear", "tx linearized to cluster" }, #define S_BSTUCK AFTER(S_TX_LINEAR) { 6, "bstuck", "bstuck", "stuck beacon conditions" }, #define S_INTRCOAL AFTER(S_BSTUCK) { 5, "intrcoal", "intrcoal", "interrupts coalesced" }, #define S_RATE AFTER(S_INTRCOAL) #else #define S_RATE AFTER(S_MIB) #endif { 5, "rate", "rate", "current transmit rate" }, #define S_WATCHDOG AFTER(S_RATE) { 5, "wdog", "wdog", "watchdog timeouts" }, #define S_FATAL AFTER(S_WATCHDOG) { 5, "fatal", "fatal", "hardware error interrupts" }, #define S_BMISS AFTER(S_FATAL) { 5, "bmiss", "bmiss", "beacon miss interrupts" }, #define S_RXORN AFTER(S_BMISS) { 5, "rxorn", "rxorn", "recv overrun interrupts" }, #define S_RXEOL AFTER(S_RXORN) { 5, "rxeol", "rxeol", "recv eol interrupts" }, #define S_TXURN AFTER(S_RXEOL) { 5, "txurn", "txurn", "txmit underrun interrupts" }, #define S_TX_MGMT AFTER(S_TXURN) { 5, "txmgt", "txmgt", "tx management frames" }, #define S_TX_DISCARD AFTER(S_TX_MGMT) { 5, "txdisc", "txdisc", "tx frames discarded prior to association" }, #define S_TX_INVALID AFTER(S_TX_DISCARD) { 5, "txinv", "txinv", "tx invalid (19)" }, #define S_TX_QSTOP AFTER(S_TX_INVALID) { 5, "qstop", "qstop", "tx stopped 'cuz no xmit buffer" }, #define S_TX_ENCAP AFTER(S_TX_QSTOP) { 5, "txencode", "txencode", "tx encapsulation failed" }, #define S_TX_NONODE AFTER(S_TX_ENCAP) { 5, "txnonode", "txnonode", "tx failed 'cuz no node" }, #define S_TX_NOBUF AFTER(S_TX_NONODE) { 5, "txnobuf", "txnobuf", "tx failed 'cuz dma buffer allocation failed" }, #define S_TX_NOFRAG AFTER(S_TX_NOBUF) { 5, "txnofrag", "txnofrag", "tx failed 'cuz frag buffer allocation(s) failed" }, #define S_TX_NOMBUF AFTER(S_TX_NOFRAG) { 5, "txnombuf", "txnombuf", "tx failed 'cuz mbuf allocation failed" }, #ifndef __linux__ #define S_TX_NOMCL AFTER(S_TX_NOMBUF) { 5, "txnomcl", "txnomcl", "tx failed 'cuz cluster allocation failed" }, #define S_TX_FIFOERR AFTER(S_TX_NOMCL) #else #define S_TX_FIFOERR AFTER(S_TX_NOMBUF) #endif { 5, "efifo", "efifo", "tx failed 'cuz FIFO underrun" }, #define S_TX_FILTERED AFTER(S_TX_FIFOERR) { 5, "efilt", "efilt", "tx failed 'cuz destination filtered" }, #define S_TX_BADRATE AFTER(S_TX_FILTERED) { 5, "txbadrate", "txbadrate", "tx failed 'cuz bogus xmit rate" }, #define S_TX_NOACK AFTER(S_TX_BADRATE) { 5, "noack", "noack", "tx frames with no ack marked" }, #define S_TX_RTS AFTER(S_TX_NOACK) { 5, "rts", "rts", "tx frames with rts enabled" }, #define S_TX_CTS AFTER(S_TX_RTS) { 5, "cts", "cts", "tx frames with cts enabled" }, #define S_TX_SHORTPRE AFTER(S_TX_CTS) { 5, "shpre", "shpre", "tx frames with short preamble" }, #define S_TX_PROTECT AFTER(S_TX_SHORTPRE) { 5, "protect", "protect", "tx frames with 11g protection" }, #define S_RX_ORN AFTER(S_TX_PROTECT) { 5, "rxorn", "rxorn", "rx failed 'cuz of desc overrun" }, #define S_RX_CRC_ERR AFTER(S_RX_ORN) { 6, "crcerr", "crcerr", "rx failed 'cuz of bad CRC" }, #define S_RX_FIFO_ERR AFTER(S_RX_CRC_ERR) { 5, "rxfifo", "rxfifo", "rx failed 'cuz of FIFO overrun" }, #define S_RX_CRYPTO_ERR AFTER(S_RX_FIFO_ERR) { 5, "crypt", "crypt", "rx failed 'cuz decryption" }, #define S_RX_MIC_ERR AFTER(S_RX_CRYPTO_ERR) { 4, "mic", "mic", "rx failed 'cuz MIC failure" }, #define S_RX_TOOSHORT AFTER(S_RX_MIC_ERR) { 5, "rxshort", "rxshort", "rx failed 'cuz frame too short" }, #define S_RX_NOMBUF AFTER(S_RX_TOOSHORT) { 5, "rxnombuf", "rxnombuf", "rx setup failed 'cuz no mbuf" }, #define S_RX_MGT AFTER(S_RX_NOMBUF) { 5, "rxmgt", "rxmgt", "rx management frames" }, #define S_RX_CTL AFTER(S_RX_MGT) { 5, "rxctl", "rxctl", "rx control frames" }, #define S_RX_PHY_ERR AFTER(S_RX_CTL) { 7, "phyerr", "phyerr", "rx failed 'cuz of PHY err" }, #define S_RX_PHY_UNDERRUN AFTER(S_RX_PHY_ERR) { 4, "phyund", "TUnd", "transmit underrun" }, #define S_RX_PHY_TIMING AFTER(S_RX_PHY_UNDERRUN) { 4, "phytim", "Tim", "timing error" }, #define S_RX_PHY_PARITY AFTER(S_RX_PHY_TIMING) { 4, "phypar", "IPar", "illegal parity" }, #define S_RX_PHY_RATE AFTER(S_RX_PHY_PARITY) { 4, "phyrate", "IRate", "illegal rate" }, #define S_RX_PHY_LENGTH AFTER(S_RX_PHY_RATE) { 4, "phylen", "ILen", "illegal length" }, #define S_RX_PHY_RADAR AFTER(S_RX_PHY_LENGTH) { 4, "phyradar", "Radar", "radar detect" }, #define S_RX_PHY_SERVICE AFTER(S_RX_PHY_RADAR) { 4, "physervice", "Service", "illegal service" }, #define S_RX_PHY_TOR AFTER(S_RX_PHY_SERVICE) { 4, "phytor", "TOR", "transmit override receive" }, #define S_RX_PHY_OFDM_TIMING AFTER(S_RX_PHY_TOR) { 6, "ofdmtim", "ofdmtim", "OFDM timing" }, #define S_RX_PHY_OFDM_SIGNAL_PARITY AFTER(S_RX_PHY_OFDM_TIMING) { 6, "ofdmsig", "ofdmsig", "OFDM illegal parity" }, #define S_RX_PHY_OFDM_RATE_ILLEGAL AFTER(S_RX_PHY_OFDM_SIGNAL_PARITY) { 6, "ofdmrate", "ofdmrate", "OFDM illegal rate" }, #define S_RX_PHY_OFDM_POWER_DROP AFTER(S_RX_PHY_OFDM_RATE_ILLEGAL) { 6, "ofdmpow", "ofdmpow", "OFDM power drop" }, #define S_RX_PHY_OFDM_SERVICE AFTER(S_RX_PHY_OFDM_POWER_DROP) { 6, "ofdmservice", "ofdmservice", "OFDM illegal service" }, #define S_RX_PHY_OFDM_RESTART AFTER(S_RX_PHY_OFDM_SERVICE) { 6, "ofdmrestart", "ofdmrestart", "OFDM restart" }, #define S_RX_PHY_CCK_TIMING AFTER(S_RX_PHY_OFDM_RESTART) { 6, "ccktim", "ccktim", "CCK timing" }, #define S_RX_PHY_CCK_HEADER_CRC AFTER(S_RX_PHY_CCK_TIMING) { 6, "cckhead", "cckhead", "CCK header crc" }, #define S_RX_PHY_CCK_RATE_ILLEGAL AFTER(S_RX_PHY_CCK_HEADER_CRC) { 6, "cckrate", "cckrate", "CCK illegal rate" }, #define S_RX_PHY_CCK_SERVICE AFTER(S_RX_PHY_CCK_RATE_ILLEGAL) { 6, "cckservice", "cckservice", "CCK illegal service" }, #define S_RX_PHY_CCK_RESTART AFTER(S_RX_PHY_CCK_SERVICE) { 6, "cckrestar", "cckrestar", "CCK restart" }, #define S_BE_NOMBUF AFTER(S_RX_PHY_CCK_RESTART) { 4, "benombuf", "benombuf", "beacon setup failed 'cuz no mbuf" }, #define S_BE_XMIT AFTER(S_BE_NOMBUF) { 7, "bexmit", "bexmit", "beacons transmitted" }, #define S_PER_CAL AFTER(S_BE_XMIT) { 4, "pcal", "pcal", "periodic calibrations" }, #define S_PER_CALFAIL AFTER(S_PER_CAL) { 4, "pcalf", "pcalf", "periodic calibration failures" }, #define S_PER_RFGAIN AFTER(S_PER_CALFAIL) { 4, "prfga", "prfga", "rfgain value change" }, #if ATH_SUPPORT_TDMA #define S_TDMA_UPDATE AFTER(S_PER_RFGAIN) { 5, "tdmau", "tdmau", "TDMA slot timing updates" }, #define S_TDMA_TIMERS AFTER(S_TDMA_UPDATE) { 5, "tdmab", "tdmab", "TDMA slot update set beacon timers" }, #define S_TDMA_TSF AFTER(S_TDMA_TIMERS) { 5, "tdmat", "tdmat", "TDMA slot update set TSF" }, #define S_TDMA_TSFADJ AFTER(S_TDMA_TSF) { 8, "tdmadj", "tdmadj", "TDMA slot adjust (usecs, smoothed)" }, #define S_TDMA_ACK AFTER(S_TDMA_TSFADJ) { 5, "tdmack", "tdmack", "TDMA tx failed 'cuz ACK required" }, #define S_RATE_CALLS AFTER(S_TDMA_ACK) #else #define S_RATE_CALLS AFTER(S_PER_RFGAIN) #endif { 5, "ratec", "ratec", "rate control checks" }, #define S_RATE_RAISE AFTER(S_RATE_CALLS) { 5, "rate+", "rate+", "rate control raised xmit rate" }, #define S_RATE_DROP AFTER(S_RATE_RAISE) { 5, "rate-", "rate-", "rate control dropped xmit rate" }, #define S_TX_RSSI AFTER(S_RATE_DROP) { 4, "arssi", "arssi", "rssi of last ack" }, #define S_RX_RSSI AFTER(S_TX_RSSI) { 4, "rssi", "rssi", "avg recv rssi" }, #define S_RX_NOISE AFTER(S_RX_RSSI) { 5, "noise", "noise", "rx noise floor" }, #define S_BMISS_PHANTOM AFTER(S_RX_NOISE) { 5, "bmissphantom", "bmissphantom", "phantom beacon misses" }, #define S_TX_RAW AFTER(S_BMISS_PHANTOM) { 5, "txraw", "txraw", "tx frames through raw api" }, #define S_TX_RAW_FAIL AFTER(S_TX_RAW) { 5, "txrawfail", "txrawfail", "raw tx failed 'cuz interface/hw down" }, #define S_RX_TOOBIG AFTER(S_TX_RAW_FAIL) { 5, "rx2big", "rx2big", "rx failed 'cuz frame too large" }, #define S_RX_AGG AFTER(S_RX_TOOBIG) { 5, "rxagg", "rxagg", "A-MPDU sub-frames received" }, #define S_RX_HALFGI AFTER(S_RX_AGG) { 5, "rxhalfgi", "rxhgi", "Half-GI frames received" }, #define S_RX_2040 AFTER(S_RX_HALFGI) { 6, "rx2040", "rx2040", "40MHz frames received" }, #define S_RX_PRE_CRC_ERR AFTER(S_RX_2040) { 11, "rxprecrcerr", "rxprecrcerr", "CRC errors for non-last A-MPDU subframes" }, #define S_RX_POST_CRC_ERR AFTER(S_RX_PRE_CRC_ERR) { 12, "rxpostcrcerr", "rxpostcrcerr", "CRC errors for last subframe in an A-MPDU" }, #define S_RX_DECRYPT_BUSY_ERR AFTER(S_RX_POST_CRC_ERR) { 10, "rxdescbusy", "rxdescbusy", "Decryption engine busy" }, #define S_RX_HI_CHAIN AFTER(S_RX_DECRYPT_BUSY_ERR) { 4, "rxhi", "rxhi", "Frames received with RX chain in high power mode" }, #define S_RX_STBC AFTER(S_RX_HI_CHAIN) { 6, "rxstbc", "rxstbc", "Frames received w/ STBC encoding" }, #define S_TX_HTPROTECT AFTER(S_RX_STBC) { 7, "txhtprot", "txhtprot", "Frames transmitted with HT Protection" }, #define S_RX_QEND AFTER(S_TX_HTPROTECT) { 7, "rxquend", "rxquend", "Hit end of RX descriptor queue" }, #define S_TX_TIMEOUT AFTER(S_RX_QEND) { 4, "txtimeout", "TXTX", "TX Timeout" }, #define S_TX_CSTIMEOUT AFTER(S_TX_TIMEOUT) { 4, "csttimeout", "CSTX", "Carrier Sense Timeout" }, #define S_TX_XTXOP_ERR AFTER(S_TX_CSTIMEOUT) { 5, "xtxoperr", "TXOPX", "TXOP exceed" }, #define S_TX_TIMEREXPIRED_ERR AFTER(S_TX_XTXOP_ERR) { 7, "texperr", "texperr", "TX Timer expired" }, #define S_TX_DESCCFG_ERR AFTER(S_TX_TIMEREXPIRED_ERR) { 10, "desccfgerr", "desccfgerr", "TX descriptor error" }, #define S_TX_SWRETRIES AFTER(S_TX_DESCCFG_ERR) { 9, "txswretry", "txswretry", "Number of frames retransmitted in software" }, #define S_TX_SWRETRIES_MAX AFTER(S_TX_SWRETRIES) { 7, "txswmax", "txswmax", "Number of frames exceeding software retry" }, #define S_TX_DATA_UNDERRUN AFTER(S_TX_SWRETRIES_MAX) { 5, "txdataunderrun", "TXDAU", "A-MPDU TX FIFO data underrun" }, #define S_TX_DELIM_UNDERRUN AFTER(S_TX_DATA_UNDERRUN) { 5, "txdelimunderrun", "TXDEU", "A-MPDU TX Delimiter underrun" }, #define S_TX_AGGR_OK AFTER(S_TX_DELIM_UNDERRUN) { 5, "txaggrok", "TXAOK", "A-MPDU sub-frame TX attempt success" }, #define S_TX_AGGR_FAIL AFTER(S_TX_AGGR_OK) { 4, "txaggrfail", "TXAF", "A-MPDU sub-frame TX attempt failures" }, #define S_TX_AGGR_FAILALL AFTER(S_TX_AGGR_FAIL) { 7, "txaggrfailall", "TXAFALL", "A-MPDU TX frame failures" }, #ifndef __linux__ #define S_CABQ_XMIT AFTER(S_TX_AGGR_FAILALL) { 7, "cabxmit", "cabxmit", "cabq frames transmitted" }, #define S_CABQ_BUSY AFTER(S_CABQ_XMIT) { 8, "cabqbusy", "cabqbusy", "cabq xmit overflowed beacon interval" }, #define S_TX_NODATA AFTER(S_CABQ_BUSY) { 8, "txnodata", "txnodata", "tx discarded empty frame" }, #define S_TX_BUSDMA AFTER(S_TX_NODATA) { 8, "txbusdma", "txbusdma", "tx failed for dma resrcs" }, #define S_RX_BUSDMA AFTER(S_TX_BUSDMA) { 8, "rxbusdma", "rxbusdma", "rx setup failed for dma resrcs" }, #define S_FF_TXOK AFTER(S_RX_BUSDMA) #else #define S_FF_TXOK AFTER(S_TX_AGGR_FAILALL) #endif { 5, "fftxok", "fftxok", "fast frames xmit successfully" }, #define S_FF_TXERR AFTER(S_FF_TXOK) { 5, "fftxerr", "fftxerr", "fast frames not xmit due to error" }, #define S_FF_RX AFTER(S_FF_TXERR) { 5, "ffrx", "ffrx", "fast frames received" }, #define S_FF_FLUSH AFTER(S_FF_RX) { 5, "ffflush", "ffflush", "fast frames flushed from staging q" }, #define S_TX_QFULL AFTER(S_FF_FLUSH) { 5, "txqfull", "txqfull", "tx discarded 'cuz queue is full" }, #define S_ANT_DEFSWITCH AFTER(S_TX_QFULL) { 5, "defsw", "defsw", "switched default/rx antenna" }, #define S_ANT_TXSWITCH AFTER(S_ANT_DEFSWITCH) { 5, "txsw", "txsw", "tx used alternate antenna" }, #ifdef ATH_SUPPORT_ANI #define S_ANI_NOISE AFTER(S_ANT_TXSWITCH) { 2, "ni", "NI", "noise immunity level" }, #define S_ANI_SPUR AFTER(S_ANI_NOISE) { 2, "si", "SI", "spur immunity level" }, #define S_ANI_STEP AFTER(S_ANI_SPUR) { 2, "step", "ST", "first step level" }, #define S_ANI_OFDM AFTER(S_ANI_STEP) { 4, "owsd", "OWSD", "OFDM weak signal detect" }, #define S_ANI_CCK AFTER(S_ANI_OFDM) { 4, "cwst", "CWST", "CCK weak signal threshold" }, #define S_ANI_MAXSPUR AFTER(S_ANI_CCK) { 3, "maxsi","MSI", "max spur immunity level" }, #define S_ANI_LISTEN AFTER(S_ANI_MAXSPUR) { 6, "listen","LISTEN", "listen time" }, #define S_ANI_NIUP AFTER(S_ANI_LISTEN) { 4, "ni+", "NI+", "ANI increased noise immunity" }, #define S_ANI_NIDOWN AFTER(S_ANI_NIUP) { 4, "ni-", "NI-", "ANI decrease noise immunity" }, #define S_ANI_SIUP AFTER(S_ANI_NIDOWN) { 4, "si+", "SI+", "ANI increased spur immunity" }, #define S_ANI_SIDOWN AFTER(S_ANI_SIUP) { 4, "si-", "SI-", "ANI decrease spur immunity" }, #define S_ANI_OFDMON AFTER(S_ANI_SIDOWN) { 5, "ofdm+","OFDM+", "ANI enabled OFDM weak signal detect" }, #define S_ANI_OFDMOFF AFTER(S_ANI_OFDMON) { 5, "ofdm-","OFDM-", "ANI disabled OFDM weak signal detect" }, #define S_ANI_CCKHI AFTER(S_ANI_OFDMOFF) { 5, "cck+", "CCK+", "ANI enabled CCK weak signal threshold" }, #define S_ANI_CCKLO AFTER(S_ANI_CCKHI) { 5, "cck-", "CCK-", "ANI disabled CCK weak signal threshold" }, #define S_ANI_STEPUP AFTER(S_ANI_CCKLO) { 5, "step+","STEP+", "ANI increased first step level" }, #define S_ANI_STEPDOWN AFTER(S_ANI_STEPUP) { 5, "step-","STEP-", "ANI decreased first step level" }, #define S_ANI_OFDMERRS AFTER(S_ANI_STEPDOWN) { 8, "ofdm", "OFDM", "cumulative OFDM phy error count" }, #define S_ANI_CCKERRS AFTER(S_ANI_OFDMERRS) { 8, "cck", "CCK", "cumulative CCK phy error count" }, #define S_ANI_RESET AFTER(S_ANI_CCKERRS) { 5, "reset","RESET", "ANI parameters zero'd for non-STA operation" }, #define S_ANI_LZERO AFTER(S_ANI_RESET) { 5, "lzero","LZERO", "ANI forced listen time to zero" }, #define S_ANI_LNEG AFTER(S_ANI_LZERO) { 5, "lneg", "LNEG", "ANI calculated listen time < 0" }, #define S_MIB_ACKBAD AFTER(S_ANI_LNEG) { 5, "ackbad","ACKBAD", "missing ACK's" }, #define S_MIB_RTSBAD AFTER(S_MIB_ACKBAD) { 5, "rtsbad","RTSBAD", "RTS without CTS" }, #define S_MIB_RTSGOOD AFTER(S_MIB_RTSBAD) { 5, "rtsgood","RTSGOOD", "successful RTS" }, #define S_MIB_FCSBAD AFTER(S_MIB_RTSGOOD) { 5, "fcsbad","FCSBAD", "bad FCS" }, #define S_MIB_BEACONS AFTER(S_MIB_FCSBAD) { 5, "beacons","beacons", "beacons received" }, #define S_NODE_AVGBRSSI AFTER(S_MIB_BEACONS) { 3, "avgbrssi","BSI", "average rssi (beacons only)" }, #define S_NODE_AVGRSSI AFTER(S_NODE_AVGBRSSI) { 3, "avgrssi","DSI", "average rssi (all rx'd frames)" }, #define S_NODE_AVGARSSI AFTER(S_NODE_AVGRSSI) { 3, "avgtxrssi","TSI", "average rssi (ACKs only)" }, #define S_ANT_TX0 AFTER(S_NODE_AVGARSSI) #else #define S_ANT_TX0 AFTER(S_ANT_TXSWITCH) #endif /* ATH_SUPPORT_ANI */ { 8, "tx0", "ant0(tx)", "frames tx on antenna 0" }, #define S_ANT_TX1 AFTER(S_ANT_TX0) { 8, "tx1", "ant1(tx)", "frames tx on antenna 1" }, #define S_ANT_TX2 AFTER(S_ANT_TX1) { 8, "tx2", "ant2(tx)", "frames tx on antenna 2" }, #define S_ANT_TX3 AFTER(S_ANT_TX2) { 8, "tx3", "ant3(tx)", "frames tx on antenna 3" }, #define S_ANT_TX4 AFTER(S_ANT_TX3) { 8, "tx4", "ant4(tx)", "frames tx on antenna 4" }, #define S_ANT_TX5 AFTER(S_ANT_TX4) { 8, "tx5", "ant5(tx)", "frames tx on antenna 5" }, #define S_ANT_TX6 AFTER(S_ANT_TX5) { 8, "tx6", "ant6(tx)", "frames tx on antenna 6" }, #define S_ANT_TX7 AFTER(S_ANT_TX6) { 8, "tx7", "ant7(tx)", "frames tx on antenna 7" }, #define S_ANT_RX0 AFTER(S_ANT_TX7) { 8, "rx0", "ant0(rx)", "frames rx on antenna 0" }, #define S_ANT_RX1 AFTER(S_ANT_RX0) { 8, "rx1", "ant1(rx)", "frames rx on antenna 1" }, #define S_ANT_RX2 AFTER(S_ANT_RX1) { 8, "rx2", "ant2(rx)", "frames rx on antenna 2" }, #define S_ANT_RX3 AFTER(S_ANT_RX2) { 8, "rx3", "ant3(rx)", "frames rx on antenna 3" }, #define S_ANT_RX4 AFTER(S_ANT_RX3) { 8, "rx4", "ant4(rx)", "frames rx on antenna 4" }, #define S_ANT_RX5 AFTER(S_ANT_RX4) { 8, "rx5", "ant5(rx)", "frames rx on antenna 5" }, #define S_ANT_RX6 AFTER(S_ANT_RX5) { 8, "rx6", "ant6(rx)", "frames rx on antenna 6" }, #define S_ANT_RX7 AFTER(S_ANT_RX6) { 8, "rx7", "ant7(rx)", "frames rx on antenna 7" }, #define S_TX_SIGNAL AFTER(S_ANT_RX7) { 4, "asignal", "asig", "signal of last ack (dBm)" }, #define S_RX_SIGNAL AFTER(S_TX_SIGNAL) { 4, "signal", "sig", "avg recv signal (dBm)" }, #define S_BMISSCOUNT AFTER(S_RX_SIGNAL) { 8, "bmisscount", "bmisscnt", "beacon miss count" }, }; #define S_PHY_MIN S_RX_PHY_UNDERRUN #define S_PHY_MAX S_RX_PHY_CCK_RESTART #define S_LAST S_ANT_TX0 #define S_MAX S_BMISSCOUNT+1 struct _athstats { struct ath_stats ath; #ifdef ATH_SUPPORT_ANI HAL_ANI_STATS ani_stats; HAL_ANI_STATE ani_state; #endif }; struct athstatfoo_p { struct athstatfoo base; int s; int optstats; #define ATHSTATS_ANI 0x0001 struct ifreq ifr; struct ath_diag atd; struct _athstats cur; struct _athstats total; }; static void ath_setifname(struct athstatfoo *wf0, const char *ifname) { struct athstatfoo_p *wf = (struct athstatfoo_p *) wf0; strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name)); #ifdef ATH_SUPPORT_ANI strncpy(wf->atd.ad_name, ifname, sizeof (wf->atd.ad_name)); wf->optstats |= ATHSTATS_ANI; #endif } static void ath_zerostats(struct athstatfoo *wf0) { struct athstatfoo_p *wf = (struct athstatfoo_p *) wf0; if (ioctl(wf->s, SIOCZATHSTATS, &wf->ifr) < 0) err(-1, "ioctl: %s", wf->ifr.ifr_name); } static void ath_collect(struct athstatfoo_p *wf, struct _athstats *stats) { wf->ifr.ifr_data = (caddr_t) &stats->ath; if (ioctl(wf->s, SIOCGATHSTATS, &wf->ifr) < 0) err(1, "ioctl: %s", wf->ifr.ifr_name); #ifdef ATH_SUPPORT_ANI if (wf->optstats & ATHSTATS_ANI) { wf->atd.ad_id = HAL_DIAG_ANI_CURRENT; /* HAL_DIAG_ANI_CURRENT */ wf->atd.ad_out_data = (caddr_t) &stats->ani_state; wf->atd.ad_out_size = sizeof(stats->ani_state); if (ioctl(wf->s, SIOCGATHDIAG, &wf->atd) < 0) { warn("ioctl: %s", wf->atd.ad_name); wf->optstats &= ~ATHSTATS_ANI; } wf->atd.ad_id = HAL_DIAG_ANI_STATS; /* HAL_DIAG_ANI_STATS */ wf->atd.ad_out_data = (caddr_t) &stats->ani_stats; wf->atd.ad_out_size = sizeof(stats->ani_stats); if (ioctl(wf->s, SIOCGATHDIAG, &wf->atd) < 0) warn("ioctl: %s", wf->atd.ad_name); } #endif /* ATH_SUPPORT_ANI */ } static void ath_collect_cur(struct bsdstat *sf) { struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; ath_collect(wf, &wf->cur); } static void ath_collect_tot(struct bsdstat *sf) { struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; ath_collect(wf, &wf->total); } static void ath_update_tot(struct bsdstat *sf) { struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; wf->total = wf->cur; } static void snprintrate(char b[], size_t bs, int rate) { if (rate & IEEE80211_RATE_MCS) snprintf(b, bs, "MCS%u", rate &~ IEEE80211_RATE_MCS); else if (rate & 1) snprintf(b, bs, "%u.5M", rate / 2); else snprintf(b, bs, "%uM", rate / 2); } static int ath_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->cur.ath.ast_##x - wf->total.ath.ast_##x); return 1 #define PHY(x) \ snprintf(b, bs, "%u", wf->cur.ath.ast_rx_phy[x] - wf->total.ath.ast_rx_phy[x]); return 1 #define ANI(x) \ snprintf(b, bs, "%u", wf->cur.ani_state.x); return 1 #define ANISTAT(x) \ snprintf(b, bs, "%u", wf->cur.ani_stats.ast_ani_##x - wf->total.ani_stats.ast_ani_##x); return 1 #define MIBSTAT(x) \ snprintf(b, bs, "%u", wf->cur.ani_stats.ast_mibstats.x - wf->total.ani_stats.ast_mibstats.x); return 1 #define TXANT(x) \ snprintf(b, bs, "%u", wf->cur.ath.ast_ant_tx[x] - wf->total.ath.ast_ant_tx[x]); return 1 #define RXANT(x) \ snprintf(b, bs, "%u", wf->cur.ath.ast_ant_rx[x] - wf->total.ath.ast_ant_rx[x]); return 1 switch (s) { case S_INPUT: snprintf(b, bs, "%lu", (unsigned long) ((wf->cur.ath.ast_rx_packets - wf->total.ath.ast_rx_packets) - (wf->cur.ath.ast_rx_mgt - wf->total.ath.ast_rx_mgt))); return 1; case S_OUTPUT: snprintf(b, bs, "%lu", (unsigned long) (wf->cur.ath.ast_tx_packets - wf->total.ath.ast_tx_packets)); return 1; case S_RATE: snprintrate(b, bs, wf->cur.ath.ast_tx_rate); return 1; case S_WATCHDOG: STAT(watchdog); case S_FATAL: STAT(hardware); case S_BMISS: STAT(bmiss); case S_BMISS_PHANTOM: STAT(bmiss_phantom); #ifdef S_BSTUCK case S_BSTUCK: STAT(bstuck); #endif case S_RXORN: STAT(rxorn); case S_RXEOL: STAT(rxeol); case S_TXURN: STAT(txurn); case S_MIB: STAT(mib); #ifdef S_INTRCOAL case S_INTRCOAL: STAT(intrcoal); #endif case S_TX_MGMT: STAT(tx_mgmt); case S_TX_DISCARD: STAT(tx_discard); case S_TX_QSTOP: STAT(tx_qstop); case S_TX_ENCAP: STAT(tx_encap); case S_TX_NONODE: STAT(tx_nonode); case S_TX_NOBUF: STAT(tx_nobuf); case S_TX_NOFRAG: STAT(tx_nofrag); case S_TX_NOMBUF: STAT(tx_nombuf); #ifdef S_TX_NOMCL case S_TX_NOMCL: STAT(tx_nomcl); case S_TX_LINEAR: STAT(tx_linear); case S_TX_NODATA: STAT(tx_nodata); case S_TX_BUSDMA: STAT(tx_busdma); #endif case S_TX_XRETRIES: STAT(tx_xretries); case S_TX_FIFOERR: STAT(tx_fifoerr); case S_TX_FILTERED: STAT(tx_filtered); case S_TX_SHORTRETRY: STAT(tx_shortretry); case S_TX_LONGRETRY: STAT(tx_longretry); case S_TX_BADRATE: STAT(tx_badrate); case S_TX_NOACK: STAT(tx_noack); case S_TX_RTS: STAT(tx_rts); case S_TX_CTS: STAT(tx_cts); case S_TX_SHORTPRE: STAT(tx_shortpre); case S_TX_ALTRATE: STAT(tx_altrate); case S_TX_PROTECT: STAT(tx_protect); case S_TX_RAW: STAT(tx_raw); case S_TX_RAW_FAIL: STAT(tx_raw_fail); case S_RX_NOMBUF: STAT(rx_nombuf); #ifdef S_RX_BUSDMA case S_RX_BUSDMA: STAT(rx_busdma); #endif case S_RX_ORN: STAT(rx_orn); case S_RX_CRC_ERR: STAT(rx_crcerr); case S_RX_FIFO_ERR: STAT(rx_fifoerr); case S_RX_CRYPTO_ERR: STAT(rx_badcrypt); case S_RX_MIC_ERR: STAT(rx_badmic); case S_RX_PHY_ERR: STAT(rx_phyerr); case S_RX_PHY_UNDERRUN: PHY(HAL_PHYERR_UNDERRUN); case S_RX_PHY_TIMING: PHY(HAL_PHYERR_TIMING); case S_RX_PHY_PARITY: PHY(HAL_PHYERR_PARITY); case S_RX_PHY_RATE: PHY(HAL_PHYERR_RATE); case S_RX_PHY_LENGTH: PHY(HAL_PHYERR_LENGTH); case S_RX_PHY_RADAR: PHY(HAL_PHYERR_RADAR); case S_RX_PHY_SERVICE: PHY(HAL_PHYERR_SERVICE); case S_RX_PHY_TOR: PHY(HAL_PHYERR_TOR); case S_RX_PHY_OFDM_TIMING: PHY(HAL_PHYERR_OFDM_TIMING); case S_RX_PHY_OFDM_SIGNAL_PARITY: PHY(HAL_PHYERR_OFDM_SIGNAL_PARITY); case S_RX_PHY_OFDM_RATE_ILLEGAL: PHY(HAL_PHYERR_OFDM_RATE_ILLEGAL); case S_RX_PHY_OFDM_POWER_DROP: PHY(HAL_PHYERR_OFDM_POWER_DROP); case S_RX_PHY_OFDM_SERVICE: PHY(HAL_PHYERR_OFDM_SERVICE); case S_RX_PHY_OFDM_RESTART: PHY(HAL_PHYERR_OFDM_RESTART); case S_RX_PHY_CCK_TIMING: PHY(HAL_PHYERR_CCK_TIMING); case S_RX_PHY_CCK_HEADER_CRC: PHY(HAL_PHYERR_CCK_HEADER_CRC); case S_RX_PHY_CCK_RATE_ILLEGAL: PHY(HAL_PHYERR_CCK_RATE_ILLEGAL); case S_RX_PHY_CCK_SERVICE: PHY(HAL_PHYERR_CCK_SERVICE); case S_RX_PHY_CCK_RESTART: PHY(HAL_PHYERR_CCK_RESTART); case S_RX_TOOSHORT: STAT(rx_tooshort); case S_RX_TOOBIG: STAT(rx_toobig); case S_RX_MGT: STAT(rx_mgt); case S_RX_CTL: STAT(rx_ctl); case S_TX_RSSI: snprintf(b, bs, "%d", wf->cur.ath.ast_tx_rssi); return 1; case S_RX_RSSI: snprintf(b, bs, "%d", wf->cur.ath.ast_rx_rssi); return 1; case S_BE_XMIT: STAT(be_xmit); case S_BE_NOMBUF: STAT(be_nombuf); case S_PER_CAL: STAT(per_cal); case S_PER_CALFAIL: STAT(per_calfail); case S_PER_RFGAIN: STAT(per_rfgain); #ifdef S_TDMA_UPDATE case S_TDMA_UPDATE: STAT(tdma_update); case S_TDMA_TIMERS: STAT(tdma_timers); case S_TDMA_TSF: STAT(tdma_tsf); case S_TDMA_TSFADJ: snprintf(b, bs, "-%d/+%d", wf->cur.ath.ast_tdma_tsfadjm, wf->cur.ath.ast_tdma_tsfadjp); return 1; case S_TDMA_ACK: STAT(tdma_ack); #endif case S_RATE_CALLS: STAT(rate_calls); case S_RATE_RAISE: STAT(rate_raise); case S_RATE_DROP: STAT(rate_drop); case S_ANT_DEFSWITCH: STAT(ant_defswitch); case S_ANT_TXSWITCH: STAT(ant_txswitch); #ifdef S_ANI_NOISE case S_ANI_NOISE: ANI(noiseImmunityLevel); case S_ANI_SPUR: ANI(spurImmunityLevel); case S_ANI_STEP: ANI(firstepLevel); case S_ANI_OFDM: ANI(ofdmWeakSigDetectOff); case S_ANI_CCK: ANI(cckWeakSigThreshold); case S_ANI_LISTEN: ANI(listenTime); case S_ANI_NIUP: ANISTAT(niup); case S_ANI_NIDOWN: ANISTAT(nidown); case S_ANI_SIUP: ANISTAT(spurup); case S_ANI_SIDOWN: ANISTAT(spurdown); case S_ANI_OFDMON: ANISTAT(ofdmon); case S_ANI_OFDMOFF: ANISTAT(ofdmoff); case S_ANI_CCKHI: ANISTAT(cckhigh); case S_ANI_CCKLO: ANISTAT(ccklow); case S_ANI_STEPUP: ANISTAT(stepup); case S_ANI_STEPDOWN: ANISTAT(stepdown); case S_ANI_OFDMERRS: ANISTAT(ofdmerrs); case S_ANI_CCKERRS: ANISTAT(cckerrs); case S_ANI_RESET: ANISTAT(reset); case S_ANI_LZERO: ANISTAT(lzero); case S_ANI_LNEG: ANISTAT(lneg); case S_MIB_ACKBAD: MIBSTAT(ackrcv_bad); case S_MIB_RTSBAD: MIBSTAT(rts_bad); case S_MIB_RTSGOOD: MIBSTAT(rts_good); case S_MIB_FCSBAD: MIBSTAT(fcs_bad); case S_MIB_BEACONS: MIBSTAT(beacons); case S_NODE_AVGBRSSI: snprintf(b, bs, "%u", HAL_RSSI(wf->cur.ani_stats.ast_nodestats.ns_avgbrssi)); return 1; case S_NODE_AVGRSSI: snprintf(b, bs, "%u", HAL_RSSI(wf->cur.ani_stats.ast_nodestats.ns_avgrssi)); return 1; case S_NODE_AVGARSSI: snprintf(b, bs, "%u", HAL_RSSI(wf->cur.ani_stats.ast_nodestats.ns_avgtxrssi)); return 1; #endif case S_ANT_TX0: TXANT(0); case S_ANT_TX1: TXANT(1); case S_ANT_TX2: TXANT(2); case S_ANT_TX3: TXANT(3); case S_ANT_TX4: TXANT(4); case S_ANT_TX5: TXANT(5); case S_ANT_TX6: TXANT(6); case S_ANT_TX7: TXANT(7); case S_ANT_RX0: RXANT(0); case S_ANT_RX1: RXANT(1); case S_ANT_RX2: RXANT(2); case S_ANT_RX3: RXANT(3); case S_ANT_RX4: RXANT(4); case S_ANT_RX5: RXANT(5); case S_ANT_RX6: RXANT(6); case S_ANT_RX7: RXANT(7); #ifdef S_CABQ_XMIT case S_CABQ_XMIT: STAT(cabq_xmit); case S_CABQ_BUSY: STAT(cabq_busy); #endif case S_FF_TXOK: STAT(ff_txok); case S_FF_TXERR: STAT(ff_txerr); case S_FF_RX: STAT(ff_rx); case S_FF_FLUSH: STAT(ff_flush); case S_TX_QFULL: STAT(tx_qfull); case S_BMISSCOUNT: STAT(be_missed); case S_RX_NOISE: snprintf(b, bs, "%d", wf->cur.ath.ast_rx_noise); return 1; case S_TX_SIGNAL: snprintf(b, bs, "%d", wf->cur.ath.ast_tx_rssi + wf->cur.ath.ast_rx_noise); return 1; case S_RX_SIGNAL: snprintf(b, bs, "%d", wf->cur.ath.ast_rx_rssi + wf->cur.ath.ast_rx_noise); return 1; case S_RX_AGG: STAT(rx_agg); case S_RX_HALFGI: STAT(rx_halfgi); case S_RX_2040: STAT(rx_2040); case S_RX_PRE_CRC_ERR: STAT(rx_pre_crc_err); case S_RX_POST_CRC_ERR: STAT(rx_post_crc_err); case S_RX_DECRYPT_BUSY_ERR: STAT(rx_decrypt_busy_err); case S_RX_HI_CHAIN: STAT(rx_hi_rx_chain); case S_RX_STBC: STAT(rx_stbc); case S_TX_HTPROTECT: STAT(tx_htprotect); case S_RX_QEND: STAT(rx_hitqueueend); case S_TX_TIMEOUT: STAT(tx_timeout); case S_TX_CSTIMEOUT: STAT(tx_cst); case S_TX_XTXOP_ERR: STAT(tx_xtxop); case S_TX_TIMEREXPIRED_ERR: STAT(tx_timerexpired); case S_TX_DESCCFG_ERR: STAT(tx_desccfgerr); case S_TX_SWRETRIES: STAT(tx_swretries); case S_TX_SWRETRIES_MAX: STAT(tx_swretrymax); case S_TX_DATA_UNDERRUN: STAT(tx_data_underrun); case S_TX_DELIM_UNDERRUN: STAT(tx_delim_underrun); case S_TX_AGGR_OK: STAT(tx_aggr_ok); case S_TX_AGGR_FAIL: STAT(tx_aggr_fail); case S_TX_AGGR_FAILALL: STAT(tx_aggr_failall); } b[0] = '\0'; return 0; #undef RXANT #undef TXANT #undef ANI #undef ANISTAT #undef MIBSTAT #undef PHY #undef STAT } static int ath_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->total.ath.ast_##x); return 1 #define PHY(x) \ snprintf(b, bs, "%u", wf->total.ath.ast_rx_phy[x]); return 1 #define ANI(x) \ snprintf(b, bs, "%u", wf->total.ani_state.x); return 1 #define ANISTAT(x) \ snprintf(b, bs, "%u", wf->total.ani_stats.ast_ani_##x); return 1 #define MIBSTAT(x) \ snprintf(b, bs, "%u", wf->total.ani_stats.ast_mibstats.x); return 1 #define TXANT(x) \ snprintf(b, bs, "%u", wf->total.ath.ast_ant_tx[x]); return 1 #define RXANT(x) \ snprintf(b, bs, "%u", wf->total.ath.ast_ant_rx[x]); return 1 switch (s) { case S_INPUT: snprintf(b, bs, "%lu", (unsigned long) wf->total.ath.ast_rx_packets - (unsigned long) wf->total.ath.ast_rx_mgt); return 1; case S_OUTPUT: snprintf(b, bs, "%lu", (unsigned long) wf->total.ath.ast_tx_packets); return 1; case S_RATE: snprintrate(b, bs, wf->total.ath.ast_tx_rate); return 1; case S_WATCHDOG: STAT(watchdog); case S_FATAL: STAT(hardware); case S_BMISS: STAT(bmiss); case S_BMISS_PHANTOM: STAT(bmiss_phantom); #ifdef S_BSTUCK case S_BSTUCK: STAT(bstuck); #endif case S_RXORN: STAT(rxorn); case S_RXEOL: STAT(rxeol); case S_TXURN: STAT(txurn); case S_MIB: STAT(mib); #ifdef S_INTRCOAL case S_INTRCOAL: STAT(intrcoal); #endif case S_TX_MGMT: STAT(tx_mgmt); case S_TX_DISCARD: STAT(tx_discard); case S_TX_QSTOP: STAT(tx_qstop); case S_TX_ENCAP: STAT(tx_encap); case S_TX_NONODE: STAT(tx_nonode); case S_TX_NOBUF: STAT(tx_nobuf); case S_TX_NOFRAG: STAT(tx_nofrag); case S_TX_NOMBUF: STAT(tx_nombuf); #ifdef S_TX_NOMCL case S_TX_NOMCL: STAT(tx_nomcl); case S_TX_LINEAR: STAT(tx_linear); case S_TX_NODATA: STAT(tx_nodata); case S_TX_BUSDMA: STAT(tx_busdma); #endif case S_TX_XRETRIES: STAT(tx_xretries); case S_TX_FIFOERR: STAT(tx_fifoerr); case S_TX_FILTERED: STAT(tx_filtered); case S_TX_SHORTRETRY: STAT(tx_shortretry); case S_TX_LONGRETRY: STAT(tx_longretry); case S_TX_BADRATE: STAT(tx_badrate); case S_TX_NOACK: STAT(tx_noack); case S_TX_RTS: STAT(tx_rts); case S_TX_CTS: STAT(tx_cts); case S_TX_SHORTPRE: STAT(tx_shortpre); case S_TX_ALTRATE: STAT(tx_altrate); case S_TX_PROTECT: STAT(tx_protect); case S_TX_RAW: STAT(tx_raw); case S_TX_RAW_FAIL: STAT(tx_raw_fail); case S_RX_NOMBUF: STAT(rx_nombuf); #ifdef S_RX_BUSDMA case S_RX_BUSDMA: STAT(rx_busdma); #endif case S_RX_ORN: STAT(rx_orn); case S_RX_CRC_ERR: STAT(rx_crcerr); case S_RX_FIFO_ERR: STAT(rx_fifoerr); case S_RX_CRYPTO_ERR: STAT(rx_badcrypt); case S_RX_MIC_ERR: STAT(rx_badmic); case S_RX_PHY_ERR: STAT(rx_phyerr); case S_RX_PHY_UNDERRUN: PHY(HAL_PHYERR_UNDERRUN); case S_RX_PHY_TIMING: PHY(HAL_PHYERR_TIMING); case S_RX_PHY_PARITY: PHY(HAL_PHYERR_PARITY); case S_RX_PHY_RATE: PHY(HAL_PHYERR_RATE); case S_RX_PHY_LENGTH: PHY(HAL_PHYERR_LENGTH); case S_RX_PHY_RADAR: PHY(HAL_PHYERR_RADAR); case S_RX_PHY_SERVICE: PHY(HAL_PHYERR_SERVICE); case S_RX_PHY_TOR: PHY(HAL_PHYERR_TOR); case S_RX_PHY_OFDM_TIMING: PHY(HAL_PHYERR_OFDM_TIMING); case S_RX_PHY_OFDM_SIGNAL_PARITY: PHY(HAL_PHYERR_OFDM_SIGNAL_PARITY); case S_RX_PHY_OFDM_RATE_ILLEGAL: PHY(HAL_PHYERR_OFDM_RATE_ILLEGAL); case S_RX_PHY_OFDM_POWER_DROP: PHY(HAL_PHYERR_OFDM_POWER_DROP); case S_RX_PHY_OFDM_SERVICE: PHY(HAL_PHYERR_OFDM_SERVICE); case S_RX_PHY_OFDM_RESTART: PHY(HAL_PHYERR_OFDM_RESTART); case S_RX_PHY_CCK_TIMING: PHY(HAL_PHYERR_CCK_TIMING); case S_RX_PHY_CCK_HEADER_CRC: PHY(HAL_PHYERR_CCK_HEADER_CRC); case S_RX_PHY_CCK_RATE_ILLEGAL: PHY(HAL_PHYERR_CCK_RATE_ILLEGAL); case S_RX_PHY_CCK_SERVICE: PHY(HAL_PHYERR_CCK_SERVICE); case S_RX_PHY_CCK_RESTART: PHY(HAL_PHYERR_CCK_RESTART); case S_RX_TOOSHORT: STAT(rx_tooshort); case S_RX_TOOBIG: STAT(rx_toobig); case S_RX_MGT: STAT(rx_mgt); case S_RX_CTL: STAT(rx_ctl); case S_TX_RSSI: snprintf(b, bs, "%d", wf->total.ath.ast_tx_rssi); return 1; case S_RX_RSSI: snprintf(b, bs, "%d", wf->total.ath.ast_rx_rssi); return 1; case S_BE_XMIT: STAT(be_xmit); case S_BE_NOMBUF: STAT(be_nombuf); case S_PER_CAL: STAT(per_cal); case S_PER_CALFAIL: STAT(per_calfail); case S_PER_RFGAIN: STAT(per_rfgain); #ifdef S_TDMA_UPDATE case S_TDMA_UPDATE: STAT(tdma_update); case S_TDMA_TIMERS: STAT(tdma_timers); case S_TDMA_TSF: STAT(tdma_tsf); case S_TDMA_TSFADJ: snprintf(b, bs, "-%d/+%d", wf->total.ath.ast_tdma_tsfadjm, wf->total.ath.ast_tdma_tsfadjp); return 1; case S_TDMA_ACK: STAT(tdma_ack); #endif case S_RATE_CALLS: STAT(rate_calls); case S_RATE_RAISE: STAT(rate_raise); case S_RATE_DROP: STAT(rate_drop); case S_ANT_DEFSWITCH: STAT(ant_defswitch); case S_ANT_TXSWITCH: STAT(ant_txswitch); #ifdef S_ANI_NOISE case S_ANI_NOISE: ANI(noiseImmunityLevel); case S_ANI_SPUR: ANI(spurImmunityLevel); case S_ANI_STEP: ANI(firstepLevel); case S_ANI_OFDM: ANI(ofdmWeakSigDetectOff); case S_ANI_CCK: ANI(cckWeakSigThreshold); case S_ANI_LISTEN: ANI(listenTime); case S_ANI_NIUP: ANISTAT(niup); case S_ANI_NIDOWN: ANISTAT(nidown); case S_ANI_SIUP: ANISTAT(spurup); case S_ANI_SIDOWN: ANISTAT(spurdown); case S_ANI_OFDMON: ANISTAT(ofdmon); case S_ANI_OFDMOFF: ANISTAT(ofdmoff); case S_ANI_CCKHI: ANISTAT(cckhigh); case S_ANI_CCKLO: ANISTAT(ccklow); case S_ANI_STEPUP: ANISTAT(stepup); case S_ANI_STEPDOWN: ANISTAT(stepdown); case S_ANI_OFDMERRS: ANISTAT(ofdmerrs); case S_ANI_CCKERRS: ANISTAT(cckerrs); case S_ANI_RESET: ANISTAT(reset); case S_ANI_LZERO: ANISTAT(lzero); case S_ANI_LNEG: ANISTAT(lneg); case S_MIB_ACKBAD: MIBSTAT(ackrcv_bad); case S_MIB_RTSBAD: MIBSTAT(rts_bad); case S_MIB_RTSGOOD: MIBSTAT(rts_good); case S_MIB_FCSBAD: MIBSTAT(fcs_bad); case S_MIB_BEACONS: MIBSTAT(beacons); case S_NODE_AVGBRSSI: snprintf(b, bs, "%u", HAL_RSSI(wf->total.ani_stats.ast_nodestats.ns_avgbrssi)); return 1; case S_NODE_AVGRSSI: snprintf(b, bs, "%u", HAL_RSSI(wf->total.ani_stats.ast_nodestats.ns_avgrssi)); return 1; case S_NODE_AVGARSSI: snprintf(b, bs, "%u", HAL_RSSI(wf->total.ani_stats.ast_nodestats.ns_avgtxrssi)); return 1; #endif case S_ANT_TX0: TXANT(0); case S_ANT_TX1: TXANT(1); case S_ANT_TX2: TXANT(2); case S_ANT_TX3: TXANT(3); case S_ANT_TX4: TXANT(4); case S_ANT_TX5: TXANT(5); case S_ANT_TX6: TXANT(6); case S_ANT_TX7: TXANT(7); case S_ANT_RX0: RXANT(0); case S_ANT_RX1: RXANT(1); case S_ANT_RX2: RXANT(2); case S_ANT_RX3: RXANT(3); case S_ANT_RX4: RXANT(4); case S_ANT_RX5: RXANT(5); case S_ANT_RX6: RXANT(6); case S_ANT_RX7: RXANT(7); #ifdef S_CABQ_XMIT case S_CABQ_XMIT: STAT(cabq_xmit); case S_CABQ_BUSY: STAT(cabq_busy); #endif case S_FF_TXOK: STAT(ff_txok); case S_FF_TXERR: STAT(ff_txerr); case S_FF_RX: STAT(ff_rx); case S_FF_FLUSH: STAT(ff_flush); case S_TX_QFULL: STAT(tx_qfull); case S_BMISSCOUNT: STAT(be_missed); case S_RX_NOISE: snprintf(b, bs, "%d", wf->total.ath.ast_rx_noise); return 1; case S_TX_SIGNAL: snprintf(b, bs, "%d", wf->total.ath.ast_tx_rssi + wf->total.ath.ast_rx_noise); return 1; case S_RX_SIGNAL: snprintf(b, bs, "%d", wf->total.ath.ast_rx_rssi + wf->total.ath.ast_rx_noise); return 1; case S_RX_AGG: STAT(rx_agg); case S_RX_HALFGI: STAT(rx_halfgi); case S_RX_2040: STAT(rx_2040); case S_RX_PRE_CRC_ERR: STAT(rx_pre_crc_err); case S_RX_POST_CRC_ERR: STAT(rx_post_crc_err); case S_RX_DECRYPT_BUSY_ERR: STAT(rx_decrypt_busy_err); case S_RX_HI_CHAIN: STAT(rx_hi_rx_chain); case S_RX_STBC: STAT(rx_stbc); case S_TX_HTPROTECT: STAT(tx_htprotect); case S_RX_QEND: STAT(rx_hitqueueend); case S_TX_TIMEOUT: STAT(tx_timeout); case S_TX_CSTIMEOUT: STAT(tx_cst); case S_TX_XTXOP_ERR: STAT(tx_xtxop); case S_TX_TIMEREXPIRED_ERR: STAT(tx_timerexpired); case S_TX_DESCCFG_ERR: STAT(tx_desccfgerr); case S_TX_SWRETRIES: STAT(tx_swretries); case S_TX_SWRETRIES_MAX: STAT(tx_swretrymax); case S_TX_DATA_UNDERRUN: STAT(tx_data_underrun); case S_TX_DELIM_UNDERRUN: STAT(tx_delim_underrun); case S_TX_AGGR_OK: STAT(tx_aggr_ok); case S_TX_AGGR_FAIL: STAT(tx_aggr_fail); case S_TX_AGGR_FAILALL: STAT(tx_aggr_failall); } b[0] = '\0'; return 0; #undef RXANT #undef TXANT #undef ANI #undef ANISTAT #undef MIBSTAT #undef PHY #undef STAT } static void ath_print_verbose(struct bsdstat *sf, FILE *fd) { struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; #define isphyerr(i) (S_PHY_MIN <= i && i <= S_PHY_MAX) const struct fmt *f; char s[32]; const char *indent; int i, width; width = 0; for (i = 0; i < S_LAST; i++) { f = &sf->stats[i]; if (!isphyerr(i) && f->width > width) width = f->width; } for (i = 0; i < S_LAST; i++) { if (ath_get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) { if (isphyerr(i)) indent = " "; else indent = ""; fprintf(fd, "%s%-*s %s\n", indent, width, s, athstats[i].desc); } } fprintf(fd, "Antenna profile:\n"); for (i = 0; i < 8; i++) if (wf->total.ath.ast_ant_rx[i] || wf->total.ath.ast_ant_tx[i]) fprintf(fd, "[%u] tx %8u rx %8u\n", i, wf->total.ath.ast_ant_tx[i], wf->total.ath.ast_ant_rx[i]); #undef isphyerr } BSDSTAT_DEFINE_BOUNCE(athstatfoo) struct athstatfoo * athstats_new(const char *ifname, const char *fmtstring) { -#define N(a) (sizeof(a) / sizeof(a[0])) struct athstatfoo_p *wf; wf = calloc(1, sizeof(struct athstatfoo_p)); if (wf != NULL) { - bsdstat_init(&wf->base.base, "athstats", athstats, N(athstats)); + bsdstat_init(&wf->base.base, "athstats", athstats, + nitems(athstats)); /* override base methods */ wf->base.base.collect_cur = ath_collect_cur; wf->base.base.collect_tot = ath_collect_tot; wf->base.base.get_curstat = ath_get_curstat; wf->base.base.get_totstat = ath_get_totstat; wf->base.base.update_tot = ath_update_tot; wf->base.base.print_verbose = ath_print_verbose; /* setup bounce functions for public methods */ BSDSTAT_BOUNCE(wf, athstatfoo); /* setup our public methods */ wf->base.setifname = ath_setifname; #if 0 wf->base.setstamac = wlan_setstamac; #endif wf->base.zerostats = ath_zerostats; wf->s = socket(AF_INET, SOCK_DGRAM, 0); if (wf->s < 0) err(1, "socket"); ath_setifname(&wf->base, ifname); wf->base.setfmt(&wf->base, fmtstring); } return &wf->base; -#undef N } Index: head/tools/tools/ath/athstats/main.c =================================================================== --- head/tools/tools/ath/athstats/main.c (revision 287296) +++ head/tools/tools/ath/athstats/main.c (revision 287297) @@ -1,164 +1,164 @@ /*- * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * Simple Atheros-specific tool to inspect and monitor network traffic * statistics. * * athstats [-i interface] [-bz] [-l] [-o fmtstring] [interval] * * (default interface is ath0). If interval is specified a rolling output * a la netstat -i is displayed every interval seconds. The format of * the rolling display can be controlled a la ps. The -l option will * print a list of all possible statistics for use with the -o option. */ +#include + +#include +#include #include #include -#include -#include #include -#include +#include #include "athstats.h" static struct { const char *tag; const char *fmt; } tags[] = { { "default", "input,output,altrate,short,long,xretry,crcerr,crypt,phyerr,rssi,rate" }, { "ani", "avgbrssi,avgrssi,avgtxrssi,NI,SI,step,owsd,cwst,NI+,NI-,SI+,SI-,OFDM,CCK,LISTEN" }, { "tdma", "input,output,bexmit,tdmau,tdmadj,crcerr,phyerr,phytor,rssi,noise,rate" }, }; static const char * getfmt(const char *tag) { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; - for (i = 0; i < N(tags); i++) + for (i = 0; i < nitems(tags); i++) if (strcasecmp(tags[i].tag, tag) == 0) return tags[i].fmt; return tag; -#undef N } static int signalled; static void catchalarm(int signo __unused) { signalled = 1; } int main(int argc, char *argv[]) { struct athstatfoo *wf; const char *ifname; int c, banner = 1; ifname = getenv("ATH"); if (ifname == NULL) ifname = "ath0"; wf = athstats_new(ifname, getfmt("default")); while ((c = getopt(argc, argv, "bi:lo:z")) != -1) { switch (c) { case 'b': banner = 0; break; case 'i': wf->setifname(wf, optarg); break; case 'l': wf->print_fields(wf, stdout); return 0; case 'o': wf->setfmt(wf, getfmt(optarg)); break; case 'z': wf->zerostats(wf); break; default: errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] [-z] [interval]\n", argv[0]); /*NOTREACHED*/ } } argc -= optind; argv += optind; if (argc > 0) { u_long interval = strtoul(argv[0], NULL, 0); int line, omask; if (interval < 1) interval = 1; signal(SIGALRM, catchalarm); signalled = 0; alarm(interval); banner: if (banner) wf->print_header(wf, stdout); line = 0; loop: if (line != 0) { wf->collect_cur(wf); wf->print_current(wf, stdout); wf->update_tot(wf); } else { wf->collect_tot(wf); wf->print_total(wf, stdout); } fflush(stdout); omask = sigblock(sigmask(SIGALRM)); if (!signalled) sigpause(0); sigsetmask(omask); signalled = 0; alarm(interval); line++; if (line == 21) /* XXX tty line count */ goto banner; else goto loop; /*NOTREACHED*/ } else { wf->collect_tot(wf); wf->print_verbose(wf, stdout); } return 0; } Index: head/tools/tools/ath/common/ah_osdep.h =================================================================== --- head/tools/tools/ath/common/ah_osdep.h (revision 287296) +++ head/tools/tools/ath/common/ah_osdep.h (revision 287297) @@ -1,76 +1,78 @@ /*- * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ #ifndef _ATH_AH_OSDEP_H_ #define _ATH_AH_OSDEP_H_ /* * Atheros Hardware Access Layer (HAL) OS Dependent Definitions. */ #include +#include + /* * Bus i/o type definitions. */ typedef void *HAL_SOFTC; typedef int HAL_BUS_TAG; typedef void *HAL_BUS_HANDLE; typedef uint32_t HAL_DMA_ADDR; #define OS_DELAY(_n) DELAY(_n) #define OS_INLINE __inline #define OS_MEMZERO(_a, _size) bzero((_a), (_size)) #define OS_MEMCPY(_dst, _src, _size) bcopy((_src), (_dst), (_size)) #define OS_MACEQU(_a, _b) \ (bcmp((_a), (_b), IEEE80211_ADDR_LEN) == 0) struct ath_hal; extern u_int32_t OS_GETUPTIME(struct ath_hal *); extern void OS_REG_WRITE(struct ath_hal *, u_int32_t, u_int32_t); extern u_int32_t OS_REG_READ(struct ath_hal *, u_int32_t); extern void OS_MARK(struct ath_hal *, u_int id, u_int32_t value); #define OS_GETUPTIME(_ah) 0 #define OS_REG_WRITE(_ah, _reg, _val) #define OS_REG_READ(_ah, _reg) 0 #define OS_MARK(_ah, _id, _v) #define __packed __attribute__((__packed__)) /* * Linux/BSD gcc compatibility shims. */ #ifndef __printflike #define __printflike(_a,_b) \ __attribute__ ((__format__ (__printf__, _a, _b))) #endif #include #ifndef __va_list #define __va_list va_list #endif #define OS_INLINE __inline #endif /* _ATH_AH_OSDEP_H_ */ Index: head/tools/tools/ath/common/dumpregs_5210.c =================================================================== --- head/tools/tools/ath/common/dumpregs_5210.c (revision 287296) +++ head/tools/tools/ath/common/dumpregs_5210.c (revision 287297) @@ -1,125 +1,126 @@ /*- * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ + +#include + #include "diag.h" #include "ah.h" #include "ah_internal.h" #include "ar5210/ar5210reg.h" #include "ar5210/ar5210phy.h" #include "dumpregs.h" -#define N(a) (sizeof(a) / sizeof(a[0])) - static struct dumpreg ar5210regs[] = { DEFBASIC(AR_TXDP0, "TXDP0"), DEFBASIC(AR_TXDP1, "TXDP1"), DEFBASICfmt(AR_CR, "CR", AR_CR_BITS), DEFBASIC(AR_RXDP, "RXDP"), DEFBASICfmt(AR_CFG, "CFG", AR_CFG_BITS), /* NB: read clears pending interrupts */ DEFVOIDfmt(AR_ISR, "ISR", AR_ISR_BITS), DEFBASICfmt(AR_IMR, "IMR", AR_IMR_BITS), DEFBASICfmt(AR_IER, "IER", AR_IER_BITS), DEFBASICfmt(AR_BCR, "BCR", AR_BCR_BITS), DEFBASICfmt(AR_BSR, "BSR", AR_BSR_BITS), DEFBASICfmt(AR_TXCFG, "TXCFG", AR_TXCFG_BITS), DEFBASIC(AR_RXCFG, "RXCFG"), DEFBASIC(AR_MIBC, "MIBC"), DEFBASIC(AR_TOPS, "TOPS"), DEFBASIC(AR_RXNOFRM, "RXNOFR"), DEFBASIC(AR_TXNOFRM, "TXNOFR"), DEFBASIC(AR_RPGTO, "RPGTO"), DEFBASIC(AR_RFCNT, "RFCNT"), DEFBASIC(AR_MISC, "MISC"), DEFBASICfmt(AR_RC, "RC", AR_RC_BITS), DEFBASICfmt(AR_SCR, "SCR", AR_SCR_BITS), DEFBASICfmt(AR_INTPEND, "INTPEND", AR_INTPEND_BITS), DEFBASIC(AR_SFR, "SFR"), DEFBASICfmt(AR_PCICFG, "PCICFG", AR_PCICFG_BITS), DEFBASIC(AR_GPIOCR, "GPIOCR"), DEFVOID(AR_GPIODO, "GPIODO"), DEFVOID(AR_GPIODI, "GPIODI"), DEFBASIC(AR_SREV, "SREV"), DEFBASIC(AR_STA_ID0, "STA_ID0"), DEFBASICfmt(AR_STA_ID1, "STA_ID1", AR_STA_ID1_BITS), DEFBASIC(AR_BSS_ID0, "BSS_ID0"), DEFBASIC(AR_BSS_ID1, "BSS_ID1"), DEFBASIC(AR_SLOT_TIME, "SLOTTIME"), DEFBASIC(AR_TIME_OUT, "TIME_OUT"), DEFBASIC(AR_RSSI_THR, "RSSI_THR"), DEFBASIC(AR_RETRY_LMT, "RETRY_LM"), DEFBASIC(AR_USEC, "USEC"), DEFBASICfmt(AR_BEACON, "BEACON", AR_BEACON_BITS), DEFBASIC(AR_CFP_PERIOD, "CFP_PER"), DEFBASIC(AR_TIMER0, "TIMER0"), DEFBASIC(AR_TIMER1, "TIMER1"), DEFBASIC(AR_TIMER2, "TIMER2"), DEFBASIC(AR_TIMER3, "TIMER3"), DEFBASIC(AR_IFS0, "IFS0"), DEFBASIC(AR_IFS1, "IFS1" ), DEFBASIC(AR_CFP_DUR, "CFP_DUR"), DEFBASICfmt(AR_RX_FILTER, "RXFILTER", AR_BEACON_BITS), DEFBASIC(AR_MCAST_FIL0, "MCAST_0"), DEFBASIC(AR_MCAST_FIL1, "MCAST_1"), DEFBASIC(AR_TX_MASK0, "TX_MASK0"), DEFBASIC(AR_TX_MASK1, "TX_MASK1"), DEFVOID(AR_CLR_TMASK, "CLR_TMASK"), DEFBASIC(AR_TRIG_LEV, "TRIG_LEV"), DEFBASICfmt(AR_DIAG_SW, "DIAG_SW", AR_DIAG_SW_BITS), DEFBASIC(AR_TSF_L32, "TSF_L32"), DEFBASIC(AR_TSF_U32, "TSF_U32"), DEFBASIC(AR_LAST_TSTP, "LAST_TST"), DEFBASIC(AR_RETRY_CNT, "RETRYCNT"), DEFBASIC(AR_BACKOFF, "BACKOFF"), DEFBASIC(AR_NAV, "NAV"), DEFBASIC(AR_RTS_OK, "RTS_OK"), DEFBASIC(AR_RTS_FAIL, "RTS_FAIL"), DEFBASIC(AR_ACK_FAIL, "ACK_FAIL"), DEFBASIC(AR_FCS_FAIL, "FCS_FAIL"), DEFBASIC(AR_BEACON_CNT, "BEAC_CNT"), DEFVOIDfmt(AR_PHY_FRCTL, "PHY_FRCTL", AR_PHY_FRCTL_BITS), DEFVOIDfmt(AR_PHY_AGC, "PHY_AGC", AR_PHY_AGC_BITS), DEFVOID(AR_PHY_CHIPID, "PHY_CHIPID"), DEFVOIDfmt(AR_PHY_ACTIVE, "PHY_ACTIVE", AR_PHY_ACTIVE_BITS), DEFVOIDfmt(AR_PHY_AGCCTL, "PHY_AGCCTL", AR_PHY_AGCCTL_BITS), }; static __constructor void ar5210_ctor(void) { #define MAC5210 SREV(1,0), SREV(2,0) - register_regs(ar5210regs, N(ar5210regs), MAC5210, PHYANY); + register_regs(ar5210regs, nitems(ar5210regs), MAC5210, PHYANY); register_keycache(64, MAC5210, PHYANY); register_range(0x9800, 0x9840, DUMP_BASEBAND, MAC5210, PHYANY); } Index: head/tools/tools/ath/common/dumpregs_5211.c =================================================================== --- head/tools/tools/ath/common/dumpregs_5211.c (revision 287296) +++ head/tools/tools/ath/common/dumpregs_5211.c (revision 287297) @@ -1,293 +1,294 @@ /*- * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ + +#include + #include "diag.h" #include "ah.h" #include "ah_internal.h" #include "ar5211/ar5211reg.h" #include "ar5211/ar5211phy.h" #include "dumpregs.h" -#define N(a) (sizeof(a) / sizeof(a[0])) - static struct dumpreg ar5211regs[] = { DEFBASICfmt(AR_CR, "CR", AR_CR_BITS), DEFBASIC(AR_RXDP, "RXDP"), DEFBASICfmt(AR_CFG, "CFG", AR_CFG_BITS), DEFBASICfmt(AR_IER, "IER", AR_IER_BITS), DEFBASIC(AR_RTSD0, "RTSD0"), DEFBASIC(AR_RTSD1, "RTSD1"), DEFBASICfmt(AR_TXCFG, "TXCFG", AR_TXCFG_BITS), DEFBASIC(AR_RXCFG, "RXCFG"), DEFBASIC(AR5211_JUMBO_LAST, "JLAST"), DEFBASIC(AR_MIBC, "MIBC"), DEFBASIC(AR_TOPS, "TOPS"), DEFBASIC(AR_RXNPTO, "RXNPTO"), DEFBASIC(AR_TXNPTO, "TXNPTO"), DEFBASIC(AR_RFGTO, "RFGTO"), DEFBASIC(AR_RFCNT, "RFCNT"), DEFBASIC(AR_MACMISC, "MISC"), DEFVOID(AR5311_QDCLKGATE, "AR5311_QDCLKGATE"), DEFINT(AR_ISR, "ISR"), DEFINT(AR_ISR_S0, "ISR_S0"), DEFINT(AR_ISR_S1, "ISR_S1"), DEFINT(AR_ISR_S2, "ISR_S2"), DEFINT(AR_ISR_S3, "ISR_S3"), DEFINT(AR_ISR_S4, "ISR_S4"), DEFINT(AR_IMR, "IMR"), DEFINT(AR_IMR_S0, "IMR_S0"), DEFINT(AR_IMR_S1, "IMR_S1"), DEFINT(AR_IMR_S2, "IMR_S2"), DEFINT(AR_IMR_S3, "IMR_S3"), DEFINT(AR_IMR_S4, "IMR_S4"), /* NB: don't read the RAC so we don't affect operation */ DEFVOID(AR_ISR_RAC, "ISR_RAC"), DEFINT(AR_ISR_S0_S, "ISR_S0_S"), DEFINT(AR_ISR_S1_S, "ISR_S1_S"), DEFINT(AR_ISR_S2_S, "ISR_S2_S"), DEFINT(AR_ISR_S3_S, "ISR_S3_S"), DEFINT(AR_ISR_S4_S, "ISR_S4_S"), DEFQCU(AR_Q0_TXDP, "Q0_TXDP"), DEFQCU(AR_Q1_TXDP, "Q1_TXDP"), DEFQCU(AR_Q2_TXDP, "Q2_TXDP"), DEFQCU(AR_Q3_TXDP, "Q3_TXDP"), DEFQCU(AR_Q4_TXDP, "Q4_TXDP"), DEFQCU(AR_Q5_TXDP, "Q5_TXDP"), DEFQCU(AR_Q6_TXDP, "Q6_TXDP"), DEFQCU(AR_Q7_TXDP, "Q7_TXDP"), DEFQCU(AR_Q8_TXDP, "Q8_TXDP"), DEFQCU(AR_Q9_TXDP, "Q9_TXDP"), DEFQCU(AR_Q_TXE, "Q_TXE"), DEFQCU(AR_Q_TXD, "Q_TXD"), DEFQCU(AR_Q0_CBRCFG, "Q0_CBR"), DEFQCU(AR_Q1_CBRCFG, "Q1_CBR"), DEFQCU(AR_Q2_CBRCFG, "Q2_CBR"), DEFQCU(AR_Q3_CBRCFG, "Q3_CBR"), DEFQCU(AR_Q4_CBRCFG, "Q4_CBR"), DEFQCU(AR_Q5_CBRCFG, "Q5_CBR"), DEFQCU(AR_Q6_CBRCFG, "Q6_CBR"), DEFQCU(AR_Q7_CBRCFG, "Q7_CBR"), DEFQCU(AR_Q8_CBRCFG, "Q8_CBR"), DEFQCU(AR_Q9_CBRCFG, "Q9_CBR"), DEFQCU(AR_Q0_RDYTIMECFG, "Q0_RDYT"), DEFQCU(AR_Q1_RDYTIMECFG, "Q1_RDYT"), DEFQCU(AR_Q2_RDYTIMECFG, "Q2_RDYT"), DEFQCU(AR_Q3_RDYTIMECFG, "Q3_RDYT"), DEFQCU(AR_Q4_RDYTIMECFG, "Q4_RDYT"), DEFQCU(AR_Q5_RDYTIMECFG, "Q5_RDYT"), DEFQCU(AR_Q6_RDYTIMECFG, "Q6_RDYT"), DEFQCU(AR_Q7_RDYTIMECFG, "Q7_RDYT"), DEFQCU(AR_Q8_RDYTIMECFG, "Q8_RDYT"), DEFQCU(AR_Q9_RDYTIMECFG, "Q9_RDYT"), DEFQCU(AR_Q_ONESHOTARM_SC, "Q_ONESHOTARM_SC"), DEFQCU(AR_Q_ONESHOTARM_CC, "Q_ONESHOTARM_CC"), DEFQCU(AR_Q0_MISC, "Q0_MISC"), DEFQCU(AR_Q1_MISC, "Q1_MISC"), DEFQCU(AR_Q2_MISC, "Q2_MISC"), DEFQCU(AR_Q3_MISC, "Q3_MISC"), DEFQCU(AR_Q4_MISC, "Q4_MISC"), DEFQCU(AR_Q5_MISC, "Q5_MISC"), DEFQCU(AR_Q6_MISC, "Q6_MISC"), DEFQCU(AR_Q7_MISC, "Q7_MISC"), DEFQCU(AR_Q8_MISC, "Q8_MISC"), DEFQCU(AR_Q9_MISC, "Q9_MISC"), DEFQCU(AR_Q0_STS, "Q0_STS"), DEFQCU(AR_Q1_STS, "Q1_STS"), DEFQCU(AR_Q2_STS, "Q2_STS"), DEFQCU(AR_Q3_STS, "Q3_STS"), DEFQCU(AR_Q4_STS, "Q4_STS"), DEFQCU(AR_Q5_STS, "Q5_STS"), DEFQCU(AR_Q6_STS, "Q6_STS"), DEFQCU(AR_Q7_STS, "Q7_STS"), DEFQCU(AR_Q8_STS, "Q8_STS"), DEFQCU(AR_Q9_STS, "Q9_STS"), DEFQCU(AR_Q_RDYTIMESHDN, "Q_RDYTIMSHD"), DEFQCU(AR_D0_QCUMASK, "D0_MASK"), DEFQCU(AR_D1_QCUMASK, "D1_MASK"), DEFQCU(AR_D2_QCUMASK, "D2_MASK"), DEFQCU(AR_D3_QCUMASK, "D3_MASK"), DEFQCU(AR_D4_QCUMASK, "D4_MASK"), DEFQCU(AR_D5_QCUMASK, "D5_MASK"), DEFQCU(AR_D6_QCUMASK, "D6_MASK"), DEFQCU(AR_D7_QCUMASK, "D7_MASK"), DEFQCU(AR_D8_QCUMASK, "D8_MASK"), DEFQCU(AR_D9_QCUMASK, "D9_MASK"), DEFDCU(AR_D0_LCL_IFS, "D0_IFS"), DEFDCU(AR_D1_LCL_IFS, "D1_IFS"), DEFDCU(AR_D2_LCL_IFS, "D2_IFS"), DEFDCU(AR_D3_LCL_IFS, "D3_IFS"), DEFDCU(AR_D4_LCL_IFS, "D4_IFS"), DEFDCU(AR_D5_LCL_IFS, "D5_IFS"), DEFDCU(AR_D6_LCL_IFS, "D6_IFS"), DEFDCU(AR_D7_LCL_IFS, "D7_IFS"), DEFDCU(AR_D8_LCL_IFS, "D8_IFS"), DEFDCU(AR_D9_LCL_IFS, "D9_IFS"), DEFDCU(AR_D0_RETRY_LIMIT, "D0_RTRY"), DEFDCU(AR_D1_RETRY_LIMIT, "D1_RTRY"), DEFDCU(AR_D2_RETRY_LIMIT, "D2_RTRY"), DEFDCU(AR_D3_RETRY_LIMIT, "D3_RTRY"), DEFDCU(AR_D4_RETRY_LIMIT, "D4_RTRY"), DEFDCU(AR_D5_RETRY_LIMIT, "D5_RTRY"), DEFDCU(AR_D6_RETRY_LIMIT, "D6_RTRY"), DEFDCU(AR_D7_RETRY_LIMIT, "D7_RTRY"), DEFDCU(AR_D8_RETRY_LIMIT, "D8_RTRY"), DEFDCU(AR_D9_RETRY_LIMIT, "D9_RTRY"), DEFDCU(AR_D0_CHNTIME, "D0_CHNT"), DEFDCU(AR_D1_CHNTIME, "D1_CHNT"), DEFDCU(AR_D2_CHNTIME, "D2_CHNT"), DEFDCU(AR_D3_CHNTIME, "D3_CHNT"), DEFDCU(AR_D4_CHNTIME, "D4_CHNT"), DEFDCU(AR_D5_CHNTIME, "D5_CHNT"), DEFDCU(AR_D6_CHNTIME, "D6_CHNT"), DEFDCU(AR_D7_CHNTIME, "D7_CHNT"), DEFDCU(AR_D8_CHNTIME, "D8_CHNT"), DEFDCU(AR_D9_CHNTIME, "D9_CHNT"), DEFDCU(AR_D0_MISC, "D0_MISC"), DEFDCU(AR_D1_MISC, "D1_MISC"), DEFDCU(AR_D2_MISC, "D2_MISC"), DEFDCU(AR_D3_MISC, "D3_MISC"), DEFDCU(AR_D4_MISC, "D4_MISC"), DEFDCU(AR_D5_MISC, "D5_MISC"), DEFDCU(AR_D6_MISC, "D6_MISC"), DEFDCU(AR_D7_MISC, "D7_MISC"), DEFDCU(AR_D8_MISC, "D8_MISC"), DEFDCU(AR_D9_MISC, "D9_MISC"), DEFDCU(AR_D0_SEQNUM, "D0_SEQ"), DEFDCU(AR_D1_SEQNUM, "D1_SEQ"), DEFDCU(AR_D2_SEQNUM, "D2_SEQ"), DEFDCU(AR_D3_SEQNUM, "D3_SEQ"), DEFDCU(AR_D4_SEQNUM, "D4_SEQ"), DEFDCU(AR_D5_SEQNUM, "D5_SEQ"), DEFDCU(AR_D6_SEQNUM, "D6_SEQ"), DEFDCU(AR_D7_SEQNUM, "D7_SEQ"), DEFDCU(AR_D8_SEQNUM, "D8_SEQ"), DEFDCU(AR_D9_SEQNUM, "D9_SEQ"), DEFBASIC(AR_D_GBL_IFS_SIFS, "D_SIFS"), DEFBASIC(AR_D_GBL_IFS_SLOT, "D_SLOT"), DEFBASIC(AR_D_GBL_IFS_EIFS, "D_EIFS"), DEFBASIC(AR_D_GBL_IFS_MISC, "D_MISC"), DEFBASIC(AR_D_FPCTL, "D_FPCTL"), DEFBASIC(AR_D_TXPSE, "D_TXPSE"), DEFVOID(AR_D_TXBLK_CMD, "D_CMD"), #if 0 DEFVOID(AR_D_TXBLK_DATA, "D_DATA"), #endif DEFVOID(AR_D_TXBLK_CLR, "D_CLR"), DEFVOID(AR_D_TXBLK_SET, "D_SET"), DEFBASICfmt(AR_RC, "RC", AR_RC_BITS), DEFBASICfmt(AR_SCR, "SCR", AR_SCR_BITS), DEFBASICfmt(AR_INTPEND, "INTPEND", AR_INTPEND_BITS), DEFBASIC(AR_SFR, "SFR"), DEFBASICfmt(AR_PCICFG, "PCICFG", AR_PCICFG_BITS), DEFBASIC(AR_GPIOCR, "GPIOCR"), DEFBASIC(AR_GPIODO, "GPIODO"), DEFBASIC(AR_GPIODI, "GPIODI"), DEFBASIC(AR_SREV, "SREV"), DEFVOID(AR_EEPROM_ADDR, "EEADDR"), DEFVOID(AR_EEPROM_DATA, "EEDATA"), DEFVOID(AR_EEPROM_CMD, "EECMD"), DEFVOID(AR_EEPROM_STS, "EESTS"), DEFVOID(AR_EEPROM_CFG, "EECFG"), DEFBASIC(AR_STA_ID0, "STA_ID0"), DEFBASICfmt(AR_STA_ID1, "STA_ID1", AR_STA_ID1_BITS), DEFBASIC(AR_BSS_ID0, "BSS_ID0"), DEFBASIC(AR_BSS_ID1, "BSS_ID1"), DEFBASIC(AR_SLOT_TIME, "SLOTTIME"), DEFBASIC(AR_TIME_OUT, "TIME_OUT"), DEFBASIC(AR_RSSI_THR, "RSSI_THR"), DEFBASIC(AR_USEC, "USEC"), DEFBASICfmt(AR_BEACON, "BEACON", AR_BEACON_BITS), DEFBASIC(AR_CFP_PERIOD, "CFP_PER"), DEFBASIC(AR_TIMER0, "TIMER0"), DEFBASIC(AR_TIMER1, "TIMER1"), DEFBASIC(AR_TIMER2, "TIMER2"), DEFBASIC(AR_TIMER3, "TIMER3"), DEFBASIC(AR_CFP_DUR, "CFP_DUR"), DEFBASICfmt(AR_RX_FILTER, "RXFILTER", AR_RX_FILTER_BITS), DEFBASIC(AR_MCAST_FIL0, "MCAST_0"), DEFBASIC(AR_MCAST_FIL1, "MCAST_1"), DEFBASICfmt(AR_DIAG_SW, "DIAG_SW", AR_DIAG_SW_BITS), DEFBASIC(AR_TSF_L32, "TSF_L32"), DEFBASIC(AR_TSF_U32, "TSF_U32"), DEFBASIC(AR_TST_ADDAC, "TST_ADAC"), DEFBASIC(AR_DEF_ANTENNA, "DEF_ANT"), DEFBASIC(AR_LAST_TSTP, "LAST_TST"), DEFBASIC(AR_NAV, "NAV"), DEFBASIC(AR_RTS_OK, "RTS_OK"), DEFBASIC(AR_RTS_FAIL, "RTS_FAIL"), DEFBASIC(AR_ACK_FAIL, "ACK_FAIL"), DEFBASIC(AR_FCS_FAIL, "FCS_FAIL"), DEFBASIC(AR_BEACON_CNT, "BEAC_CNT"), DEFVOID(AR_PHY_TURBO, "PHY_TURBO"), DEFVOID(AR_PHY_CHIP_ID, "PHY_CHIP_ID"), DEFVOID(AR_PHY_ACTIVE, "PHY_ACTIVE"), DEFVOID(AR_PHY_AGC_CONTROL, "PHY_AGC_CONTROL"), DEFVOID(AR_PHY_PLL_CTL, "PHY_PLL_CTL"), DEFVOID(AR_PHY_RX_DELAY, "PHY_RX_DELAY"), DEFVOID(AR_PHY_TIMING_CTRL4,"PHY_TIMING_CTRL4"), DEFVOID(AR_PHY_RADAR_0, "PHY_RADAR_0"), DEFVOID(AR_PHY_IQCAL_RES_PWR_MEAS_I,"PHY_IQCAL_RES_PWR_MEAS_I"), DEFVOID(AR_PHY_IQCAL_RES_PWR_MEAS_Q,"PHY_IQCAL_RES_PWR_MEAS_Q"), DEFVOID(AR_PHY_IQCAL_RES_IQ_CORR_MEAS,"PHY_IQCAL_RES_IQ_CORR_MEAS"), DEFVOID(AR_PHY_CURRENT_RSSI,"PHY_CURRENT_RSSI"), DEFVOID(AR5211_PHY_MODE, "PHY_MODE"), }; static __constructor void ar5211_ctor(void) { #define MAC5211 SREV(2,0), SREV(4,5) - register_regs(ar5211regs, N(ar5211regs), MAC5211, PHYANY); + register_regs(ar5211regs, nitems(ar5211regs), MAC5211, PHYANY); register_keycache(128, MAC5211, PHYANY); register_range(0x9800, 0x987c, DUMP_BASEBAND, MAC5211, PHYANY); register_range(0x9900, 0x995c, DUMP_BASEBAND, MAC5211, PHYANY); register_range(0x9c00, 0x9c1c, DUMP_BASEBAND, MAC5211, PHYANY); } Index: head/tools/tools/ath/common/dumpregs_5212.c =================================================================== --- head/tools/tools/ath/common/dumpregs_5212.c (revision 287296) +++ head/tools/tools/ath/common/dumpregs_5212.c (revision 287297) @@ -1,433 +1,434 @@ /*- * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ + +#include + #include "diag.h" #include "ah.h" #include "ah_internal.h" #include "ar5212/ar5212reg.h" #include "ar5212/ar5212phy.h" #include "dumpregs.h" -#define N(a) (sizeof(a) / sizeof(a[0])) - #define MAC5212 SREV(4,5), SREV(16,0) #define MAC5213 SREV(5,9), SREV(16,0) static struct dumpreg ar5212regs[] = { DEFBASIC(AR_CR, "CR"), DEFBASIC(AR_RXDP, "RXDP"), DEFBASICfmt(AR_CFG, "CFG", "\20\1SWTD\2SWTB\3SWRD\4SWRB\5SWRG\6AP_ADHOC\11PHOK\12EEBS"), DEFBASIC(AR_IER, "IER"), DEFBASIC(AR_TXCFG, "TXCFG"), DEFBASICfmt(AR_RXCFG, "RXCFG", "\20\6JUMBO_ENA\7JUMBO_WRAP\10SLEEP_DEBUG"), DEFBASIC(AR_MIBC, "MIBC"), DEFBASIC(AR_TOPS, "TOPS"), DEFBASIC(AR_RXNPTO, "RXNPTO"), DEFBASIC(AR_TXNPTO, "TXNPTO"), DEFBASIC(AR_RPGTO, "RPGTO"), DEFBASIC(AR_RPCNT, "RPCNT"), DEFBASIC(AR_MACMISC, "MACMISC"), DEFBASIC(AR_SPC_0, "SPC_0"), DEFBASIC(AR_SPC_1, "SPC_1"), DEFINTfmt(AR_ISR, "ISR", "\20\1RXOK\2RXDESC\3RXERR\4RXNOPKT\5RXEOL\6RXORN\7TXOK\10TXDESC" "\11TXERR\12TXNOPKT\13TXEOL\14TXURN\15MIB\16SWI\17RXPHY\20RXKCM" "\21SWBA\22BRSSI\23BMISS\24HIUERR\25BNR\26RXCHIRP\27RXDOPPL\30BCNMISS" "\31TIM\32GPIO\33QCBROVF\34QCBRURN\35QTRIG"), DEFINT(AR_ISR_S0, "ISR_S0"), DEFINT(AR_ISR_S1, "ISR_S1"), DEFINTfmt(AR_ISR_S2, "ISR_S2", "\20\21MCABT\22SSERR\23DPERR\24TIM\25CABEND\26DTIMSYNC\27BCNTO" "\30CABTO\31DTIM"), DEFINT(AR_ISR_S3, "ISR_S3"), DEFINT(AR_ISR_S4, "ISR_S4"), DEFINTfmt(AR_IMR, "IMR", "\20\1RXOK\2RXDESC\3RXERR\4RXNOPKT\5RXEOL\6RXORN\7TXOK\10TXDESC" "\11TXERR\12TXNOPKT\13TXEOL\14TXURN\15MIB\16SWI\17RXPHY\20RXKCM" "\21SWBA\22BRSSI\23BMISS\24HIUERR\25BNR\26RXCHIRP\27RXDOPPL\30BCNMISS" "\31TIM\32GPIO\33QCBROVF\34QCBRURN\35QTRIG"), DEFINT(AR_IMR_S0, "IMR_S0"), DEFINT(AR_IMR_S1, "IMR_S1"), DEFINTfmt(AR_IMR_S2, "IMR_S2", "\20\21MCABT\22SSERR\23DPERR\24TIM\25CABEND\26DTIMSYNC\27BCNTO" "\30CABTO\31DTIM"), DEFINT(AR_IMR_S3, "IMR_S3"), DEFINT(AR_IMR_S4, "IMR_S4"), /* NB: don't read the RAC so we don't affect operation */ DEFVOID(AR_ISR_RAC, "ISR_RAC"), DEFINT(AR_ISR_S0_S, "ISR_S0_S"), DEFINT(AR_ISR_S1_S, "ISR_S1_S"), DEFINT(AR_ISR_S2_S, "ISR_S2_S"), DEFINT(AR_ISR_S3_S, "ISR_S3_S"), DEFINT(AR_ISR_S4_S, "ISR_S4_S"), DEFBASIC(AR_DMADBG_0, "DMADBG0"), DEFBASIC(AR_DMADBG_1, "DMADBG1"), DEFBASIC(AR_DMADBG_2, "DMADBG2"), DEFBASIC(AR_DMADBG_3, "DMADBG3"), DEFBASIC(AR_DMADBG_4, "DMADBG4"), DEFBASIC(AR_DMADBG_5, "DMADBG5"), DEFBASIC(AR_DMADBG_6, "DMADBG6"), DEFBASIC(AR_DMADBG_7, "DMADBG7"), DEFBASIC(AR_DCM_A, "DCM_A"), DEFBASIC(AR_DCM_D, "DCM_D"), DEFBASIC(AR_DCCFG, "DCCFG"), DEFBASIC(AR_CCFG, "CCFG"), DEFBASIC(AR_CCUCFG, "CCUCFG"), DEFBASIC(AR_CPC_0, "CPC0"), DEFBASIC(AR_CPC_1, "CPC1"), DEFBASIC(AR_CPC_2, "CPC2"), DEFBASIC(AR_CPC_3, "CPC3"), DEFBASIC(AR_CPCOVF, "CPCOVF"), DEFQCU(AR_Q0_TXDP, "Q0_TXDP"), DEFQCU(AR_Q1_TXDP, "Q1_TXDP"), DEFQCU(AR_Q2_TXDP, "Q2_TXDP"), DEFQCU(AR_Q3_TXDP, "Q3_TXDP"), DEFQCU(AR_Q4_TXDP, "Q4_TXDP"), DEFQCU(AR_Q5_TXDP, "Q5_TXDP"), DEFQCU(AR_Q6_TXDP, "Q6_TXDP"), DEFQCU(AR_Q7_TXDP, "Q7_TXDP"), DEFQCU(AR_Q8_TXDP, "Q8_TXDP"), DEFQCU(AR_Q9_TXDP, "Q9_TXDP"), DEFQCU(AR_Q_TXE, "Q_TXE"), DEFQCU(AR_Q_TXD, "Q_TXD"), DEFQCU(AR_Q0_CBRCFG, "Q0_CBR"), DEFQCU(AR_Q1_CBRCFG, "Q1_CBR"), DEFQCU(AR_Q2_CBRCFG, "Q2_CBR"), DEFQCU(AR_Q3_CBRCFG, "Q3_CBR"), DEFQCU(AR_Q4_CBRCFG, "Q4_CBR"), DEFQCU(AR_Q5_CBRCFG, "Q5_CBR"), DEFQCU(AR_Q6_CBRCFG, "Q6_CBR"), DEFQCU(AR_Q7_CBRCFG, "Q7_CBR"), DEFQCU(AR_Q8_CBRCFG, "Q8_CBR"), DEFQCU(AR_Q9_CBRCFG, "Q9_CBR"), DEFQCU(AR_Q0_RDYTIMECFG, "Q0_RDYT"), DEFQCU(AR_Q1_RDYTIMECFG, "Q1_RDYT"), DEFQCU(AR_Q2_RDYTIMECFG, "Q2_RDYT"), DEFQCU(AR_Q3_RDYTIMECFG, "Q3_RDYT"), DEFQCU(AR_Q4_RDYTIMECFG, "Q4_RDYT"), DEFQCU(AR_Q5_RDYTIMECFG, "Q5_RDYT"), DEFQCU(AR_Q6_RDYTIMECFG, "Q6_RDYT"), DEFQCU(AR_Q7_RDYTIMECFG, "Q7_RDYT"), DEFQCU(AR_Q8_RDYTIMECFG, "Q8_RDYT"), DEFQCU(AR_Q9_RDYTIMECFG, "Q9_RDYT"), DEFQCU(AR_Q_ONESHOTARM_SC, "Q_ONESHOTARM_SC"), DEFQCU(AR_Q_ONESHOTARM_CC, "Q_ONESHOTARM_CC"), DEFQCU(AR_Q0_MISC, "Q0_MISC"), DEFQCU(AR_Q1_MISC, "Q1_MISC"), DEFQCU(AR_Q2_MISC, "Q2_MISC"), DEFQCU(AR_Q3_MISC, "Q3_MISC"), DEFQCU(AR_Q4_MISC, "Q4_MISC"), DEFQCU(AR_Q5_MISC, "Q5_MISC"), DEFQCU(AR_Q6_MISC, "Q6_MISC"), DEFQCU(AR_Q7_MISC, "Q7_MISC"), DEFQCU(AR_Q8_MISC, "Q8_MISC"), DEFQCU(AR_Q9_MISC, "Q9_MISC"), DEFQCU(AR_Q0_STS, "Q0_STS"), DEFQCU(AR_Q1_STS, "Q1_STS"), DEFQCU(AR_Q2_STS, "Q2_STS"), DEFQCU(AR_Q3_STS, "Q3_STS"), DEFQCU(AR_Q4_STS, "Q4_STS"), DEFQCU(AR_Q5_STS, "Q5_STS"), DEFQCU(AR_Q6_STS, "Q6_STS"), DEFQCU(AR_Q7_STS, "Q7_STS"), DEFQCU(AR_Q8_STS, "Q8_STS"), DEFQCU(AR_Q9_STS, "Q9_STS"), DEFQCU(AR_Q_RDYTIMESHDN, "Q_RDYTIMSHD"), DEFQCU(AR_Q_CBBS, "Q_CBBS"), DEFQCU(AR_Q_CBBA, "Q_CBBA"), DEFQCU(AR_Q_CBC, "Q_CBC"), DEFDCU(AR_D0_QCUMASK, "D0_MASK"), DEFDCU(AR_D1_QCUMASK, "D1_MASK"), DEFDCU(AR_D2_QCUMASK, "D2_MASK"), DEFDCU(AR_D3_QCUMASK, "D3_MASK"), DEFDCU(AR_D4_QCUMASK, "D4_MASK"), DEFDCU(AR_D5_QCUMASK, "D5_MASK"), DEFDCU(AR_D6_QCUMASK, "D6_MASK"), DEFDCU(AR_D7_QCUMASK, "D7_MASK"), DEFDCU(AR_D8_QCUMASK, "D8_MASK"), DEFDCU(AR_D9_QCUMASK, "D9_MASK"), DEFDCU(AR_D0_LCL_IFS, "D0_IFS"), DEFDCU(AR_D1_LCL_IFS, "D1_IFS"), DEFDCU(AR_D2_LCL_IFS, "D2_IFS"), DEFDCU(AR_D3_LCL_IFS, "D3_IFS"), DEFDCU(AR_D4_LCL_IFS, "D4_IFS"), DEFDCU(AR_D5_LCL_IFS, "D5_IFS"), DEFDCU(AR_D6_LCL_IFS, "D6_IFS"), DEFDCU(AR_D7_LCL_IFS, "D7_IFS"), DEFDCU(AR_D8_LCL_IFS, "D8_IFS"), DEFDCU(AR_D9_LCL_IFS, "D9_IFS"), DEFDCU(AR_D0_RETRY_LIMIT, "D0_RTRY"), DEFDCU(AR_D1_RETRY_LIMIT, "D1_RTRY"), DEFDCU(AR_D2_RETRY_LIMIT, "D2_RTRY"), DEFDCU(AR_D3_RETRY_LIMIT, "D3_RTRY"), DEFDCU(AR_D4_RETRY_LIMIT, "D4_RTRY"), DEFDCU(AR_D5_RETRY_LIMIT, "D5_RTRY"), DEFDCU(AR_D6_RETRY_LIMIT, "D6_RTRY"), DEFDCU(AR_D7_RETRY_LIMIT, "D7_RTRY"), DEFDCU(AR_D8_RETRY_LIMIT, "D8_RTRY"), DEFDCU(AR_D9_RETRY_LIMIT, "D9_RTRY"), DEFDCU(AR_D0_CHNTIME, "D0_CHNT"), DEFDCU(AR_D1_CHNTIME, "D1_CHNT"), DEFDCU(AR_D2_CHNTIME, "D2_CHNT"), DEFDCU(AR_D3_CHNTIME, "D3_CHNT"), DEFDCU(AR_D4_CHNTIME, "D4_CHNT"), DEFDCU(AR_D5_CHNTIME, "D5_CHNT"), DEFDCU(AR_D6_CHNTIME, "D6_CHNT"), DEFDCU(AR_D7_CHNTIME, "D7_CHNT"), DEFDCU(AR_D8_CHNTIME, "D8_CHNT"), DEFDCU(AR_D9_CHNTIME, "D9_CHNT"), DEFDCU(AR_D0_MISC, "D0_MISC"), DEFDCU(AR_D1_MISC, "D1_MISC"), DEFDCU(AR_D2_MISC, "D2_MISC"), DEFDCU(AR_D3_MISC, "D3_MISC"), DEFDCU(AR_D4_MISC, "D4_MISC"), DEFDCU(AR_D5_MISC, "D5_MISC"), DEFDCU(AR_D6_MISC, "D6_MISC"), DEFDCU(AR_D7_MISC, "D7_MISC"), DEFDCU(AR_D8_MISC, "D8_MISC"), DEFDCU(AR_D9_MISC, "D9_MISC"), _DEFREG(AR_D_SEQNUM, "D_SEQ", DUMP_BASIC | DUMP_DCU), DEFBASIC(AR_D_GBL_IFS_SIFS, "D_SIFS"), DEFBASIC(AR_D_GBL_IFS_SLOT, "D_SLOT"), DEFBASIC(AR_D_GBL_IFS_EIFS, "D_EIFS"), DEFBASIC(AR_D_GBL_IFS_MISC, "D_MISC"), DEFBASIC(AR_D_FPCTL, "D_FPCTL"), DEFBASIC(AR_D_TXPSE, "D_TXPSE"), DEFVOID(AR_D_TXBLK_CMD, "D_CMD"), #if 0 DEFVOID(AR_D_TXBLK_DATA, "D_DATA"), #endif DEFVOID(AR_D_TXBLK_CLR, "D_CLR"), DEFVOID(AR_D_TXBLK_SET, "D_SET"), DEFBASIC(AR_RC, "RC"), DEFBASICfmt(AR_SCR, "SCR", "\20\22SLDTP\23SLDWP\24SLEPOL\25MIBIE"), DEFBASIC(AR_INTPEND, "INTPEND"), DEFBASIC(AR_SFR, "SFR"), DEFBASIC(AR_PCICFG, "PCICFG"), DEFBASIC(AR_GPIOCR, "GPIOCR"), DEFBASIC(AR_GPIODO, "GPIODO"), DEFBASIC(AR_GPIODI, "GPIODI"), DEFBASIC(AR_SREV, "SREV"), DEFBASICx(AR_PCIE_PMC, "PCIEPMC", SREV(4,8), SREV(13,7)), DEFBASICx(AR_PCIE_SERDES, "SERDES", SREV(4,8), SREV(13,7)), DEFBASICx(AR_PCIE_SERDES2, "SERDES2", SREV(4,8), SREV(13,7)), DEFVOID(AR_EEPROM_ADDR, "EEADDR"), DEFVOID(AR_EEPROM_DATA, "EEDATA"), DEFVOID(AR_EEPROM_CMD, "EECMD"), DEFVOID(AR_EEPROM_STS, "EESTS"), DEFVOID(AR_EEPROM_CFG, "EECFG"), DEFBASIC(AR_STA_ID0, "STA_ID0"), DEFBASICfmt(AR_STA_ID1, "STA_ID1", "\20\21STA_AP\22ADHOC\23PWR_SAV\24KSRCHDIS\25PCF\26USE_DEFANT" "\27UPD_DEFANT\30RTS_USE_DEF\31ACKCTS_6MB\32BASE_RATE11B\33USE_DA_SG" "\34CRPT_MIC_ENABLE\35KSRCH_MODE\36PRE_SEQNUM\37CBCIV_ENDIAN" "\40MCAST_KSRCH"), DEFBASIC(AR_BSS_ID0, "BSS_ID0"), DEFBASIC(AR_BSS_ID1, "BSS_ID1"), DEFBASIC(AR_SLOT_TIME, "SLOTTIME"), DEFBASIC(AR_TIME_OUT, "TIME_OUT"), DEFBASIC(AR_RSSI_THR, "RSSI_THR"), DEFBASIC(AR_USEC, "USEC"), DEFBASIC(AR_BEACON, "BEACON"), DEFBASIC(AR_CFP_PERIOD, "CFP_PER"), DEFBASIC(AR_TIMER0, "TIMER0"), DEFBASIC(AR_TIMER1, "TIMER1"), DEFBASIC(AR_TIMER2, "TIMER2"), DEFBASIC(AR_TIMER3, "TIMER3"), DEFBASIC(AR_CFP_DUR, "CFP_DUR"), DEFBASICfmt(AR_RX_FILTER, "RXFILTER", "\20\1UCAST\2MCAST\3BCAST\4CONTROL\5BEACON\6PROM\7XR_POLL\10PROBE_REQ"), DEFBASIC(AR_MCAST_FIL0, "MCAST_0"), DEFBASIC(AR_MCAST_FIL1, "MCAST_1"), DEFBASICfmt(AR_DIAG_SW, "DIAG_SW", "\20\1CACHE_ACK\2ACK_DIS\3CTS_DIS\4ENCRYPT_DIS\5DECRYPT_DIS\6RX_DIS" "\7CORR_FCS\10CHAN_INFO\11EN_SCRAMSD\22FRAME_NV0\25RX_CLR_HI" "\26IGNORE_CS\27CHAN_IDLE\30PHEAR_ME"), DEFBASIC(AR_TSF_L32, "TSF_L32"), DEFBASIC(AR_TSF_U32, "TSF_U32"), DEFBASIC(AR_TST_ADDAC, "TST_ADAC"), DEFBASIC(AR_DEF_ANTENNA, "DEF_ANT"), DEFBASIC(AR_QOS_MASK, "QOS_MASK"), DEFBASIC(AR_SEQ_MASK, "SEQ_MASK"), DEFBASIC(AR_OBSERV_2, "OBSERV2"), DEFBASIC(AR_OBSERV_1, "OBSERV1"), DEFBASIC(AR_LAST_TSTP, "LAST_TST"), DEFBASIC(AR_NAV, "NAV"), DEFBASIC(AR_RTS_OK, "RTS_OK"), DEFBASIC(AR_RTS_FAIL, "RTS_FAIL"), DEFBASIC(AR_ACK_FAIL, "ACK_FAIL"), DEFBASIC(AR_FCS_FAIL, "FCS_FAIL"), DEFBASIC(AR_BEACON_CNT, "BEAC_CNT"), DEFBASIC(AR_SLEEP1, "SLEEP1"), DEFBASIC(AR_SLEEP2, "SLEEP2"), DEFBASIC(AR_SLEEP3, "SLEEP3"), DEFBASIC(AR_BSSMSKL, "BSSMSKL"), DEFBASIC(AR_BSSMSKU, "BSSMSKU"), DEFBASIC(AR_TPC, "TPC"), DEFBASIC(AR_TFCNT, "TFCNT"), DEFBASIC(AR_RFCNT, "RFCNT"), DEFBASIC(AR_RCCNT, "RCCNT"), DEFBASIC(AR_CCCNT, "CCCNT"), DEFBASIC(AR_QUIET1, "QUIET1"), DEFBASIC(AR_QUIET2, "QUIET2"), DEFBASIC(AR_TSF_PARM, "TSF_PARM"), DEFBASIC(AR_NOACK, "NOACK"), DEFBASIC(AR_PHY_ERR, "PHY_ERR"), DEFBASIC(AR_QOS_CONTROL, "QOS_CTRL"), DEFBASIC(AR_QOS_SELECT, "QOS_SEL"), DEFBASIC(AR_MISC_MODE, "MISCMODE"), DEFBASIC(AR_FILTOFDM, "FILTOFDM"), DEFBASIC(AR_FILTCCK, "FILTCCK"), DEFBASIC(AR_PHYCNT1, "PHYCNT1"), DEFBASIC(AR_PHYCNTMASK1, "PHYCMSK1"), DEFBASIC(AR_PHYCNT2, "PHYCNT2"), DEFBASIC(AR_PHYCNTMASK2, "PHYCMSK2"), DEFVOID(AR_PHYCNT1, "PHYCNT1"), DEFVOID(AR_PHYCNTMASK1, "PHYCNTMASK1"), DEFVOID(AR_PHYCNT2, "PHYCNT2"), DEFVOID(AR_PHYCNTMASK2, "PHYCNTMASK2"), DEFVOID(AR_PHY_TEST, "PHY_TEST"), DEFVOID(AR_PHY_TURBO, "PHY_TURBO"), DEFVOID(AR_PHY_TESTCTRL, "PHY_TESTCTRL"), DEFVOID(AR_PHY_TIMING3, "PHY_TIMING3"), DEFVOID(AR_PHY_CHIP_ID, "PHY_CHIP_ID"), DEFVOIDfmt(AR_PHY_ACTIVE, "PHY_ACTIVE", "\20\1ENA"), DEFVOID(AR_PHY_TX_CTL, "PHY_TX_CTL"), DEFVOID(AR_PHY_ADC_CTL, "PHY_ADC_CTL"), DEFVOID(AR_PHY_BB_XP_PA_CTL,"PHY_BB_XP_PA_CTL"), DEFVOID(AR_PHY_TSTDAC_CONST,"PHY_TSTDAC_CONST"), DEFVOID(AR_PHY_SETTLING, "PHY_SETTLING"), DEFVOID(AR_PHY_RXGAIN, "PHY_RXGAIN"), DEFVOID(AR_PHY_DESIRED_SZ, "PHY_DESIRED_SZ"), DEFVOID(AR_PHY_FIND_SIG, "PHY_FIND_SIG"), DEFVOID(AR_PHY_AGC_CTL1, "PHY_AGC_CTL1"), DEFVOIDfmt(AR_PHY_AGC_CONTROL, "PHY_AGC_CONTROL", "\20\1CAL\2NF\16ENA_NF\22NO_UPDATE_NF"), DEFVOIDfmt(AR_PHY_SFCORR_LOW, "PHY_SFCORR_LOW", "\20\1USE_SELF_CORR_LOW"), DEFVOID(AR_PHY_SFCORR, "PHY_SFCORR"), DEFVOID(AR_PHY_SLEEP_CTR_CONTROL, "PHY_SLEEP_CTR_CONTROL"), DEFVOID(AR_PHY_SLEEP_CTR_LIMIT, "PHY_SLEEP_CTR_LIMIT"), DEFVOID(AR_PHY_SLEEP_SCAL, "PHY_SLEEP_SCAL"), DEFVOID(AR_PHY_BIN_MASK_1, "PHY_BIN_MASK_1"), DEFVOID(AR_PHY_BIN_MASK_2, "PHY_BIN_MASK_2"), DEFVOID(AR_PHY_BIN_MASK_3, "PHY_BIN_MASK_3"), DEFVOID(AR_PHY_MASK_CTL, "PHY_MASK_CTL"), DEFVOID(AR_PHY_PLL_CTL, "PHY_PLL_CTL"), DEFVOID(AR_PHY_RX_DELAY, "PHY_RX_DELAY"), DEFVOID(AR_PHY_TIMING_CTRL4,"PHY_TIMING_CTRL4"), DEFVOID(AR_PHY_TIMING5, "PHY_TIMING5"), DEFVOID(AR_PHY_PAPD_PROBE, "PHY_PAPD_PROBE"), DEFVOID(AR_PHY_POWER_TX_RATE1,"PHY_POWER_TX_RATE1"), DEFVOID(AR_PHY_POWER_TX_RATE2,"PHY_POWER_TX_RATE2"), DEFVOID(AR_PHY_POWER_TX_RATE_MAX, "PHY_POWER_TX_RATE_MAX"), DEFVOID(AR_PHY_FRAME_CTL, "PHY_FRAME_CTL"), DEFVOID(AR_PHY_TXPWRADJ, "PHY_TXPWRADJ"), DEFVOID(AR_PHY_RADAR_0, "PHY_RADAR_0"), DEFVOID(AR_PHY_SIGMA_DELTA, "PHY_SIGMA_DELTA"), DEFVOID(AR_PHY_RESTART, "PHY_RESTART"), DEFVOID(AR_PHY_RFBUS_REQ, "PHY_RFBUS_REQ"), DEFVOID(AR_PHY_TIMING7, "PHY_TIMING7"), DEFVOID(AR_PHY_TIMING8, "PHY_TIMING8"), DEFVOID(AR_PHY_BIN_MASK2_1, "PHY_BIN_MASK2_1"), DEFVOID(AR_PHY_BIN_MASK2_2, "PHY_BIN_MASK2_2"), DEFVOID(AR_PHY_BIN_MASK2_3, "PHY_BIN_MASK2_3"), DEFVOID(AR_PHY_BIN_MASK2_4, "PHY_BIN_MASK2_4"), DEFVOID(AR_PHY_TIMING9, "PHY_TIMING9"), DEFVOID(AR_PHY_TIMING10, "PHY_TIMING10"), DEFVOID(AR_PHY_TIMING11, "PHY_TIMING11"), DEFVOID(AR_PHY_HEAVY_CLIP_ENABLE, "PHY_HEAVY_CLIP_ENABLE"), DEFVOID(AR_PHY_M_SLEEP, "PHY_M_SLEEP"), DEFVOID(AR_PHY_REFCLKDLY, "PHY_REFCLKDLY"), DEFVOID(AR_PHY_REFCLKPD, "PHY_REFCLKPD"), DEFVOID(AR_PHY_IQCAL_RES_PWR_MEAS_I, "PHY_IQCAL_RES_PWR_MEAS_I"), DEFVOID(AR_PHY_IQCAL_RES_PWR_MEAS_Q, "PHY_IQCAL_RES_PWR_MEAS_Q"), DEFVOID(AR_PHY_IQCAL_RES_IQ_CORR_MEAS, "PHY_IQCAL_RES_IQ_CORR_MEAS"), DEFVOID(AR_PHY_CURRENT_RSSI,"PHY_CURRENT_RSSI"), DEFVOID(AR_PHY_RFBUS_GNT, "PHY_RFBUS_GNT"), DEFVOIDfmt(AR_PHY_MODE, "PHY_MODE", "\20\1CCK\2RF2GHZ\3DYNAMIC\4AR5112\5HALF\6QUARTER"), DEFVOID(AR_PHY_CCK_TX_CTRL, "PHY_CCK_TX_CTRL"), DEFVOID(AR_PHY_CCK_DETECT, "PHY_CCK_DETECT"), DEFVOID(AR_PHY_GAIN_2GHZ, "PHY_GAIN_2GHZ"), DEFVOID(AR_PHY_CCK_RXCTRL4, "PHY_CCK_RXCTRL4"), DEFVOID(AR_PHY_DAG_CTRLCCK, "PHY_DAG_CTRLCCK"), DEFVOID(AR_PHY_DAG_CTRLCCK, "PHY_DAG_CTRLCCK"), DEFVOID(AR_PHY_POWER_TX_RATE3,"PHY_POWER_TX_RATE3"), DEFVOID(AR_PHY_POWER_TX_RATE4,"PHY_POWER_TX_RATE4"), DEFVOID(AR_PHY_FAST_ADC, "PHY_FAST_ADC"), DEFVOID(AR_PHY_BLUETOOTH, "PHY_BLUETOOTH"), DEFVOID(AR_PHY_TPCRG1, "PHY_TPCRG1"), DEFVOID(AR_PHY_TPCRG5, "PHY_TPCRG5"), /* XXX { AR_RATE_DURATION(0), AR_RATE_DURATION(0x20) }, */ }; static __constructor void ar5212_ctor(void) { - register_regs(ar5212regs, N(ar5212regs), MAC5212, PHYANY); + register_regs(ar5212regs, nitems(ar5212regs), MAC5212, PHYANY); register_keycache(128, MAC5212, PHYANY); register_range(0x9800, 0x987c, DUMP_BASEBAND, MAC5212, PHYANY); register_range(0x9900, 0x995c, DUMP_BASEBAND, MAC5212, PHYANY); register_range(0x9c00, 0x9c1c, DUMP_BASEBAND, MAC5212, PHYANY); register_range(0xa180, 0xa238, DUMP_BASEBAND, MAC5212, PHYANY); register_range(0xa258, 0xa26c, DUMP_BASEBAND, SREV(7,8), SREV(15,15), PHYANY); } Index: head/tools/tools/ath/common/dumpregs_5416.c =================================================================== --- head/tools/tools/ath/common/dumpregs_5416.c (revision 287296) +++ head/tools/tools/ath/common/dumpregs_5416.c (revision 287297) @@ -1,423 +1,424 @@ /*- * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ + +#include + #include "diag.h" #include "ah.h" #include "ah_internal.h" #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" #include "dumpregs.h" -#define N(a) (sizeof(a) / sizeof(a[0])) - #define MAC5416 SREV(13,8), SREV(0xffff,0xffff) /* XXX */ static struct dumpreg ar5416regs[] = { DEFBASIC(AR_CR, "CR"), DEFBASIC(AR_RXDP, "RXDP"), DEFBASIC(AR_CFG, "CFG"), DEFBASIC(AR_MIRT, "MIRT"), DEFBASIC(AR_TIMT, "TIMT"), DEFBASIC(AR_CST, "CST"), DEFBASIC(AR_IER, "IER"), DEFBASIC(AR_TXCFG, "TXCFG"), DEFBASICfmt(AR_RXCFG, "RXCFG", "\20\6JUMBO_ENA\7JUMBO_WRAP\10SLEEP_DEBUG"), DEFBASIC(AR_MIBC, "MIBC"), DEFBASIC(AR_TOPS, "TOPS"), DEFBASIC(AR_RXNPTO, "RXNPTO"), DEFBASIC(AR_TXNPTO, "TXNPTO"), DEFBASIC(AR_RPGTO, "RPGTO"), DEFBASIC(AR_RPCNT, "RPCNT"), DEFBASIC(AR_MACMISC, "MACMISC"), DEFBASIC(AR_SPC_0, "SPC_0"), DEFBASIC(AR_SPC_1, "SPC_1"), DEFBASIC(AR_GTXTO, "GTXTO"), DEFBASIC(AR_GTTM, "GTTM"), DEFINTfmt(AR_ISR, "ISR", "\20\1RXOK\2RXDESC\3RXERR\4RXNOPKT\5RXEOL\6RXORN\7TXOK\10TXDESC" "\11TXERR\12TXNOPKT\13TXEOL\14TXURN\15MIB\16SWI\17RXPHY\20RXKCM" "\21SWBA\22BRSSI\23BMISS\24HIUERR\25BNR\26RXCHIRP\27RXDOPPL\30BCNMISS" "\31TIM\32GPIO\33QCBROVF\34QCBRURN\35QTRIG"), DEFINT(AR_ISR_S0, "ISR_S0"), DEFINT(AR_ISR_S1, "ISR_S1"), DEFINTfmt(AR_ISR_S2, "ISR_S2", "\20\21MCABT\22SSERR\23DPERR\24TIM\25CABEND\26DTIMSYNC\27BCNTO" "\30CABTO\31DTIM"), DEFINT(AR_ISR_S3, "ISR_S3"), DEFINT(AR_ISR_S4, "ISR_S4"), DEFINT(AR_ISR_S5, "ISR_S5"), DEFINTfmt(AR_IMR, "IMR", "\20\1RXOK\2RXDESC\3RXERR\4RXNOPKT\5RXEOL\6RXORN\7TXOK\10TXDESC" "\11TXERR\12TXNOPKT\13TXEOL\14TXURN\15MIB\16SWI\17RXPHY\20RXKCM" "\21SWBA\22BRSSI\23BMISS\24HIUERR\25BNR\26RXCHIRP\27RXDOPPL\30BCNMISS" "\31TIM\32GPIO\33QCBROVF\34QCBRURN\35QTRIG"), DEFINT(AR_IMR_S0, "IMR_S0"), DEFINT(AR_IMR_S1, "IMR_S1"), DEFINTfmt(AR_IMR_S2, "IMR_S2", "\20\21MCABT\22SSERR\23DPERR\24TIM\25CABEND\26DTIMSYNC\27BCNTO" "\30CABTO\31DTIM"), DEFINT(AR_IMR_S3, "IMR_S3"), DEFINT(AR_IMR_S4, "IMR_S4"), /* NB: don't read the RAC so we don't affect operation */ DEFVOID(AR_ISR_RAC, "ISR_RAC"), DEFINT(AR_ISR_S0_S, "ISR_S0_S"), DEFINT(AR_ISR_S1_S, "ISR_S1_S"), DEFINT(AR_ISR_S2_S, "ISR_S2_S"), DEFINT(AR_ISR_S3_S, "ISR_S3_S"), DEFINT(AR_ISR_S4_S, "ISR_S4_S"), DEFINT(AR_ISR_S5_S, "ISR_S5_S"), DEFBASIC(AR_DMADBG_0, "DMADBG0"), DEFBASIC(AR_DMADBG_1, "DMADBG1"), DEFBASIC(AR_DMADBG_2, "DMADBG2"), DEFBASIC(AR_DMADBG_3, "DMADBG3"), DEFBASIC(AR_DMADBG_4, "DMADBG4"), DEFBASIC(AR_DMADBG_5, "DMADBG5"), DEFBASIC(AR_DMADBG_6, "DMADBG6"), DEFBASIC(AR_DMADBG_7, "DMADBG7"), DEFBASIC(AR_DCM_A, "DCM_A"), DEFBASIC(AR_DCM_D, "DCM_D"), DEFBASIC(AR_DCCFG, "DCCFG"), DEFBASIC(AR_CCFG, "CCFG"), DEFBASIC(AR_CCUCFG, "CCUCFG"), DEFBASIC(AR_CPC_0, "CPC0"), DEFBASIC(AR_CPC_1, "CPC1"), DEFBASIC(AR_CPC_2, "CPC2"), DEFBASIC(AR_CPC_3, "CPC3"), DEFBASIC(AR_CPCOVF, "CPCOVF"), DEFQCU(AR_Q0_TXDP, "Q0_TXDP"), DEFQCU(AR_Q1_TXDP, "Q1_TXDP"), DEFQCU(AR_Q2_TXDP, "Q2_TXDP"), DEFQCU(AR_Q3_TXDP, "Q3_TXDP"), DEFQCU(AR_Q4_TXDP, "Q4_TXDP"), DEFQCU(AR_Q5_TXDP, "Q5_TXDP"), DEFQCU(AR_Q6_TXDP, "Q6_TXDP"), DEFQCU(AR_Q7_TXDP, "Q7_TXDP"), DEFQCU(AR_Q8_TXDP, "Q8_TXDP"), DEFQCU(AR_Q9_TXDP, "Q9_TXDP"), DEFQCU(AR_Q_TXE, "Q_TXE"), DEFQCU(AR_Q_TXD, "Q_TXD"), DEFQCU(AR_Q0_CBRCFG, "Q0_CBR"), DEFQCU(AR_Q1_CBRCFG, "Q1_CBR"), DEFQCU(AR_Q2_CBRCFG, "Q2_CBR"), DEFQCU(AR_Q3_CBRCFG, "Q3_CBR"), DEFQCU(AR_Q4_CBRCFG, "Q4_CBR"), DEFQCU(AR_Q5_CBRCFG, "Q5_CBR"), DEFQCU(AR_Q6_CBRCFG, "Q6_CBR"), DEFQCU(AR_Q7_CBRCFG, "Q7_CBR"), DEFQCU(AR_Q8_CBRCFG, "Q8_CBR"), DEFQCU(AR_Q9_CBRCFG, "Q9_CBR"), DEFQCU(AR_Q0_RDYTIMECFG, "Q0_RDYT"), DEFQCU(AR_Q1_RDYTIMECFG, "Q1_RDYT"), DEFQCU(AR_Q2_RDYTIMECFG, "Q2_RDYT"), DEFQCU(AR_Q3_RDYTIMECFG, "Q3_RDYT"), DEFQCU(AR_Q4_RDYTIMECFG, "Q4_RDYT"), DEFQCU(AR_Q5_RDYTIMECFG, "Q5_RDYT"), DEFQCU(AR_Q6_RDYTIMECFG, "Q6_RDYT"), DEFQCU(AR_Q7_RDYTIMECFG, "Q7_RDYT"), DEFQCU(AR_Q8_RDYTIMECFG, "Q8_RDYT"), DEFQCU(AR_Q9_RDYTIMECFG, "Q9_RDYT"), DEFQCU(AR_Q_ONESHOTARM_SC, "Q_ONESHOTARM_SC"), DEFQCU(AR_Q_ONESHOTARM_CC, "Q_ONESHOTARM_CC"), DEFQCU(AR_Q0_MISC, "Q0_MISC"), DEFQCU(AR_Q1_MISC, "Q1_MISC"), DEFQCU(AR_Q2_MISC, "Q2_MISC"), DEFQCU(AR_Q3_MISC, "Q3_MISC"), DEFQCU(AR_Q4_MISC, "Q4_MISC"), DEFQCU(AR_Q5_MISC, "Q5_MISC"), DEFQCU(AR_Q6_MISC, "Q6_MISC"), DEFQCU(AR_Q7_MISC, "Q7_MISC"), DEFQCU(AR_Q8_MISC, "Q8_MISC"), DEFQCU(AR_Q9_MISC, "Q9_MISC"), DEFQCU(AR_Q0_STS, "Q0_STS"), DEFQCU(AR_Q1_STS, "Q1_STS"), DEFQCU(AR_Q2_STS, "Q2_STS"), DEFQCU(AR_Q3_STS, "Q3_STS"), DEFQCU(AR_Q4_STS, "Q4_STS"), DEFQCU(AR_Q5_STS, "Q5_STS"), DEFQCU(AR_Q6_STS, "Q6_STS"), DEFQCU(AR_Q7_STS, "Q7_STS"), DEFQCU(AR_Q8_STS, "Q8_STS"), DEFQCU(AR_Q9_STS, "Q9_STS"), DEFQCU(AR_Q_RDYTIMESHDN, "Q_RDYTIMSHD"), DEFQCU(AR_Q_CBBS, "Q_CBBS"), DEFQCU(AR_Q_CBBA, "Q_CBBA"), DEFQCU(AR_Q_CBC, "Q_CBC"), DEFDCU(AR_D0_QCUMASK, "D0_MASK"), DEFDCU(AR_D1_QCUMASK, "D1_MASK"), DEFDCU(AR_D2_QCUMASK, "D2_MASK"), DEFDCU(AR_D3_QCUMASK, "D3_MASK"), DEFDCU(AR_D4_QCUMASK, "D4_MASK"), DEFDCU(AR_D5_QCUMASK, "D5_MASK"), DEFDCU(AR_D6_QCUMASK, "D6_MASK"), DEFDCU(AR_D7_QCUMASK, "D7_MASK"), DEFDCU(AR_D8_QCUMASK, "D8_MASK"), DEFDCU(AR_D9_QCUMASK, "D9_MASK"), DEFDCU(AR_D0_LCL_IFS, "D0_IFS"), DEFDCU(AR_D1_LCL_IFS, "D1_IFS"), DEFDCU(AR_D2_LCL_IFS, "D2_IFS"), DEFDCU(AR_D3_LCL_IFS, "D3_IFS"), DEFDCU(AR_D4_LCL_IFS, "D4_IFS"), DEFDCU(AR_D5_LCL_IFS, "D5_IFS"), DEFDCU(AR_D6_LCL_IFS, "D6_IFS"), DEFDCU(AR_D7_LCL_IFS, "D7_IFS"), DEFDCU(AR_D8_LCL_IFS, "D8_IFS"), DEFDCU(AR_D9_LCL_IFS, "D9_IFS"), DEFDCU(AR_D0_RETRY_LIMIT, "D0_RTRY"), DEFDCU(AR_D1_RETRY_LIMIT, "D1_RTRY"), DEFDCU(AR_D2_RETRY_LIMIT, "D2_RTRY"), DEFDCU(AR_D3_RETRY_LIMIT, "D3_RTRY"), DEFDCU(AR_D4_RETRY_LIMIT, "D4_RTRY"), DEFDCU(AR_D5_RETRY_LIMIT, "D5_RTRY"), DEFDCU(AR_D6_RETRY_LIMIT, "D6_RTRY"), DEFDCU(AR_D7_RETRY_LIMIT, "D7_RTRY"), DEFDCU(AR_D8_RETRY_LIMIT, "D8_RTRY"), DEFDCU(AR_D9_RETRY_LIMIT, "D9_RTRY"), DEFDCU(AR_D0_CHNTIME, "D0_CHNT"), DEFDCU(AR_D1_CHNTIME, "D1_CHNT"), DEFDCU(AR_D2_CHNTIME, "D2_CHNT"), DEFDCU(AR_D3_CHNTIME, "D3_CHNT"), DEFDCU(AR_D4_CHNTIME, "D4_CHNT"), DEFDCU(AR_D5_CHNTIME, "D5_CHNT"), DEFDCU(AR_D6_CHNTIME, "D6_CHNT"), DEFDCU(AR_D7_CHNTIME, "D7_CHNT"), DEFDCU(AR_D8_CHNTIME, "D8_CHNT"), DEFDCU(AR_D9_CHNTIME, "D9_CHNT"), DEFDCU(AR_D0_MISC, "D0_MISC"), DEFDCU(AR_D1_MISC, "D1_MISC"), DEFDCU(AR_D2_MISC, "D2_MISC"), DEFDCU(AR_D3_MISC, "D3_MISC"), DEFDCU(AR_D4_MISC, "D4_MISC"), DEFDCU(AR_D5_MISC, "D5_MISC"), DEFDCU(AR_D6_MISC, "D6_MISC"), DEFDCU(AR_D7_MISC, "D7_MISC"), DEFDCU(AR_D8_MISC, "D8_MISC"), DEFDCU(AR_D9_MISC, "D9_MISC"), _DEFREG(AR_D_SEQNUM, "D_SEQ", DUMP_BASIC | DUMP_DCU), DEFBASIC(AR_D_GBL_IFS_SIFS, "D_SIFS"), DEFBASIC(AR_D_GBL_IFS_SLOT, "D_SLOT"), DEFBASIC(AR_D_GBL_IFS_EIFS, "D_EIFS"), DEFBASIC(AR_D_GBL_IFS_MISC, "D_MISC"), DEFBASIC(AR_D_FPCTL, "D_FPCTL"), DEFBASIC(AR_D_TXPSE, "D_TXPSE"), DEFVOID(AR_D_TXBLK_CMD, "D_CMD"), #if 0 DEFVOID(AR_D_TXBLK_DATA, "D_DATA"), #endif DEFVOID(AR_D_TXBLK_CLR, "D_CLR"), DEFVOID(AR_D_TXBLK_SET, "D_SET"), DEFBASIC(AR_MAC_LED, "MAC_LED"), DEFBASICfmt(AR_RC, "RC", "\20\1AHB\2APB\11HOSTIF"), DEFBASIC(AR_SCR, "SCR"), DEFBASIC(AR_INTPEND, "INTPEND"), DEFBASIC(AR_SFR, "SFR"), DEFBASIC(AR_PCICFG, "PCICFG"), DEFBASIC(AR_SREV, "SREV"), DEFBASIC(AR_AHB_MODE, "AHBMODE"), DEFBASIC(AR_PCIE_PM_CTRL, "PCIEPMC"), DEFBASIC(AR5416_PCIE_SERDES,"SERDES"), DEFBASIC(AR5416_PCIE_SERDES2, "SERDES2"), DEFVOID(AR_INTR_SYNC_CAUSE_CLR, "INTR_SYNC_CAUSE_CLR"), DEFVOID(AR_INTR_SYNC_CAUSE, "INTR_SYNC_CAUSE"), DEFVOID(AR_INTR_SYNC_ENABLE,"INTR_SYNC_ENABLE"), DEFBASIC(AR_INTR_ASYNC_MASK,"IASYNCM"), DEFBASIC(AR_INTR_SYNC_MASK, "ISYNCM"), DEFVOID(AR_INTR_ASYNC_CAUSE,"INTR_ASYNC_CAUSE"), DEFVOID(AR_INTR_ASYNC_ENABLE,"INTR_ASYNC_ENABLE"), DEFBASICfmt(AR_RTC_RC, "RTC_RC", "\20\1MAC_WARM\2MAC_COLD"), DEFBASIC(AR_RTC_PLL_CONTROL,"RTC_PLL"), DEFVOID(AR_RTC_RESET, "RTC_RESET"), DEFVOIDfmt(AR_RTC_STATUS, "RTC_STATUS", "\20\1SHUTDOWN\2ON\3SLEEP\4WAKEUP\5COLDRESET\6PLLCHANGE"), DEFVOID(AR_RTC_SLEEP_CLK, "RTC_SLEEP_CLK"), DEFVOIDfmt(AR_RTC_FORCE_WAKE,"RTC_FORCE_WAKE", "\20\1EN\2WAKE_ON_INT"), DEFVOID(AR_RTC_INTR_CAUSE, "RTC_INTR_CAUSE"), DEFVOID(AR_RTC_INTR_MASK, "RTC_INTR_MASK"), DEFBASIC(AR_GPIO_IN_OUT, "GPIOIO"), DEFBASIC(AR_GPIO_OE_OUT, "GPIOOE"), DEFBASIC(AR_GPIO_INTR_POL, "GPIOPOL"), DEFBASIC(AR_GPIO_INPUT_EN_VAL, "GPIOIEV"), DEFBASIC(AR_GPIO_INPUT_MUX1, "GPIMUX1"), DEFBASIC(AR_GPIO_INPUT_MUX2, "GPIMUX2"), DEFBASIC(AR_GPIO_OUTPUT_MUX1, "GPOMUX1"), DEFBASIC(AR_GPIO_OUTPUT_MUX2, "GPOMUX2"), DEFBASIC(AR_GPIO_OUTPUT_MUX3, "GPOMUX3"), DEFBASIC(AR_OBS, "OBS"), DEFVOID(AR_EEPROM_ADDR, "EEADDR"), DEFVOID(AR_EEPROM_DATA, "EEDATA"), DEFVOID(AR_EEPROM_CMD, "EECMD"), DEFVOID(AR_EEPROM_STS, "EESTS"), DEFVOID(AR_EEPROM_CFG, "EECFG"), DEFBASIC(AR_STA_ID0, "STA_ID0"), DEFBASICfmt(AR_STA_ID1, "STA_ID1", "\20\21AP\22ADHOC\23PWR_SAV\24KSRCHDIS\25PCF\26USE_DEFANT" "\27UPD_DEFANT\30RTS_USE_DEF\31ACKCTS_6MB\32BASE_RATE_11B" "\33USE_DA_SG\34CRPT_MIC_ENABLE\35KSRCH_MODE\36PRE_SEQNUM" "\37CBCIV_ENDIAN\40MCAST_KSRC"), DEFBASIC(AR_BSS_ID0, "BSS_ID0"), DEFBASIC(AR_BSS_ID1, "BSS_ID1"), DEFBASIC(AR_SLOT_TIME, "SLOTTIME"), DEFBASIC(AR_TIME_OUT, "TIME_OUT"), DEFBASIC(AR_RSSI_THR, "RSSI_THR"), DEFBASIC(AR_USEC, "USEC"), DEFBASIC(AR_BEACON, "BEACON"), DEFBASIC(AR_CFP_PERIOD, "CFP_PER"), DEFBASIC(AR_TIMER0, "TIMER0"), DEFBASIC(AR_TIMER1, "TIMER1"), DEFBASIC(AR_TIMER2, "TIMER2"), DEFBASIC(AR_TIMER3, "TIMER3"), DEFBASIC(AR_CFP_DUR, "CFP_DUR"), DEFBASIC(AR_RX_FILTER, "RXFILTER"), DEFBASIC(AR_MCAST_FIL0, "MCAST_0"), DEFBASIC(AR_MCAST_FIL1, "MCAST_1"), DEFBASICfmt(AR_DIAG_SW, "DIAG_SW", "\20\1CACHE_ACK\2ACK_DIS\3CTS_DIS\4ENCRYPT_DIS\5DECRYPT_DIS\6RX_DIS" "\7CORR_FCS\10CHAN_INFO\11EN_SCRAMSD\22FRAME_NV0\25RX_CLR_HI" "\26IGNORE_CS\27CHAN_IDLE\30PHEAR_ME"), DEFBASIC(AR_TSF_L32, "TSF_L32"), DEFBASIC(AR_TSF_U32, "TSF_U32"), DEFBASIC(AR_TST_ADDAC, "TST_ADAC"), DEFBASIC(AR_DEF_ANTENNA, "DEF_ANT"), DEFBASIC(AR_QOS_MASK, "QOS_MASK"), DEFBASIC(AR_SEQ_MASK, "SEQ_MASK"), DEFBASIC(AR_OBSERV_2, "OBSERV2"), DEFBASIC(AR_OBSERV_1, "OBSERV1"), DEFBASIC(AR_LAST_TSTP, "LAST_TST"), DEFBASIC(AR_NAV, "NAV"), DEFBASIC(AR_RTS_OK, "RTS_OK"), DEFBASIC(AR_RTS_FAIL, "RTS_FAIL"), DEFBASIC(AR_ACK_FAIL, "ACK_FAIL"), DEFBASIC(AR_FCS_FAIL, "FCS_FAIL"), DEFBASIC(AR_BEACON_CNT, "BEAC_CNT"), DEFBASIC(AR_SLEEP1, "SLEEP1"), DEFBASIC(AR_SLEEP2, "SLEEP2"), DEFBASIC(AR_SLEEP3, "SLEEP3"), DEFBASIC(AR_BSSMSKL, "BSSMSKL"), DEFBASIC(AR_BSSMSKU, "BSSMSKU"), DEFBASIC(AR_TPC, "TPC"), DEFBASIC(AR_TFCNT, "TFCNT"), DEFBASIC(AR_RFCNT, "RFCNT"), DEFBASIC(AR_RCCNT, "RCCNT"), DEFBASIC(AR_CCCNT, "CCCNT"), DEFBASIC(AR_QUIET1, "QUIET1"), DEFBASIC(AR_QUIET2, "QUIET2"), DEFBASIC(AR_TSF_PARM, "TSF_PARM"), DEFBASIC(AR_NOACK, "NOACK"), DEFBASIC(AR_PHY_ERR, "PHY_ERR"), DEFBASIC(AR_QOS_CONTROL, "QOS_CTRL"), DEFBASIC(AR_QOS_SELECT, "QOS_SEL"), DEFBASIC(AR_MISC_MODE, "MISCMODE"), DEFBASIC(AR_FILTOFDM, "FILTOFDM"), DEFBASIC(AR_FILTCCK, "FILTCCK"), DEFBASIC(AR_PHYCNT1, "PHYCNT1"), DEFBASIC(AR_PHYCNTMASK1, "PHYCMSK1"), DEFBASIC(AR_PHYCNT2, "PHYCNT2"), DEFBASIC(AR_PHYCNTMASK2, "PHYCMSK2"), DEFBASIC(AR_TXOP_X, "TXOPX"), DEFBASIC(AR_NEXT_TBTT, "NXTTBTT"), DEFBASIC(AR_NEXT_DBA, "NXTDBA"), DEFBASIC(AR_NEXT_SWBA, "NXTSWBA"), DEFBASIC(AR_NEXT_CFP, "NXTCFP"), DEFBASIC(AR_NEXT_HCF, "NXTHCF"), DEFBASIC(AR_NEXT_DTIM, "NXTDTIM"), DEFBASIC(AR_NEXT_QUIET, "NXTQUIET"), DEFBASIC(AR_NEXT_NDP, "NXTNDP"), DEFBASIC(AR5416_BEACON_PERIOD, "BCNPER"), DEFBASIC(AR_DBA_PERIOD, "DBAPER"), DEFBASIC(AR_SWBA_PERIOD, "SWBAPER"), DEFBASIC(AR_TIM_PERIOD, "TIMPER"), DEFBASIC(AR_DTIM_PERIOD, "DTIMPER"), DEFBASIC(AR_QUIET_PERIOD, "QUIETPER"), DEFBASIC(AR_NDP_PERIOD, "NDPPER"), DEFBASIC(AR_TIMER_MODE, "TIMERMOD"), DEFBASIC(AR_2040_MODE, "2040MODE"), DEFBASIC(AR_PCU_TXBUF_CTRL, "PCUTXBUF"), DEFBASIC(AR_SLP32_MODE, "SLP32MOD"), DEFBASIC(AR_SLP32_WAKE, "SLP32WAK"), DEFBASIC(AR_SLP32_INC, "SLP32INC"), DEFBASIC(AR_SLP_CNT, "SLPCNT"), DEFBASIC(AR_SLP_MIB_CTRL, "SLPMIB"), DEFBASIC(AR_EXTRCCNT, "EXTRCCNT"), DEFBASIC(AR_PHY_TURBO, "PHYTURBO"), DEFVOID(AR_PHY_ADC_SERIAL_CTL, "PHY_ADC_SERIAL_CTL"), /* XXX { AR_RATE_DURATION(0), AR_RATE_DURATION(0x20) }, */ }; static __constructor void ar5416_ctor(void) { - register_regs(ar5416regs, N(ar5416regs), MAC5416, PHYANY); + register_regs(ar5416regs, nitems(ar5416regs), MAC5416, PHYANY); register_keycache(128, MAC5416, PHYANY); register_range(0x9800, 0x987c, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0x9900, 0x997c, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0x99a4, 0x99a4, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0x9c00, 0x9c1c, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0xa180, 0xa238, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0xa258, 0xa26c, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0xa3c8, 0xa3d4, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0xa864, 0xa864, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0xa9bc, 0xa9bc, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0xb864, 0xb864, DUMP_BASEBAND, MAC5416, PHYANY); register_range(0xb9bc, 0xb9bc, DUMP_BASEBAND, MAC5416, PHYANY); } Index: head/tools/tools/crypto/cryptostats.c =================================================================== --- head/tools/tools/crypto/cryptostats.c (revision 287296) +++ head/tools/tools/crypto/cryptostats.c (revision 287297) @@ -1,105 +1,109 @@ /*- * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Little program to dump the crypto statistics block and, optionally, * zero all the stats or just the timing stuff. */ -#include -#include -#include #include #include #include + #include + +#include +#include +#include +#include +#include static void printt(const char* tag, struct cryptotstat *ts) { uint64_t avg, min, max; if (ts->count == 0) return; avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count; min = 1000000000LL*ts->min.tv_sec + ts->min.tv_nsec; max = 1000000000LL*ts->max.tv_sec + ts->max.tv_nsec; printf("%16.16s: avg %6llu ns : min %6llu ns : max %7llu ns [%u samps]\n", tag, avg, min, max, ts->count); } int main(int argc, char *argv[]) { struct cryptostats stats; size_t slen; slen = sizeof (stats); if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) err(1, "kern.cryptostats"); if (argc > 1 && strcmp(argv[1], "-z") == 0) { bzero(&stats.cs_invoke, sizeof (stats.cs_invoke)); bzero(&stats.cs_done, sizeof (stats.cs_done)); bzero(&stats.cs_cb, sizeof (stats.cs_cb)); bzero(&stats.cs_finis, sizeof (stats.cs_finis)); stats.cs_invoke.min.tv_sec = 10000; stats.cs_done.min.tv_sec = 10000; stats.cs_cb.min.tv_sec = 10000; stats.cs_finis.min.tv_sec = 10000; if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0) err(1, "kern.cryptostats"); exit(0); } if (argc > 1 && strcmp(argv[1], "-Z") == 0) { bzero(&stats, sizeof (stats)); stats.cs_invoke.min.tv_sec = 10000; stats.cs_done.min.tv_sec = 10000; stats.cs_cb.min.tv_sec = 10000; stats.cs_finis.min.tv_sec = 10000; if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0) err(1, "kern.cryptostats"); exit(0); } printf("%u symmetric crypto ops (%u errors, %u times driver blocked)\n" , stats.cs_ops, stats.cs_errs, stats.cs_blocks); printf("%u key ops (%u errors, %u times driver blocked)\n" , stats.cs_kops, stats.cs_kerrs, stats.cs_kblocks); printf("%u crypto dispatch thread activations\n", stats.cs_intrs); printf("%u crypto return thread activations\n", stats.cs_rets); if (stats.cs_invoke.count) { printf("\n"); printt("dispatch->invoke", &stats.cs_invoke); printt("invoke->done", &stats.cs_done); printt("done->cb", &stats.cs_cb); printt("cb->finis", &stats.cs_finis); } return 0; } Index: head/tools/tools/crypto/cryptotest.c =================================================================== --- head/tools/tools/crypto/cryptotest.c (revision 287296) +++ head/tools/tools/crypto/cryptotest.c (revision 287297) @@ -1,622 +1,622 @@ /*- * Copyright (c) 2004 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * Simple tool for testing hardware/system crypto support. * * cryptotest [-czsbv] [-a algorithm] [count] [size ...] * * Run count iterations of a crypt+decrypt or mac operation on a buffer of * size bytes. A random key and iv are used. Options: * -c check the results * -d dev pin work on device dev * -z run all available algorithms on a variety of buffer sizes * -v be verbose * -b mark operations for batching * -p profile kernel crypto operations (must be root) * -t n fork n threads and run tests concurrently * Known algorithms are: * null null cbc * des des cbc * 3des 3des cbc * blf blowfish cbc * cast cast cbc * skj skipjack cbc * aes rijndael/aes 128-bit cbc * aes192 rijndael/aes 192-bit cbc * aes256 rijndael/aes 256-bit cbc * md5 md5 hmac * sha1 sha1 hmac * sha256 256-bit sha2 hmac * sha384 384-bit sha2 hmac * sha512 512--bit sha2 hmac * * For a test of how fast a crypto card is, use something like: * cryptotest -z 1024 * This will run a series of tests using the available crypto/cipher * algorithms over a variety of buffer sizes. The 1024 says to do 1024 * iterations. Extra arguments can be used to specify one or more buffer * sizes to use in doing tests. * * To fork multiple processes all doing the same work, specify -t X on the * command line to get X "threads" running simultaneously. No effort is made * to synchronize the threads or otherwise maximize load. * * If the kernel crypto code is built with CRYPTO_TIMING and you run as root, * then you can specify the -p option to get a "profile" of the time spent * processing crypto operations. At present this data is only meaningful for * symmetric operations. To get meaningful numbers you must run on an idle * machine. * * Expect ~400 Mb/s for a Broadcom 582x for 8K buffers on a reasonable CPU * (64-bit PCI helps). Hifn 7811 parts top out at ~110 Mb/s. */ -#include + #include -#include #include -#include -#include -#include -#include #include +#include +#include +#include + +#include +#include #include +#include #include #include +#include -#include -#include #include #define CHUNK 64 /* how much to display */ -#define N(a) (sizeof (a) / sizeof (a[0])) #define streq(a,b) (strcasecmp(a,b) == 0) void hexdump(char *, int); int verbose = 0; int opflags = 0; int verify = 0; int crid = CRYPTO_FLAG_HARDWARE; struct alg { const char* name; int ishash; int blocksize; int minkeylen; int maxkeylen; int code; } algorithms[] = { #ifdef CRYPTO_NULL_CBC { "null", 0, 8, 1, 256, CRYPTO_NULL_CBC }, #endif { "des", 0, 8, 8, 8, CRYPTO_DES_CBC }, { "3des", 0, 8, 24, 24, CRYPTO_3DES_CBC }, { "blf", 0, 8, 5, 56, CRYPTO_BLF_CBC }, { "cast", 0, 8, 5, 16, CRYPTO_CAST_CBC }, { "skj", 0, 8, 10, 10, CRYPTO_SKIPJACK_CBC }, { "aes", 0, 16, 16, 16, CRYPTO_RIJNDAEL128_CBC}, { "aes192", 0, 16, 24, 24, CRYPTO_RIJNDAEL128_CBC}, { "aes256", 0, 16, 32, 32, CRYPTO_RIJNDAEL128_CBC}, #ifdef notdef { "arc4", 0, 8, 1, 32, CRYPTO_ARC4 }, #endif { "md5", 1, 8, 16, 16, CRYPTO_MD5_HMAC }, { "sha1", 1, 8, 20, 20, CRYPTO_SHA1_HMAC }, { "sha256", 1, 8, 32, 32, CRYPTO_SHA2_256_HMAC }, { "sha384", 1, 8, 48, 48, CRYPTO_SHA2_384_HMAC }, { "sha512", 1, 8, 64, 64, CRYPTO_SHA2_512_HMAC }, }; static void usage(const char* cmd) { printf("usage: %s [-czsbv] [-d dev] [-a algorithm] [count] [size ...]\n", cmd); printf("where algorithm is one of:\n"); printf(" des 3des (default) blowfish cast skipjack\n"); printf(" aes (aka rijndael) aes192 aes256 arc4\n"); printf("count is the number of encrypt/decrypt ops to do\n"); printf("size is the number of bytes of text to encrypt+decrypt\n"); printf("\n"); printf("-c check the results (slows timing)\n"); printf("-d use specific device\n"); printf("-z run all available algorithms on a variety of sizes\n"); printf("-v be verbose\n"); printf("-b mark operations for batching\n"); printf("-p profile kernel crypto operation (must be root)\n"); exit(-1); } static struct alg* getalgbycode(int cipher) { int i; - for (i = 0; i < N(algorithms); i++) + for (i = 0; i < nitems(algorithms); i++) if (cipher == algorithms[i].code) return &algorithms[i]; return NULL; } static struct alg* getalgbyname(const char* name) { int i; - for (i = 0; i < N(algorithms); i++) + for (i = 0; i < nitems(algorithms); i++) if (streq(name, algorithms[i].name)) return &algorithms[i]; return NULL; } static int devcrypto(void) { static int fd = -1; if (fd < 0) { fd = open(_PATH_DEV "crypto", O_RDWR, 0); if (fd < 0) err(1, _PATH_DEV "crypto"); if (fcntl(fd, F_SETFD, 1) == -1) err(1, "fcntl(F_SETFD) (devcrypto)"); } return fd; } static int crlookup(const char *devname) { struct crypt_find_op find; find.crid = -1; strlcpy(find.name, devname, sizeof(find.name)); if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) err(1, "ioctl(CIOCFINDDEV)"); return find.crid; } static const char * crfind(int crid) { static struct crypt_find_op find; bzero(&find, sizeof(find)); find.crid = crid; if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1) err(1, "ioctl(CIOCFINDDEV): crid %d", crid); return find.name; } static int crget(void) { int fd; if (ioctl(devcrypto(), CRIOGET, &fd) == -1) err(1, "ioctl(CRIOGET)"); if (fcntl(fd, F_SETFD, 1) == -1) err(1, "fcntl(F_SETFD) (crget)"); return fd; } static char rdigit(void) { const char a[] = { 0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41, 0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01 }; - return 0x20+a[random()%N(a)]; + return 0x20+a[random()%nitems(a)]; } static void runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) { int i, fd = crget(); struct timeval start, stop, dt; char *cleartext, *ciphertext, *originaltext; struct session2_op sop; struct crypt_op cop; char iv[EALG_MAX_BLOCK_LEN]; bzero(&sop, sizeof(sop)); if (!alg->ishash) { sop.keylen = (alg->minkeylen + alg->maxkeylen)/2; sop.key = (char *) malloc(sop.keylen); if (sop.key == NULL) err(1, "malloc (key)"); for (i = 0; i < sop.keylen; i++) sop.key[i] = rdigit(); sop.cipher = alg->code; } else { sop.mackeylen = (alg->minkeylen + alg->maxkeylen)/2; sop.mackey = (char *) malloc(sop.mackeylen); if (sop.mackey == NULL) err(1, "malloc (mac)"); for (i = 0; i < sop.mackeylen; i++) sop.mackey[i] = rdigit(); sop.mac = alg->code; } sop.crid = crid; if (ioctl(fd, cmd, &sop) < 0) { if (cmd == CIOCGSESSION || cmd == CIOCGSESSION2) { close(fd); if (verbose) { printf("cipher %s", alg->name); if (alg->ishash) printf(" mackeylen %u\n", sop.mackeylen); else printf(" keylen %u\n", sop.keylen); perror("CIOCGSESSION"); } /* hardware doesn't support algorithm; skip it */ return; } printf("cipher %s keylen %u mackeylen %u\n", alg->name, sop.keylen, sop.mackeylen); err(1, "CIOCGSESSION"); } originaltext = malloc(3*size); if (originaltext == NULL) err(1, "malloc (text)"); cleartext = originaltext+size; ciphertext = cleartext+size; for (i = 0; i < size; i++) cleartext[i] = rdigit(); memcpy(originaltext, cleartext, size); - for (i = 0; i < N(iv); i++) + for (i = 0; i < nitems(iv); i++) iv[i] = rdigit(); if (verbose) { printf("session = 0x%x\n", sop.ses); printf("device = %s\n", crfind(sop.crid)); printf("count = %d, size = %d\n", count, size); if (!alg->ishash) { printf("iv:"); hexdump(iv, sizeof iv); } printf("cleartext:"); hexdump(cleartext, MIN(size, CHUNK)); } gettimeofday(&start, NULL); if (!alg->ishash) { for (i = 0; i < count; i++) { cop.ses = sop.ses; cop.op = COP_ENCRYPT; cop.flags = opflags; cop.len = size; cop.src = cleartext; cop.dst = ciphertext; cop.mac = 0; cop.iv = iv; if (ioctl(fd, CIOCCRYPT, &cop) < 0) err(1, "ioctl(CIOCCRYPT)"); if (verify && bcmp(ciphertext, cleartext, size) == 0) { printf("cipher text unchanged:"); hexdump(ciphertext, size); } memset(cleartext, 'x', MIN(size, CHUNK)); cop.ses = sop.ses; cop.op = COP_DECRYPT; cop.flags = opflags; cop.len = size; cop.src = ciphertext; cop.dst = cleartext; cop.mac = 0; cop.iv = iv; if (ioctl(fd, CIOCCRYPT, &cop) < 0) err(1, "ioctl(CIOCCRYPT)"); if (verify && bcmp(cleartext, originaltext, size) != 0) { printf("decrypt mismatch:\n"); printf("original:"); hexdump(originaltext, size); printf("cleartext:"); hexdump(cleartext, size); } } } else { for (i = 0; i < count; i++) { cop.ses = sop.ses; cop.op = 0; cop.flags = opflags; cop.len = size; cop.src = cleartext; cop.dst = 0; cop.mac = ciphertext; cop.iv = 0; if (ioctl(fd, CIOCCRYPT, &cop) < 0) err(1, "ioctl(CIOCCRYPT)"); } } gettimeofday(&stop, NULL); if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0) perror("ioctl(CIOCFSESSION)"); if (verbose) { printf("cleartext:"); hexdump(cleartext, MIN(size, CHUNK)); } timersub(&stop, &start, tv); free(originaltext); close(fd); } #ifdef __FreeBSD__ static void resetstats() { struct cryptostats stats; size_t slen; slen = sizeof (stats); if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) { perror("kern.crypto_stats"); return; } bzero(&stats.cs_invoke, sizeof (stats.cs_invoke)); bzero(&stats.cs_done, sizeof (stats.cs_done)); bzero(&stats.cs_cb, sizeof (stats.cs_cb)); bzero(&stats.cs_finis, sizeof (stats.cs_finis)); stats.cs_invoke.min.tv_sec = 10000; stats.cs_done.min.tv_sec = 10000; stats.cs_cb.min.tv_sec = 10000; stats.cs_finis.min.tv_sec = 10000; if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0) perror("kern.cryptostats"); } static void printt(const char* tag, struct cryptotstat *ts) { uint64_t avg, min, max; if (ts->count == 0) return; avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count; min = 1000000000LL*ts->min.tv_sec + ts->min.tv_nsec; max = 1000000000LL*ts->max.tv_sec + ts->max.tv_nsec; printf("%16.16s: avg %6llu ns : min %6llu ns : max %7llu ns [%u samps]\n", tag, avg, min, max, ts->count); } #endif static void runtests(struct alg *alg, int count, int size, u_long cmd, int threads, int profile) { int i, status; double t; void *region; struct timeval *tvp; struct timeval total; int otiming; if (size % alg->blocksize) { if (verbose) printf("skipping blocksize %u 'cuz not a multiple of " "%s blocksize %u\n", size, alg->name, alg->blocksize); return; } region = mmap(NULL, threads * sizeof (struct timeval), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); if (region == MAP_FAILED) { perror("mmap"); return; } tvp = (struct timeval *) region; #ifdef __FreeBSD__ if (profile) { size_t tlen = sizeof (otiming); int timing = 1; resetstats(); if (sysctlbyname("debug.crypto_timing", &otiming, &tlen, &timing, sizeof (timing)) < 0) perror("debug.crypto_timing"); } #endif if (threads > 1) { for (i = 0; i < threads; i++) if (fork() == 0) { runtest(alg, count, size, cmd, &tvp[i]); exit(0); } while (waitpid(WAIT_MYPGRP, &status, 0) != -1) ; } else runtest(alg, count, size, cmd, tvp); t = 0; for (i = 0; i < threads; i++) t += (((double)tvp[i].tv_sec * 1000000 + tvp[i].tv_usec) / 1000000); if (t) { int nops = alg->ishash ? count : 2*count; #if 0 t /= threads; printf("%6.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", t, nops, alg->name, size, (double)nops*size / t, (double)nops*size / t * 8 / 1024 / 1024); #else nops *= threads; printf("%8.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", t, nops, alg->name, size, (double)nops*size / t, (double)nops*size / t * 8 / 1024 / 1024); #endif } #ifdef __FreeBSD__ if (profile) { struct cryptostats stats; size_t slen = sizeof (stats); if (sysctlbyname("debug.crypto_timing", NULL, NULL, &otiming, sizeof (otiming)) < 0) perror("debug.crypto_timing"); if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) perror("kern.cryptostats"); if (stats.cs_invoke.count) { printt("dispatch->invoke", &stats.cs_invoke); printt("invoke->done", &stats.cs_done); printt("done->cb", &stats.cs_cb); printt("cb->finis", &stats.cs_finis); } } #endif fflush(stdout); } int main(int argc, char **argv) { struct alg *alg = NULL; int count = 1; int sizes[128], nsizes = 0; u_long cmd = CIOCGSESSION2; int testall = 0; int maxthreads = 1; int profile = 0; int i, ch; while ((ch = getopt(argc, argv, "cpzsva:bd:t:")) != -1) { switch (ch) { #ifdef CIOCGSSESSION case 's': cmd = CIOCGSSESSION; break; #endif case 'v': verbose++; break; case 'a': alg = getalgbyname(optarg); if (alg == NULL) { if (streq(optarg, "rijndael")) alg = getalgbyname("aes"); else usage(argv[0]); } break; case 'd': crid = crlookup(optarg); break; case 't': maxthreads = atoi(optarg); break; case 'z': testall = 1; break; case 'p': profile = 1; break; case 'b': opflags |= COP_F_BATCH; break; case 'c': verify = 1; break; default: usage(argv[0]); } } argc -= optind, argv += optind; if (argc > 0) count = atoi(argv[0]); while (argc > 1) { int s = atoi(argv[1]); - if (nsizes < N(sizes)) { + if (nsizes < nitems(sizes)) { sizes[nsizes++] = s; } else { printf("Too many sizes, ignoring %u\n", s); } argc--, argv++; } if (nsizes == 0) { if (alg) sizes[nsizes++] = alg->blocksize; else sizes[nsizes++] = 8; if (testall) { while (sizes[nsizes-1] < 8*1024) { sizes[nsizes] = sizes[nsizes-1]<<1; nsizes++; } } } if (testall) { - for (i = 0; i < N(algorithms); i++) { + for (i = 0; i < nitems(algorithms); i++) { int j; alg = &algorithms[i]; for (j = 0; j < nsizes; j++) runtests(alg, count, sizes[j], cmd, maxthreads, profile); } } else { if (alg == NULL) alg = getalgbycode(CRYPTO_3DES_CBC); for (i = 0; i < nsizes; i++) runtests(alg, count, sizes[i], cmd, maxthreads, profile); } return (0); } void hexdump(char *p, int n) { int i, off; for (off = 0; n > 0; off += 16, n -= 16) { printf("%s%04x:", off == 0 ? "\n" : "", off); i = (n >= 16 ? 16 : n); do { printf(" %02x", *p++ & 0xff); } while (--i); printf("\n"); } } Index: head/tools/tools/crypto/hifnstats.c =================================================================== --- head/tools/tools/crypto/hifnstats.c (revision 287296) +++ head/tools/tools/crypto/hifnstats.c (revision 287297) @@ -1,60 +1,65 @@ /*- * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ -#include + #include +#include + +#include +#include + #include "../../../sys/dev/hifn/hifn7751var.h" /* * Little program to dump the statistics block for the hifn driver. */ int main(int argc, char *argv[]) { struct hifn_stats stats; size_t slen; slen = sizeof (stats); - if (sysctlbyname("hw.hifn.stats", &stats, &slen, NULL, NULL) < 0) + if (sysctlbyname("hw.hifn.stats", &stats, &slen, NULL, 0) < 0) err(1, "kern.hifn.stats"); printf("input %llu bytes %u packets\n", stats.hst_ibytes, stats.hst_ipackets); printf("output %llu bytes %u packets\n", stats.hst_obytes, stats.hst_opackets); printf("invalid %u nomem %u abort %u\n", stats.hst_invalid, stats.hst_nomem, stats.hst_abort); printf("noirq %u unaligned %u\n", stats.hst_noirq, stats.hst_unaligned); printf("totbatch %u maxbatch %u\n", stats.hst_totbatch, stats.hst_maxbatch); printf("nomem: map %u load %u mbuf %u mcl %u cr %u sd %u\n", stats.hst_nomem_map, stats.hst_nomem_load, stats.hst_nomem_mbuf, stats.hst_nomem_mcl, stats.hst_nomem_cr, stats.hst_nomem_sd); return 0; } Index: head/tools/tools/crypto/ipsecstats.c =================================================================== --- head/tools/tools/crypto/ipsecstats.c (revision 287296) +++ head/tools/tools/crypto/ipsecstats.c (revision 287297) @@ -1,178 +1,182 @@ /*- * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ -#include + +#include +#include + #include #include #include + +#include #include #include struct alg { int a; const char *name; }; static const struct alg aalgs[] = { { SADB_AALG_NONE, "none", }, { SADB_AALG_MD5HMAC, "hmac-md5", }, { SADB_AALG_SHA1HMAC, "hmac-sha1", }, { SADB_X_AALG_MD5, "md5", }, { SADB_X_AALG_SHA, "sha", }, { SADB_X_AALG_NULL, "null", }, { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, }; static const struct alg espalgs[] = { { SADB_EALG_NONE, "none", }, { SADB_EALG_DESCBC, "des-cbc", }, { SADB_EALG_3DESCBC, "3des-cbc", }, { SADB_EALG_NULL, "null", }, { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, }; static const struct alg ipcompalgs[] = { { SADB_X_CALG_NONE, "none", }, { SADB_X_CALG_OUI, "oui", }, { SADB_X_CALG_DEFLATE, "deflate", }, { SADB_X_CALG_LZS, "lzs", }, }; -#define N(a) (sizeof(a)/sizeof(a[0])) static const char* algname(int a, const struct alg algs[], int nalgs) { static char buf[80]; int i; for (i = 0; i < nalgs; i++) if (algs[i].a == a) return algs[i].name; snprintf(buf, sizeof(buf), "alg#%u", a); return buf; } /* * Little program to dump the statistics block for fast ipsec. */ int main(int argc, char *argv[]) { #define STAT(x,fmt) if (x) printf(fmt "\n", (uintmax_t)x) struct ipsecstat ips; struct ahstat ahs; struct espstat esps; size_t slen; int i; slen = sizeof (ips); - if (sysctlbyname("net.inet.ipsec.ipsecstats", &ips, &slen, NULL, NULL) < 0) + if (sysctlbyname("net.inet.ipsec.ipsecstats", &ips, &slen, NULL, 0) < 0) err(1, "net.inet.ipsec.ipsecstats"); slen = sizeof (ahs); - if (sysctlbyname("net.inet.ah.stats", &ahs, &slen, NULL, NULL) < 0) + if (sysctlbyname("net.inet.ah.stats", &ahs, &slen, NULL, 0) < 0) err(1, "net.inet.ah.stats"); slen = sizeof (esps); - if (sysctlbyname("net.inet.esp.stats", &esps, &slen, NULL, NULL) < 0) + if (sysctlbyname("net.inet.esp.stats", &esps, &slen, NULL, 0) < 0) err(1, "net.inet.esp.stats"); #define AHSTAT(x,fmt) if (x) printf("ah " fmt ": %ju\n", (uintmax_t)x) AHSTAT(ahs.ahs_input, "input packets processed"); AHSTAT(ahs.ahs_output, "output packets processed"); AHSTAT(ahs.ahs_hdrops, "headers too short"); AHSTAT(ahs.ahs_nopf, "headers for unsupported address family"); AHSTAT(ahs.ahs_notdb, "packets with no SA"); AHSTAT(ahs.ahs_badkcr, "packets with bad kcr"); AHSTAT(ahs.ahs_badauth, "packets with bad authentication"); AHSTAT(ahs.ahs_noxform, "packets with no xform"); AHSTAT(ahs.ahs_qfull, "packets dropped packet 'cuz queue full"); AHSTAT(ahs.ahs_wrap, "packets dropped for replace counter wrap"); AHSTAT(ahs.ahs_replay, "packets dropped for possible replay"); AHSTAT(ahs.ahs_badauthl, "packets dropped for bad authenticator length"); AHSTAT(ahs.ahs_invalid, "packets with an invalid SA"); AHSTAT(ahs.ahs_toobig, "packets too big"); AHSTAT(ahs.ahs_pdrops, "packets dropped due to policy"); AHSTAT(ahs.ahs_crypto, "failed crypto requests"); AHSTAT(ahs.ahs_tunnel, "tunnel sanity check failures"); for (i = 0; i < AH_ALG_MAX; i++) if (ahs.ahs_hist[i]) printf("ah packets with %s: %ju\n" - , algname(i, aalgs, N(aalgs)) + , algname(i, aalgs, nitems(aalgs)) , (uintmax_t)ahs.ahs_hist[i] ); AHSTAT(ahs.ahs_ibytes, "bytes received"); AHSTAT(ahs.ahs_obytes, "bytes transmitted"); #undef AHSTAT #define ESPSTAT(x,fmt) if (x) printf("esp " fmt ": %ju\n", (uintmax_t)x) ESPSTAT(esps.esps_input, "input packets processed"); ESPSTAT(esps.esps_output, "output packets processed"); ESPSTAT(esps.esps_hdrops, "headers too short"); ESPSTAT(esps.esps_nopf, "headers for unsupported address family"); ESPSTAT(esps.esps_notdb, "packets with no SA"); ESPSTAT(esps.esps_badkcr, "packets with bad kcr"); ESPSTAT(esps.esps_qfull, "packets dropped packet 'cuz queue full"); ESPSTAT(esps.esps_noxform, "packets with no xform"); ESPSTAT(esps.esps_badilen, "packets with bad ilen"); ESPSTAT(esps.esps_badenc, "packets with bad encryption"); ESPSTAT(esps.esps_badauth, "packets with bad authentication"); ESPSTAT(esps.esps_wrap, "packets dropped for replay counter wrap"); ESPSTAT(esps.esps_replay, "packets dropped for possible replay"); ESPSTAT(esps.esps_invalid, "packets with an invalid SA"); ESPSTAT(esps.esps_toobig, "packets too big"); ESPSTAT(esps.esps_pdrops, "packets dropped due to policy"); ESPSTAT(esps.esps_crypto, "failed crypto requests"); ESPSTAT(esps.esps_tunnel, "tunnel sanity check failures"); for (i = 0; i < ESP_ALG_MAX; i++) if (esps.esps_hist[i]) printf("esp packets with %s: %ju\n" - , algname(i, espalgs, N(espalgs)) + , algname(i, espalgs, nitems(espalgs)) , (uintmax_t)esps.esps_hist[i] ); ESPSTAT(esps.esps_ibytes, "bytes received"); ESPSTAT(esps.esps_obytes, "bytes transmitted"); #undef ESPSTAT printf("\n"); if (ips.ips_in_polvio+ips.ips_out_polvio) printf("policy violations: input %ju output %ju\n", (uintmax_t)ips.ips_in_polvio, (uintmax_t)ips.ips_out_polvio); STAT(ips.ips_out_nosa, "no SA found %ju (output)"); STAT(ips.ips_out_nomem, "no memory available %ju (output)"); STAT(ips.ips_out_noroute, "no route available %ju (output)"); STAT(ips.ips_out_inval, "generic error %ju (output)"); STAT(ips.ips_out_bundlesa, "bundled SA processed %ju (output)"); printf("m_clone processing: %ju mbufs + %ju clusters coalesced\n", (uintmax_t)ips.ips_mbcoalesced, (uintmax_t)ips.ips_clcoalesced); STAT(ips.ips_clcopied, "m_clone processing: %ju clusters copied\n"); STAT(ips.ips_mbinserted, "m_makespace: %ju mbufs inserted\n"); printf("header position [front/middle/end]: %ju/%ju/%ju\n", (uintmax_t)ips.ips_input_front, (uintmax_t)ips.ips_input_middle, (uintmax_t)ips.ips_input_end); return 0; } Index: head/tools/tools/crypto/safestats.c =================================================================== --- head/tools/tools/crypto/safestats.c (revision 287296) +++ head/tools/tools/crypto/safestats.c (revision 287297) @@ -1,69 +1,74 @@ /*- * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ -#include + #include +#include + +#include +#include + #include "../../../sys/dev/safe/safevar.h" /* * Little program to dump the statistics block for the safe driver. */ int main(int argc, char *argv[]) { struct safe_stats stats; size_t slen; slen = sizeof (stats); - if (sysctlbyname("hw.safe.stats", &stats, &slen, NULL, NULL) < 0) + if (sysctlbyname("hw.safe.stats", &stats, &slen, NULL, 0) < 0) err(1, "hw.safe.stats"); printf("input %llu bytes %u packets\n", stats.st_ibytes, stats.st_ipackets); printf("output %llu bytes %u packets\n", stats.st_obytes, stats.st_opackets); printf("invalid %u badsession %u badflags %u\n", stats.st_invalid, stats.st_badsession, stats.st_badflags); printf("nodesc %u badalg %u ringfull %u\n", stats.st_nodesc, stats.st_badalg, stats.st_ringfull); printf("peoperr %u dmaerr %u bypasstoobig %u\n", stats.st_peoperr, stats.st_dmaerr, stats.st_bypasstoobig); printf("skipmismatch %u lenmismatch %u coffmisaligned %u cofftoobig %u\n", stats.st_skipmismatch, stats.st_lenmismatch, stats.st_coffmisaligned, stats.st_cofftoobig); printf("iovmisaligned %u iovnotuniform %u noicvcopy %u\n", stats.st_iovmisaligned, stats.st_iovnotuniform, stats.st_noicvcopy); printf("unaligned %u notuniform %u nomap %u noload %u\n", stats.st_unaligned, stats.st_notuniform, stats.st_nomap, stats.st_noload); printf("nomcl %u mbuf %u maxqchip %u\n", stats.st_nomcl, stats.st_nombuf, stats.st_maxqchip); printf("rng %u rngalarm %u\n", stats.st_rng, stats.st_rngalarm); return 0; } Index: head/tools/tools/crypto/ubsecstats.c =================================================================== --- head/tools/tools/crypto/ubsecstats.c (revision 287296) +++ head/tools/tools/crypto/ubsecstats.c (revision 287297) @@ -1,69 +1,74 @@ /*- * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ -#include + #include +#include + +#include +#include + #include "../../../sys/dev/ubsec/ubsecvar.h" /* * Little program to dump the statistics block for the ubsec driver. */ int main(int argc, char *argv[]) { struct ubsec_stats stats; size_t slen; slen = sizeof (stats); - if (sysctlbyname("hw.ubsec.stats", &stats, &slen, NULL, NULL) < 0) + if (sysctlbyname("hw.ubsec.stats", &stats, &slen, NULL, 0) < 0) err(1, "kern.ubsec_stats"); printf("input %llu bytes %u packets\n", stats.hst_ibytes, stats.hst_ipackets); printf("output %llu bytes %u packets\n", stats.hst_obytes, stats.hst_opackets); printf("invalid %u badsession %u badflags %u\n", stats.hst_invalid, stats.hst_badsession, stats.hst_badflags); printf("nodesc %u badalg %u nomem %u queuefull %u\n", stats.hst_nodesc, stats.hst_badalg, stats.hst_nomem, stats.hst_queuefull); printf("dmaerr %u mcrerr %u nodmafree %u\n", stats.hst_dmaerr, stats.hst_mcrerr, stats.hst_nodmafree); printf("lenmismatch %u skipmisatch %u iovmisalined %u\n", stats.hst_lenmismatch, stats.hst_skipmismatch, stats.hst_iovmisaligned); printf("noirq %u unaligned %u nomap %u noload %u nomcl %u\n", stats.hst_noirq, stats.hst_unaligned, stats.hst_nomap, stats.hst_noload, stats.hst_nomcl); printf("totbatch %u maxbatch %u\n", stats.hst_totbatch, stats.hst_maxbatch); printf("maxqueue %u maxqchip %u mcr1full %u\n", stats.hst_maxqueue, stats.hst_maxqchip, stats.hst_mcr1full); printf("rng %u modexp %u moexpcrt %u\n", stats.hst_rng, stats.hst_modexp, stats.hst_modexpcrt); return 0; } Index: head/tools/tools/cxgbetool/cxgbetool.c =================================================================== --- head/tools/tools/cxgbetool/cxgbetool.c (revision 287296) +++ head/tools/tools/cxgbetool/cxgbetool.c (revision 287297) @@ -1,2603 +1,2603 @@ /*- * Copyright (c) 2011 Chelsio Communications, Inc. * All rights reserved. * Written by: Navdeep Parhar * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include #include -#include #include #include -#include -#include + #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "t4_ioctl.h" -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define in_range(val, lo, hi) ( val < 0 || (val <= hi && val >= lo)) #define max(x, y) ((x) > (y) ? (x) : (y)) static const char *progname, *nexus; static int chip_id; /* 4 for T4, 5 for T5 */ struct reg_info { const char *name; uint32_t addr; uint32_t len; }; struct mod_regs { const char *name; const struct reg_info *ri; }; struct field_desc { const char *name; /* Field name */ unsigned short start; /* Start bit position */ unsigned short end; /* End bit position */ unsigned char shift; /* # of low order bits omitted and implicitly 0 */ unsigned char hex; /* Print field in hex instead of decimal */ unsigned char islog2; /* Field contains the base-2 log of the value */ }; #include "reg_defs_t4.c" #include "reg_defs_t4vf.c" #include "reg_defs_t5.c" static void usage(FILE *fp) { fprintf(fp, "Usage: %s [operation]\n", progname); fprintf(fp, "\tclearstats clear port statistics\n" "\tcontext show an SGE context\n" "\tfilter [ ] ... set a filter\n" "\tfilter delete|clear delete a filter\n" "\tfilter list list all filters\n" "\tfilter mode [] ... get/set global filter mode\n" "\ti2c [] read from i2c device\n" "\tloadfw install firmware\n" "\tmemdump dump a memory range\n" "\tmodinfo [raw] optics/cable information\n" "\treg
[=] read/write register\n" "\treg64
[=] read/write 64 bit register\n" "\tregdump [] ... dump registers\n" "\tsched-class params .. configure TX scheduler class\n" "\tsched-queue bind NIC queues to TX Scheduling class\n" "\tstdio interactive mode\n" "\ttcb read TCB\n" "\ttracer tx|rx set and enable a tracer\n" "\ttracer disable|enable disable or enable a tracer\n" "\ttracer list list all tracers\n" ); } static inline unsigned int get_card_vers(unsigned int version) { return (version & 0x3ff); } static int real_doit(unsigned long cmd, void *data, const char *cmdstr) { static int fd = -1; int rc = 0; if (fd == -1) { char buf[64]; snprintf(buf, sizeof(buf), "/dev/%s", nexus); if ((fd = open(buf, O_RDWR)) < 0) { warn("open(%s)", nexus); rc = errno; return (rc); } chip_id = nexus[1] - '0'; } rc = ioctl(fd, cmd, data); if (rc < 0) { warn("%s", cmdstr); rc = errno; } return (rc); } #define doit(x, y) real_doit(x, y, #x) static char * str_to_number(const char *s, long *val, long long *vall) { char *p; if (vall) *vall = strtoll(s, &p, 0); else if (val) *val = strtol(s, &p, 0); else p = NULL; return (p); } static int read_reg(long addr, int size, long long *val) { struct t4_reg reg; int rc; reg.addr = (uint32_t) addr; reg.size = (uint32_t) size; reg.val = 0; rc = doit(CHELSIO_T4_GETREG, ®); *val = reg.val; return (rc); } static int write_reg(long addr, int size, long long val) { struct t4_reg reg; reg.addr = (uint32_t) addr; reg.size = (uint32_t) size; reg.val = (uint64_t) val; return doit(CHELSIO_T4_SETREG, ®); } static int register_io(int argc, const char *argv[], int size) { char *p, *v; long addr; long long val; int w = 0, rc; if (argc == 1) { /* OR = */ p = str_to_number(argv[0], &addr, NULL); if (*p) { if (*p != '=') { warnx("invalid register \"%s\"", argv[0]); return (EINVAL); } w = 1; v = p + 1; p = str_to_number(v, NULL, &val); if (*p) { warnx("invalid value \"%s\"", v); return (EINVAL); } } } else if (argc == 2) { /* */ w = 1; p = str_to_number(argv[0], &addr, NULL); if (*p) { warnx("invalid register \"%s\"", argv[0]); return (EINVAL); } p = str_to_number(argv[1], NULL, &val); if (*p) { warnx("invalid value \"%s\"", argv[1]); return (EINVAL); } } else { warnx("reg: invalid number of arguments (%d)", argc); return (EINVAL); } if (w) rc = write_reg(addr, size, val); else { rc = read_reg(addr, size, &val); if (rc == 0) printf("0x%llx [%llu]\n", val, val); } return (rc); } static inline uint32_t xtract(uint32_t val, int shift, int len) { return (val >> shift) & ((1 << len) - 1); } static int dump_block_regs(const struct reg_info *reg_array, const uint32_t *regs) { uint32_t reg_val = 0; for ( ; reg_array->name; ++reg_array) if (!reg_array->len) { reg_val = regs[reg_array->addr / 4]; printf("[%#7x] %-47s %#-10x %u\n", reg_array->addr, reg_array->name, reg_val, reg_val); } else { uint32_t v = xtract(reg_val, reg_array->addr, reg_array->len); printf(" %*u:%u %-47s %#-10x %u\n", reg_array->addr < 10 ? 3 : 2, reg_array->addr + reg_array->len - 1, reg_array->addr, reg_array->name, v, v); } return (1); } static int dump_regs_table(int argc, const char *argv[], const uint32_t *regs, const struct mod_regs *modtab, int nmodules) { int i, j, match; for (i = 0; i < argc; i++) { for (j = 0; j < nmodules; j++) { if (!strcmp(argv[i], modtab[j].name)) break; } if (j == nmodules) { warnx("invalid register block \"%s\"", argv[i]); fprintf(stderr, "\nAvailable blocks:"); for ( ; nmodules; nmodules--, modtab++) fprintf(stderr, " %s", modtab->name); fprintf(stderr, "\n"); return (EINVAL); } } for ( ; nmodules; nmodules--, modtab++) { match = argc == 0 ? 1 : 0; for (i = 0; !match && i < argc; i++) { if (!strcmp(argv[i], modtab->name)) match = 1; } if (match) dump_block_regs(modtab->ri, regs); } return (0); } #define T4_MODREGS(name) { #name, t4_##name##_regs } static int dump_regs_t4(int argc, const char *argv[], const uint32_t *regs) { static struct mod_regs t4_mod[] = { T4_MODREGS(sge), { "pci", t4_pcie_regs }, T4_MODREGS(dbg), T4_MODREGS(mc), T4_MODREGS(ma), { "edc0", t4_edc_0_regs }, { "edc1", t4_edc_1_regs }, T4_MODREGS(cim), T4_MODREGS(tp), T4_MODREGS(ulp_rx), T4_MODREGS(ulp_tx), { "pmrx", t4_pm_rx_regs }, { "pmtx", t4_pm_tx_regs }, T4_MODREGS(mps), { "cplsw", t4_cpl_switch_regs }, T4_MODREGS(smb), { "i2c", t4_i2cm_regs }, T4_MODREGS(mi), T4_MODREGS(uart), T4_MODREGS(pmu), T4_MODREGS(sf), T4_MODREGS(pl), T4_MODREGS(le), T4_MODREGS(ncsi), T4_MODREGS(xgmac) }; - return dump_regs_table(argc, argv, regs, t4_mod, ARRAY_SIZE(t4_mod)); + return dump_regs_table(argc, argv, regs, t4_mod, nitems(t4_mod)); } #undef T4_MODREGS static int dump_regs_t4vf(int argc, const char *argv[], const uint32_t *regs) { static struct mod_regs t4vf_mod[] = { { "sge", t4vf_sge_regs }, { "mps", t4vf_mps_regs }, { "pl", t4vf_pl_regs }, { "mbdata", t4vf_mbdata_regs }, { "cim", t4vf_cim_regs }, }; - return dump_regs_table(argc, argv, regs, t4vf_mod, - ARRAY_SIZE(t4vf_mod)); + return dump_regs_table(argc, argv, regs, t4vf_mod, nitems(t4vf_mod)); } #define T5_MODREGS(name) { #name, t5_##name##_regs } static int dump_regs_t5(int argc, const char *argv[], const uint32_t *regs) { static struct mod_regs t5_mod[] = { T5_MODREGS(sge), { "pci", t5_pcie_regs }, T5_MODREGS(dbg), { "mc0", t5_mc_0_regs }, { "mc1", t5_mc_1_regs }, T5_MODREGS(ma), { "edc0", t5_edc_t50_regs }, { "edc1", t5_edc_t51_regs }, T5_MODREGS(cim), T5_MODREGS(tp), { "ulprx", t5_ulp_rx_regs }, { "ulptx", t5_ulp_tx_regs }, { "pmrx", t5_pm_rx_regs }, { "pmtx", t5_pm_tx_regs }, T5_MODREGS(mps), { "cplsw", t5_cpl_switch_regs }, T5_MODREGS(smb), { "i2c", t5_i2cm_regs }, T5_MODREGS(mi), T5_MODREGS(uart), T5_MODREGS(pmu), T5_MODREGS(sf), T5_MODREGS(pl), T5_MODREGS(le), T5_MODREGS(ncsi), T5_MODREGS(mac), { "hma", t5_hma_t5_regs } }; - return dump_regs_table(argc, argv, regs, t5_mod, ARRAY_SIZE(t5_mod)); + return dump_regs_table(argc, argv, regs, t5_mod, nitems(t5_mod)); } #undef T5_MODREGS static int dump_regs(int argc, const char *argv[]) { int vers, revision, rc; struct t4_regdump regs; uint32_t len; len = max(T4_REGDUMP_SIZE, T5_REGDUMP_SIZE); regs.data = calloc(1, len); if (regs.data == NULL) { warnc(ENOMEM, "regdump"); return (ENOMEM); } regs.len = len; rc = doit(CHELSIO_T4_REGDUMP, ®s); if (rc != 0) return (rc); vers = get_card_vers(regs.version); revision = (regs.version >> 10) & 0x3f; if (vers == 4) { if (revision == 0x3f) rc = dump_regs_t4vf(argc, argv, regs.data); else rc = dump_regs_t4(argc, argv, regs.data); } else if (vers == 5) rc = dump_regs_t5(argc, argv, regs.data); else { warnx("%s (type %d, rev %d) is not a known card.", nexus, vers, revision); return (ENOTSUP); } free(regs.data); return (rc); } static void do_show_info_header(uint32_t mode) { uint32_t i; printf ("%4s %8s", "Idx", "Hits"); for (i = T4_FILTER_FCoE; i <= T4_FILTER_IP_FRAGMENT; i <<= 1) { switch (mode & i) { case T4_FILTER_FCoE: printf (" FCoE"); break; case T4_FILTER_PORT: printf (" Port"); break; case T4_FILTER_VNIC: printf (" vld:VNIC"); break; case T4_FILTER_VLAN: printf (" vld:VLAN"); break; case T4_FILTER_IP_TOS: printf (" TOS"); break; case T4_FILTER_IP_PROTO: printf (" Prot"); break; case T4_FILTER_ETH_TYPE: printf (" EthType"); break; case T4_FILTER_MAC_IDX: printf (" MACIdx"); break; case T4_FILTER_MPS_HIT_TYPE: printf (" MPS"); break; case T4_FILTER_IP_FRAGMENT: printf (" Frag"); break; default: /* compressed filter field not enabled */ break; } } printf(" %20s %20s %9s %9s %s\n", "DIP", "SIP", "DPORT", "SPORT", "Action"); } /* * Parse an argument sub-vector as a { [:] } * ordered tuple. If the parameter name in the argument sub-vector does not * match the passed in parameter name, then a zero is returned for the * function and no parsing is performed. If there is a match, then the value * and optional mask are parsed and returned in the provided return value * pointers. If no optional mask is specified, then a default mask of all 1s * will be returned. * * An error in parsing the value[:mask] will result in an error message and * program termination. */ static int parse_val_mask(const char *param, const char *args[], uint32_t *val, uint32_t *mask) { char *p; if (strcmp(param, args[0]) != 0) return (EINVAL); *val = strtoul(args[1], &p, 0); if (p > args[1]) { if (p[0] == 0) { *mask = ~0; return (0); } if (p[0] == ':' && p[1] != 0) { *mask = strtoul(p+1, &p, 0); if (p[0] == 0) return (0); } } warnx("parameter \"%s\" has bad \"value[:mask]\" %s", args[0], args[1]); return (EINVAL); } /* * Parse an argument sub-vector as a { [/] } * ordered tuple. If the parameter name in the argument sub-vector does not * match the passed in parameter name, then a zero is returned for the * function and no parsing is performed. If there is a match, then the value * and optional mask are parsed and returned in the provided return value * pointers. If no optional mask is specified, then a default mask of all 1s * will be returned. * * The value return parameter "afp" is used to specify the expected address * family -- IPv4 or IPv6 -- of the address[/mask] and return its actual * format. A passed in value of AF_UNSPEC indicates that either IPv4 or IPv6 * is acceptable; AF_INET means that only IPv4 addresses are acceptable; and * AF_INET6 means that only IPv6 are acceptable. AF_INET is returned for IPv4 * and AF_INET6 for IPv6 addresses, respectively. IPv4 address/mask pairs are * returned in the first four bytes of the address and mask return values with * the address A.B.C.D returned with { A, B, C, D } returned in addresses { 0, * 1, 2, 3}, respectively. * * An error in parsing the value[:mask] will result in an error message and * program termination. */ static int parse_ipaddr(const char *param, const char *args[], int *afp, uint8_t addr[], uint8_t mask[]) { const char *colon, *afn; char *slash; uint8_t *m; int af, ret; unsigned int masksize; /* * Is this our parameter? */ if (strcmp(param, args[0]) != 0) return (EINVAL); /* * Fundamental IPv4 versus IPv6 selection. */ colon = strchr(args[1], ':'); if (!colon) { afn = "IPv4"; af = AF_INET; masksize = 32; } else { afn = "IPv6"; af = AF_INET6; masksize = 128; } if (*afp == AF_UNSPEC) *afp = af; else if (*afp != af) { warnx("address %s is not of expected family %s", args[1], *afp == AF_INET ? "IP" : "IPv6"); return (EINVAL); } /* * Parse address (temporarily stripping off any "/mask" * specification). */ slash = strchr(args[1], '/'); if (slash) *slash = 0; ret = inet_pton(af, args[1], addr); if (slash) *slash = '/'; if (ret <= 0) { warnx("Cannot parse %s %s address %s", param, afn, args[1]); return (EINVAL); } /* * Parse optional mask specification. */ if (slash) { char *p; unsigned int prefix = strtoul(slash + 1, &p, 10); if (p == slash + 1) { warnx("missing address prefix for %s", param); return (EINVAL); } if (*p) { warnx("%s is not a valid address prefix", slash + 1); return (EINVAL); } if (prefix > masksize) { warnx("prefix %u is too long for an %s address", prefix, afn); return (EINVAL); } memset(mask, 0, masksize / 8); masksize = prefix; } /* * Fill in mask. */ for (m = mask; masksize >= 8; m++, masksize -= 8) *m = ~0; if (masksize) *m = ~0 << (8 - masksize); return (0); } /* * Parse an argument sub-vector as a { } ordered * tuple. If the parameter name in the argument sub-vector does not match the * passed in parameter name, then a zero is returned for the function and no * parsing is performed. If there is a match, then the value is parsed and * returned in the provided return value pointer. */ static int parse_val(const char *param, const char *args[], uint32_t *val) { char *p; if (strcmp(param, args[0]) != 0) return (EINVAL); *val = strtoul(args[1], &p, 0); if (p > args[1] && p[0] == 0) return (0); warnx("parameter \"%s\" has bad \"value\" %s", args[0], args[1]); return (EINVAL); } static void filters_show_ipaddr(int type, uint8_t *addr, uint8_t *addrm) { int noctets, octet; printf(" "); if (type == 0) { noctets = 4; printf("%3s", " "); } else noctets = 16; for (octet = 0; octet < noctets; octet++) printf("%02x", addr[octet]); printf("/"); for (octet = 0; octet < noctets; octet++) printf("%02x", addrm[octet]); } static void do_show_one_filter_info(struct t4_filter *t, uint32_t mode) { uint32_t i; printf("%4d", t->idx); if (t->hits == UINT64_MAX) printf(" %8s", "-"); else printf(" %8ju", t->hits); /* * Compressed header portion of filter. */ for (i = T4_FILTER_FCoE; i <= T4_FILTER_IP_FRAGMENT; i <<= 1) { switch (mode & i) { case T4_FILTER_FCoE: printf(" %1d/%1d", t->fs.val.fcoe, t->fs.mask.fcoe); break; case T4_FILTER_PORT: printf(" %1d/%1d", t->fs.val.iport, t->fs.mask.iport); break; case T4_FILTER_VNIC: printf(" %1d:%1x:%02x/%1d:%1x:%02x", t->fs.val.vnic_vld, (t->fs.val.vnic >> 7) & 0x7, t->fs.val.vnic & 0x7f, t->fs.mask.vnic_vld, (t->fs.mask.vnic >> 7) & 0x7, t->fs.mask.vnic & 0x7f); break; case T4_FILTER_VLAN: printf(" %1d:%04x/%1d:%04x", t->fs.val.vlan_vld, t->fs.val.vlan, t->fs.mask.vlan_vld, t->fs.mask.vlan); break; case T4_FILTER_IP_TOS: printf(" %02x/%02x", t->fs.val.tos, t->fs.mask.tos); break; case T4_FILTER_IP_PROTO: printf(" %02x/%02x", t->fs.val.proto, t->fs.mask.proto); break; case T4_FILTER_ETH_TYPE: printf(" %04x/%04x", t->fs.val.ethtype, t->fs.mask.ethtype); break; case T4_FILTER_MAC_IDX: printf(" %03x/%03x", t->fs.val.macidx, t->fs.mask.macidx); break; case T4_FILTER_MPS_HIT_TYPE: printf(" %1x/%1x", t->fs.val.matchtype, t->fs.mask.matchtype); break; case T4_FILTER_IP_FRAGMENT: printf(" %1d/%1d", t->fs.val.frag, t->fs.mask.frag); break; default: /* compressed filter field not enabled */ break; } } /* * Fixed portion of filter. */ filters_show_ipaddr(t->fs.type, t->fs.val.dip, t->fs.mask.dip); filters_show_ipaddr(t->fs.type, t->fs.val.sip, t->fs.mask.sip); printf(" %04x/%04x %04x/%04x", t->fs.val.dport, t->fs.mask.dport, t->fs.val.sport, t->fs.mask.sport); /* * Variable length filter action. */ if (t->fs.action == FILTER_DROP) printf(" Drop"); else if (t->fs.action == FILTER_SWITCH) { printf(" Switch: port=%d", t->fs.eport); if (t->fs.newdmac) printf( ", dmac=%02x:%02x:%02x:%02x:%02x:%02x " ", l2tidx=%d", t->fs.dmac[0], t->fs.dmac[1], t->fs.dmac[2], t->fs.dmac[3], t->fs.dmac[4], t->fs.dmac[5], t->l2tidx); if (t->fs.newsmac) printf( ", smac=%02x:%02x:%02x:%02x:%02x:%02x " ", smtidx=%d", t->fs.smac[0], t->fs.smac[1], t->fs.smac[2], t->fs.smac[3], t->fs.smac[4], t->fs.smac[5], t->smtidx); if (t->fs.newvlan == VLAN_REMOVE) printf(", vlan=none"); else if (t->fs.newvlan == VLAN_INSERT) printf(", vlan=insert(%x)", t->fs.vlan); else if (t->fs.newvlan == VLAN_REWRITE) printf(", vlan=rewrite(%x)", t->fs.vlan); } else { printf(" Pass: Q="); if (t->fs.dirsteer == 0) { printf("RSS"); if (t->fs.maskhash) printf("(TCB=hash)"); } else { printf("%d", t->fs.iq); if (t->fs.dirsteerhash == 0) printf("(QID)"); else printf("(hash)"); } } if (t->fs.prio) printf(" Prio"); if (t->fs.rpttid) printf(" RptTID"); printf("\n"); } static int show_filters(void) { uint32_t mode = 0, header = 0; struct t4_filter t; int rc; /* Get the global filter mode first */ rc = doit(CHELSIO_T4_GET_FILTER_MODE, &mode); if (rc != 0) return (rc); t.idx = 0; for (t.idx = 0; ; t.idx++) { rc = doit(CHELSIO_T4_GET_FILTER, &t); if (rc != 0 || t.idx == 0xffffffff) break; if (!header) { do_show_info_header(mode); header = 1; } do_show_one_filter_info(&t, mode); }; return (rc); } static int get_filter_mode(void) { uint32_t mode = 0; int rc; rc = doit(CHELSIO_T4_GET_FILTER_MODE, &mode); if (rc != 0) return (rc); if (mode & T4_FILTER_IPv4) printf("ipv4 "); if (mode & T4_FILTER_IPv6) printf("ipv6 "); if (mode & T4_FILTER_IP_SADDR) printf("sip "); if (mode & T4_FILTER_IP_DADDR) printf("dip "); if (mode & T4_FILTER_IP_SPORT) printf("sport "); if (mode & T4_FILTER_IP_DPORT) printf("dport "); if (mode & T4_FILTER_IP_FRAGMENT) printf("frag "); if (mode & T4_FILTER_MPS_HIT_TYPE) printf("matchtype "); if (mode & T4_FILTER_MAC_IDX) printf("macidx "); if (mode & T4_FILTER_ETH_TYPE) printf("ethtype "); if (mode & T4_FILTER_IP_PROTO) printf("proto "); if (mode & T4_FILTER_IP_TOS) printf("tos "); if (mode & T4_FILTER_VLAN) printf("vlan "); if (mode & T4_FILTER_VNIC) printf("vnic/ovlan "); if (mode & T4_FILTER_PORT) printf("iport "); if (mode & T4_FILTER_FCoE) printf("fcoe "); printf("\n"); return (0); } static int set_filter_mode(int argc, const char *argv[]) { uint32_t mode = 0; for (; argc; argc--, argv++) { if (!strcmp(argv[0], "frag")) mode |= T4_FILTER_IP_FRAGMENT; if (!strcmp(argv[0], "matchtype")) mode |= T4_FILTER_MPS_HIT_TYPE; if (!strcmp(argv[0], "macidx")) mode |= T4_FILTER_MAC_IDX; if (!strcmp(argv[0], "ethtype")) mode |= T4_FILTER_ETH_TYPE; if (!strcmp(argv[0], "proto")) mode |= T4_FILTER_IP_PROTO; if (!strcmp(argv[0], "tos")) mode |= T4_FILTER_IP_TOS; if (!strcmp(argv[0], "vlan")) mode |= T4_FILTER_VLAN; if (!strcmp(argv[0], "ovlan") || !strcmp(argv[0], "vnic")) mode |= T4_FILTER_VNIC; if (!strcmp(argv[0], "iport")) mode |= T4_FILTER_PORT; if (!strcmp(argv[0], "fcoe")) mode |= T4_FILTER_FCoE; } return doit(CHELSIO_T4_SET_FILTER_MODE, &mode); } static int del_filter(uint32_t idx) { struct t4_filter t; t.idx = idx; return doit(CHELSIO_T4_DEL_FILTER, &t); } static int set_filter(uint32_t idx, int argc, const char *argv[]) { int af = AF_UNSPEC, start_arg = 0; struct t4_filter t; if (argc < 2) { warnc(EINVAL, "%s", __func__); return (EINVAL); }; bzero(&t, sizeof (t)); t.idx = idx; t.fs.hitcnts = 1; for (start_arg = 0; start_arg + 2 <= argc; start_arg += 2) { const char **args = &argv[start_arg]; uint32_t val, mask; if (!strcmp(argv[start_arg], "type")) { int newaf; if (!strcasecmp(argv[start_arg + 1], "ipv4")) newaf = AF_INET; else if (!strcasecmp(argv[start_arg + 1], "ipv6")) newaf = AF_INET6; else { warnx("invalid type \"%s\"; " "must be one of \"ipv4\" or \"ipv6\"", argv[start_arg + 1]); return (EINVAL); } if (af != AF_UNSPEC && af != newaf) { warnx("conflicting IPv4/IPv6 specifications."); return (EINVAL); } af = newaf; } else if (!parse_val_mask("fcoe", args, &val, &mask)) { t.fs.val.fcoe = val; t.fs.mask.fcoe = mask; } else if (!parse_val_mask("iport", args, &val, &mask)) { t.fs.val.iport = val; t.fs.mask.iport = mask; } else if (!parse_val_mask("ovlan", args, &val, &mask)) { t.fs.val.vnic = val; t.fs.mask.vnic = mask; t.fs.val.vnic_vld = 1; t.fs.mask.vnic_vld = 1; } else if (!parse_val_mask("vnic", args, &val, &mask)) { t.fs.val.vnic = val; t.fs.mask.vnic = mask; t.fs.val.vnic_vld = 1; t.fs.mask.vnic_vld = 1; } else if (!parse_val_mask("ivlan", args, &val, &mask)) { t.fs.val.vlan = val; t.fs.mask.vlan = mask; t.fs.val.vlan_vld = 1; t.fs.mask.vlan_vld = 1; } else if (!parse_val_mask("tos", args, &val, &mask)) { t.fs.val.tos = val; t.fs.mask.tos = mask; } else if (!parse_val_mask("proto", args, &val, &mask)) { t.fs.val.proto = val; t.fs.mask.proto = mask; } else if (!parse_val_mask("ethtype", args, &val, &mask)) { t.fs.val.ethtype = val; t.fs.mask.ethtype = mask; } else if (!parse_val_mask("macidx", args, &val, &mask)) { t.fs.val.macidx = val; t.fs.mask.macidx = mask; } else if (!parse_val_mask("matchtype", args, &val, &mask)) { t.fs.val.matchtype = val; t.fs.mask.matchtype = mask; } else if (!parse_val_mask("frag", args, &val, &mask)) { t.fs.val.frag = val; t.fs.mask.frag = mask; } else if (!parse_val_mask("dport", args, &val, &mask)) { t.fs.val.dport = val; t.fs.mask.dport = mask; } else if (!parse_val_mask("sport", args, &val, &mask)) { t.fs.val.sport = val; t.fs.mask.sport = mask; } else if (!parse_ipaddr("dip", args, &af, t.fs.val.dip, t.fs.mask.dip)) { /* nada */; } else if (!parse_ipaddr("sip", args, &af, t.fs.val.sip, t.fs.mask.sip)) { /* nada */; } else if (!strcmp(argv[start_arg], "action")) { if (!strcmp(argv[start_arg + 1], "pass")) t.fs.action = FILTER_PASS; else if (!strcmp(argv[start_arg + 1], "drop")) t.fs.action = FILTER_DROP; else if (!strcmp(argv[start_arg + 1], "switch")) t.fs.action = FILTER_SWITCH; else { warnx("invalid action \"%s\"; must be one of" " \"pass\", \"drop\" or \"switch\"", argv[start_arg + 1]); return (EINVAL); } } else if (!parse_val("hitcnts", args, &val)) { t.fs.hitcnts = val; } else if (!parse_val("prio", args, &val)) { t.fs.prio = val; } else if (!parse_val("rpttid", args, &val)) { t.fs.rpttid = 1; } else if (!parse_val("queue", args, &val)) { t.fs.dirsteer = 1; t.fs.iq = val; } else if (!parse_val("tcbhash", args, &val)) { t.fs.maskhash = 1; t.fs.dirsteerhash = 1; } else if (!parse_val("eport", args, &val)) { t.fs.eport = val; } else if (!strcmp(argv[start_arg], "dmac")) { struct ether_addr *daddr; daddr = ether_aton(argv[start_arg + 1]); if (daddr == NULL) { warnx("invalid dmac address \"%s\"", argv[start_arg + 1]); return (EINVAL); } memcpy(t.fs.dmac, daddr, ETHER_ADDR_LEN); t.fs.newdmac = 1; } else if (!strcmp(argv[start_arg], "smac")) { struct ether_addr *saddr; saddr = ether_aton(argv[start_arg + 1]); if (saddr == NULL) { warnx("invalid smac address \"%s\"", argv[start_arg + 1]); return (EINVAL); } memcpy(t.fs.smac, saddr, ETHER_ADDR_LEN); t.fs.newsmac = 1; } else if (!strcmp(argv[start_arg], "vlan")) { char *p; if (!strcmp(argv[start_arg + 1], "none")) { t.fs.newvlan = VLAN_REMOVE; } else if (argv[start_arg + 1][0] == '=') { t.fs.newvlan = VLAN_REWRITE; } else if (argv[start_arg + 1][0] == '+') { t.fs.newvlan = VLAN_INSERT; } else if (isdigit(argv[start_arg + 1][0]) && !parse_val_mask("vlan", args, &val, &mask)) { t.fs.val.vlan = val; t.fs.mask.vlan = mask; t.fs.val.vlan_vld = 1; t.fs.mask.vlan_vld = 1; } else { warnx("unknown vlan parameter \"%s\"; must" " be one of \"none\", \"=\", " " \"+\", or \"\"", argv[start_arg + 1]); return (EINVAL); } if (t.fs.newvlan == VLAN_REWRITE || t.fs.newvlan == VLAN_INSERT) { t.fs.vlan = strtoul(argv[start_arg + 1] + 1, &p, 0); if (p == argv[start_arg + 1] + 1 || p[0] != 0) { warnx("invalid vlan \"%s\"", argv[start_arg + 1]); return (EINVAL); } } } else { warnx("invalid parameter \"%s\"", argv[start_arg]); return (EINVAL); } } if (start_arg != argc) { warnx("no value for \"%s\"", argv[start_arg]); return (EINVAL); } /* * Check basic sanity of option combinations. */ if (t.fs.action != FILTER_SWITCH && (t.fs.eport || t.fs.newdmac || t.fs.newsmac || t.fs.newvlan)) { warnx("prio, port dmac, smac and vlan only make sense with" " \"action switch\""); return (EINVAL); } if (t.fs.action != FILTER_PASS && (t.fs.rpttid || t.fs.dirsteer || t.fs.maskhash)) { warnx("rpttid, queue and tcbhash don't make sense with" " action \"drop\" or \"switch\""); return (EINVAL); } t.fs.type = (af == AF_INET6 ? 1 : 0); /* default IPv4 */ return doit(CHELSIO_T4_SET_FILTER, &t); } static int filter_cmd(int argc, const char *argv[]) { long long val; uint32_t idx; char *s; if (argc == 0) { warnx("filter: no arguments."); return (EINVAL); }; /* list */ if (strcmp(argv[0], "list") == 0) { if (argc != 1) warnx("trailing arguments after \"list\" ignored."); return show_filters(); } /* mode */ if (argc == 1 && strcmp(argv[0], "mode") == 0) return get_filter_mode(); /* mode */ if (strcmp(argv[0], "mode") == 0) return set_filter_mode(argc - 1, argv + 1); /* ... */ s = str_to_number(argv[0], NULL, &val); if (*s || val > 0xffffffffU) { warnx("\"%s\" is neither an index nor a filter subcommand.", argv[0]); return (EINVAL); } idx = (uint32_t) val; /* delete|clear */ if (argc == 2 && (strcmp(argv[1], "delete") == 0 || strcmp(argv[1], "clear") == 0)) { return del_filter(idx); } /* [ ] ... */ return set_filter(idx, argc - 1, argv + 1); } /* * Shows the fields of a multi-word structure. The structure is considered to * consist of @nwords 32-bit words (i.e, it's an (@nwords * 32)-bit structure) * whose fields are described by @fd. The 32-bit words are given in @words * starting with the least significant 32-bit word. */ static void show_struct(const uint32_t *words, int nwords, const struct field_desc *fd) { unsigned int w = 0; const struct field_desc *p; for (p = fd; p->name; p++) w = max(w, strlen(p->name)); while (fd->name) { unsigned long long data; int first_word = fd->start / 32; int shift = fd->start % 32; int width = fd->end - fd->start + 1; unsigned long long mask = (1ULL << width) - 1; data = (words[first_word] >> shift) | ((uint64_t)words[first_word + 1] << (32 - shift)); if (shift) data |= ((uint64_t)words[first_word + 2] << (64 - shift)); data &= mask; if (fd->islog2) data = 1 << data; printf("%-*s ", w, fd->name); printf(fd->hex ? "%#llx\n" : "%llu\n", data << fd->shift); fd++; } } #define FIELD(name, start, end) { name, start, end, 0, 0, 0 } #define FIELD1(name, start) FIELD(name, start, start) static void show_t5_ctxt(const struct t4_sge_context *p) { static struct field_desc egress_t5[] = { FIELD("DCA_ST:", 181, 191), FIELD1("StatusPgNS:", 180), FIELD1("StatusPgRO:", 179), FIELD1("FetchNS:", 178), FIELD1("FetchRO:", 177), FIELD1("Valid:", 176), FIELD("PCIeDataChannel:", 174, 175), FIELD1("StatusPgTPHintEn:", 173), FIELD("StatusPgTPHint:", 171, 172), FIELD1("FetchTPHintEn:", 170), FIELD("FetchTPHint:", 168, 169), FIELD1("FCThreshOverride:", 167), { "WRLength:", 162, 166, 9, 0, 1 }, FIELD1("WRLengthKnown:", 161), FIELD1("ReschedulePending:", 160), FIELD1("OnChipQueue:", 159), FIELD1("FetchSizeMode:", 158), { "FetchBurstMin:", 156, 157, 4, 0, 1 }, FIELD1("FLMPacking:", 155), FIELD("FetchBurstMax:", 153, 154), FIELD("uPToken:", 133, 152), FIELD1("uPTokenEn:", 132), FIELD1("UserModeIO:", 131), FIELD("uPFLCredits:", 123, 130), FIELD1("uPFLCreditEn:", 122), FIELD("FID:", 111, 121), FIELD("HostFCMode:", 109, 110), FIELD1("HostFCOwner:", 108), { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, FIELD("CIDX:", 89, 104), FIELD("PIDX:", 73, 88), { "BaseAddress:", 18, 72, 9, 1 }, FIELD("QueueSize:", 2, 17), FIELD1("QueueType:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc fl_t5[] = { FIELD("DCA_ST:", 181, 191), FIELD1("StatusPgNS:", 180), FIELD1("StatusPgRO:", 179), FIELD1("FetchNS:", 178), FIELD1("FetchRO:", 177), FIELD1("Valid:", 176), FIELD("PCIeDataChannel:", 174, 175), FIELD1("StatusPgTPHintEn:", 173), FIELD("StatusPgTPHint:", 171, 172), FIELD1("FetchTPHintEn:", 170), FIELD("FetchTPHint:", 168, 169), FIELD1("FCThreshOverride:", 167), FIELD1("ReschedulePending:", 160), FIELD1("OnChipQueue:", 159), FIELD1("FetchSizeMode:", 158), { "FetchBurstMin:", 156, 157, 4, 0, 1 }, FIELD1("FLMPacking:", 155), FIELD("FetchBurstMax:", 153, 154), FIELD1("FLMcongMode:", 152), FIELD("MaxuPFLCredits:", 144, 151), FIELD("FLMcontextID:", 133, 143), FIELD1("uPTokenEn:", 132), FIELD1("UserModeIO:", 131), FIELD("uPFLCredits:", 123, 130), FIELD1("uPFLCreditEn:", 122), FIELD("FID:", 111, 121), FIELD("HostFCMode:", 109, 110), FIELD1("HostFCOwner:", 108), { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, FIELD("CIDX:", 89, 104), FIELD("PIDX:", 73, 88), { "BaseAddress:", 18, 72, 9, 1 }, FIELD("QueueSize:", 2, 17), FIELD1("QueueType:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc ingress_t5[] = { FIELD("DCA_ST:", 143, 153), FIELD1("ISCSICoalescing:", 142), FIELD1("Queue_Valid:", 141), FIELD1("TimerPending:", 140), FIELD1("DropRSS:", 139), FIELD("PCIeChannel:", 137, 138), FIELD1("SEInterruptArmed:", 136), FIELD1("CongestionMgtEnable:", 135), FIELD1("NoSnoop:", 134), FIELD1("RelaxedOrdering:", 133), FIELD1("GTSmode:", 132), FIELD1("TPHintEn:", 131), FIELD("TPHint:", 129, 130), FIELD1("UpdateScheduling:", 128), FIELD("UpdateDelivery:", 126, 127), FIELD1("InterruptSent:", 125), FIELD("InterruptIDX:", 114, 124), FIELD1("InterruptDestination:", 113), FIELD1("InterruptArmed:", 112), FIELD("RxIntCounter:", 106, 111), FIELD("RxIntCounterThreshold:", 104, 105), FIELD1("Generation:", 103), { "BaseAddress:", 48, 102, 9, 1 }, FIELD("PIDX:", 32, 47), FIELD("CIDX:", 16, 31), { "QueueSize:", 4, 15, 4, 0 }, { "QueueEntrySize:", 2, 3, 4, 0, 1 }, FIELD1("QueueEntryOverride:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc flm_t5[] = { FIELD1("Valid:", 89), FIELD("SplitLenMode:", 87, 88), FIELD1("TPHintEn:", 86), FIELD("TPHint:", 84, 85), FIELD1("NoSnoop:", 83), FIELD1("RelaxedOrdering:", 82), FIELD("DCA_ST:", 71, 81), FIELD("EQid:", 54, 70), FIELD("SplitEn:", 52, 53), FIELD1("PadEn:", 51), FIELD1("PackEn:", 50), FIELD1("Cache_Lock :", 49), FIELD1("CongDrop:", 48), FIELD("PackOffset:", 16, 47), FIELD("CIDX:", 8, 15), FIELD("PIDX:", 0, 7), { NULL } }; static struct field_desc conm_t5[] = { FIELD1("CngMPSEnable:", 21), FIELD("CngTPMode:", 19, 20), FIELD1("CngDBPHdr:", 18), FIELD1("CngDBPData:", 17), FIELD1("CngIMSG:", 16), { "CngChMap:", 0, 15, 0, 1, 0 }, { NULL } }; if (p->mem_id == SGE_CONTEXT_EGRESS) show_struct(p->data, 6, (p->data[0] & 2) ? fl_t5 : egress_t5); else if (p->mem_id == SGE_CONTEXT_FLM) show_struct(p->data, 3, flm_t5); else if (p->mem_id == SGE_CONTEXT_INGRESS) show_struct(p->data, 5, ingress_t5); else if (p->mem_id == SGE_CONTEXT_CNM) show_struct(p->data, 1, conm_t5); } static void show_t4_ctxt(const struct t4_sge_context *p) { static struct field_desc egress_t4[] = { FIELD1("StatusPgNS:", 180), FIELD1("StatusPgRO:", 179), FIELD1("FetchNS:", 178), FIELD1("FetchRO:", 177), FIELD1("Valid:", 176), FIELD("PCIeDataChannel:", 174, 175), FIELD1("DCAEgrQEn:", 173), FIELD("DCACPUID:", 168, 172), FIELD1("FCThreshOverride:", 167), FIELD("WRLength:", 162, 166), FIELD1("WRLengthKnown:", 161), FIELD1("ReschedulePending:", 160), FIELD1("OnChipQueue:", 159), FIELD1("FetchSizeMode", 158), { "FetchBurstMin:", 156, 157, 4, 0, 1 }, { "FetchBurstMax:", 153, 154, 6, 0, 1 }, FIELD("uPToken:", 133, 152), FIELD1("uPTokenEn:", 132), FIELD1("UserModeIO:", 131), FIELD("uPFLCredits:", 123, 130), FIELD1("uPFLCreditEn:", 122), FIELD("FID:", 111, 121), FIELD("HostFCMode:", 109, 110), FIELD1("HostFCOwner:", 108), { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, FIELD("CIDX:", 89, 104), FIELD("PIDX:", 73, 88), { "BaseAddress:", 18, 72, 9, 1 }, FIELD("QueueSize:", 2, 17), FIELD1("QueueType:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc fl_t4[] = { FIELD1("StatusPgNS:", 180), FIELD1("StatusPgRO:", 179), FIELD1("FetchNS:", 178), FIELD1("FetchRO:", 177), FIELD1("Valid:", 176), FIELD("PCIeDataChannel:", 174, 175), FIELD1("DCAEgrQEn:", 173), FIELD("DCACPUID:", 168, 172), FIELD1("FCThreshOverride:", 167), FIELD1("ReschedulePending:", 160), FIELD1("OnChipQueue:", 159), FIELD1("FetchSizeMode", 158), { "FetchBurstMin:", 156, 157, 4, 0, 1 }, { "FetchBurstMax:", 153, 154, 6, 0, 1 }, FIELD1("FLMcongMode:", 152), FIELD("MaxuPFLCredits:", 144, 151), FIELD("FLMcontextID:", 133, 143), FIELD1("uPTokenEn:", 132), FIELD1("UserModeIO:", 131), FIELD("uPFLCredits:", 123, 130), FIELD1("uPFLCreditEn:", 122), FIELD("FID:", 111, 121), FIELD("HostFCMode:", 109, 110), FIELD1("HostFCOwner:", 108), { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, FIELD("CIDX:", 89, 104), FIELD("PIDX:", 73, 88), { "BaseAddress:", 18, 72, 9, 1 }, FIELD("QueueSize:", 2, 17), FIELD1("QueueType:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc ingress_t4[] = { FIELD1("NoSnoop:", 145), FIELD1("RelaxedOrdering:", 144), FIELD1("GTSmode:", 143), FIELD1("ISCSICoalescing:", 142), FIELD1("Valid:", 141), FIELD1("TimerPending:", 140), FIELD1("DropRSS:", 139), FIELD("PCIeChannel:", 137, 138), FIELD1("SEInterruptArmed:", 136), FIELD1("CongestionMgtEnable:", 135), FIELD1("DCAIngQEnable:", 134), FIELD("DCACPUID:", 129, 133), FIELD1("UpdateScheduling:", 128), FIELD("UpdateDelivery:", 126, 127), FIELD1("InterruptSent:", 125), FIELD("InterruptIDX:", 114, 124), FIELD1("InterruptDestination:", 113), FIELD1("InterruptArmed:", 112), FIELD("RxIntCounter:", 106, 111), FIELD("RxIntCounterThreshold:", 104, 105), FIELD1("Generation:", 103), { "BaseAddress:", 48, 102, 9, 1 }, FIELD("PIDX:", 32, 47), FIELD("CIDX:", 16, 31), { "QueueSize:", 4, 15, 4, 0 }, { "QueueEntrySize:", 2, 3, 4, 0, 1 }, FIELD1("QueueEntryOverride:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc flm_t4[] = { FIELD1("NoSnoop:", 79), FIELD1("RelaxedOrdering:", 78), FIELD1("Valid:", 77), FIELD("DCACPUID:", 72, 76), FIELD1("DCAFLEn:", 71), FIELD("EQid:", 54, 70), FIELD("SplitEn:", 52, 53), FIELD1("PadEn:", 51), FIELD1("PackEn:", 50), FIELD1("DBpriority:", 48), FIELD("PackOffset:", 16, 47), FIELD("CIDX:", 8, 15), FIELD("PIDX:", 0, 7), { NULL } }; static struct field_desc conm_t4[] = { FIELD1("CngDBPHdr:", 6), FIELD1("CngDBPData:", 5), FIELD1("CngIMSG:", 4), { "CngChMap:", 0, 3, 0, 1, 0}, { NULL } }; if (p->mem_id == SGE_CONTEXT_EGRESS) show_struct(p->data, 6, (p->data[0] & 2) ? fl_t4 : egress_t4); else if (p->mem_id == SGE_CONTEXT_FLM) show_struct(p->data, 3, flm_t4); else if (p->mem_id == SGE_CONTEXT_INGRESS) show_struct(p->data, 5, ingress_t4); else if (p->mem_id == SGE_CONTEXT_CNM) show_struct(p->data, 1, conm_t4); } #undef FIELD #undef FIELD1 static int get_sge_context(int argc, const char *argv[]) { int rc; char *p; long cid; struct t4_sge_context cntxt = {0}; if (argc != 2) { warnx("sge_context: incorrect number of arguments."); return (EINVAL); } if (!strcmp(argv[0], "egress")) cntxt.mem_id = SGE_CONTEXT_EGRESS; else if (!strcmp(argv[0], "ingress")) cntxt.mem_id = SGE_CONTEXT_INGRESS; else if (!strcmp(argv[0], "fl")) cntxt.mem_id = SGE_CONTEXT_FLM; else if (!strcmp(argv[0], "cong")) cntxt.mem_id = SGE_CONTEXT_CNM; else { warnx("unknown context type \"%s\"; known types are egress, " "ingress, fl, and cong.", argv[0]); return (EINVAL); } p = str_to_number(argv[1], &cid, NULL); if (*p) { warnx("invalid context id \"%s\"", argv[1]); return (EINVAL); } cntxt.cid = cid; rc = doit(CHELSIO_T4_GET_SGE_CONTEXT, &cntxt); if (rc != 0) return (rc); if (chip_id == 4) show_t4_ctxt(&cntxt); else show_t5_ctxt(&cntxt); return (0); } static int loadfw(int argc, const char *argv[]) { int rc, fd; struct t4_data data = {0}; const char *fname = argv[0]; struct stat st = {0}; if (argc != 1) { warnx("loadfw: incorrect number of arguments."); return (EINVAL); } fd = open(fname, O_RDONLY); if (fd < 0) { warn("open(%s)", fname); return (errno); } if (fstat(fd, &st) < 0) { warn("fstat"); close(fd); return (errno); } data.len = st.st_size; data.data = mmap(0, data.len, PROT_READ, MAP_PRIVATE, fd, 0); if (data.data == MAP_FAILED) { warn("mmap"); close(fd); return (errno); } rc = doit(CHELSIO_T4_LOAD_FW, &data); munmap(data.data, data.len); close(fd); return (rc); } static int read_mem(uint32_t addr, uint32_t len, void (*output)(uint32_t *, uint32_t)) { int rc; struct t4_mem_range mr; mr.addr = addr; mr.len = len; mr.data = malloc(mr.len); if (mr.data == 0) { warn("read_mem: malloc"); return (errno); } rc = doit(CHELSIO_T4_GET_MEM, &mr); if (rc != 0) goto done; if (output) (*output)(mr.data, mr.len); done: free(mr.data); return (rc); } /* * Display memory as list of 'n' 4-byte values per line. */ static void show_mem(uint32_t *buf, uint32_t len) { const char *s; int i, n = 8; while (len) { for (i = 0; len && i < n; i++, buf++, len -= 4) { s = i ? " " : ""; printf("%s%08x", s, htonl(*buf)); } printf("\n"); } } static int memdump(int argc, const char *argv[]) { char *p; long l; uint32_t addr, len; if (argc != 2) { warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &l, NULL); if (*p) { warnx("invalid address \"%s\"", argv[0]); return (EINVAL); } addr = l; p = str_to_number(argv[1], &l, NULL); if (*p) { warnx("memdump: invalid length \"%s\"", argv[1]); return (EINVAL); } len = l; return (read_mem(addr, len, show_mem)); } /* * Display TCB as list of 'n' 4-byte values per line. */ static void show_tcb(uint32_t *buf, uint32_t len) { const char *s; int i, n = 8; while (len) { for (i = 0; len && i < n; i++, buf++, len -= 4) { s = i ? " " : ""; printf("%s%08x", s, htonl(*buf)); } printf("\n"); } } #define A_TP_CMM_TCB_BASE 0x7d10 #define TCB_SIZE 128 static int read_tcb(int argc, const char *argv[]) { char *p; long l; long long val; unsigned int tid; uint32_t addr; int rc; if (argc != 1) { warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &l, NULL); if (*p) { warnx("invalid tid \"%s\"", argv[0]); return (EINVAL); } tid = l; rc = read_reg(A_TP_CMM_TCB_BASE, 4, &val); if (rc != 0) return (rc); addr = val + tid * TCB_SIZE; return (read_mem(addr, TCB_SIZE, show_tcb)); } static int read_i2c(int argc, const char *argv[]) { char *p; long l; struct t4_i2c_data i2cd; int rc, i; if (argc < 3 || argc > 4) { warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &l, NULL); if (*p || l > UCHAR_MAX) { warnx("invalid port id \"%s\"", argv[0]); return (EINVAL); } i2cd.port_id = l; p = str_to_number(argv[1], &l, NULL); if (*p || l > UCHAR_MAX) { warnx("invalid i2c device address \"%s\"", argv[1]); return (EINVAL); } i2cd.dev_addr = l; p = str_to_number(argv[2], &l, NULL); if (*p || l > UCHAR_MAX) { warnx("invalid byte offset \"%s\"", argv[2]); return (EINVAL); } i2cd.offset = l; if (argc == 4) { p = str_to_number(argv[3], &l, NULL); if (*p || l > sizeof(i2cd.data)) { warnx("invalid number of bytes \"%s\"", argv[3]); return (EINVAL); } i2cd.len = l; } else i2cd.len = 1; rc = doit(CHELSIO_T4_GET_I2C, &i2cd); if (rc != 0) return (rc); for (i = 0; i < i2cd.len; i++) printf("0x%x [%u]\n", i2cd.data[i], i2cd.data[i]); return (0); } static int clearstats(int argc, const char *argv[]) { char *p; long l; uint32_t port; if (argc != 1) { warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &l, NULL); if (*p) { warnx("invalid port id \"%s\"", argv[0]); return (EINVAL); } port = l; return doit(CHELSIO_T4_CLEAR_STATS, &port); } static int show_tracers(void) { struct t4_tracer t; char *s; int rc, port_idx, i; long long val; /* Magic values: MPS_TRC_CFG = 0x9800. MPS_TRC_CFG[1:1] = TrcEn */ rc = read_reg(0x9800, 4, &val); if (rc != 0) return (rc); printf("tracing is %s\n", val & 2 ? "ENABLED" : "DISABLED"); t.idx = 0; for (t.idx = 0; ; t.idx++) { rc = doit(CHELSIO_T4_GET_TRACER, &t); if (rc != 0 || t.idx == 0xff) break; if (t.tp.port < 4) { s = "Rx"; port_idx = t.tp.port; } else if (t.tp.port < 8) { s = "Tx"; port_idx = t.tp.port - 4; } else if (t.tp.port < 12) { s = "loopback"; port_idx = t.tp.port - 8; } else if (t.tp.port < 16) { s = "MPS Rx"; port_idx = t.tp.port - 12; } else if (t.tp.port < 20) { s = "MPS Tx"; port_idx = t.tp.port - 16; } else { s = "unknown"; port_idx = t.tp.port; } printf("\ntracer %u (currently %s) captures ", t.idx, t.enabled ? "ENABLED" : "DISABLED"); if (t.tp.port < 8) printf("port %u %s, ", port_idx, s); else printf("%s %u, ", s, port_idx); printf("snap length: %u, min length: %u\n", t.tp.snap_len, t.tp.min_len); printf("packets captured %smatch filter\n", t.tp.invert ? "do not " : ""); if (t.tp.skip_ofst) { printf("filter pattern: "); for (i = 0; i < t.tp.skip_ofst * 2; i += 2) printf("%08x%08x", t.tp.data[i], t.tp.data[i + 1]); printf("/"); for (i = 0; i < t.tp.skip_ofst * 2; i += 2) printf("%08x%08x", t.tp.mask[i], t.tp.mask[i + 1]); printf("@0\n"); } printf("filter pattern: "); for (i = t.tp.skip_ofst * 2; i < T4_TRACE_LEN / 4; i += 2) printf("%08x%08x", t.tp.data[i], t.tp.data[i + 1]); printf("/"); for (i = t.tp.skip_ofst * 2; i < T4_TRACE_LEN / 4; i += 2) printf("%08x%08x", t.tp.mask[i], t.tp.mask[i + 1]); printf("@%u\n", (t.tp.skip_ofst + t.tp.skip_len) * 8); } return (rc); } static int tracer_onoff(uint8_t idx, int enabled) { struct t4_tracer t; t.idx = idx; t.enabled = enabled; t.valid = 0; return doit(CHELSIO_T4_SET_TRACER, &t); } static void create_tracing_ifnet() { char *cmd[] = { "/sbin/ifconfig", __DECONST(char *, nexus), "create", NULL }; char *env[] = {NULL}; if (vfork() == 0) { close(STDERR_FILENO); execve(cmd[0], cmd, env); _exit(0); } } /* * XXX: Allow user to specify snaplen, minlen, and pattern (including inverted * matching). Right now this is a quick-n-dirty implementation that traces the * first 128B of all tx or rx on a port */ static int set_tracer(uint8_t idx, int argc, const char *argv[]) { struct t4_tracer t; int len, port; bzero(&t, sizeof (t)); t.idx = idx; t.enabled = 1; t.valid = 1; if (argc != 1) { warnx("must specify tx or rx."); return (EINVAL); } len = strlen(argv[0]); if (len != 3) { warnx("argument must be 3 characters (tx or rx)"); return (EINVAL); } if (strncmp(argv[0], "tx", 2) == 0) { port = argv[0][2] - '0'; if (port < 0 || port > 3) { warnx("'%c' in %s is invalid", argv[0][2], argv[0]); return (EINVAL); } port += 4; } else if (strncmp(argv[0], "rx", 2) == 0) { port = argv[0][2] - '0'; if (port < 0 || port > 3) { warnx("'%c' in %s is invalid", argv[0][2], argv[0]); return (EINVAL); } } else { warnx("argument '%s' isn't tx or rx", argv[0]); return (EINVAL); } t.tp.snap_len = 128; t.tp.min_len = 0; t.tp.skip_ofst = 0; t.tp.skip_len = 0; t.tp.invert = 0; t.tp.port = port; create_tracing_ifnet(); return doit(CHELSIO_T4_SET_TRACER, &t); } static int tracer_cmd(int argc, const char *argv[]) { long long val; uint8_t idx; char *s; if (argc == 0) { warnx("tracer: no arguments."); return (EINVAL); }; /* list */ if (strcmp(argv[0], "list") == 0) { if (argc != 1) warnx("trailing arguments after \"list\" ignored."); return show_tracers(); } /* ... */ s = str_to_number(argv[0], NULL, &val); if (*s || val > 0xff) { warnx("\"%s\" is neither an index nor a tracer subcommand.", argv[0]); return (EINVAL); } idx = (int8_t)val; /* disable */ if (argc == 2 && strcmp(argv[1], "disable") == 0) return tracer_onoff(idx, 0); /* enable */ if (argc == 2 && strcmp(argv[1], "enable") == 0) return tracer_onoff(idx, 1); /* ... */ return set_tracer(idx, argc - 1, argv + 1); } static int modinfo_raw(int port_id) { uint8_t offset; struct t4_i2c_data i2cd; int rc; for (offset = 0; offset < 96; offset += sizeof(i2cd.data)) { bzero(&i2cd, sizeof(i2cd)); i2cd.port_id = port_id; i2cd.dev_addr = 0xa0; i2cd.offset = offset; i2cd.len = sizeof(i2cd.data); rc = doit(CHELSIO_T4_GET_I2C, &i2cd); if (rc != 0) return (rc); printf("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", offset, i2cd.data[0], i2cd.data[1], i2cd.data[2], i2cd.data[3], i2cd.data[4], i2cd.data[5], i2cd.data[6], i2cd.data[7]); printf(" %c%c%c%c %c%c%c%c\n", isprint(i2cd.data[0]) ? i2cd.data[0] : '.', isprint(i2cd.data[1]) ? i2cd.data[1] : '.', isprint(i2cd.data[2]) ? i2cd.data[2] : '.', isprint(i2cd.data[3]) ? i2cd.data[3] : '.', isprint(i2cd.data[4]) ? i2cd.data[4] : '.', isprint(i2cd.data[5]) ? i2cd.data[5] : '.', isprint(i2cd.data[6]) ? i2cd.data[6] : '.', isprint(i2cd.data[7]) ? i2cd.data[7] : '.'); } return (0); } static int modinfo(int argc, const char *argv[]) { long port; char string[16], *p; struct t4_i2c_data i2cd; int rc, i; uint16_t temp, vcc, tx_bias, tx_power, rx_power; if (argc < 1) { warnx("must supply a port"); return (EINVAL); } if (argc > 2) { warnx("too many arguments"); return (EINVAL); } p = str_to_number(argv[0], &port, NULL); if (*p || port > UCHAR_MAX) { warnx("invalid port id \"%s\"", argv[0]); return (EINVAL); } if (argc == 2) { if (!strcmp(argv[1], "raw")) return (modinfo_raw(port)); else { warnx("second argument can only be \"raw\""); return (EINVAL); } } bzero(&i2cd, sizeof(i2cd)); i2cd.len = 1; i2cd.port_id = port; i2cd.dev_addr = SFF_8472_BASE; i2cd.offset = SFF_8472_ID; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; if (i2cd.data[0] > SFF_8472_ID_LAST) printf("Unknown ID\n"); else printf("ID: %s\n", sff_8472_id[i2cd.data[0]]); bzero(&string, sizeof(string)); for (i = SFF_8472_VENDOR_START; i < SFF_8472_VENDOR_END; i++) { i2cd.offset = i; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; string[i - SFF_8472_VENDOR_START] = i2cd.data[0]; } printf("Vendor %s\n", string); bzero(&string, sizeof(string)); for (i = SFF_8472_SN_START; i < SFF_8472_SN_END; i++) { i2cd.offset = i; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; string[i - SFF_8472_SN_START] = i2cd.data[0]; } printf("SN %s\n", string); bzero(&string, sizeof(string)); for (i = SFF_8472_PN_START; i < SFF_8472_PN_END; i++) { i2cd.offset = i; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; string[i - SFF_8472_PN_START] = i2cd.data[0]; } printf("PN %s\n", string); bzero(&string, sizeof(string)); for (i = SFF_8472_REV_START; i < SFF_8472_REV_END; i++) { i2cd.offset = i; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; string[i - SFF_8472_REV_START] = i2cd.data[0]; } printf("Rev %s\n", string); i2cd.offset = SFF_8472_DIAG_TYPE; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; if ((char )i2cd.data[0] & (SFF_8472_DIAG_IMPL | SFF_8472_DIAG_INTERNAL)) { /* Switch to reading from the Diagnostic address. */ i2cd.dev_addr = SFF_8472_DIAG; i2cd.len = 1; i2cd.offset = SFF_8472_TEMP; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; temp = i2cd.data[0] << 8; printf("Temp: "); if ((temp & SFF_8472_TEMP_SIGN) == SFF_8472_TEMP_SIGN) printf("-"); else printf("+"); printf("%dC\n", (temp & SFF_8472_TEMP_MSK) >> SFF_8472_TEMP_SHIFT); i2cd.offset = SFF_8472_VCC; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; vcc = i2cd.data[0] << 8; printf("Vcc %fV\n", vcc / SFF_8472_VCC_FACTOR); i2cd.offset = SFF_8472_TX_BIAS; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; tx_bias = i2cd.data[0] << 8; printf("TX Bias %fuA\n", tx_bias / SFF_8472_BIAS_FACTOR); i2cd.offset = SFF_8472_TX_POWER; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; tx_power = i2cd.data[0] << 8; printf("TX Power %fmW\n", tx_power / SFF_8472_POWER_FACTOR); i2cd.offset = SFF_8472_RX_POWER; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; rx_power = i2cd.data[0] << 8; printf("RX Power %fmW\n", rx_power / SFF_8472_POWER_FACTOR); } else printf("Diagnostics not supported.\n"); return(0); fail: if (rc == EPERM) warnx("No module/cable in port %ld", port); return (rc); } /* XXX: pass in a low/high and do range checks as well */ static int get_sched_param(const char *param, const char *args[], long *val) { char *p; if (strcmp(param, args[0]) != 0) return (EINVAL); p = str_to_number(args[1], val, NULL); if (*p) { warnx("parameter \"%s\" has bad value \"%s\"", args[0], args[1]); return (EINVAL); } return (0); } static int sched_class(int argc, const char *argv[]) { struct t4_sched_params op; int errs, i; memset(&op, 0xff, sizeof(op)); op.subcmd = -1; op.type = -1; if (argc == 0) { warnx("missing scheduling sub-command"); return (EINVAL); } if (!strcmp(argv[0], "config")) { op.subcmd = SCHED_CLASS_SUBCMD_CONFIG; op.u.config.minmax = -1; } else if (!strcmp(argv[0], "params")) { op.subcmd = SCHED_CLASS_SUBCMD_PARAMS; op.u.params.level = op.u.params.mode = op.u.params.rateunit = op.u.params.ratemode = op.u.params.channel = op.u.params.cl = op.u.params.minrate = op.u.params.maxrate = op.u.params.weight = op.u.params.pktsize = -1; } else { warnx("invalid scheduling sub-command \"%s\"", argv[0]); return (EINVAL); } /* Decode remaining arguments ... */ errs = 0; for (i = 1; i < argc; i += 2) { const char **args = &argv[i]; long l; if (i + 1 == argc) { warnx("missing argument for \"%s\"", args[0]); errs++; break; } if (!strcmp(args[0], "type")) { if (!strcmp(args[1], "packet")) op.type = SCHED_CLASS_TYPE_PACKET; else { warnx("invalid type parameter \"%s\"", args[1]); errs++; } continue; } if (op.subcmd == SCHED_CLASS_SUBCMD_CONFIG) { if(!get_sched_param("minmax", args, &l)) op.u.config.minmax = (int8_t)l; else { warnx("unknown scheduler config parameter " "\"%s\"", args[0]); errs++; } continue; } /* Rest applies only to SUBCMD_PARAMS */ if (op.subcmd != SCHED_CLASS_SUBCMD_PARAMS) continue; if (!strcmp(args[0], "level")) { if (!strcmp(args[1], "cl-rl")) op.u.params.level = SCHED_CLASS_LEVEL_CL_RL; else if (!strcmp(args[1], "cl-wrr")) op.u.params.level = SCHED_CLASS_LEVEL_CL_WRR; else if (!strcmp(args[1], "ch-rl")) op.u.params.level = SCHED_CLASS_LEVEL_CH_RL; else { warnx("invalid level parameter \"%s\"", args[1]); errs++; } } else if (!strcmp(args[0], "mode")) { if (!strcmp(args[1], "class")) op.u.params.mode = SCHED_CLASS_MODE_CLASS; else if (!strcmp(args[1], "flow")) op.u.params.mode = SCHED_CLASS_MODE_FLOW; else { warnx("invalid mode parameter \"%s\"", args[1]); errs++; } } else if (!strcmp(args[0], "rate-unit")) { if (!strcmp(args[1], "bits")) op.u.params.rateunit = SCHED_CLASS_RATEUNIT_BITS; else if (!strcmp(args[1], "pkts")) op.u.params.rateunit = SCHED_CLASS_RATEUNIT_PKTS; else { warnx("invalid rate-unit parameter \"%s\"", args[1]); errs++; } } else if (!strcmp(args[0], "rate-mode")) { if (!strcmp(args[1], "relative")) op.u.params.ratemode = SCHED_CLASS_RATEMODE_REL; else if (!strcmp(args[1], "absolute")) op.u.params.ratemode = SCHED_CLASS_RATEMODE_ABS; else { warnx("invalid rate-mode parameter \"%s\"", args[1]); errs++; } } else if (!get_sched_param("channel", args, &l)) op.u.params.channel = (int8_t)l; else if (!get_sched_param("class", args, &l)) op.u.params.cl = (int8_t)l; else if (!get_sched_param("min-rate", args, &l)) op.u.params.minrate = (int32_t)l; else if (!get_sched_param("max-rate", args, &l)) op.u.params.maxrate = (int32_t)l; else if (!get_sched_param("weight", args, &l)) op.u.params.weight = (int16_t)l; else if (!get_sched_param("pkt-size", args, &l)) op.u.params.pktsize = (int16_t)l; else { warnx("unknown scheduler parameter \"%s\"", args[0]); errs++; } } /* * Catch some logical fallacies in terms of argument combinations here * so we can offer more than just the EINVAL return from the driver. * The driver will be able to catch a lot more issues since it knows * the specifics of the device hardware capabilities like how many * channels, classes, etc. the device supports. */ if (op.type < 0) { warnx("sched \"type\" parameter missing"); errs++; } if (op.subcmd == SCHED_CLASS_SUBCMD_CONFIG) { if (op.u.config.minmax < 0) { warnx("sched config \"minmax\" parameter missing"); errs++; } } if (op.subcmd == SCHED_CLASS_SUBCMD_PARAMS) { if (op.u.params.level < 0) { warnx("sched params \"level\" parameter missing"); errs++; } if (op.u.params.mode < 0) { warnx("sched params \"mode\" parameter missing"); errs++; } if (op.u.params.rateunit < 0) { warnx("sched params \"rate-unit\" parameter missing"); errs++; } if (op.u.params.ratemode < 0) { warnx("sched params \"rate-mode\" parameter missing"); errs++; } if (op.u.params.channel < 0) { warnx("sched params \"channel\" missing"); errs++; } if (op.u.params.cl < 0) { warnx("sched params \"class\" missing"); errs++; } if (op.u.params.maxrate < 0 && (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { warnx("sched params \"max-rate\" missing for " "rate-limit level"); errs++; } if (op.u.params.weight < 0 && op.u.params.level == SCHED_CLASS_LEVEL_CL_WRR) { warnx("sched params \"weight\" missing for " "weighted-round-robin level"); errs++; } if (op.u.params.pktsize < 0 && (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { warnx("sched params \"pkt-size\" missing for " "rate-limit level"); errs++; } if (op.u.params.mode == SCHED_CLASS_MODE_FLOW && op.u.params.ratemode != SCHED_CLASS_RATEMODE_ABS) { warnx("sched params mode flow needs rate-mode absolute"); errs++; } if (op.u.params.ratemode == SCHED_CLASS_RATEMODE_REL && !in_range(op.u.params.maxrate, 1, 100)) { warnx("sched params \"max-rate\" takes " "percentage value(1-100) for rate-mode relative"); errs++; } if (op.u.params.ratemode == SCHED_CLASS_RATEMODE_ABS && !in_range(op.u.params.maxrate, 1, 10000000)) { warnx("sched params \"max-rate\" takes " "value(1-10000000) for rate-mode absolute"); errs++; } if (op.u.params.maxrate > 0 && op.u.params.maxrate < op.u.params.minrate) { warnx("sched params \"max-rate\" is less than " "\"min-rate\""); errs++; } } if (errs > 0) { warnx("%d error%s in sched-class command", errs, errs == 1 ? "" : "s"); return (EINVAL); } return doit(CHELSIO_T4_SCHED_CLASS, &op); } static int sched_queue(int argc, const char *argv[]) { struct t4_sched_queue op = {0}; char *p; long val; if (argc != 3) { /* need " */ warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &val, NULL); if (*p || val > UCHAR_MAX) { warnx("invalid port id \"%s\"", argv[0]); return (EINVAL); } op.port = (uint8_t)val; if (!strcmp(argv[1], "all") || !strcmp(argv[1], "*")) op.queue = -1; else { p = str_to_number(argv[1], &val, NULL); if (*p || val < -1) { warnx("invalid queue \"%s\"", argv[1]); return (EINVAL); } op.queue = (int8_t)val; } if (!strcmp(argv[2], "unbind") || !strcmp(argv[2], "clear")) op.cl = -1; else { p = str_to_number(argv[2], &val, NULL); if (*p || val < -1) { warnx("invalid class \"%s\"", argv[2]); return (EINVAL); } op.cl = (int8_t)val; } return doit(CHELSIO_T4_SCHED_QUEUE, &op); } static int run_cmd(int argc, const char *argv[]) { int rc = -1; const char *cmd = argv[0]; /* command */ argc--; argv++; if (!strcmp(cmd, "reg") || !strcmp(cmd, "reg32")) rc = register_io(argc, argv, 4); else if (!strcmp(cmd, "reg64")) rc = register_io(argc, argv, 8); else if (!strcmp(cmd, "regdump")) rc = dump_regs(argc, argv); else if (!strcmp(cmd, "filter")) rc = filter_cmd(argc, argv); else if (!strcmp(cmd, "context")) rc = get_sge_context(argc, argv); else if (!strcmp(cmd, "loadfw")) rc = loadfw(argc, argv); else if (!strcmp(cmd, "memdump")) rc = memdump(argc, argv); else if (!strcmp(cmd, "tcb")) rc = read_tcb(argc, argv); else if (!strcmp(cmd, "i2c")) rc = read_i2c(argc, argv); else if (!strcmp(cmd, "clearstats")) rc = clearstats(argc, argv); else if (!strcmp(cmd, "tracer")) rc = tracer_cmd(argc, argv); else if (!strcmp(cmd, "modinfo")) rc = modinfo(argc, argv); else if (!strcmp(cmd, "sched-class")) rc = sched_class(argc, argv); else if (!strcmp(cmd, "sched-queue")) rc = sched_queue(argc, argv); else { rc = EINVAL; warnx("invalid command \"%s\"", cmd); } return (rc); } #define MAX_ARGS 15 static int run_cmd_loop(void) { int i, rc = 0; char buffer[128], *buf; const char *args[MAX_ARGS + 1]; /* * Simple loop: displays a "> " prompt and processes any input as a * cxgbetool command. You're supposed to enter only the part after * "cxgbetool t4nexX". Use "quit" or "exit" to exit. */ for (;;) { fprintf(stdout, "> "); fflush(stdout); buf = fgets(buffer, sizeof(buffer), stdin); if (buf == NULL) { if (ferror(stdin)) { warn("stdin error"); rc = errno; /* errno from fgets */ } break; } i = 0; while ((args[i] = strsep(&buf, " \t\n")) != NULL) { if (args[i][0] != 0 && ++i == MAX_ARGS) break; } args[i] = 0; if (i == 0) continue; /* skip empty line */ if (!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) break; rc = run_cmd(i, args); } /* rc normally comes from the last command (not including quit/exit) */ return (rc); } int main(int argc, const char *argv[]) { int rc = -1; progname = argv[0]; if (argc == 2) { if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { usage(stdout); exit(0); } } if (argc < 3) { usage(stderr); exit(EINVAL); } nexus = argv[1]; /* progname and nexus */ argc -= 2; argv += 2; if (argc == 1 && !strcmp(argv[0], "stdio")) rc = run_cmd_loop(); else rc = run_cmd(argc, argv); return (rc); } Index: head/tools/tools/mwl/mwldebug/mwldebug.c =================================================================== --- head/tools/tools/mwl/mwldebug/mwldebug.c (revision 287296) +++ head/tools/tools/mwl/mwldebug/mwldebug.c (revision 287297) @@ -1,212 +1,210 @@ /*- * Copyright (c) 2007 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * mwldebug [-i interface] flags * (default interface is mwl0). */ -#include + #include #include #include #include #include -#include -#include #include +#include #include +#include +#include #include -#include -#define N(a) (sizeof(a)/sizeof(a[0])) - const char *progname; enum { MWL_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ MWL_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */ MWL_DEBUG_RECV = 0x00000004, /* basic recv operation */ MWL_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */ MWL_DEBUG_RESET = 0x00000010, /* reset processing */ MWL_DEBUG_BEACON = 0x00000020, /* beacon handling */ MWL_DEBUG_INTR = 0x00000040, /* ISR */ MWL_DEBUG_TX_PROC = 0x00000080, /* tx ISR proc */ MWL_DEBUG_RX_PROC = 0x00000100, /* rx ISR proc */ MWL_DEBUG_KEYCACHE = 0x00000200, /* key cache management */ MWL_DEBUG_STATE = 0x00000400, /* 802.11 state transitions */ MWL_DEBUG_NODE = 0x00000800, /* node management */ MWL_DEBUG_RECV_ALL = 0x00001000, /* trace all frames (beacons) */ MWL_DEBUG_TSO = 0x00002000, /* TSO processing */ MWL_DEBUG_AMPDU = 0x00004000, /* BA stream handling */ MWL_DEBUG_ANY = 0xffffffff }; static struct { const char *name; u_int bit; } flags[] = { { "xmit", MWL_DEBUG_XMIT }, { "xmit_desc", MWL_DEBUG_XMIT_DESC }, { "recv", MWL_DEBUG_RECV }, { "recv_desc", MWL_DEBUG_RECV_DESC }, { "reset", MWL_DEBUG_RESET }, { "beacon", MWL_DEBUG_BEACON }, { "intr", MWL_DEBUG_INTR }, { "xmit_proc", MWL_DEBUG_TX_PROC }, { "recv_proc", MWL_DEBUG_RX_PROC }, { "keycache", MWL_DEBUG_KEYCACHE }, { "state", MWL_DEBUG_STATE }, { "node", MWL_DEBUG_NODE }, { "recv_all", MWL_DEBUG_RECV_ALL }, { "tso", MWL_DEBUG_TSO }, { "ampdu", MWL_DEBUG_AMPDU }, /* XXX these are a hack; there should be a separate sysctl knob */ { "hal", 0x02000000 }, /* cmd-completion processing */ { "hal2", 0x01000000 }, /* cmd submission processing */ { "halhang", 0x04000000 }, /* disable fw hang stuff */ }; static u_int getflag(const char *name, int len) { int i; - for (i = 0; i < N(flags); i++) + for (i = 0; i < nitems(flags); i++) if (strncasecmp(flags[i].name, name, len) == 0) return flags[i].bit; return 0; } #if 0 static const char * getflagname(u_int flag) { int i; - for (i = 0; i < N(flags); i++) + for (i = 0; i < nitems(flags); i++) if (flags[i].bit == flag) return flags[i].name; return "???"; } #endif static void usage(void) { int i; fprintf(stderr, "usage: %s [-i device] [flags]\n", progname); fprintf(stderr, "where flags are:\n"); - for (i = 0; i < N(flags); i++) + for (i = 0; i < nitems(flags); i++) printf("%s\n", flags[i].name); exit(-1); } int main(int argc, char *argv[]) { const char *ifname = "mwl0"; const char *cp, *tp; const char *sep; int c, op, i; u_int32_t debug, ndebug; size_t debuglen; char oid[256]; progname = argv[0]; if (argc > 1) { if (strcmp(argv[1], "-i") == 0) { if (argc < 2) errx(1, "missing interface name for -i option"); ifname = argv[2]; if (strncmp(ifname, "mv", 2) != 0) errx(2, "huh, this is for mv devices?"); argc -= 2, argv += 2; } else if (strcmp(argv[1], "-?") == 0) usage(); } snprintf(oid, sizeof(oid), "dev.mwl.%s.debug", ifname+3); debuglen = sizeof(debug); if (sysctlbyname(oid, &debug, &debuglen, NULL, 0) < 0) err(1, "sysctl-get(%s)", oid); ndebug = debug; for (; argc > 1; argc--, argv++) { cp = argv[1]; do { u_int bit; if (*cp == '-') { cp++; op = -1; } else if (*cp == '+') { cp++; op = 1; } else op = 0; for (tp = cp; *tp != '\0' && *tp != '+' && *tp != '-';) tp++; bit = getflag(cp, tp-cp); if (op < 0) ndebug &= ~bit; else if (op > 0) ndebug |= bit; else { if (bit == 0) { c = *cp; if (isdigit(c)) bit = strtoul(cp, NULL, 0); else errx(1, "unknown flag %.*s", (int)(tp-cp), cp); } ndebug = bit; } } while (*(cp = tp) != '\0'); } if (debug != ndebug) { printf("%s: 0x%x => ", oid, debug); if (sysctlbyname(oid, NULL, NULL, &ndebug, sizeof(ndebug)) < 0) err(1, "sysctl-set(%s)", oid); printf("0x%x", ndebug); debug = ndebug; } else printf("%s: 0x%x", oid, debug); sep = "<"; - for (i = 0; i < N(flags); i++) + for (i = 0; i < nitems(flags); i++) if (debug & flags[i].bit) { printf("%s%s", sep, flags[i].name); sep = ","; } printf("%s\n", *sep != '<' ? ">" : ""); return 0; } Index: head/tools/tools/mwl/mwlstats/mwlstats.c =================================================================== --- head/tools/tools/mwl/mwlstats/mwlstats.c (revision 287296) +++ head/tools/tools/mwl/mwlstats/mwlstats.c (revision 287297) @@ -1,578 +1,579 @@ /*- * Copyright (c) 2007 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * mwl statistics class. */ -#include + +#include #include +#include #include #include -#include + #include #include -#include -#include +#include #include +#include +#include #include #include -#include #include "../../../../sys/net80211/ieee80211_ioctl.h" #include "../../../../sys/net80211/ieee80211_radiotap.h" /* * Get Hardware Statistics. */ struct mwl_hal_hwstats { uint32_t TxRetrySuccesses; uint32_t TxMultipleRetrySuccesses; uint32_t TxFailures; uint32_t RTSSuccesses; uint32_t RTSFailures; uint32_t AckFailures; uint32_t RxDuplicateFrames; uint32_t FCSErrorCount; uint32_t TxWatchDogTimeouts; uint32_t RxOverflows; uint32_t RxFragErrors; uint32_t RxMemErrors; uint32_t PointerErrors; uint32_t TxUnderflows; uint32_t TxDone; uint32_t TxDoneBufTryPut; uint32_t TxDoneBufPut; uint32_t Wait4TxBuf; uint32_t TxAttempts; uint32_t TxSuccesses; uint32_t TxFragments; uint32_t TxMulticasts; uint32_t RxNonCtlPkts; uint32_t RxMulticasts; uint32_t RxUndecryptableFrames; uint32_t RxICVErrors; uint32_t RxExcludedFrames; }; #include "../../../../sys/dev/mwl/if_mwlioctl.h" #include "mwlstats.h" #define AFTER(prev) ((prev)+1) static const struct fmt mwlstats[] = { #define S_INPUT 0 { 8, "input", "input", "total frames received" }, #define S_RX_MCAST AFTER(S_INPUT) { 7, "rxmcast", "rxmcast", "rx multicast frames" }, #define S_RX_NONCTL AFTER(S_RX_MCAST) { 8, "rxnonctl", "rxnonctl" "rx non control frames" }, #define S_RX_MGT AFTER(S_RX_NONCTL) { 5, "rxmgt", "rxmgt", "rx management frames" }, #define S_RX_CTL AFTER(S_RX_MGT) { 5, "rxctl", "rxctl", "rx control frames" }, #define S_OUTPUT AFTER(S_RX_CTL) { 8, "output", "output", "total frames transmit" }, #define S_TX_MCAST AFTER(S_OUTPUT) { 7, "txmcast", "txmcast", "tx multicast frames" }, #define S_TX_MGMT AFTER(S_TX_MCAST) { 5, "txmgt", "txmgt", "tx management frames" }, #define S_TX_RETRY AFTER(S_TX_MGMT) { 7, "txretry", "txretry", "tx success with 1 retry" }, #define S_TX_MRETRY AFTER(S_TX_RETRY) { 8, "txmretry", "txmretry", "tx success with >1 retry" }, #define S_TX_RTSGOOD AFTER(S_TX_MRETRY) { 7, "rtsgood", "rtsgood", "RTS tx success" }, #define S_TX_RTSBAD AFTER(S_TX_RTSGOOD) { 6, "rtsbad", "rtsbad", "RTS tx failed" }, #define S_TX_NOACK AFTER(S_TX_RTSBAD) { 5, "noack", "noack", "tx failed because no ACK was received" }, #define S_RX_DUPLICATE AFTER(S_TX_NOACK) { 5, "rxdup", "rxdup", "rx discarded by f/w as dup" }, #define S_RX_FCS AFTER(S_RX_DUPLICATE) { 5, "rxfcs", "rxfcs", "rx discarded by f/w for bad FCS" }, #define S_TX_WATCHDOG AFTER(S_RX_FCS) { 7, "txwatch", "txwatch", "MAC tx hang (f/w recovery)" }, #define S_RX_OVERFLOW AFTER(S_TX_WATCHDOG) { 6, "rxover", "rxover", "no f/w buffer for rx" }, #define S_RX_FRAGERROR AFTER(S_RX_OVERFLOW) { 6, "rxfrag", "rxfrag", "rx failed in f/w due to defrag" }, #define S_RX_MEMERROR AFTER(S_RX_FRAGERROR) { 5, "rxmem", "rxmem", "rx failed in f/w 'cuz out of of memory" }, #define S_PTRERROR AFTER(S_RX_MEMERROR) { 6, "badptr", "badptr", "MAC internal pointer problem" }, #define S_TX_UNDERFLOW AFTER(S_PTRERROR) { 7, "txunder", "txunder", "tx failed in f/w 'cuz of underflow" }, #define S_TX_DONE AFTER(S_TX_UNDERFLOW) { 6, "txdone", "txdone", "MAC tx ops completed" }, #define S_TX_DONEBUFPUT AFTER(S_TX_DONE) { 9, "txdoneput", "txdoneput", "tx buffers returned by f/w to host" }, #define S_TX_WAIT4BUF AFTER(S_TX_DONEBUFPUT) { 6, "txwait", "txwait", "no f/w buffers available when supplied a tx descriptor" }, #define S_TX_ATTEMPTS AFTER(S_TX_WAIT4BUF) { 5, "txtry", "txtry", "tx descriptors processed by f/w" }, #define S_TX_SUCCESS AFTER(S_TX_ATTEMPTS) { 4, "txok", "txok", "tx attempts successful" }, #define S_TX_FRAGS AFTER(S_TX_SUCCESS) { 6, "txfrag", "txfrag", "tx attempts with fragmentation" }, #define S_RX_UNDECRYPT AFTER(S_TX_FRAGS) { 7, "rxcrypt", "rxcrypt", "rx failed in f/w 'cuz decrypt failed" }, #define S_RX_ICVERROR AFTER(S_RX_UNDECRYPT) { 5, "rxicv", "rxicv", "rx failed in f/w 'cuz ICV check" }, #define S_RX_EXCLUDE AFTER(S_RX_ICVERROR) { 8, "rxfilter", "rxfilter", "rx frames filtered in f/w" }, #define S_TX_LINEAR AFTER(S_RX_EXCLUDE) { 5, "txlinear", "txlinear", "tx linearized to cluster" }, #define S_TX_DISCARD AFTER(S_TX_LINEAR) { 5, "txdisc", "txdisc", "tx frames discarded prior to association" }, #define S_TX_QSTOP AFTER(S_TX_DISCARD) { 5, "qstop", "qstop", "tx stopped 'cuz no xmit buffer" }, #define S_TX_ENCAP AFTER(S_TX_QSTOP) { 5, "txencode", "txencode", "tx encapsulation failed" }, #define S_TX_NOMBUF AFTER(S_TX_ENCAP) { 5, "txnombuf", "txnombuf", "tx failed 'cuz mbuf allocation failed" }, #define S_TX_SHORTPRE AFTER(S_TX_NOMBUF) { 5, "shpre", "shpre", "tx frames with short preamble" }, #define S_TX_NOHEADROOM AFTER(S_TX_SHORTPRE) { 5, "nohead", "nohead", "tx frames discarded for lack of headroom" }, #define S_TX_BADFRAMETYPE AFTER(S_TX_NOHEADROOM) { 5, "badtxtype", "badtxtype", "tx frames discarded for invalid/unknown 802.11 frame type" }, #define S_RX_CRYPTO_ERR AFTER(S_TX_BADFRAMETYPE) { 5, "crypt", "crypt", "rx failed 'cuz decryption" }, #define S_RX_NOMBUF AFTER(S_RX_CRYPTO_ERR) { 5, "rxnombuf", "rxnombuf", "rx setup failed 'cuz no mbuf" }, #define S_RX_TKIPMIC AFTER(S_RX_NOMBUF) { 5, "rxtkipmic", "rxtkipmic", "rx failed 'cuz TKIP MIC error" }, #define S_RX_NODMABUF AFTER(S_RX_TKIPMIC) { 5, "rxnodmabuf", "rxnodmabuf", "rx failed 'cuz no DMA buffer available" }, #define S_RX_DMABUFMISSING AFTER(S_RX_NODMABUF) { 5, "rxdmabufmissing", "rxdmabufmissing", "rx descriptor with no DMA buffer attached" }, #define S_TX_NODATA AFTER(S_RX_DMABUFMISSING) { 5, "txnodata", "txnodata", "tx discarded empty frame" }, #define S_TX_BUSDMA AFTER(S_TX_NODATA) { 5, "txbusdma", "txbusdma", "tx failed for dma resources" }, #define S_RX_BUSDMA AFTER(S_TX_BUSDMA) { 5, "rxbusdma", "rxbusdma", "rx setup failed for dma resources" }, #define S_AMPDU_NOSTREAM AFTER(S_RX_BUSDMA) { 5, "ampdu_nostream","ampdu_nostream","ADDBA request failed 'cuz all BA streams in use" }, #define S_AMPDU_REJECT AFTER(S_AMPDU_NOSTREAM) { 5, "ampdu_reject","ampdu_reject","ADDBA request failed 'cuz station already has one BA stream" }, #define S_ADDBA_NOSTREAM AFTER(S_AMPDU_REJECT) { 5, "addba_nostream","addba_nostream","ADDBA response processed but no BA stream present" }, #define S_TX_TSO AFTER(S_ADDBA_NOSTREAM) { 8, "txtso", "tso", "tx frames using TSO" }, #define S_TSO_BADETH AFTER(S_TX_TSO) { 5, "tsoeth", "tsoeth", "TSO failed 'cuz ether header type not IPv4" }, #define S_TSO_NOHDR AFTER(S_TSO_BADETH) { 5, "tsonohdr", "tsonohdr", "TSO failed 'cuz header not in first mbuf" }, #define S_TSO_BADSPLIT AFTER(S_TSO_NOHDR) { 5, "tsobadsplit", "tsobadsplit", "TSO failed 'cuz payload split failed" }, #define S_BAWATCHDOG AFTER(S_TSO_BADSPLIT) { 5, "bawatchdog", "bawatchdog", "BA watchdog interrupts" }, #define S_BAWATCHDOG_NOTFOUND AFTER(S_BAWATCHDOG) { 5, "bawatchdog_notfound", "bawatchdog_notfound", "BA watchdog for unknown stream" }, #define S_BAWATCHDOG_EMPTY AFTER(S_BAWATCHDOG_NOTFOUND) { 5, "bawatchdog_empty", "bawatchdog_empty", "BA watchdog on all streams but none found" }, #define S_BAWATCHDOG_FAILED AFTER(S_BAWATCHDOG_EMPTY) { 5, "bawatchdog_failed", "bawatchdog_failed", "BA watchdog processing failed to get bitmap from f/w" }, #define S_RADARDETECT AFTER(S_BAWATCHDOG_FAILED) { 5, "radardetect", "radardetect", "radar detect interrupts" }, #define S_RATE AFTER(S_RADARDETECT) { 4, "rate", "rate", "rate of last transmit" }, #define S_TX_RSSI AFTER(S_RATE) { 4, "arssi", "arssi", "rssi of last ack" }, #define S_RX_RSSI AFTER(S_TX_RSSI) { 4, "rssi", "rssi", "avg recv rssi" }, #define S_RX_NOISE AFTER(S_RX_RSSI) { 5, "noise", "noise", "rx noise floor" }, #define S_TX_SIGNAL AFTER(S_RX_NOISE) { 4, "asignal", "asig", "signal of last ack (dBm)" }, #define S_RX_SIGNAL AFTER(S_TX_SIGNAL) { 4, "signal", "sig", "avg recv signal (dBm)" }, #define S_ANT_TX0 AFTER(S_RX_SIGNAL) { 8, "tx0", "ant0(tx)", "frames tx on antenna 0" }, #define S_ANT_TX1 (S_RX_SIGNAL+2) { 8, "tx1", "ant1(tx)", "frames tx on antenna 1" }, #define S_ANT_TX2 (S_RX_SIGNAL+3) { 8, "tx2", "ant2(tx)", "frames tx on antenna 2" }, #define S_ANT_TX3 (S_RX_SIGNAL+4) { 8, "tx3", "ant3(tx)", "frames tx on antenna 3" }, #define S_ANT_RX0 AFTER(S_ANT_TX3) { 8, "rx0", "ant0(rx)", "frames rx on antenna 0" }, #define S_ANT_RX1 (S_ANT_TX3+2) { 8, "rx1", "ant1(rx)", "frames rx on antenna 1" }, #define S_ANT_RX2 (S_ANT_TX3+3) { 8, "rx2", "ant2(rx)", "frames rx on antenna 2" }, #define S_ANT_RX3 (S_ANT_TX3+4) { 8, "rx3", "ant3(rx)", "frames rx on antenna 3" }, }; /* NB: this intentionally avoids per-antenna stats */ #define S_LAST (S_RX_SIGNAL+1) struct mwlstatfoo_p { struct mwlstatfoo base; int s; struct ifreq ifr; struct mwl_stats cur; struct mwl_stats total; }; static void mwl_setifname(struct mwlstatfoo *wf0, const char *ifname) { struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) wf0; strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name)); } static void mwl_collect(struct mwlstatfoo_p *wf, struct mwl_stats *stats) { wf->ifr.ifr_data = (caddr_t) stats; if (ioctl(wf->s, SIOCGMVSTATS, &wf->ifr) < 0) err(1, "%s: ioctl: %s", __func__, wf->ifr.ifr_name); } static void mwl_collect_cur(struct bsdstat *sf) { struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; mwl_collect(wf, &wf->cur); } static void mwl_collect_tot(struct bsdstat *sf) { struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; mwl_collect(wf, &wf->total); } static void mwl_update_tot(struct bsdstat *sf) { struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; wf->total = wf->cur; } static void setrate(char b[], size_t bs, uint8_t rate) { if (rate & IEEE80211_RATE_MCS) snprintf(b, bs, "MCS%u", rate & IEEE80211_RATE_VAL); else if (rate & 1) snprintf(b, bs, "%u.5M", rate / 2); else snprintf(b, bs, "%uM", rate / 2); } static int mwl_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->cur.mst_##x - wf->total.mst_##x); return 1 #define HWSTAT(x) \ snprintf(b, bs, "%u", wf->cur.hw_stats.x - wf->total.hw_stats.x); return 1 #define RXANT(x) \ snprintf(b, bs, "%u", wf->cur.mst_ant_rx[x] - wf->total.mst_ant_rx[x]); return 1 #define TXANT(x) \ snprintf(b, bs, "%u", wf->cur.mst_ant_tx[x] - wf->total.mst_ant_tx[x]); return 1 switch (s) { case S_INPUT: snprintf(b, bs, "%lu", (u_long)( (wf->cur.mst_rx_packets - wf->total.mst_rx_packets))); return 1; case S_OUTPUT: snprintf(b, bs, "%lu", (u_long)( wf->cur.mst_tx_packets - wf->total.mst_tx_packets)); return 1; case S_RATE: setrate(b, bs, wf->cur.mst_tx_rate); return 1; case S_TX_RETRY: HWSTAT(TxRetrySuccesses); case S_TX_MRETRY: HWSTAT(TxMultipleRetrySuccesses); case S_TX_RTSGOOD: HWSTAT(RTSSuccesses); case S_TX_RTSBAD: HWSTAT(RTSFailures); case S_TX_NOACK: HWSTAT(AckFailures); case S_RX_DUPLICATE: HWSTAT(RxDuplicateFrames); case S_RX_FCS: HWSTAT(FCSErrorCount); case S_TX_WATCHDOG: HWSTAT(TxWatchDogTimeouts); case S_RX_OVERFLOW: HWSTAT(RxOverflows); case S_RX_FRAGERROR: HWSTAT(RxFragErrors); case S_RX_MEMERROR: HWSTAT(RxMemErrors); case S_PTRERROR: HWSTAT(PointerErrors); case S_TX_UNDERFLOW: HWSTAT(TxUnderflows); case S_TX_DONE: HWSTAT(TxDone); case S_TX_DONEBUFPUT: HWSTAT(TxDoneBufPut); case S_TX_WAIT4BUF: HWSTAT(Wait4TxBuf); case S_TX_ATTEMPTS: HWSTAT(TxAttempts); case S_TX_SUCCESS: HWSTAT(TxSuccesses); case S_TX_FRAGS: HWSTAT(TxFragments); case S_TX_MCAST: HWSTAT(TxMulticasts); case S_RX_NONCTL: HWSTAT(RxNonCtlPkts); case S_RX_MCAST: HWSTAT(RxMulticasts); case S_RX_UNDECRYPT: HWSTAT(RxUndecryptableFrames); case S_RX_ICVERROR: HWSTAT(RxICVErrors); case S_RX_EXCLUDE: HWSTAT(RxExcludedFrames); case S_TX_MGMT: STAT(tx_mgmt); case S_TX_DISCARD: STAT(tx_discard); case S_TX_QSTOP: STAT(tx_qstop); case S_TX_ENCAP: STAT(tx_encap); case S_TX_NOMBUF: STAT(tx_nombuf); case S_TX_LINEAR: STAT(tx_linear); case S_TX_NODATA: STAT(tx_nodata); case S_TX_BUSDMA: STAT(tx_busdma); case S_TX_SHORTPRE: STAT(tx_shortpre); case S_TX_NOHEADROOM: STAT(tx_noheadroom); case S_TX_BADFRAMETYPE: STAT(tx_badframetype); case S_RX_CRYPTO_ERR: STAT(rx_crypto); case S_RX_TKIPMIC: STAT(rx_tkipmic); case S_RX_NODMABUF: STAT(rx_nodmabuf); case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing); case S_RX_NOMBUF: STAT(rx_nombuf); case S_RX_BUSDMA: STAT(rx_busdma); case S_AMPDU_NOSTREAM: STAT(ampdu_nostream); case S_AMPDU_REJECT: STAT(ampdu_reject); case S_ADDBA_NOSTREAM: STAT(addba_nostream); case S_TX_TSO: STAT(tx_tso); case S_TSO_BADETH: STAT(tso_badeth); case S_TSO_NOHDR: STAT(tso_nohdr); case S_TSO_BADSPLIT: STAT(tso_badsplit); case S_BAWATCHDOG: STAT(bawatchdog); case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound); case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty); case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed); case S_RADARDETECT: STAT(radardetect); case S_RX_RSSI: snprintf(b, bs, "%d", wf->cur.mst_rx_rssi); return 1; case S_ANT_TX0: TXANT(0); case S_ANT_TX1: TXANT(1); case S_ANT_TX2: TXANT(2); case S_ANT_TX3: TXANT(3); case S_ANT_RX0: RXANT(0); case S_ANT_RX1: RXANT(1); case S_ANT_RX2: RXANT(2); case S_ANT_RX3: RXANT(3); case S_RX_NOISE: snprintf(b, bs, "%d", wf->cur.mst_rx_noise); return 1; case S_RX_SIGNAL: snprintf(b, bs, "%d", wf->cur.mst_rx_rssi + wf->cur.mst_rx_noise); return 1; } b[0] = '\0'; return 0; #undef RXANT #undef TXANT #undef HWSTAT #undef STAT } static int mwl_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->total.mst_##x); return 1 #define HWSTAT(x) \ snprintf(b, bs, "%u", wf->total.hw_stats.x); return 1 #define TXANT(x) \ snprintf(b, bs, "%u", wf->total.mst_ant_tx[x]); return 1 #define RXANT(x) \ snprintf(b, bs, "%u", wf->total.mst_ant_rx[x]); return 1 switch (s) { case S_INPUT: snprintf(b, bs, "%lu", (u_long)wf->total.mst_rx_packets); return 1; case S_OUTPUT: snprintf(b, bs, "%lu", (u_long) wf->total.mst_tx_packets); return 1; case S_RATE: setrate(b, bs, wf->total.mst_tx_rate); return 1; case S_TX_RETRY: HWSTAT(TxRetrySuccesses); case S_TX_MRETRY: HWSTAT(TxMultipleRetrySuccesses); case S_TX_RTSGOOD: HWSTAT(RTSSuccesses); case S_TX_RTSBAD: HWSTAT(RTSFailures); case S_TX_NOACK: HWSTAT(AckFailures); case S_RX_DUPLICATE: HWSTAT(RxDuplicateFrames); case S_RX_FCS: HWSTAT(FCSErrorCount); case S_TX_WATCHDOG: HWSTAT(TxWatchDogTimeouts); case S_RX_OVERFLOW: HWSTAT(RxOverflows); case S_RX_FRAGERROR: HWSTAT(RxFragErrors); case S_RX_MEMERROR: HWSTAT(RxMemErrors); case S_PTRERROR: HWSTAT(PointerErrors); case S_TX_UNDERFLOW: HWSTAT(TxUnderflows); case S_TX_DONE: HWSTAT(TxDone); case S_TX_DONEBUFPUT: HWSTAT(TxDoneBufPut); case S_TX_WAIT4BUF: HWSTAT(Wait4TxBuf); case S_TX_ATTEMPTS: HWSTAT(TxAttempts); case S_TX_SUCCESS: HWSTAT(TxSuccesses); case S_TX_FRAGS: HWSTAT(TxFragments); case S_TX_MCAST: HWSTAT(TxMulticasts); case S_RX_NONCTL: HWSTAT(RxNonCtlPkts); case S_RX_MCAST: HWSTAT(RxMulticasts); case S_RX_UNDECRYPT: HWSTAT(RxUndecryptableFrames); case S_RX_ICVERROR: HWSTAT(RxICVErrors); case S_RX_EXCLUDE: HWSTAT(RxExcludedFrames); case S_TX_MGMT: STAT(tx_mgmt); case S_TX_DISCARD: STAT(tx_discard); case S_TX_QSTOP: STAT(tx_qstop); case S_TX_ENCAP: STAT(tx_encap); case S_TX_NOMBUF: STAT(tx_nombuf); case S_TX_LINEAR: STAT(tx_linear); case S_TX_NODATA: STAT(tx_nodata); case S_TX_BUSDMA: STAT(tx_busdma); case S_TX_SHORTPRE: STAT(tx_shortpre); case S_TX_NOHEADROOM: STAT(tx_noheadroom); case S_TX_BADFRAMETYPE: STAT(tx_badframetype); case S_RX_CRYPTO_ERR: STAT(rx_crypto); case S_RX_TKIPMIC: STAT(rx_tkipmic); case S_RX_NODMABUF: STAT(rx_nodmabuf); case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing); case S_RX_NOMBUF: STAT(rx_nombuf); case S_RX_BUSDMA: STAT(rx_busdma); case S_AMPDU_NOSTREAM: STAT(ampdu_nostream); case S_AMPDU_REJECT: STAT(ampdu_reject); case S_ADDBA_NOSTREAM: STAT(addba_nostream); case S_TX_TSO: STAT(tx_tso); case S_TSO_BADETH: STAT(tso_badeth); case S_TSO_NOHDR: STAT(tso_nohdr); case S_TSO_BADSPLIT: STAT(tso_badsplit); case S_BAWATCHDOG: STAT(bawatchdog); case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound); case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty); case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed); case S_RADARDETECT: STAT(radardetect); case S_RX_RSSI: snprintf(b, bs, "%d", wf->total.mst_rx_rssi); return 1; case S_ANT_TX0: TXANT(0); case S_ANT_TX1: TXANT(1); case S_ANT_TX2: TXANT(2); case S_ANT_TX3: TXANT(3); case S_ANT_RX0: RXANT(0); case S_ANT_RX1: RXANT(1); case S_ANT_RX2: RXANT(2); case S_ANT_RX3: RXANT(3); case S_RX_NOISE: snprintf(b, bs, "%d", wf->total.mst_rx_noise); return 1; case S_RX_SIGNAL: snprintf(b, bs, "%d", wf->total.mst_rx_rssi + wf->total.mst_rx_noise); return 1; } b[0] = '\0'; return 0; #undef RXANT #undef TXANT #undef HWSTAT #undef STAT } static void mwl_print_verbose(struct bsdstat *sf, FILE *fd) { struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; const struct fmt *f; char s[32]; const char *indent; int i, width; width = 0; for (i = 0; i < S_LAST; i++) { f = &sf->stats[i]; if (f->width > width) width = f->width; } for (i = 0; i < S_LAST; i++) { f = &sf->stats[i]; if (mwl_get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) { indent = ""; fprintf(fd, "%s%-*s %s\n", indent, width, s, f->desc); } } fprintf(fd, "Antenna profile:\n"); for (i = 0; i < 4; i++) if (wf->total.mst_ant_rx[i] || wf->total.mst_ant_tx[i]) fprintf(fd, "[%u] tx %8u rx %8u\n", i, wf->total.mst_ant_tx[i], wf->total.mst_ant_rx[i]); } BSDSTAT_DEFINE_BOUNCE(mwlstatfoo) struct mwlstatfoo * mwlstats_new(const char *ifname, const char *fmtstring) { -#define N(a) (sizeof(a) / sizeof(a[0])) struct mwlstatfoo_p *wf; wf = calloc(1, sizeof(struct mwlstatfoo_p)); if (wf != NULL) { - bsdstat_init(&wf->base.base, "mwlstats", mwlstats, N(mwlstats)); + bsdstat_init(&wf->base.base, "mwlstats", mwlstats, + nitems(mwlstats)); /* override base methods */ wf->base.base.collect_cur = mwl_collect_cur; wf->base.base.collect_tot = mwl_collect_tot; wf->base.base.get_curstat = mwl_get_curstat; wf->base.base.get_totstat = mwl_get_totstat; wf->base.base.update_tot = mwl_update_tot; wf->base.base.print_verbose = mwl_print_verbose; /* setup bounce functions for public methods */ BSDSTAT_BOUNCE(wf, mwlstatfoo); /* setup our public methods */ wf->base.setifname = mwl_setifname; #if 0 wf->base.setstamac = wlan_setstamac; #endif wf->s = socket(AF_INET, SOCK_DGRAM, 0); if (wf->s < 0) err(1, "socket"); mwl_setifname(&wf->base, ifname); wf->base.setfmt(&wf->base, fmtstring); } return &wf->base; -#undef N } Index: head/tools/tools/net80211/wlanstats/main.c =================================================================== --- head/tools/tools/net80211/wlanstats/main.c (revision 287296) +++ head/tools/tools/net80211/wlanstats/main.c (revision 287297) @@ -1,286 +1,285 @@ /*- * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * wlanstats [-i interface] * (default interface is wlan0). */ -#include +#include #include + #include #include -#include -#include -#include -#include #include +#include +#include +#include #include +#include #include "wlanstats.h" static struct { const char *tag; const char *fmt; } tags[] = { { "default", "input,rx_mgmt,output,rx_badkeyid,scan_active,scan_bg,bmiss,rssi,noise,rate" }, { "ampdu", "input,output,ampdu_reorder,ampdu_oor,rx_dup,ampdu_flush,ampdu_move," "ampdu_drop,ampdu_bar,ampdu_baroow,ampdu_barmove,ampdu_bartx," "ampdu_bartxfail,ampdu_bartxretry,rssi,rate" }, }; static const char * getfmt(const char *tag) { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; - for (i = 0; i < N(tags); i++) + for (i = 0; i < nitems(tags); i++) if (strcasecmp(tags[i].tag, tag) == 0) return tags[i].fmt; return tag; -#undef N } static int signalled; static void catchalarm(int signo __unused) { signalled = 1; } #if 0 static void print_sta_stats(FILE *fd, const u_int8_t macaddr[IEEE80211_ADDR_LEN]) { #define STAT(x,fmt) \ if (ns->ns_##x) { fprintf(fd, "%s" #x " " fmt, sep, ns->ns_##x); sep = " "; } struct ieee80211req ireq; struct ieee80211req_sta_stats stats; const struct ieee80211_nodestats *ns = &stats.is_stats; const char *sep; (void) memset(&ireq, 0, sizeof(ireq)); (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name)); ireq.i_type = IEEE80211_IOC_STA_STATS; ireq.i_data = &stats; ireq.i_len = sizeof(stats); memcpy(stats.is_u.macaddr, macaddr, IEEE80211_ADDR_LEN); if (ioctl(s, SIOCG80211, &ireq) < 0) err(1, "unable to get station stats for %s", ether_ntoa((const struct ether_addr*) macaddr)); fprintf(fd, "%s:\n", ether_ntoa((const struct ether_addr*) macaddr)); sep = "\t"; STAT(rx_data, "%u"); STAT(rx_mgmt, "%u"); STAT(rx_ctrl, "%u"); STAT(rx_beacons, "%u"); STAT(rx_proberesp, "%u"); STAT(rx_ucast, "%u"); STAT(rx_mcast, "%u"); STAT(rx_bytes, "%llu"); STAT(rx_dup, "%u"); STAT(rx_noprivacy, "%u"); STAT(rx_wepfail, "%u"); STAT(rx_demicfail, "%u"); STAT(rx_decap, "%u"); STAT(rx_defrag, "%u"); STAT(rx_disassoc, "%u"); STAT(rx_deauth, "%u"); STAT(rx_decryptcrc, "%u"); STAT(rx_unauth, "%u"); STAT(rx_unencrypted, "%u"); fprintf(fd, "\n"); sep = "\t"; STAT(tx_data, "%u"); STAT(tx_mgmt, "%u"); STAT(tx_probereq, "%u"); STAT(tx_ucast, "%u"); STAT(tx_mcast, "%u"); STAT(tx_bytes, "%llu"); STAT(tx_novlantag, "%u"); STAT(tx_vlanmismatch, "%u"); fprintf(fd, "\n"); sep = "\t"; STAT(tx_assoc, "%u"); STAT(tx_assoc_fail, "%u"); STAT(tx_auth, "%u"); STAT(tx_auth_fail, "%u"); STAT(tx_deauth, "%u"); STAT(tx_deauth_code, "%llu"); STAT(tx_disassoc, "%u"); STAT(tx_disassoc_code, "%u"); fprintf(fd, "\n"); #undef STAT } #endif void usage(void) { printf("wlanstats: [-ah] [-i ifname] [-l] [-o fmt] [interval]\n"); } int main(int argc, char *argv[]) { struct wlanstatfoo *wf; struct ether_addr *ea; const uint8_t *mac = NULL; const char *ifname; int allnodes = 0; int c, mode; ifname = getenv("WLAN"); if (ifname == NULL) ifname = "wlan0"; wf = wlanstats_new(ifname, getfmt("default")); while ((c = getopt(argc, argv, "ahi:lm:o:")) != -1) { switch (c) { case 'a': allnodes++; break; case 'h': usage(); exit(0); case 'i': wf->setifname(wf, optarg); break; case 'l': wf->print_fields(wf, stdout); return 0; case 'm': ea = ether_aton(optarg); if (!ea) errx(1, "%s: invalid ethernet address", optarg); mac = ea->octet; break; case 'o': wf->setfmt(wf, getfmt(optarg)); break; default: usage(); exit(1); /*NOTREACHED*/ } } argc -= optind; argv += optind; mode = wf->getopmode(wf); wf->setstamac(wf, mac); if (argc > 0) { u_long interval = strtoul(argv[0], NULL, 0); int line, omask; if (interval < 1) interval = 1; signal(SIGALRM, catchalarm); signalled = 0; alarm(interval); banner: wf->print_header(wf, stdout); line = 0; loop: if (line != 0) { wf->collect_cur(wf); wf->print_current(wf, stdout); wf->update_tot(wf); } else { wf->collect_tot(wf); wf->print_total(wf, stdout); } fflush(stdout); omask = sigblock(sigmask(SIGALRM)); if (!signalled) sigpause(0); sigsetmask(omask); signalled = 0; alarm(interval); line++; /* refresh every display in case sta roams */ if (mac == NULL && mode == IEEE80211_M_STA) wf->setstamac(wf, NULL); if (line == 21) /* XXX tty line count */ goto banner; else goto loop; /*NOTREACHED*/ #if 0 } else if (allnodes) { struct ieee80211req_sta_info *si; union { struct ieee80211req_sta_req req; uint8_t buf[24*1024]; } u; uint8_t *cp; struct ieee80211req ireq; int len; /* * Retrieve station/neighbor table and print stats for each. */ (void) memset(&ireq, 0, sizeof(ireq)); (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name)); ireq.i_type = IEEE80211_IOC_STA_INFO; memset(&u.req.macaddr, 0xff, sizeof(u.req.macaddr)); ireq.i_data = &u; ireq.i_len = sizeof(u); if (ioctl(s, SIOCG80211, &ireq) < 0) err(1, "unable to get station information"); len = ireq.i_len; if (len >= sizeof(struct ieee80211req_sta_info)) { cp = u.req.info; do { si = (struct ieee80211req_sta_info *) cp; if (si->isi_len < sizeof(*si)) break; print_sta_stats(stdout, si->isi_macaddr); cp += si->isi_len, len -= si->isi_len; } while (len >= sizeof(struct ieee80211req_sta_info)); } #endif } else { wf->collect_tot(wf); wf->print_verbose(wf, stdout); } return 0; } Index: head/tools/tools/net80211/wlanstats/wlanstats.c =================================================================== --- head/tools/tools/net80211/wlanstats/wlanstats.c (revision 287296) +++ head/tools/tools/net80211/wlanstats/wlanstats.c (revision 287297) @@ -1,1034 +1,1031 @@ /*- * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * net80211 statistics class. */ -#include + +#include #include #include #include + #include #include #include #include #include +#include +#include +#include #include #include -#include #include #include -#include -#include #include "../../../../sys/net80211/ieee80211_ioctl.h" #include "wlanstats.h" #ifndef IEEE80211_ADDR_COPY #define IEEE80211_ADDR_COPY(dst, src) memcpy(dst, src, IEEE80211_ADDR_LEN) #define IEEE80211_ADDR_EQ(a1,a2) (memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0) #endif #define AFTER(prev) ((prev)+1) static const struct fmt wlanstats[] = { #define S_RX_BADVERSION 0 { 5, "rx_badversion", "bvers", "rx frame with bad version" }, #define S_RX_TOOSHORT AFTER(S_RX_BADVERSION) { 5, "rx_tooshort", "2short", "rx frame too short" }, #define S_RX_WRONGBSS AFTER(S_RX_TOOSHORT) { 5, "rx_wrongbss", "wrbss", "rx from wrong bssid" }, #define S_RX_DUP AFTER(S_RX_WRONGBSS) { 5, "rx_dup", "rxdup", "rx discard 'cuz dup" }, #define S_RX_WRONGDIR AFTER(S_RX_DUP) { 5, "rx_wrongdir", "wrdir", "rx w/ wrong direction" }, #define S_RX_MCASTECHO AFTER(S_RX_WRONGDIR) { 5, "rx_mcastecho", "mecho", "rx discard 'cuz mcast echo" }, #define S_RX_NOTASSOC AFTER(S_RX_MCASTECHO) { 6, "rx_notassoc", "!assoc", "rx discard 'cuz sta !assoc" }, #define S_RX_NOPRIVACY AFTER(S_RX_NOTASSOC) { 6, "rx_noprivacy", "nopriv", "rx w/ wep but privacy off" }, #define S_RX_UNENCRYPTED AFTER(S_RX_NOPRIVACY) { 6, "rx_unencrypted", "unencr", "rx w/o wep and privacy on" }, #define S_RX_WEPFAIL AFTER(S_RX_UNENCRYPTED) { 7, "rx_wepfail", "wepfail", "rx wep processing failed" }, #define S_RX_DECAP AFTER(S_RX_WEPFAIL) { 5, "rx_decap", "decap", "rx decapsulation failed" }, #define S_RX_MGTDISCARD AFTER(S_RX_DECAP) { 8, "rx_mgtdiscard", "mgtdiscard", "rx discard mgt frames" }, #define S_RX_CTL AFTER(S_RX_MGTDISCARD) { 5, "rx_ctl", "ctl", "rx ctrl frames" }, #define S_RX_BEACON AFTER(S_RX_CTL) { 6, "rx_beacon", "beacon", "rx beacon frames" }, #define S_RX_RSTOOBIG AFTER(S_RX_BEACON) { 6, "rx_rstoobig", "rs2big", "rx rate set truncated" }, #define S_RX_ELEM_MISSING AFTER(S_RX_RSTOOBIG) { 6, "rx_elem_missing","iemiss", "rx required element missing" }, #define S_RX_ELEM_TOOBIG AFTER(S_RX_ELEM_MISSING) { 6, "rx_elem_toobig", "ie2big", "rx element too big" }, #define S_RX_ELEM_TOOSMALL AFTER(S_RX_ELEM_TOOBIG) { 7, "rx_elem_toosmall","ie2small","rx element too small" }, #define S_RX_ELEM_UNKNOWN AFTER(S_RX_ELEM_TOOSMALL) { 5, "rx_elem_unknown","ieunk", "rx element unknown" }, #define S_RX_BADCHAN AFTER(S_RX_ELEM_UNKNOWN) { 6, "rx_badchan", "badchan", "rx frame w/ invalid chan" }, #define S_RX_CHANMISMATCH AFTER(S_RX_BADCHAN) { 5, "rx_chanmismatch","chanmismatch", "rx frame chan mismatch" }, #define S_RX_NODEALLOC AFTER(S_RX_CHANMISMATCH) { 5, "rx_nodealloc", "nodealloc", "nodes allocated (rx)" }, #define S_RX_SSIDMISMATCH AFTER(S_RX_NODEALLOC) { 5, "rx_ssidmismatch","ssidmismatch", "rx frame ssid mismatch" }, #define S_RX_AUTH_UNSUPPORTED AFTER(S_RX_SSIDMISMATCH) { 5, "rx_auth_unsupported","auth_unsupported", "rx w/ unsupported auth alg" }, #define S_RX_AUTH_FAIL AFTER(S_RX_AUTH_UNSUPPORTED) { 5, "rx_auth_fail", "auth_fail", "rx sta auth failure" }, #define S_RX_AUTH_FAIL_CODE AFTER(S_RX_AUTH_FAIL) { 5, "rx_auth_fail_code","auth_fail_code", "last rx auth failure reason" }, #define S_RX_AUTH_COUNTERMEASURES AFTER(S_RX_AUTH_FAIL_CODE) { 5, "rx_auth_countermeasures", "auth_countermeasures", "rx sta auth failure 'cuz of TKIP countermeasures" }, #define S_RX_ASSOC_BSS AFTER(S_RX_AUTH_COUNTERMEASURES) { 5, "rx_assoc_bss", "assoc_bss", "rx assoc from wrong bssid" }, #define S_RX_ASSOC_NOTAUTH AFTER(S_RX_ASSOC_BSS) { 5, "rx_assoc_notauth","assoc_notauth", "rx assoc w/o auth" }, #define S_RX_ASSOC_CAPMISMATCH AFTER(S_RX_ASSOC_NOTAUTH) { 5, "rx_assoc_capmismatch","assoc_capmismatch", "rx assoc w/ cap mismatch" }, #define S_RX_ASSOC_NORATE AFTER(S_RX_ASSOC_CAPMISMATCH) { 5, "rx_assoc_norate","assoc_norate", "rx assoc w/ no rate match" }, #define S_RX_ASSOC_BADWPAIE AFTER(S_RX_ASSOC_NORATE) { 5, "rx_assoc_badwpaie","assoc_badwpaie", "rx assoc w/ bad WPA IE" }, #define S_RX_DEAUTH AFTER(S_RX_ASSOC_BADWPAIE) { 5, "rx_deauth", "deauth", "rx deauthentication" }, #define S_RX_DEAUTH_CODE AFTER(S_RX_DEAUTH) { 5, "rx_deauth_code","deauth_code", "last rx deauth reason" }, #define S_RX_DISASSOC AFTER(S_RX_DEAUTH_CODE) { 5, "rx_disassoc", "disassoc", "rx disassociation" }, #define S_RX_DISASSOC_CODE AFTER(S_RX_DISASSOC) { 5, "rx_disassoc_code","disassoc_code", "last rx disassoc reason" }, #define S_BMISS AFTER(S_RX_DISASSOC_CODE) { 5, "bmiss", "bmiss", "beacon miss events handled" }, #define S_RX_BADSUBTYPE AFTER(S_BMISS) { 5, "rx_badsubtype", "badsubtype", "rx frame w/ unknown subtype" }, #define S_RX_NOBUF AFTER(S_RX_BADSUBTYPE) { 5, "rx_nobuf", "nobuf", "rx failed for lack of mbuf" }, #define S_RX_DECRYPTCRC AFTER(S_RX_NOBUF) { 5, "rx_decryptcrc", "decryptcrc", "rx decrypt failed on crc" }, #define S_RX_AHDEMO_MGT AFTER(S_RX_DECRYPTCRC) { 5, "rx_ahdemo_mgt", "ahdemo_mgt", "rx discard mgmt frame received in ahdoc demo mode" }, #define S_RX_BAD_AUTH AFTER(S_RX_AHDEMO_MGT) { 5, "rx_bad_auth", "bad_auth", "rx bad authentication request" }, #define S_RX_UNAUTH AFTER(S_RX_BAD_AUTH) { 5, "rx_unauth", "unauth", "rx discard 'cuz port unauthorized" }, #define S_RX_BADKEYID AFTER(S_RX_UNAUTH) { 5, "rx_badkeyid", "rxkid", "rx w/ incorrect keyid" }, #define S_RX_CCMPREPLAY AFTER(S_RX_BADKEYID) { 5, "rx_ccmpreplay", "ccmpreplay", "rx seq# violation (CCMP)" }, #define S_RX_CCMPFORMAT AFTER(S_RX_CCMPREPLAY) { 5, "rx_ccmpformat", "ccmpformat", "rx format bad (CCMP)" }, #define S_RX_CCMPMIC AFTER(S_RX_CCMPFORMAT) { 5, "rx_ccmpmic", "ccmpmic", "rx MIC check failed (CCMP)" }, #define S_RX_TKIPREPLAY AFTER(S_RX_CCMPMIC) { 5, "rx_tkipreplay", "tkipreplay", "rx seq# violation (TKIP)" }, #define S_RX_TKIPFORMAT AFTER(S_RX_TKIPREPLAY) { 5, "rx_tkipformat", "tkipformat", "rx format bad (TKIP)" }, #define S_RX_TKIPMIC AFTER(S_RX_TKIPFORMAT) { 5, "rx_tkipmic", "tkipmic", "rx MIC check failed (TKIP)" }, #define S_RX_TKIPICV AFTER(S_RX_TKIPMIC) { 5, "rx_tkipicv", "tkipicv", "rx ICV check failed (TKIP)" }, #define S_RX_BADCIPHER AFTER(S_RX_TKIPICV) { 5, "rx_badcipher", "badcipher", "rx failed 'cuz bad cipher/key type" }, #define S_RX_NOCIPHERCTX AFTER(S_RX_BADCIPHER) { 5, "rx_nocipherctx", "nocipherctx", "rx failed 'cuz key/cipher ctx not setup" }, #define S_RX_ACL AFTER(S_RX_NOCIPHERCTX) { 5, "rx_acl", "acl", "rx discard 'cuz acl policy" }, #define S_TX_NOBUF AFTER(S_RX_ACL) { 5, "tx_nobuf", "nobuf", "tx failed for lack of mbuf" }, #define S_TX_NONODE AFTER(S_TX_NOBUF) { 5, "tx_nonode", "nonode", "tx failed for no node" }, #define S_TX_UNKNOWNMGT AFTER(S_TX_NONODE) { 5, "tx_unknownmgt", "unknownmgt", "tx of unknown mgt frame" }, #define S_TX_BADCIPHER AFTER(S_TX_UNKNOWNMGT) { 5, "tx_badcipher", "badcipher", "tx failed 'cuz bad ciper/key type" }, #define S_TX_NODEFKEY AFTER(S_TX_BADCIPHER) { 5, "tx_nodefkey", "nodefkey", "tx failed 'cuz no defkey" }, #define S_TX_NOHEADROOM AFTER(S_TX_NODEFKEY) { 5, "tx_noheadroom", "noheadroom", "tx failed 'cuz no space for crypto hdrs" }, #define S_TX_FRAGFRAMES AFTER(S_TX_NOHEADROOM) { 5, "tx_fragframes", "fragframes", "tx frames fragmented" }, #define S_TX_FRAGS AFTER(S_TX_FRAGFRAMES) { 5, "tx_frags", "frags", "tx frags generated" }, #define S_SCAN_ACTIVE AFTER(S_TX_FRAGS) { 5, "scan_active", "ascan", "active scans started" }, #define S_SCAN_PASSIVE AFTER(S_SCAN_ACTIVE) { 5, "scan_passive", "pscan", "passive scans started" }, #define S_SCAN_BG AFTER(S_SCAN_PASSIVE) { 5, "scan_bg", "bgscn", "background scans started" }, #define S_NODE_TIMEOUT AFTER(S_SCAN_BG) { 5, "node_timeout", "node_timeout", "nodes timed out for inactivity" }, #define S_CRYPTO_NOMEM AFTER(S_NODE_TIMEOUT) { 5, "crypto_nomem", "crypto_nomem", "cipher context malloc failed" }, #define S_CRYPTO_TKIP AFTER(S_CRYPTO_NOMEM) { 5, "crypto_tkip", "crypto_tkip", "tkip crypto done in s/w" }, #define S_CRYPTO_TKIPENMIC AFTER(S_CRYPTO_TKIP) { 5, "crypto_tkipenmic","crypto_tkipenmic", "tkip tx MIC done in s/w" }, #define S_CRYPTO_TKIPDEMIC AFTER(S_CRYPTO_TKIPENMIC) { 5, "crypto_tkipdemic","crypto_tkipdemic", "tkip rx MIC done in s/w" }, #define S_CRYPTO_TKIPCM AFTER(S_CRYPTO_TKIPDEMIC) { 5, "crypto_tkipcm", "crypto_tkipcm", "tkip dropped frames 'cuz of countermeasures" }, #define S_CRYPTO_CCMP AFTER(S_CRYPTO_TKIPCM) { 5, "crypto_ccmp", "crypto_ccmp", "ccmp crypto done in s/w" }, #define S_CRYPTO_WEP AFTER(S_CRYPTO_CCMP) { 5, "crypto_wep", "crypto_wep", "wep crypto done in s/w" }, #define S_CRYPTO_SETKEY_CIPHER AFTER(S_CRYPTO_WEP) { 5, "crypto_setkey_cipher", "crypto_setkey_cipher","setkey failed 'cuz cipher rejected data" }, #define S_CRYPTO_SETKEY_NOKEY AFTER(S_CRYPTO_SETKEY_CIPHER) { 5, "crypto_setkey_nokey", "crypto_setkey_nokey","setkey failed 'cuz no key index" }, #define S_CRYPTO_DELKEY AFTER(S_CRYPTO_SETKEY_NOKEY) { 5, "crypto_delkey", "crypto_delkey", "driver key delete failed" }, #define S_CRYPTO_BADCIPHER AFTER(S_CRYPTO_DELKEY) { 5, "crypto_badcipher","crypto_badcipher", "setkey failed 'cuz unknown cipher" }, #define S_CRYPTO_NOCIPHER AFTER(S_CRYPTO_BADCIPHER) { 5, "crypto_nocipher","crypto_nocipher", "setkey failed 'cuz cipher module unavailable" }, #define S_CRYPTO_ATTACHFAIL AFTER(S_CRYPTO_NOCIPHER) { 5, "crypto_attachfail","crypto_attachfail", "setkey failed 'cuz cipher attach failed" }, #define S_CRYPTO_SWFALLBACK AFTER(S_CRYPTO_ATTACHFAIL) { 5, "crypto_swfallback","crypto_swfallback", "crypto fell back to s/w implementation" }, #define S_CRYPTO_KEYFAIL AFTER(S_CRYPTO_SWFALLBACK) { 5, "crypto_keyfail", "crypto_keyfail", "setkey failed 'cuz driver key alloc failed" }, #define S_CRYPTO_ENMICFAIL AFTER(S_CRYPTO_KEYFAIL) { 5, "crypto_enmicfail","crypto_enmicfail", "enmic failed (may be mbuf exhaustion)" }, #define S_IBSS_CAPMISMATCH AFTER(S_CRYPTO_ENMICFAIL) { 5, "ibss_capmismatch","ibss_capmismatch", "ibss merge faied 'cuz capabilities mismatch" }, #define S_IBSS_NORATE AFTER(S_IBSS_CAPMISMATCH) { 5, "ibss_norate", "ibss_norate", "ibss merge faied 'cuz rate set mismatch" }, #define S_PS_UNASSOC AFTER(S_IBSS_NORATE) { 5, "ps_unassoc", "ps_unassoc", "ps-poll received for unassociated station" }, #define S_PS_BADAID AFTER(S_PS_UNASSOC) { 5, "ps_badaid", "ps_badaid", "ps-poll received with invalid association id" }, #define S_PS_QEMPTY AFTER(S_PS_BADAID) { 5, "ps_qempty", "ps_qempty", "ps-poll received with nothing to send" }, #define S_FF_BADHDR AFTER(S_PS_QEMPTY) { 5, "ff_badhdr", "ff_badhdr", "fast frame rx'd w/ bad hdr" }, #define S_FF_TOOSHORT AFTER(S_FF_BADHDR) { 5, "ff_tooshort", "ff_tooshort", "fast frame rx decap error" }, #define S_FF_SPLIT AFTER(S_FF_TOOSHORT) { 5, "ff_split", "ff_split", "fast frame rx split error" }, #define S_FF_DECAP AFTER(S_FF_SPLIT) { 5, "ff_decap", "ff_decap", "fast frames decap'd" }, #define S_FF_ENCAP AFTER(S_FF_DECAP) { 5, "ff_encap", "ff_encap", "fast frames encap'd for tx" }, #define S_FF_ENCAPFAIL AFTER(S_FF_ENCAP) { 5, "ff_encapfail", "ff_encapfail", "fast frames encap failed" }, #define S_RX_BADBINTVAL AFTER(S_FF_ENCAPFAIL) { 5, "rx_badbintval", "rx_badbintval","rx frame with bogus beacon interval" }, #define S_RX_MGMT AFTER(S_RX_BADBINTVAL) { 8, "rx_mgmt", "mgmt", "rx management frames" }, #define S_RX_DEMICFAIL AFTER(S_RX_MGMT) { 5, "rx_demicfail", "rx_demicfail", "rx demic failed" }, #define S_RX_DEFRAG AFTER(S_RX_DEMICFAIL) { 5, "rx_defrag", "rx_defrag", "rx defragmentation failed" }, #define S_RX_ACTION AFTER(S_RX_DEFRAG) { 5, "rx_action", "rx_action", "rx action frames" }, #define S_AMSDU_TOOSHORT AFTER(S_RX_ACTION) { 8, "amsdu_tooshort", "tooshort","A-MSDU rx decap error" }, #define S_AMSDU_SPLIT AFTER(S_AMSDU_TOOSHORT) { 8, "amsdu_split", "split", "A-MSDU rx failed on frame split" }, #define S_AMSDU_DECAP AFTER(S_AMSDU_SPLIT) { 8, "amsdu_decap", "decap", "A-MSDU frames received" }, #define S_AMSDU_ENCAP AFTER(S_AMSDU_DECAP) { 8, "amsdu_encap", "encap", "A-MSDU frames transmitted" }, #define S_AMPDU_REORDER AFTER(S_AMSDU_ENCAP) { 8, "ampdu_reorder", "reorder","A-MPDU frames held in reorder q" }, #define S_AMPDU_FLUSH AFTER(S_AMPDU_REORDER) { 8, "ampdu_flush", "flush", "A-MPDU frames sent up from reorder q" }, #define S_AMPDU_BARBAD AFTER(S_AMPDU_FLUSH) { 6, "ampdu_barbad", "barbad", "A-MPDU BAR rx before ADDBA exchange (or disabled with net.link.ieee80211)" }, #define S_AMPDU_BAROOW AFTER(S_AMPDU_BARBAD) { 6, "ampdu_baroow", "baroow", "A-MPDU BAR rx out of BA window" }, #define S_AMPDU_BARMOVE AFTER(S_AMPDU_BAROOW) { 8, "ampdu_barmove", "barmove","A-MPDU BAR rx moved BA window" }, #define S_AMPDU_BAR AFTER(S_AMPDU_BARMOVE) { 8, "ampdu_bar", "rxbar", "A-MPDU BAR rx successful" }, #define S_AMPDU_MOVE AFTER(S_AMPDU_BAR) { 5, "ampdu_move", "move", "A-MPDU frame moved BA window" }, #define S_AMPDU_OOR AFTER(S_AMPDU_MOVE) { 8, "ampdu_oor", "oorx", "A-MPDU frames rx out-of-order" }, #define S_AMPDU_COPY AFTER(S_AMPDU_OOR) { 8, "ampdu_copy", "copy", "A-MPDU rx window slots copied" }, #define S_AMPDU_DROP AFTER(S_AMPDU_COPY) { 5, "ampdu_drop", "drop", "A-MPDU frames discarded for out of range seqno" }, #define S_AMPDU_AGE AFTER(S_AMPDU_DROP) { 5, "ampdu_age", "age", "A-MPDU frames sent up due to old age" }, #define S_AMPDU_STOP AFTER(S_AMPDU_AGE) { 5, "ampdu_stop", "stop", "A-MPDU streams stopped" }, #define S_AMPDU_STOP_FAILED AFTER(S_AMPDU_STOP) { 5, "ampdu_stop_failed","!stop", "A-MPDU stop requests failed 'cuz stream not running" }, #define S_ADDBA_REJECT AFTER(S_AMPDU_STOP_FAILED) { 5, "addba_reject", "reject", "ADDBA requests rejected 'cuz A-MPDU rx is disabled" }, #define S_ADDBA_NOREQUEST AFTER(S_ADDBA_REJECT) { 5, "addba_norequest","norequest","ADDBA response frames discarded because no ADDBA request was pending" }, #define S_ADDBA_BADTOKEN AFTER(S_ADDBA_NOREQUEST) { 5, "addba_badtoken", "badtoken","ADDBA response frames discarded 'cuz rx'd dialog token is wrong" }, #define S_TX_BADSTATE AFTER(S_ADDBA_BADTOKEN) { 4, "tx_badstate", "badstate", "tx failed 'cuz vap not in RUN state" }, #define S_TX_NOTASSOC AFTER(S_TX_BADSTATE) { 4, "tx_notassoc", "notassoc", "tx failed 'cuz dest sta not associated" }, #define S_TX_CLASSIFY AFTER(S_TX_NOTASSOC) { 4, "tx_classify", "classify", "tx packet classification failed" }, #define S_DWDS_MCAST AFTER(S_TX_CLASSIFY) { 8, "dwds_mcast", "dwds_mcast", "mcast frame transmitted on dwds vap discarded" }, #define S_DWDS_QDROP AFTER(S_DWDS_MCAST) { 8, "dwds_qdrop", "dwds_qdrop", "4-address frame discarded because dwds pending queue is full" }, #define S_HT_ASSOC_NOHTCAP AFTER(S_DWDS_QDROP) { 4, "ht_nohtcap", "ht_nohtcap", "non-HT station rejected in HT-only BSS" }, #define S_HT_ASSOC_DOWNGRADE AFTER(S_HT_ASSOC_NOHTCAP) { 4, "ht_downgrade", "ht_downgrade", "HT station downgraded to legacy operation" }, #define S_HT_ASSOC_NORATE AFTER(S_HT_ASSOC_DOWNGRADE) { 4, "ht_norate", "ht_norate", "HT station rejected because of HT rate set" }, #define S_MESH_WRONGMESH AFTER(S_HT_ASSOC_NORATE) { 4, "mesh_wrong", "mesh_wrong", "frame discarded because sender not a mesh sta" }, #define S_MESH_NOLINK AFTER(S_MESH_WRONGMESH) { 4, "mesh_nolink", "mesh_nolink", "frame discarded because link not established" }, #define S_MESH_FWD_TTL AFTER(S_MESH_NOLINK) { 4, "mesh_fwd_ttl", "mesh_fwd_ttl", "frame not forwarded because TTL zero" }, #define S_MESH_FWD_NOBUF AFTER(S_MESH_FWD_TTL) { 4, "mesh_fwd_nobuf", "mesh_fwd_nobuf", "frame not forwarded because mbuf could not be allocated" }, #define S_MESH_FWD_TOOSHORT AFTER(S_MESH_FWD_NOBUF) { 4, "mesh_fwd_tooshort", "mesh_fwd_tooshort", "frame not forwarded because too short to have 802.11 header" }, #define S_MESH_FWD_DISABLED AFTER(S_MESH_FWD_TOOSHORT) { 4, "mesh_fwd_disabled", "mesh_fwd_disabled", "frame not forwarded because administratively disabled" }, #define S_MESH_FWD_NOPATH AFTER(S_MESH_FWD_DISABLED) { 4, "mesh_fwd_nopath", "mesh_fwd_nopath", "frame not forwarded because no path found to destination" }, #define S_HWMP_WRONGSEQ AFTER(S_MESH_FWD_NOPATH) { 4, "hwmp_wrongseq", "hwmp_wrongseq", "frame discarded because mesh sequence number is invalid" }, #define S_HWMP_ROOTREQS AFTER(S_HWMP_WRONGSEQ) { 4, "hwmp_rootreqs", "hwmp_rootreqs", "root PREQ frames sent" }, #define S_HWMP_ROOTANN AFTER(S_HWMP_ROOTREQS) { 4, "hwmp_rootann", "hwmp_rootann", "root RANN frames received" }, #define S_MESH_BADAE AFTER(S_HWMP_ROOTANN) { 4, "mesh_badae", "mesh_badae", "frame discarded for bad AddressExtension (AE)" }, #define S_MESH_RTADDFAILED AFTER(S_MESH_BADAE) { 4, "mesh_rtadd", "mesh_rtadd", "mesh route add failed" }, #define S_MESH_NOTPROXY AFTER(S_MESH_RTADDFAILED) { 8, "mesh_notproxy", "mesh_notproxy","frame discarded because station not acting as a proxy" }, #define S_RX_BADALIGN AFTER(S_MESH_NOTPROXY) { 4, "rx_badalign", "rx_badalign","frame discarded because payload re-alignment failed" }, #define S_INPUT AFTER(S_RX_BADALIGN) { 8, "input", "input", "total data frames received" }, #define S_RX_UCAST AFTER(S_INPUT) { 8, "rx_ucast", "rx_ucast", "unicast data frames received" }, #define S_RX_MCAST AFTER(S_RX_UCAST) { 8, "rx_mcast", "rx_mcast", "multicast data frames received" }, #define S_OUTPUT AFTER(S_RX_MCAST) { 8, "output", "output", "total data frames transmit" }, #define S_TX_UCAST AFTER(S_OUTPUT) { 8, "tx_ucast", "tx_ucast", "unicast data frames sent" }, #define S_TX_MCAST AFTER(S_TX_UCAST) { 8, "tx_mcast", "tx_mcast", "multicast data frames sent" }, #define S_RATE AFTER(S_TX_MCAST) { 5, "rate", "rate", "current transmit rate" }, #define S_RSSI AFTER(S_RATE) { 5, "rssi", "rssi", "current rssi" }, #define S_NOISE AFTER(S_RSSI) { 5, "noise", "noise", "current noise floor (dBm)" }, #define S_SIGNAL AFTER(S_NOISE) { 5, "signal", "sig", "current signal (dBm)" }, #define S_BEACON_BAD AFTER(S_SIGNAL) { 9, "beacon_bad", "beaconbad", "bad beacons received" }, #define S_AMPDU_BARTX AFTER(S_BEACON_BAD) { 5, "ampdu_bartx", "bartx", "BAR frames sent" }, #define S_AMPDU_BARTX_FAIL AFTER(S_AMPDU_BARTX) { 9, "ampdu_bartxfail", "bartx_fail", "BAR frames failed to send" }, #define S_AMPDU_BARTX_RETRY AFTER(S_AMPDU_BARTX_FAIL) { 10, "ampdu_bartxretry", "bartx_retry", "BAR frames retried" }, }; struct wlanstatfoo_p { struct wlanstatfoo base; int s; int opmode; uint8_t mac[IEEE80211_ADDR_LEN]; struct ifreq ifr; struct ieee80211_stats cur; struct ieee80211_stats total; struct ieee80211req ireq; union { struct ieee80211req_sta_req info; char buf[1024]; } u_info; struct ieee80211req_sta_stats ncur; struct ieee80211req_sta_stats ntotal; }; static void wlan_setifname(struct wlanstatfoo *wf0, const char *ifname) { struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0; strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name)); strncpy(wf->ireq.i_name, ifname, sizeof (wf->ireq.i_name)); } static const char * wlan_getifname(struct wlanstatfoo *wf0) { struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0; return wf->ifr.ifr_name; } static int wlan_getopmode(struct wlanstatfoo *wf0) { struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0; if (wf->opmode == -1) { struct ifmediareq ifmr; memset(&ifmr, 0, sizeof(ifmr)); strlcpy(ifmr.ifm_name, wf->ifr.ifr_name, sizeof(ifmr.ifm_name)); if (ioctl(wf->s, SIOCGIFMEDIA, &ifmr) < 0) err(1, "%s (SIOCGIFMEDIA)", wf->ifr.ifr_name); if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { if (ifmr.ifm_current & IFM_FLAG0) wf->opmode = IEEE80211_M_AHDEMO; else wf->opmode = IEEE80211_M_IBSS; } else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) wf->opmode = IEEE80211_M_HOSTAP; else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) wf->opmode = IEEE80211_M_MONITOR; else wf->opmode = IEEE80211_M_STA; } return wf->opmode; } static void getlladdr(struct wlanstatfoo_p *wf) { const struct sockaddr_dl *sdl; struct ifaddrs *ifp, *p; if (getifaddrs(&ifp) != 0) err(1, "getifaddrs"); for (p = ifp; p != NULL; p = p->ifa_next) if (strcmp(p->ifa_name, wf->ifr.ifr_name) == 0 && p->ifa_addr->sa_family == AF_LINK) break; if (p == NULL) errx(1, "did not find link layer address for interface %s", wf->ifr.ifr_name); sdl = (const struct sockaddr_dl *) p->ifa_addr; IEEE80211_ADDR_COPY(wf->mac, LLADDR(sdl)); freeifaddrs(ifp); } static int getbssid(struct wlanstatfoo_p *wf) { wf->ireq.i_type = IEEE80211_IOC_BSSID; wf->ireq.i_data = wf->mac; wf->ireq.i_len = IEEE80211_ADDR_LEN; return ioctl(wf->s, SIOCG80211, &wf->ireq); } static void wlan_setstamac(struct wlanstatfoo *wf0, const uint8_t *mac) { static const uint8_t zeromac[IEEE80211_ADDR_LEN]; struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0; if (mac == NULL) { switch (wlan_getopmode(wf0)) { case IEEE80211_M_HOSTAP: case IEEE80211_M_MONITOR: getlladdr(wf); break; case IEEE80211_M_IBSS: case IEEE80211_M_AHDEMO: /* * NB: this may not work in which case the * mac must be specified on the command line */ if (getbssid(wf) < 0 || IEEE80211_ADDR_EQ(wf->mac, zeromac)) getlladdr(wf); break; case IEEE80211_M_STA: if (getbssid(wf) < 0) err(1, "%s (IEEE80211_IOC_BSSID)", wf->ireq.i_name); break; } } else IEEE80211_ADDR_COPY(wf->mac, mac); } /* XXX only fetch what's needed to do reports */ static void wlan_collect(struct wlanstatfoo_p *wf, struct ieee80211_stats *stats, struct ieee80211req_sta_stats *nstats) { IEEE80211_ADDR_COPY(wf->u_info.info.is_u.macaddr, wf->mac); wf->ireq.i_type = IEEE80211_IOC_STA_INFO; wf->ireq.i_data = (caddr_t) &wf->u_info; wf->ireq.i_len = sizeof(wf->u_info); if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0) { warn("%s:%s (IEEE80211_IOC_STA_INFO)", wf->ireq.i_name, ether_ntoa((const struct ether_addr*) wf->mac)); } IEEE80211_ADDR_COPY(nstats->is_u.macaddr, wf->mac); wf->ireq.i_type = IEEE80211_IOC_STA_STATS; wf->ireq.i_data = (caddr_t) nstats; wf->ireq.i_len = sizeof(*nstats); if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0) warn("%s:%s (IEEE80211_IOC_STA_STATS)", wf->ireq.i_name, ether_ntoa((const struct ether_addr*) wf->mac)); wf->ifr.ifr_data = (caddr_t) stats; if (ioctl(wf->s, SIOCG80211STATS, &wf->ifr) < 0) err(1, "%s (SIOCG80211STATS)", wf->ifr.ifr_name); } static void wlan_collect_cur(struct bsdstat *sf) { struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf; wlan_collect(wf, &wf->cur, &wf->ncur); } static void wlan_collect_tot(struct bsdstat *sf) { struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf; wlan_collect(wf, &wf->total, &wf->ntotal); } static void wlan_update_tot(struct bsdstat *sf) { struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf; wf->total = wf->cur; wf->ntotal = wf->ncur; } void setreason(char b[], size_t bs, int v) { -#define N(a) (sizeof(a)/sizeof(a[0])) static const char *reasons[] = { [IEEE80211_REASON_UNSPECIFIED] = "unspecified", [IEEE80211_REASON_AUTH_EXPIRE] = "auth expire", [IEEE80211_REASON_AUTH_LEAVE] = "auth leave", [IEEE80211_REASON_ASSOC_EXPIRE] = "assoc expire", [IEEE80211_REASON_ASSOC_TOOMANY] = "assoc toomany", [IEEE80211_REASON_NOT_AUTHED] = "not authed", [IEEE80211_REASON_NOT_ASSOCED] = "not assoced", [IEEE80211_REASON_ASSOC_LEAVE] = "assoc leave", [IEEE80211_REASON_ASSOC_NOT_AUTHED] = "assoc not authed", [IEEE80211_REASON_DISASSOC_PWRCAP_BAD] = "disassoc pwrcap bad", [IEEE80211_REASON_DISASSOC_SUPCHAN_BAD] = "disassoc supchan bad", [IEEE80211_REASON_IE_INVALID] = "ie invalid", [IEEE80211_REASON_MIC_FAILURE] = "mic failure", [IEEE80211_REASON_4WAY_HANDSHAKE_TIMEOUT]= "4-way handshake timeout", [IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT] = "group key update timeout", [IEEE80211_REASON_IE_IN_4WAY_DIFFERS] = "ie in 4-way differs", [IEEE80211_REASON_GROUP_CIPHER_INVALID] = "group cipher invalid", [IEEE80211_REASON_PAIRWISE_CIPHER_INVALID]= "pairwise cipher invalid", [IEEE80211_REASON_AKMP_INVALID] = "akmp invalid", [IEEE80211_REASON_UNSUPP_RSN_IE_VERSION]= "unsupported rsn ie version", [IEEE80211_REASON_INVALID_RSN_IE_CAP] = "invalid rsn ie cap", [IEEE80211_REASON_802_1X_AUTH_FAILED] = "802.1x auth failed", [IEEE80211_REASON_CIPHER_SUITE_REJECTED]= "cipher suite rejected", }; - if (v < N(reasons) && reasons[v] != NULL) + if (v < nitems(reasons) && reasons[v] != NULL) snprintf(b, bs, "%s (%u)", reasons[v], v); else snprintf(b, bs, "%u", v); -#undef N } void setstatus(char b[], size_t bs, int v) { -#define N(a) (sizeof(a)/sizeof(a[0])) static const char *status[] = { [IEEE80211_STATUS_SUCCESS] = "success", [IEEE80211_STATUS_UNSPECIFIED] = "unspecified", [IEEE80211_STATUS_CAPINFO] = "capinfo", [IEEE80211_STATUS_NOT_ASSOCED] = "not assoced", [IEEE80211_STATUS_OTHER] = "other", [IEEE80211_STATUS_ALG] = "algorithm", [IEEE80211_STATUS_SEQUENCE] = "sequence", [IEEE80211_STATUS_CHALLENGE] = "challenge", [IEEE80211_STATUS_TIMEOUT] = "timeout", [IEEE80211_STATUS_TOOMANY] = "toomany", [IEEE80211_STATUS_BASIC_RATE] = "basic rate", [IEEE80211_STATUS_SP_REQUIRED] = "sp required", [IEEE80211_STATUS_PBCC_REQUIRED] = "pbcc required", [IEEE80211_STATUS_CA_REQUIRED] = "ca required", [IEEE80211_STATUS_SPECMGMT_REQUIRED] = "specmgmt required", [IEEE80211_STATUS_PWRCAP_REQUIRED] = "pwrcap required", [IEEE80211_STATUS_SUPCHAN_REQUIRED] = "supchan required", [IEEE80211_STATUS_SHORTSLOT_REQUIRED] = "shortslot required", [IEEE80211_STATUS_DSSSOFDM_REQUIRED] = "dsssofdm required", [IEEE80211_STATUS_INVALID_IE] = "invalid ie", [IEEE80211_STATUS_GROUP_CIPHER_INVALID] = "group cipher invalid", [IEEE80211_STATUS_PAIRWISE_CIPHER_INVALID]= "pairwise cipher invalid", [IEEE80211_STATUS_AKMP_INVALID] = "akmp invalid", [IEEE80211_STATUS_UNSUPP_RSN_IE_VERSION]= "unsupported rsn ie version", [IEEE80211_STATUS_INVALID_RSN_IE_CAP] = "invalid rsn ie cap", [IEEE80211_STATUS_CIPHER_SUITE_REJECTED]= "cipher suite rejected", }; - if (v < N(status) && status[v] != NULL) + if (v < nitems(status) && status[v] != NULL) snprintf(b, bs, "%s (%u)", status[v], v); else snprintf(b, bs, "%u", v); -#undef N } static int wlan_getinfo(struct wlanstatfoo_p *wf, int s, char b[], size_t bs) { const struct ieee80211req_sta_info *si = &wf->u_info.info.info[0]; switch (s) { case S_RATE: snprintf(b, bs, "%uM", si->isi_txmbps/2); return 1; case S_RSSI: snprintf(b, bs, "%d", si->isi_rssi); return 1; case S_NOISE: snprintf(b, bs, "%d", si->isi_noise); return 1; case S_SIGNAL: snprintf(b, bs, "%d", si->isi_rssi + si->isi_noise); return 1; case S_RX_AUTH_FAIL_CODE: if (wf->cur.is_rx_authfail_code == 0) break; setstatus(b, bs, wf->cur.is_rx_authfail_code); return 1; case S_RX_DEAUTH_CODE: if (wf->cur.is_rx_deauth_code == 0) break; setreason(b, bs, wf->cur.is_rx_deauth_code); return 1; case S_RX_DISASSOC_CODE: if (wf->cur.is_rx_disassoc_code == 0) break; setreason(b, bs, wf->cur.is_rx_disassoc_code); return 1; } b[0] = '\0'; return 0; } static int wlan_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->cur.is_##x - wf->total.is_##x); return 1 #define NSTAT(x) \ snprintf(b, bs, "%u", \ wf->ncur.is_stats.ns_##x - wf->ntotal.is_stats.ns_##x); \ return 1 switch (s) { case S_RX_BADVERSION: STAT(rx_badversion); case S_RX_TOOSHORT: STAT(rx_tooshort); case S_RX_WRONGBSS: STAT(rx_wrongbss); case S_RX_DUP: STAT(rx_dup); case S_RX_WRONGDIR: STAT(rx_wrongdir); case S_RX_MCASTECHO: STAT(rx_mcastecho); case S_RX_NOTASSOC: STAT(rx_notassoc); case S_RX_NOPRIVACY: STAT(rx_noprivacy); case S_RX_UNENCRYPTED: STAT(rx_unencrypted); case S_RX_WEPFAIL: STAT(rx_wepfail); case S_RX_DECAP: STAT(rx_decap); case S_RX_MGTDISCARD: STAT(rx_mgtdiscard); case S_RX_CTL: STAT(rx_ctl); case S_RX_BEACON: STAT(rx_beacon); case S_RX_RSTOOBIG: STAT(rx_rstoobig); case S_RX_ELEM_MISSING: STAT(rx_elem_missing); case S_RX_ELEM_TOOBIG: STAT(rx_elem_toobig); case S_RX_ELEM_TOOSMALL: STAT(rx_elem_toosmall); case S_RX_ELEM_UNKNOWN: STAT(rx_elem_unknown); case S_RX_BADCHAN: STAT(rx_badchan); case S_RX_CHANMISMATCH: STAT(rx_chanmismatch); case S_RX_NODEALLOC: STAT(rx_nodealloc); case S_RX_SSIDMISMATCH: STAT(rx_ssidmismatch); case S_RX_AUTH_UNSUPPORTED: STAT(rx_auth_unsupported); case S_RX_AUTH_FAIL: STAT(rx_auth_fail); case S_RX_AUTH_COUNTERMEASURES: STAT(rx_auth_countermeasures); case S_RX_ASSOC_BSS: STAT(rx_assoc_bss); case S_RX_ASSOC_NOTAUTH: STAT(rx_assoc_notauth); case S_RX_ASSOC_CAPMISMATCH: STAT(rx_assoc_capmismatch); case S_RX_ASSOC_NORATE: STAT(rx_assoc_norate); case S_RX_ASSOC_BADWPAIE: STAT(rx_assoc_badwpaie); case S_RX_DEAUTH: STAT(rx_deauth); case S_RX_DISASSOC: STAT(rx_disassoc); case S_BMISS: STAT(beacon_miss); case S_RX_BADSUBTYPE: STAT(rx_badsubtype); case S_RX_NOBUF: STAT(rx_nobuf); case S_RX_DECRYPTCRC: STAT(rx_decryptcrc); case S_RX_AHDEMO_MGT: STAT(rx_ahdemo_mgt); case S_RX_BAD_AUTH: STAT(rx_bad_auth); case S_RX_UNAUTH: STAT(rx_unauth); case S_RX_BADKEYID: STAT(rx_badkeyid); case S_RX_CCMPREPLAY: STAT(rx_ccmpreplay); case S_RX_CCMPFORMAT: STAT(rx_ccmpformat); case S_RX_CCMPMIC: STAT(rx_ccmpmic); case S_RX_TKIPREPLAY: STAT(rx_tkipreplay); case S_RX_TKIPFORMAT: STAT(rx_tkipformat); case S_RX_TKIPMIC: STAT(rx_tkipmic); case S_RX_TKIPICV: STAT(rx_tkipicv); case S_RX_BADCIPHER: STAT(rx_badcipher); case S_RX_NOCIPHERCTX: STAT(rx_nocipherctx); case S_RX_ACL: STAT(rx_acl); case S_TX_NOBUF: STAT(tx_nobuf); case S_TX_NONODE: STAT(tx_nonode); case S_TX_UNKNOWNMGT: STAT(tx_unknownmgt); case S_TX_BADCIPHER: STAT(tx_badcipher); case S_TX_NODEFKEY: STAT(tx_nodefkey); case S_TX_NOHEADROOM: STAT(tx_noheadroom); case S_TX_FRAGFRAMES: STAT(tx_fragframes); case S_TX_FRAGS: STAT(tx_frags); case S_SCAN_ACTIVE: STAT(scan_active); case S_SCAN_PASSIVE: STAT(scan_passive); case S_SCAN_BG: STAT(scan_bg); case S_NODE_TIMEOUT: STAT(node_timeout); case S_CRYPTO_NOMEM: STAT(crypto_nomem); case S_CRYPTO_TKIP: STAT(crypto_tkip); case S_CRYPTO_TKIPENMIC: STAT(crypto_tkipenmic); case S_CRYPTO_TKIPDEMIC: STAT(crypto_tkipdemic); case S_CRYPTO_TKIPCM: STAT(crypto_tkipcm); case S_CRYPTO_CCMP: STAT(crypto_ccmp); case S_CRYPTO_WEP: STAT(crypto_wep); case S_CRYPTO_SETKEY_CIPHER: STAT(crypto_setkey_cipher); case S_CRYPTO_SETKEY_NOKEY: STAT(crypto_setkey_nokey); case S_CRYPTO_DELKEY: STAT(crypto_delkey); case S_CRYPTO_BADCIPHER: STAT(crypto_badcipher); case S_CRYPTO_NOCIPHER: STAT(crypto_nocipher); case S_CRYPTO_ATTACHFAIL: STAT(crypto_attachfail); case S_CRYPTO_SWFALLBACK: STAT(crypto_swfallback); case S_CRYPTO_KEYFAIL: STAT(crypto_keyfail); case S_CRYPTO_ENMICFAIL: STAT(crypto_enmicfail); case S_IBSS_CAPMISMATCH: STAT(ibss_capmismatch); case S_IBSS_NORATE: STAT(ibss_norate); case S_PS_UNASSOC: STAT(ps_unassoc); case S_PS_BADAID: STAT(ps_badaid); case S_PS_QEMPTY: STAT(ps_qempty); case S_FF_BADHDR: STAT(ff_badhdr); case S_FF_TOOSHORT: STAT(ff_tooshort); case S_FF_SPLIT: STAT(ff_split); case S_FF_DECAP: STAT(ff_decap); case S_FF_ENCAP: STAT(ff_encap); case S_RX_BADBINTVAL: STAT(rx_badbintval); case S_RX_MGMT: STAT(rx_mgmt); case S_RX_DEMICFAIL: STAT(rx_demicfail); case S_RX_DEFRAG: STAT(rx_defrag); case S_RX_ACTION: STAT(rx_action); case S_AMSDU_TOOSHORT: STAT(amsdu_tooshort); case S_AMSDU_SPLIT: STAT(amsdu_split); case S_AMSDU_DECAP: STAT(amsdu_decap); case S_AMSDU_ENCAP: STAT(amsdu_encap); case S_AMPDU_REORDER: STAT(ampdu_rx_reorder); case S_AMPDU_FLUSH: STAT(ampdu_rx_flush); case S_AMPDU_BARBAD: STAT(ampdu_bar_bad); case S_AMPDU_BAROOW: STAT(ampdu_bar_oow); case S_AMPDU_BARMOVE: STAT(ampdu_bar_move); case S_AMPDU_BAR: STAT(ampdu_bar_rx); case S_AMPDU_MOVE: STAT(ampdu_rx_move); case S_AMPDU_OOR: STAT(ampdu_rx_oor); case S_AMPDU_COPY: STAT(ampdu_rx_copy); case S_AMPDU_DROP: STAT(ampdu_rx_drop); case S_AMPDU_AGE: STAT(ampdu_rx_age); case S_AMPDU_STOP: STAT(ampdu_stop); case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed); case S_ADDBA_REJECT: STAT(addba_reject); case S_ADDBA_NOREQUEST: STAT(addba_norequest); case S_ADDBA_BADTOKEN: STAT(addba_badtoken); case S_TX_BADSTATE: STAT(tx_badstate); case S_TX_NOTASSOC: STAT(tx_notassoc); case S_TX_CLASSIFY: STAT(tx_classify); case S_DWDS_MCAST: STAT(dwds_mcast); case S_DWDS_QDROP: STAT(dwds_qdrop); case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap); case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade); case S_HT_ASSOC_NORATE: STAT(ht_assoc_norate); case S_MESH_WRONGMESH: STAT(mesh_wrongmesh); case S_MESH_NOLINK: STAT(mesh_nolink); case S_MESH_FWD_TTL: STAT(mesh_fwd_ttl); case S_MESH_FWD_NOBUF: STAT(mesh_fwd_nobuf); case S_MESH_FWD_TOOSHORT: STAT(mesh_fwd_tooshort); case S_MESH_FWD_DISABLED: STAT(mesh_fwd_disabled); case S_MESH_FWD_NOPATH: STAT(mesh_fwd_nopath); case S_HWMP_WRONGSEQ: STAT(hwmp_wrongseq); case S_HWMP_ROOTREQS: STAT(hwmp_rootreqs); case S_HWMP_ROOTANN: STAT(hwmp_rootrann); case S_MESH_BADAE: STAT(mesh_badae); case S_MESH_RTADDFAILED:STAT(mesh_rtaddfailed); case S_MESH_NOTPROXY: STAT(mesh_notproxy); case S_RX_BADALIGN: STAT(rx_badalign); case S_INPUT: NSTAT(rx_data); case S_OUTPUT: NSTAT(tx_data); case S_RX_UCAST: NSTAT(rx_ucast); case S_RX_MCAST: NSTAT(rx_mcast); case S_TX_UCAST: NSTAT(tx_ucast); case S_TX_MCAST: NSTAT(tx_mcast); case S_BEACON_BAD: STAT(beacon_bad); case S_AMPDU_BARTX: STAT(ampdu_bar_tx); case S_AMPDU_BARTX_RETRY: STAT(ampdu_bar_tx_retry); case S_AMPDU_BARTX_FAIL: STAT(ampdu_bar_tx_fail); } return wlan_getinfo(wf, s, b, bs); #undef NSTAT #undef STAT } static int wlan_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->total.is_##x); return 1 #define NSTAT(x) \ snprintf(b, bs, "%u", wf->ntotal.is_stats.ns_##x); return 1 switch (s) { case S_RX_BADVERSION: STAT(rx_badversion); case S_RX_TOOSHORT: STAT(rx_tooshort); case S_RX_WRONGBSS: STAT(rx_wrongbss); case S_RX_DUP: STAT(rx_dup); case S_RX_WRONGDIR: STAT(rx_wrongdir); case S_RX_MCASTECHO: STAT(rx_mcastecho); case S_RX_NOTASSOC: STAT(rx_notassoc); case S_RX_NOPRIVACY: STAT(rx_noprivacy); case S_RX_UNENCRYPTED: STAT(rx_unencrypted); case S_RX_WEPFAIL: STAT(rx_wepfail); case S_RX_DECAP: STAT(rx_decap); case S_RX_MGTDISCARD: STAT(rx_mgtdiscard); case S_RX_CTL: STAT(rx_ctl); case S_RX_BEACON: STAT(rx_beacon); case S_RX_RSTOOBIG: STAT(rx_rstoobig); case S_RX_ELEM_MISSING: STAT(rx_elem_missing); case S_RX_ELEM_TOOBIG: STAT(rx_elem_toobig); case S_RX_ELEM_TOOSMALL: STAT(rx_elem_toosmall); case S_RX_ELEM_UNKNOWN: STAT(rx_elem_unknown); case S_RX_BADCHAN: STAT(rx_badchan); case S_RX_CHANMISMATCH: STAT(rx_chanmismatch); case S_RX_NODEALLOC: STAT(rx_nodealloc); case S_RX_SSIDMISMATCH: STAT(rx_ssidmismatch); case S_RX_AUTH_UNSUPPORTED: STAT(rx_auth_unsupported); case S_RX_AUTH_FAIL: STAT(rx_auth_fail); case S_RX_AUTH_COUNTERMEASURES: STAT(rx_auth_countermeasures); case S_RX_ASSOC_BSS: STAT(rx_assoc_bss); case S_RX_ASSOC_NOTAUTH: STAT(rx_assoc_notauth); case S_RX_ASSOC_CAPMISMATCH: STAT(rx_assoc_capmismatch); case S_RX_ASSOC_NORATE: STAT(rx_assoc_norate); case S_RX_ASSOC_BADWPAIE: STAT(rx_assoc_badwpaie); case S_RX_DEAUTH: STAT(rx_deauth); case S_RX_DISASSOC: STAT(rx_disassoc); case S_BMISS: STAT(beacon_miss); case S_RX_BADSUBTYPE: STAT(rx_badsubtype); case S_RX_NOBUF: STAT(rx_nobuf); case S_RX_DECRYPTCRC: STAT(rx_decryptcrc); case S_RX_AHDEMO_MGT: STAT(rx_ahdemo_mgt); case S_RX_BAD_AUTH: STAT(rx_bad_auth); case S_RX_UNAUTH: STAT(rx_unauth); case S_RX_BADKEYID: STAT(rx_badkeyid); case S_RX_CCMPREPLAY: STAT(rx_ccmpreplay); case S_RX_CCMPFORMAT: STAT(rx_ccmpformat); case S_RX_CCMPMIC: STAT(rx_ccmpmic); case S_RX_TKIPREPLAY: STAT(rx_tkipreplay); case S_RX_TKIPFORMAT: STAT(rx_tkipformat); case S_RX_TKIPMIC: STAT(rx_tkipmic); case S_RX_TKIPICV: STAT(rx_tkipicv); case S_RX_BADCIPHER: STAT(rx_badcipher); case S_RX_NOCIPHERCTX: STAT(rx_nocipherctx); case S_RX_ACL: STAT(rx_acl); case S_TX_NOBUF: STAT(tx_nobuf); case S_TX_NONODE: STAT(tx_nonode); case S_TX_UNKNOWNMGT: STAT(tx_unknownmgt); case S_TX_BADCIPHER: STAT(tx_badcipher); case S_TX_NODEFKEY: STAT(tx_nodefkey); case S_TX_NOHEADROOM: STAT(tx_noheadroom); case S_TX_FRAGFRAMES: STAT(tx_fragframes); case S_TX_FRAGS: STAT(tx_frags); case S_SCAN_ACTIVE: STAT(scan_active); case S_SCAN_PASSIVE: STAT(scan_passive); case S_SCAN_BG: STAT(scan_bg); case S_NODE_TIMEOUT: STAT(node_timeout); case S_CRYPTO_NOMEM: STAT(crypto_nomem); case S_CRYPTO_TKIP: STAT(crypto_tkip); case S_CRYPTO_TKIPENMIC: STAT(crypto_tkipenmic); case S_CRYPTO_TKIPDEMIC: STAT(crypto_tkipdemic); case S_CRYPTO_TKIPCM: STAT(crypto_tkipcm); case S_CRYPTO_CCMP: STAT(crypto_ccmp); case S_CRYPTO_WEP: STAT(crypto_wep); case S_CRYPTO_SETKEY_CIPHER: STAT(crypto_setkey_cipher); case S_CRYPTO_SETKEY_NOKEY: STAT(crypto_setkey_nokey); case S_CRYPTO_DELKEY: STAT(crypto_delkey); case S_CRYPTO_BADCIPHER: STAT(crypto_badcipher); case S_CRYPTO_NOCIPHER: STAT(crypto_nocipher); case S_CRYPTO_ATTACHFAIL: STAT(crypto_attachfail); case S_CRYPTO_SWFALLBACK: STAT(crypto_swfallback); case S_CRYPTO_KEYFAIL: STAT(crypto_keyfail); case S_CRYPTO_ENMICFAIL: STAT(crypto_enmicfail); case S_IBSS_CAPMISMATCH: STAT(ibss_capmismatch); case S_IBSS_NORATE: STAT(ibss_norate); case S_PS_UNASSOC: STAT(ps_unassoc); case S_PS_BADAID: STAT(ps_badaid); case S_PS_QEMPTY: STAT(ps_qempty); case S_FF_BADHDR: STAT(ff_badhdr); case S_FF_TOOSHORT: STAT(ff_tooshort); case S_FF_SPLIT: STAT(ff_split); case S_FF_DECAP: STAT(ff_decap); case S_FF_ENCAP: STAT(ff_encap); case S_RX_BADBINTVAL: STAT(rx_badbintval); case S_RX_MGMT: STAT(rx_mgmt); case S_RX_DEMICFAIL: STAT(rx_demicfail); case S_RX_DEFRAG: STAT(rx_defrag); case S_RX_ACTION: STAT(rx_action); case S_AMSDU_TOOSHORT: STAT(amsdu_tooshort); case S_AMSDU_SPLIT: STAT(amsdu_split); case S_AMSDU_DECAP: STAT(amsdu_decap); case S_AMSDU_ENCAP: STAT(amsdu_encap); case S_AMPDU_REORDER: STAT(ampdu_rx_reorder); case S_AMPDU_FLUSH: STAT(ampdu_rx_flush); case S_AMPDU_BARBAD: STAT(ampdu_bar_bad); case S_AMPDU_BAROOW: STAT(ampdu_bar_oow); case S_AMPDU_BARMOVE: STAT(ampdu_bar_move); case S_AMPDU_BAR: STAT(ampdu_bar_rx); case S_AMPDU_MOVE: STAT(ampdu_rx_move); case S_AMPDU_OOR: STAT(ampdu_rx_oor); case S_AMPDU_COPY: STAT(ampdu_rx_copy); case S_AMPDU_DROP: STAT(ampdu_rx_drop); case S_AMPDU_AGE: STAT(ampdu_rx_age); case S_AMPDU_STOP: STAT(ampdu_stop); case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed); case S_ADDBA_REJECT: STAT(addba_reject); case S_ADDBA_NOREQUEST: STAT(addba_norequest); case S_ADDBA_BADTOKEN: STAT(addba_badtoken); case S_TX_BADSTATE: STAT(tx_badstate); case S_TX_NOTASSOC: STAT(tx_notassoc); case S_TX_CLASSIFY: STAT(tx_classify); case S_DWDS_MCAST: STAT(dwds_mcast); case S_DWDS_QDROP: STAT(dwds_qdrop); case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap); case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade); case S_HT_ASSOC_NORATE: STAT(ht_assoc_norate); case S_MESH_WRONGMESH: STAT(mesh_wrongmesh); case S_MESH_NOLINK: STAT(mesh_nolink); case S_MESH_FWD_TTL: STAT(mesh_fwd_ttl); case S_MESH_FWD_NOBUF: STAT(mesh_fwd_nobuf); case S_MESH_FWD_TOOSHORT: STAT(mesh_fwd_tooshort); case S_MESH_FWD_DISABLED: STAT(mesh_fwd_disabled); case S_MESH_FWD_NOPATH: STAT(mesh_fwd_nopath); case S_HWMP_WRONGSEQ: STAT(hwmp_wrongseq); case S_HWMP_ROOTREQS: STAT(hwmp_rootreqs); case S_HWMP_ROOTANN: STAT(hwmp_rootrann); case S_MESH_BADAE: STAT(mesh_badae); case S_MESH_RTADDFAILED:STAT(mesh_rtaddfailed); case S_MESH_NOTPROXY: STAT(mesh_notproxy); case S_RX_BADALIGN: STAT(rx_badalign); case S_INPUT: NSTAT(rx_data); case S_OUTPUT: NSTAT(tx_data); case S_RX_UCAST: NSTAT(rx_ucast); case S_RX_MCAST: NSTAT(rx_mcast); case S_TX_UCAST: NSTAT(tx_ucast); case S_TX_MCAST: NSTAT(tx_mcast); case S_BEACON_BAD: STAT(beacon_bad); case S_AMPDU_BARTX: STAT(ampdu_bar_tx); case S_AMPDU_BARTX_RETRY: STAT(ampdu_bar_tx_retry); case S_AMPDU_BARTX_FAIL: STAT(ampdu_bar_tx_fail); } return wlan_getinfo(wf, s, b, bs); #undef NSTAT #undef STAT } BSDSTAT_DEFINE_BOUNCE(wlanstatfoo) struct wlanstatfoo * wlanstats_new(const char *ifname, const char *fmtstring) { -#define N(a) (sizeof(a) / sizeof(a[0])) struct wlanstatfoo_p *wf; wf = calloc(1, sizeof(struct wlanstatfoo_p)); if (wf != NULL) { - bsdstat_init(&wf->base.base, "wlanstats", wlanstats, N(wlanstats)); + bsdstat_init(&wf->base.base, "wlanstats", wlanstats, + nitems(wlanstats)); /* override base methods */ wf->base.base.collect_cur = wlan_collect_cur; wf->base.base.collect_tot = wlan_collect_tot; wf->base.base.get_curstat = wlan_get_curstat; wf->base.base.get_totstat = wlan_get_totstat; wf->base.base.update_tot = wlan_update_tot; /* setup bounce functions for public methods */ BSDSTAT_BOUNCE(wf, wlanstatfoo); /* setup our public methods */ wf->base.setifname = wlan_setifname; wf->base.getifname = wlan_getifname; wf->base.getopmode = wlan_getopmode; wf->base.setstamac = wlan_setstamac; wf->opmode = -1; wf->s = socket(AF_INET, SOCK_DGRAM, 0); if (wf->s < 0) err(1, "socket"); wlan_setifname(&wf->base, ifname); wf->base.setfmt(&wf->base, fmtstring); } return &wf->base; -#undef N } Index: head/tools/tools/net80211/wlantxtime/wlantxtime.c =================================================================== --- head/tools/tools/net80211/wlantxtime/wlantxtime.c (revision 287296) +++ head/tools/tools/net80211/wlantxtime/wlantxtime.c (revision 287297) @@ -1,584 +1,579 @@ /*- * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * IEEE 802.11 PHY-related support. */ #include -#include #include #include #include #define IEEE80211_F_SHPREAMBLE 0x00040000 /* STATUS: use short preamble */ #include #include #include #include #include #include struct ieee80211_rate_table { int rateCount; /* NB: for proper padding */ uint8_t rateCodeToIndex[256]; /* back mapping */ struct { uint8_t phy; /* CCK/OFDM/TURBO */ uint32_t rateKbps; /* transfer rate in kbs */ uint8_t shortPreamble; /* mask for enabling short * preamble in CCK rate code */ uint8_t dot11Rate; /* value for supported rates * info element of MLME */ uint8_t ctlRateIndex; /* index of next lower basic * rate; used for dur. calcs */ uint16_t lpAckDuration; /* long preamble ACK dur. */ uint16_t spAckDuration; /* short preamble ACK dur. */ } info[32]; }; uint16_t ieee80211_compute_duration(const struct ieee80211_rate_table *rt, uint32_t frameLen, uint16_t rate, int isShortPreamble); #define KASSERT(c, msg) do { \ if (!(c)) { \ printf msg; \ putchar('\n'); \ exit(-1); \ } \ } while (0) static void panic(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); exit(-1); } /* shorthands to compact tables for readability */ #define OFDM IEEE80211_T_OFDM #define CCK IEEE80211_T_CCK #define TURBO IEEE80211_T_TURBO #define HALF IEEE80211_T_OFDM_HALF #define QUART IEEE80211_T_OFDM_QUARTER #define PBCC (IEEE80211_T_OFDM_QUARTER+1) /* XXX */ #define B(r) (0x80 | r) #define Mb(x) (x*1000) static struct ieee80211_rate_table ieee80211_11b_table = { .rateCount = 4, /* XXX no PBCC */ .info = { /* short ctrl */ /* Preamble dot11Rate Rate */ [0] = { .phy = CCK, 1000, 0x00, B(2), 0 },/* 1 Mb */ [1] = { .phy = CCK, 2000, 0x04, B(4), 1 },/* 2 Mb */ [2] = { .phy = CCK, 5500, 0x04, B(11), 1 },/* 5.5 Mb */ [3] = { .phy = CCK, 11000, 0x04, B(22), 1 },/* 11 Mb */ [4] = { .phy = PBCC, 22000, 0x04, 44, 3 } /* 22 Mb */ }, }; static struct ieee80211_rate_table ieee80211_11g_table = { .rateCount = 12, .info = { /* short ctrl */ /* Preamble dot11Rate Rate */ [0] = { .phy = CCK, 1000, 0x00, B(2), 0 }, [1] = { .phy = CCK, 2000, 0x04, B(4), 1 }, [2] = { .phy = CCK, 5500, 0x04, B(11), 2 }, [3] = { .phy = CCK, 11000, 0x04, B(22), 3 }, [4] = { .phy = OFDM, 6000, 0x00, 12, 4 }, [5] = { .phy = OFDM, 9000, 0x00, 18, 4 }, [6] = { .phy = OFDM, 12000, 0x00, 24, 6 }, [7] = { .phy = OFDM, 18000, 0x00, 36, 6 }, [8] = { .phy = OFDM, 24000, 0x00, 48, 8 }, [9] = { .phy = OFDM, 36000, 0x00, 72, 8 }, [10] = { .phy = OFDM, 48000, 0x00, 96, 8 }, [11] = { .phy = OFDM, 54000, 0x00, 108, 8 } }, }; static struct ieee80211_rate_table ieee80211_11a_table = { .rateCount = 8, .info = { /* short ctrl */ /* Preamble dot11Rate Rate */ [0] = { .phy = OFDM, 6000, 0x00, B(12), 0 }, [1] = { .phy = OFDM, 9000, 0x00, 18, 0 }, [2] = { .phy = OFDM, 12000, 0x00, B(24), 2 }, [3] = { .phy = OFDM, 18000, 0x00, 36, 2 }, [4] = { .phy = OFDM, 24000, 0x00, B(48), 4 }, [5] = { .phy = OFDM, 36000, 0x00, 72, 4 }, [6] = { .phy = OFDM, 48000, 0x00, 96, 4 }, [7] = { .phy = OFDM, 54000, 0x00, 108, 4 } }, }; static struct ieee80211_rate_table ieee80211_half_table = { .rateCount = 8, .info = { /* short ctrl */ /* Preamble dot11Rate Rate */ [0] = { .phy = HALF, 3000, 0x00, B(6), 0 }, [1] = { .phy = HALF, 4500, 0x00, 9, 0 }, [2] = { .phy = HALF, 6000, 0x00, B(12), 2 }, [3] = { .phy = HALF, 9000, 0x00, 18, 2 }, [4] = { .phy = HALF, 12000, 0x00, B(24), 4 }, [5] = { .phy = HALF, 18000, 0x00, 36, 4 }, [6] = { .phy = HALF, 24000, 0x00, 48, 4 }, [7] = { .phy = HALF, 27000, 0x00, 54, 4 } }, }; static struct ieee80211_rate_table ieee80211_quarter_table = { .rateCount = 8, .info = { /* short ctrl */ /* Preamble dot11Rate Rate */ [0] = { .phy = QUART, 1500, 0x00, B(3), 0 }, [1] = { .phy = QUART, 2250, 0x00, 4, 0 }, [2] = { .phy = QUART, 3000, 0x00, B(9), 2 }, [3] = { .phy = QUART, 4500, 0x00, 9, 2 }, [4] = { .phy = QUART, 6000, 0x00, B(12), 4 }, [5] = { .phy = QUART, 9000, 0x00, 18, 4 }, [6] = { .phy = QUART, 12000, 0x00, 24, 4 }, [7] = { .phy = QUART, 13500, 0x00, 27, 4 } }, }; static struct ieee80211_rate_table ieee80211_turbog_table = { .rateCount = 7, .info = { /* short ctrl */ /* Preamble dot11Rate Rate */ [0] = { .phy = TURBO, 12000, 0x00, B(12), 0 }, [1] = { .phy = TURBO, 24000, 0x00, B(24), 1 }, [2] = { .phy = TURBO, 36000, 0x00, 36, 1 }, [3] = { .phy = TURBO, 48000, 0x00, B(48), 3 }, [4] = { .phy = TURBO, 72000, 0x00, 72, 3 }, [5] = { .phy = TURBO, 96000, 0x00, 96, 3 }, [6] = { .phy = TURBO, 108000, 0x00, 108, 3 } }, }; static struct ieee80211_rate_table ieee80211_turboa_table = { .rateCount = 8, .info = { /* short ctrl */ /* Preamble dot11Rate Rate */ [0] = { .phy = TURBO, 12000, 0x00, B(12), 0 }, [1] = { .phy = TURBO, 18000, 0x00, 18, 0 }, [2] = { .phy = TURBO, 24000, 0x00, B(24), 2 }, [3] = { .phy = TURBO, 36000, 0x00, 36, 2 }, [4] = { .phy = TURBO, 48000, 0x00, B(48), 4 }, [5] = { .phy = TURBO, 72000, 0x00, 72, 4 }, [6] = { .phy = TURBO, 96000, 0x00, 96, 4 }, [7] = { .phy = TURBO, 108000, 0x00, 108, 4 } }, }; #undef Mb #undef B #undef OFDM #undef CCK #undef TURBO #undef XR /* * Setup a rate table's reverse lookup table and fill in * ack durations. The reverse lookup tables are assumed * to be initialized to zero (or at least the first entry). * We use this as a key that indicates whether or not * we've previously setup the reverse lookup table. * * XXX not reentrant, but shouldn't matter */ static void ieee80211_setup_ratetable(struct ieee80211_rate_table *rt) { -#define N(a) (sizeof(a)/sizeof(a[0])) #define WLAN_CTRL_FRAME_SIZE \ (sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN) int i; - for (i = 0; i < N(rt->rateCodeToIndex); i++) + for (i = 0; i < nitems(rt->rateCodeToIndex); i++) rt->rateCodeToIndex[i] = (uint8_t) -1; for (i = 0; i < rt->rateCount; i++) { uint8_t code = rt->info[i].dot11Rate; uint8_t cix = rt->info[i].ctlRateIndex; uint8_t ctl_rate = rt->info[cix].dot11Rate; rt->rateCodeToIndex[code] = i; if (code & IEEE80211_RATE_BASIC) { /* * Map w/o basic rate bit too. */ code &= IEEE80211_RATE_VAL; rt->rateCodeToIndex[code] = i; } /* * XXX for 11g the control rate to use for 5.5 and 11 Mb/s * depends on whether they are marked as basic rates; * the static tables are setup with an 11b-compatible * 2Mb/s rate which will work but is suboptimal * * NB: Control rate is always less than or equal to the * current rate, so control rate's reverse lookup entry * has been installed and following call is safe. */ rt->info[i].lpAckDuration = ieee80211_compute_duration(rt, WLAN_CTRL_FRAME_SIZE, ctl_rate, 0); rt->info[i].spAckDuration = ieee80211_compute_duration(rt, WLAN_CTRL_FRAME_SIZE, ctl_rate, IEEE80211_F_SHPREAMBLE); } #undef WLAN_CTRL_FRAME_SIZE -#undef N } /* Setup all rate tables */ static void ieee80211_phy_init(void) { -#define N(arr) (int)(sizeof(arr) / sizeof(arr[0])) static struct ieee80211_rate_table * const ratetables[] = { &ieee80211_half_table, &ieee80211_quarter_table, &ieee80211_11a_table, &ieee80211_11g_table, &ieee80211_turbog_table, &ieee80211_turboa_table, &ieee80211_turboa_table, &ieee80211_11a_table, &ieee80211_11g_table, &ieee80211_11b_table }; - int i; + unsigned int i; - for (i = 0; i < N(ratetables); ++i) + for (i = 0; i < nitems(ratetables); ++i) ieee80211_setup_ratetable(ratetables[i]); -#undef N } #define CCK_SIFS_TIME 10 #define CCK_PREAMBLE_BITS 144 #define CCK_PLCP_BITS 48 #define OFDM_SIFS_TIME 16 #define OFDM_PREAMBLE_TIME 20 #define OFDM_PLCP_BITS 22 #define OFDM_SYMBOL_TIME 4 #define OFDM_HALF_SIFS_TIME 32 #define OFDM_HALF_PREAMBLE_TIME 40 #define OFDM_HALF_PLCP_BITS 22 #define OFDM_HALF_SYMBOL_TIME 8 #define OFDM_QUARTER_SIFS_TIME 64 #define OFDM_QUARTER_PREAMBLE_TIME 80 #define OFDM_QUARTER_PLCP_BITS 22 #define OFDM_QUARTER_SYMBOL_TIME 16 #define TURBO_SIFS_TIME 8 #define TURBO_PREAMBLE_TIME 14 #define TURBO_PLCP_BITS 22 #define TURBO_SYMBOL_TIME 4 #define HT_L_STF 8 #define HT_L_LTF 8 #define HT_L_SIG 4 #define HT_SIG 8 #define HT_STF 4 #define HT_LTF(n) ((n) * 4) /* * Compute the time to transmit a frame of length frameLen bytes * using the specified rate, phy, and short preamble setting. * SIFS is included. */ uint16_t ieee80211_compute_duration(const struct ieee80211_rate_table *rt, uint32_t frameLen, uint16_t rate, int isShortPreamble) { uint8_t rix = rt->rateCodeToIndex[rate]; uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime; uint32_t kbps; KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate)); kbps = rt->info[rix].rateKbps; if (kbps == 0) /* XXX bandaid for channel changes */ return 0; switch (rt->info[rix].phy) { case IEEE80211_T_CCK: phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; if (isShortPreamble && rt->info[rix].shortPreamble) phyTime >>= 1; numBits = frameLen << 3; txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000)/kbps); break; case IEEE80211_T_OFDM: bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; KASSERT(bitsPerSymbol != 0, ("full rate bps")); numBits = OFDM_PLCP_BITS + (frameLen << 3); numSymbols = howmany(numBits, bitsPerSymbol); txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME + (numSymbols * OFDM_SYMBOL_TIME); break; case IEEE80211_T_OFDM_HALF: bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000; KASSERT(bitsPerSymbol != 0, ("1/4 rate bps")); numBits = OFDM_PLCP_BITS + (frameLen << 3); numSymbols = howmany(numBits, bitsPerSymbol); txTime = OFDM_HALF_SIFS_TIME + OFDM_HALF_PREAMBLE_TIME + (numSymbols * OFDM_HALF_SYMBOL_TIME); break; case IEEE80211_T_OFDM_QUARTER: bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000; KASSERT(bitsPerSymbol != 0, ("1/2 rate bps")); numBits = OFDM_PLCP_BITS + (frameLen << 3); numSymbols = howmany(numBits, bitsPerSymbol); txTime = OFDM_QUARTER_SIFS_TIME + OFDM_QUARTER_PREAMBLE_TIME + (numSymbols * OFDM_QUARTER_SYMBOL_TIME); break; case IEEE80211_T_TURBO: /* we still save OFDM rates in kbps - so double them */ bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000; KASSERT(bitsPerSymbol != 0, ("turbo bps")); numBits = TURBO_PLCP_BITS + (frameLen << 3); numSymbols = howmany(numBits, bitsPerSymbol); txTime = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME + (numSymbols * TURBO_SYMBOL_TIME); break; default: panic("%s: unknown phy %u (rate %u)\n", __func__, rt->info[rix].phy, rate); break; } return txTime; } uint32_t ieee80211_compute_duration_ht(const struct ieee80211_rate_table *rt, uint32_t frameLen, uint16_t rate, int streams, int isht40, int isShortGI) { static const uint16_t ht20_bps[16] = { 26, 52, 78, 104, 156, 208, 234, 260, 52, 104, 156, 208, 312, 416, 468, 520 }; static const uint16_t ht40_bps[16] = { 54, 108, 162, 216, 324, 432, 486, 540, 108, 216, 324, 432, 648, 864, 972, 1080, }; uint32_t bitsPerSymbol, numBits, numSymbols, txTime; KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate)); KASSERT((rate &~ IEEE80211_RATE_MCS) < 16, ("bad mcs 0x%x", rate)); if (isht40) bitsPerSymbol = ht40_bps[rate & 0xf]; else bitsPerSymbol = ht20_bps[rate & 0xf]; numBits = OFDM_PLCP_BITS + (frameLen << 3); numSymbols = howmany(numBits, bitsPerSymbol); if (isShortGI) txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */ else txTime = numSymbols * 4; /* 4us */ return txTime + HT_L_STF + HT_L_LTF + HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams); } static const struct ieee80211_rate_table * mode2table(const char *mode) { if (strcasecmp(mode, "half") == 0) return &ieee80211_half_table; else if (strcasecmp(mode, "quarter") == 0) return &ieee80211_quarter_table; else if (strcasecmp(mode, "hta") == 0) return &ieee80211_11a_table; /* XXX */ else if (strcasecmp(mode, "htg") == 0) return &ieee80211_11g_table; /* XXX */ else if (strcasecmp(mode, "108g") == 0) return &ieee80211_turbog_table; else if (strcasecmp(mode, "sturbo") == 0) return &ieee80211_turboa_table; else if (strcasecmp(mode, "turbo") == 0) return &ieee80211_turboa_table; else if (strcasecmp(mode, "11a") == 0) return &ieee80211_11a_table; else if (strcasecmp(mode, "11g") == 0) return &ieee80211_11g_table; else if (strcasecmp(mode, "11b") == 0) return &ieee80211_11b_table; else return NULL; } const char * srate(int rate) { static char buf[32]; if (rate & 1) snprintf(buf, sizeof(buf), "%u.5", rate/2); else snprintf(buf, sizeof(buf), "%u", rate/2); return buf; } static int checkpreamble(const struct ieee80211_rate_table *rt, uint8_t rix, int isShortPreamble, int verbose) { if (isShortPreamble) { if (rt->info[rix].phy != IEEE80211_T_CCK) { if (verbose) warnx("short preamble not meaningful, ignored"); isShortPreamble = 0; } else if (!rt->info[rix].shortPreamble) { if (verbose) warnx("short preamble not meaningful with " "rate %s, ignored", srate(rt->info[rix].dot11Rate &~ IEEE80211_RATE_BASIC)); isShortPreamble = 0; } } return isShortPreamble; } static void usage(const char *progname) { fprintf(stderr, "usage: %s [-a] [-l framelen] [-m mode] [-r rate] [-s]\n", progname); fprintf(stderr, "-a display calculations for all possible rates\n"); fprintf(stderr, "-l framelen length in bytes of 802.11 payload (default 1536)\n"); fprintf(stderr, "-m 11a calculate for 11a channel\n"); fprintf(stderr, "-m 11b calculate for 11b channel\n"); fprintf(stderr, "-m 11g calculate for 11g channel (default)\n"); fprintf(stderr, "-m half calculate for 1/2 width channel\n"); fprintf(stderr, "-m quarter calculate for 1/4 width channel\n"); fprintf(stderr, "-m 108g calculate for dynamic turbo 11g channel\n"); fprintf(stderr, "-m sturbo calculate for static turbo channel\n"); fprintf(stderr, "-m turbo calculate for dynamic turbo 11a channel\n"); fprintf(stderr, "-r rate IEEE rate code (default 54)\n"); fprintf(stderr, "-s short preamble (default long)\n"); exit(0); } int main(int argc, char *argv[]) { const struct ieee80211_rate_table *rt; const char *mode; uint32_t frameLen; uint16_t rate; uint16_t time; uint8_t rix; int ch, allrates, isShortPreamble, isShort; float frate; ieee80211_phy_init(); mode = "11g"; isShortPreamble = 0; frameLen = 1500 + sizeof(struct ieee80211_frame) + LLC_SNAPFRAMELEN + IEEE80211_CRC_LEN ; rate = 2*54; allrates = 0; while ((ch = getopt(argc, argv, "al:m:r:s")) != -1) { switch (ch) { case 'a': allrates = 1; break; case 'l': frameLen = strtoul(optarg, NULL, 0); break; case 'm': mode = optarg; break; case 'r': frate = atof(optarg); rate = (int) 2*frate; break; case 's': isShortPreamble = 1; break; default: usage(argv[0]); break; } } rt = mode2table(mode); if (rt == NULL) errx(-1, "unknown mode %s", mode); if (!allrates) { rix = rt->rateCodeToIndex[rate]; if (rix == (uint8_t) -1) errx(-1, "rate %s not valid for mode %s", srate(rate), mode); isShort = checkpreamble(rt, rix, isShortPreamble, 1); time = ieee80211_compute_duration(rt, frameLen, rate, isShort); printf("%u usec to send %u bytes @ %s Mb/s, %s preamble\n", time, frameLen, srate(rate), isShort ? "short" : "long"); } else { for (rix = 0; rix < rt->rateCount; rix++) { rate = rt->info[rix].dot11Rate &~ IEEE80211_RATE_BASIC; isShort = checkpreamble(rt, rix, isShortPreamble, 0); time = ieee80211_compute_duration(rt, frameLen, rate, isShort); printf("%u usec to send %u bytes @ %s Mb/s, %s preamble\n", time, frameLen, srate(rate), isShort ? "short" : "long"); } } return 0; } Index: head/tools/tools/npe/npestats/main.c =================================================================== --- head/tools/tools/npe/npestats/main.c (revision 287296) +++ head/tools/tools/npe/npestats/main.c (revision 287297) @@ -1,143 +1,143 @@ /*- * Copyright (c) 2009 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ +#include + +#include +#include #include #include -#include #include #include -#include #include "npestats.h" static struct { const char *tag; const char *fmt; } tags[] = { { "default", "align,fcs,macrx,overrun,learn,large,stp,badsrc,underflow,collision1,collisionM,deferred,late,excessive,mactx,carrier,toobig" }, }; static const char * getfmt(const char *tag) { -#define N(a) (sizeof(a)/sizeof(a[0])) int i; - for (i = 0; i < N(tags); i++) + for (i = 0; i < nitems(tags); i++) if (strcasecmp(tags[i].tag, tag) == 0) return tags[i].fmt; return tag; -#undef N } static int signalled; static void catchalarm(int signo __unused) { signalled = 1; } int main(int argc, char *argv[]) { struct npestatfoo *wf; const char *ifname; int c, banner = 1; ifname = getenv("NPE"); if (ifname == NULL) ifname = "npe0"; wf = npestats_new(ifname, getfmt("default")); while ((c = getopt(argc, argv, "bi:lo:z")) != -1) { switch (c) { case 'b': banner = 0; break; case 'i': wf->setifname(wf, optarg); break; case 'l': wf->print_fields(wf, stdout); return 0; case 'o': wf->setfmt(wf, getfmt(optarg)); break; default: errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] [interval]\n", argv[0]); /*NOTREACHED*/ } } argc -= optind; argv += optind; if (argc > 0) { u_long interval = strtoul(argv[0], NULL, 0); int line, omask; if (interval < 1) interval = 1; signal(SIGALRM, catchalarm); signalled = 0; alarm(interval); banner: if (banner) wf->print_header(wf, stdout); line = 0; loop: if (line != 0) { wf->collect_cur(wf); wf->print_current(wf, stdout); wf->update_tot(wf); } else { wf->collect_tot(wf); wf->print_total(wf, stdout); } fflush(stdout); omask = sigblock(sigmask(SIGALRM)); if (!signalled) sigpause(0); sigsetmask(omask); signalled = 0; alarm(interval); line++; if (line == 21) /* XXX tty line count */ goto banner; else goto loop; /*NOTREACHED*/ } else { wf->collect_tot(wf); wf->print_verbose(wf, stdout); } return 0; } Index: head/tools/tools/npe/npestats/npestats.c =================================================================== --- head/tools/tools/npe/npestats/npestats.c (revision 287296) +++ head/tools/tools/npe/npestats/npestats.c (revision 287297) @@ -1,278 +1,277 @@ /*- * Copyright (c) 2009 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * npe statistics class. */ -#include +#include #include +#include +#include #include #include -#include #include #include -#include #include "npestats.h" #define AFTER(prev) ((prev)+1) static const struct fmt npestats[] = { #define S_ALIGN 0 { 7, "align", "align", "alignment errors" }, #define S_FCS AFTER(S_ALIGN) { 7, "fcs", "fcs", "FCS errors" }, #define S_MACRX AFTER(S_FCS) { 7, "macrx", "macrx", "internal MAC rx errors" }, #define S_RXORN AFTER(S_MACRX) { 6, "overrun", "overrun", "rx overrun discards" }, #define S_LEARN AFTER(S_RXORN) { 5, "learn", "learn", "rx learned entry discards" }, #define S_LARGE AFTER(S_LEARN) { 5, "large", "large", "rx large frame discards" }, #define S_STP AFTER(S_LARGE) { 5, "stp", "stp", "rx STP blocked discards" }, #define S_RX_VLAN_TYPE AFTER(S_STP) { 5, "rx_vlan_type", "rx_vlant", "rx VLAN type filter discards" }, #define S_RX_VLAN_ID AFTER(S_RX_VLAN_TYPE) { 5, "rx_vlan_id", "rx_vlani", "rx VLAN Id filter discards" }, #define S_BADSRC AFTER(S_RX_VLAN_ID) { 5, "badsrc", "badsrc", "rx invalid source discards" }, #define S_BLACKLIST AFTER(S_BADSRC) { 5, "blacklist", "blacklist", "rx black list discards" }, #define S_WHITELIST AFTER(S_BLACKLIST) { 5, "whitelist", "whitelist", "rx white list discards" }, #define S_UNDERFLOW AFTER(S_WHITELIST) { 5, "underflow", "underflow", "rx underflow entry discards" }, #define S_COLL_SINGLE AFTER(S_UNDERFLOW) { 5, "collision1", "collision1", "single collision frames" }, #define S_COLL_MULTI AFTER(S_COLL_SINGLE) { 5, "collisionM", "collisionM", "multiple collision frames" }, #define S_DEFERRED AFTER(S_COLL_MULTI) { 5, "deferred", "deferred", "deferred transmissions" }, #define S_LATE AFTER(S_DEFERRED) { 5, "late", "late", "late collisions" }, #define S_EXCESSIVE AFTER(S_LATE) { 5, "excessive", "excessive", "excessive collisions" }, #define S_MACTX AFTER(S_EXCESSIVE) { 7, "mactx", "mactx", "internal MAC tx errors" }, #define S_CARRIER AFTER(S_MACTX) { 7, "carrier", "carrier", "carrier sense errors" }, #define S_TOOBIG AFTER(S_CARRIER) { 7, "toobig", "toobig", "tx large frame discards" }, #define S_TX_VLAN_ID AFTER(S_TOOBIG) { 7, "tx_vlan_id", "tx_vlani", "tx VLAN Id filter discards" }, }; #define S_LAST S_TX_VLAN_ID /* * Stat block returned by NPE with NPE_GETSTATS msg. */ struct npestats { uint32_t dot3StatsAlignmentErrors; uint32_t dot3StatsFCSErrors; uint32_t dot3StatsInternalMacReceiveErrors; uint32_t RxOverrunDiscards; uint32_t RxLearnedEntryDiscards; uint32_t RxLargeFramesDiscards; uint32_t RxSTPBlockedDiscards; uint32_t RxVLANTypeFilterDiscards; uint32_t RxVLANIdFilterDiscards; uint32_t RxInvalidSourceDiscards; uint32_t RxBlackListDiscards; uint32_t RxWhiteListDiscards; uint32_t RxUnderflowEntryDiscards; uint32_t dot3StatsSingleCollisionFrames; uint32_t dot3StatsMultipleCollisionFrames; uint32_t dot3StatsDeferredTransmissions; uint32_t dot3StatsLateCollisions; uint32_t dot3StatsExcessiveCollisions; uint32_t dot3StatsInternalMacTransmitErrors; uint32_t dot3StatsCarrierSenseErrors; uint32_t TxLargeFrameDiscards; uint32_t TxVLANIdFilterDiscards; }; struct npestatfoo_p { struct npestatfoo base; char oid[80]; int mib[4]; struct npestats cur; struct npestats total; }; static void npe_setifname(struct npestatfoo *wf0, const char *ifname) { struct npestatfoo_p *wf = (struct npestatfoo_p *) wf0; size_t len; snprintf(wf->oid, sizeof(wf->oid), "dev.npe.%s.stats", ifname+3); len = 4; if (sysctlnametomib(wf->oid, wf->mib, &len) < 0) err(1, "sysctlnametomib: %s", wf->oid); } static void npe_collect(struct npestatfoo_p *wf, struct npestats *stats) { size_t len = sizeof(struct npestats); if (sysctl(wf->mib, 4, stats, &len, NULL, 0) < 0) err(1, "sysctl: %s", wf->oid); } static void npe_collect_cur(struct bsdstat *sf) { struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; npe_collect(wf, &wf->cur); } static void npe_collect_tot(struct bsdstat *sf) { struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; npe_collect(wf, &wf->total); } static void npe_update_tot(struct bsdstat *sf) { struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; wf->total = wf->cur; } static int npe_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->cur.x - wf->total.x); return 1 switch (s) { case S_ALIGN: STAT(dot3StatsAlignmentErrors); case S_FCS: STAT(dot3StatsFCSErrors); case S_MACRX: STAT(dot3StatsInternalMacReceiveErrors); case S_RXORN: STAT(RxOverrunDiscards); case S_LEARN: STAT(RxLearnedEntryDiscards); case S_LARGE: STAT(RxLargeFramesDiscards); case S_STP: STAT(RxSTPBlockedDiscards); case S_RX_VLAN_TYPE: STAT(RxVLANTypeFilterDiscards); case S_RX_VLAN_ID: STAT(RxVLANIdFilterDiscards); case S_BADSRC: STAT(RxInvalidSourceDiscards); case S_BLACKLIST: STAT(RxBlackListDiscards); case S_WHITELIST: STAT(RxWhiteListDiscards); case S_UNDERFLOW: STAT(RxUnderflowEntryDiscards); case S_COLL_SINGLE: STAT(dot3StatsSingleCollisionFrames); case S_COLL_MULTI: STAT(dot3StatsMultipleCollisionFrames); case S_DEFERRED: STAT(dot3StatsDeferredTransmissions); case S_LATE: STAT(dot3StatsLateCollisions); case S_EXCESSIVE: STAT(dot3StatsExcessiveCollisions); case S_MACTX: STAT(dot3StatsInternalMacTransmitErrors); case S_CARRIER: STAT(dot3StatsCarrierSenseErrors); case S_TOOBIG: STAT(TxLargeFrameDiscards); case S_TX_VLAN_ID: STAT(TxVLANIdFilterDiscards); } b[0] = '\0'; return 0; #undef STAT } static int npe_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs) { struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; #define STAT(x) \ snprintf(b, bs, "%u", wf->total.x); return 1 switch (s) { case S_ALIGN: STAT(dot3StatsAlignmentErrors); case S_FCS: STAT(dot3StatsFCSErrors); case S_MACRX: STAT(dot3StatsInternalMacReceiveErrors); case S_RXORN: STAT(RxOverrunDiscards); case S_LEARN: STAT(RxLearnedEntryDiscards); case S_LARGE: STAT(RxLargeFramesDiscards); case S_STP: STAT(RxSTPBlockedDiscards); case S_RX_VLAN_TYPE: STAT(RxVLANTypeFilterDiscards); case S_RX_VLAN_ID: STAT(RxVLANIdFilterDiscards); case S_BADSRC: STAT(RxInvalidSourceDiscards); case S_BLACKLIST: STAT(RxBlackListDiscards); case S_WHITELIST: STAT(RxWhiteListDiscards); case S_UNDERFLOW: STAT(RxUnderflowEntryDiscards); case S_COLL_SINGLE: STAT(dot3StatsSingleCollisionFrames); case S_COLL_MULTI: STAT(dot3StatsMultipleCollisionFrames); case S_DEFERRED: STAT(dot3StatsDeferredTransmissions); case S_LATE: STAT(dot3StatsLateCollisions); case S_EXCESSIVE: STAT(dot3StatsExcessiveCollisions); case S_MACTX: STAT(dot3StatsInternalMacTransmitErrors); case S_CARRIER: STAT(dot3StatsCarrierSenseErrors); case S_TOOBIG: STAT(TxLargeFrameDiscards); case S_TX_VLAN_ID: STAT(TxVLANIdFilterDiscards); } b[0] = '\0'; return 0; #undef STAT } BSDSTAT_DEFINE_BOUNCE(npestatfoo) struct npestatfoo * npestats_new(const char *ifname, const char *fmtstring) { -#define N(a) (sizeof(a) / sizeof(a[0])) struct npestatfoo_p *wf; wf = calloc(1, sizeof(struct npestatfoo_p)); if (wf != NULL) { - bsdstat_init(&wf->base.base, "npestats", npestats, N(npestats)); + bsdstat_init(&wf->base.base, "npestats", npestats, + nitems(npestats)); /* override base methods */ wf->base.base.collect_cur = npe_collect_cur; wf->base.base.collect_tot = npe_collect_tot; wf->base.base.get_curstat = npe_get_curstat; wf->base.base.get_totstat = npe_get_totstat; wf->base.base.update_tot = npe_update_tot; /* setup bounce functions for public methods */ BSDSTAT_BOUNCE(wf, npestatfoo); /* setup our public methods */ wf->base.setifname = npe_setifname; npe_setifname(&wf->base, ifname); wf->base.setfmt(&wf->base, fmtstring); } return &wf->base; -#undef N }