summaryrefslogtreecommitdiffstats
path: root/sys/dev/patm/genrtab/genrtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/patm/genrtab/genrtab.c')
-rw-r--r--sys/dev/patm/genrtab/genrtab.c458
1 files changed, 458 insertions, 0 deletions
diff --git a/sys/dev/patm/genrtab/genrtab.c b/sys/dev/patm/genrtab/genrtab.c
new file mode 100644
index 0000000..eef0749
--- /dev/null
+++ b/sys/dev/patm/genrtab/genrtab.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright (c) 2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * This program is used to generate the different rate tables for the IDT77252
+ * driver. The generated tables are slightly different from those in the
+ * IDT manual.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <math.h>
+#include <ieeefp.h>
+
+/* verbosity flag */
+static int verbose;
+
+/* number of table entries */
+static const u_int tsize = 256;
+
+/* number of rate difference tables to create */
+static const u_int ndtables = 16;
+
+/* cell rate offset for log 0 */
+static const double offset = 10.0;
+
+/*
+ * Make an internal form of the interval and be sure to round down.
+ */
+static u_int
+d2interval(double d)
+{
+ fp_rnd_t r;
+ u_int s, id;
+
+ r = fpsetround(FP_RZ);
+ id = (u_int)rint(32 * d);
+ fpsetround(r);
+
+ s = 0;
+ while (id >= 32 * 32) {
+ s++;
+ id >>= 1;
+ }
+ return ((s << 10) | (id));
+}
+
+/*
+ * Convert an internal interval back to a real one.
+ */
+static double
+interval2d(u_int id)
+{
+ return ((1 << ((id >> 10) & 0xf)) * ((id & 0x3ff) / 32.0));
+}
+
+/*
+ * Convert double to ATM-Forum format. Make sure to round up.
+ */
+static u_int
+cps2atmf(double cps)
+{
+ fp_rnd_t r;
+ u_int s, id;
+
+ if (cps < 1.0)
+ return (0);
+
+ s = 0;
+ while (cps >= 2.0) {
+ s++;
+ cps /= 2;
+ }
+ r = fpsetround(FP_RP);
+ id = (u_int)rint(512 * cps);
+ fpsetround(r);
+
+ return ((1 << 14) | (s << 9) | (id & 0x1ff));
+}
+
+/*
+ * Convert ATM forum format to double
+ */
+static double
+atmf2cps(u_int atmf)
+{
+ return (((atmf >> 14) & 1) * (1 << ((atmf >> 9) & 0x1f)) *
+ ((512 + (atmf & 0x1ff)) / 512.0));
+}
+
+/*
+ * A cell rate to the logarithmic one
+ */
+static double
+cps2log(u_int alink, double lg)
+{
+ if (lg <= offset)
+ return (0);
+ if (lg >= alink)
+ return (tsize - 1);
+
+ return ((tsize - 1) * (1 - log(alink / lg) / log(alink / offset)));
+}
+
+/*
+ * Convert log to cell rate
+ */
+static double
+log2cps(u_int alink, u_int lg)
+{
+ return (alink / pow(alink / offset,
+ (double)(tsize - lg - 1) / (tsize - 1)));
+}
+
+/*
+ * Convert a double to an internal scaled double
+ */
+static u_int
+d2ifp(double fp)
+{
+ fp_rnd_t r;
+ u_int s, ifp;
+
+ fp *= (1 << 16);
+
+ r = fpsetround(FP_RN);
+ ifp = (u_int)rint(fp);
+ fpsetround(r);
+
+ s = 0;
+ while (ifp >= 1024) {
+ s++;
+ ifp >>= 1;
+ }
+ return ((s << 10) | (ifp));
+}
+
+/*
+ * Convert internal scaled float to double
+ */
+static double
+ifp2d(u_int p)
+{
+ return ((p & 0x3ff) * (1 << ((p >> 10) & 0xf)) / 65536.0);
+}
+
+/*
+ * Generate log to rate conversion table
+ */
+static void
+gen_log2rate(u_int alink)
+{
+ u_int i, iinterval, atmf, n, nrm;
+ double rate, interval, xinterval, cps, xcps;
+
+ for (i = 0; i < 256; i++) {
+ /* get the desired rate */
+ rate = alink / pow(alink / offset,
+ (double)(tsize - i - 1) / (tsize - 1));
+
+ /* convert this to an interval */
+ interval = alink / rate;
+
+ /* make the internal form of this interval, be sure to
+ * round down */
+ iinterval = d2interval(interval);
+
+ /* now convert back */
+ xinterval = interval2d(iinterval);
+
+ /* make a cps from this interval */
+ cps = alink / xinterval;
+
+ /* convert this to its ATM forum format */
+ atmf = cps2atmf(cps);
+
+ /* and back */
+ xcps = atmf2cps(atmf);
+
+ /* decide on NRM */
+ if (xcps < 40.0) {
+ nrm = 0;
+ n = 3;
+ } else if (xcps < 80.0) {
+ nrm = 1;
+ n = 4;
+ } else if (xcps < 160.0) {
+ nrm = 2;
+ n = 8;
+ } else if (xcps < 320.0) {
+ nrm = 3;
+ n = 16;
+ } else {
+ nrm = 4;
+ n = 32;
+ }
+
+ /* print */
+ if (verbose)
+ printf(" 0x%08x, /* %03u: cps=%f nrm=%u int=%f */\n",
+ (atmf << 17) | (nrm << 14) | iinterval, i,
+ xcps, n, xinterval);
+ else
+ printf("0x%08x,\n", (atmf << 17) | (nrm << 14) |
+ iinterval);
+ }
+}
+
+/*
+ * Generate rate to log conversion table
+ */
+static void
+gen_rate2log(u_int alink)
+{
+ u_int i, atmf, val, ilcr;
+ double cps, lcr;
+ fp_rnd_t r;
+
+ val = 0;
+ for (i = 0; i < 512; i++) {
+ /* make ATM Forum CPS from index */
+ atmf = (((i & 0x1f0) >> 4) << 9) |
+ ((i & 0xf) << 5) | (1 << 14);
+
+ /* make cps */
+ cps = atmf2cps(atmf);
+
+ /* convert to log */
+ lcr = cps2log(alink, cps);
+
+ r = fpsetround(FP_RN);
+ ilcr = (u_int)rint(lcr);
+ fpsetround(r);
+
+ /* put together */
+ val |= ilcr << (8 * (i % 4));
+
+ /* print */
+ if (i % 4 == 3) {
+ if (verbose)
+ printf(" 0x%08x,\t", val);
+ else
+ printf("0x%08x,\n", val);
+ val = 0;
+ } else if (verbose)
+ printf("\t\t");
+ if (verbose)
+ printf("/* %03u: %f -> %f */\n", i,
+ cps, log2cps(alink, ilcr));
+ }
+}
+
+/*
+ * Generate one entry into the global table
+ */
+static void
+gen_glob_entry(u_int alink, u_int fill, u_int ci, u_int ni)
+{
+ if (verbose)
+ printf(" 0x%08x, /* %2u/32 %8.6f, %6u, ci=%u, ni=%u */\n",
+ cps2atmf(alink * fill / 32.0) | (ci << 17) | (ni << 16),
+ fill, fill / 32.0, alink * fill / 32, ci, ni);
+ else
+ printf("0x%08x,\n",
+ cps2atmf(alink * fill / 32.0) | (ci << 17) | (ni << 16));
+}
+
+/*
+ * Generate global parameter table
+ */
+static void
+gen_glob(u_int alink)
+{
+ u_int i;
+
+ gen_glob_entry(alink, 32, 0, 0);
+ gen_glob_entry(alink, 16, 0, 0);
+ gen_glob_entry(alink, 8, 0, 1);
+ gen_glob_entry(alink, 4, 0, 1);
+ gen_glob_entry(alink, 2, 1, 1);
+ gen_glob_entry(alink, 1, 1, 1);
+ gen_glob_entry(alink, 0, 1, 1);
+ gen_glob_entry(alink, 0, 1, 1);
+
+ for (i = 0; i < tsize/2 - 8; i++) {
+ if (i % 16 == 0)
+ printf(" ");
+ printf(" 0,");
+ if (i % 16 == 15)
+ printf("\n");
+ }
+ printf("\n");
+}
+
+/*
+ * Generate additive rate increase tables
+ */
+static void
+gen_air(u_int alink)
+{
+ u_int t, i;
+ double diff; /* cell rate to increase by */
+ double cps;
+ double add;
+ u_int val, a;
+
+ for (t = 0; t < ndtables; t++) {
+ diff = (double)alink / (1 << t);
+ printf("/* AIR %u: diff=%f */\n", t, diff);
+ val = 0;
+ for (i = 0; i < tsize; i++) {
+ cps = log2cps(alink, i);
+ cps += diff;
+ if (cps > alink)
+ cps = alink;
+
+ add = cps2log(alink, cps) - i;
+
+ a = d2ifp(add);
+
+ if (i % 2) {
+ val |= a << 16;
+ if (verbose)
+ printf(" 0x%08x,\t", val);
+ else
+ printf("0x%08x,\n", val);
+ } else {
+ val = a;
+ if (verbose)
+ printf("\t\t");
+ }
+ if (verbose)
+ printf("/* %3u: %f */\n", i, ifp2d(add));
+ }
+ }
+}
+
+/*
+ * Generate rate decrease table
+ */
+static void
+gen_rdf(u_int alink)
+{
+ double d;
+ u_int t, i, f, val, diff;
+
+ for (t = 0; t < ndtables; t++) {
+ /* compute the log index difference */
+ if (t == 0) {
+ d = tsize - 1;
+ } else {
+ f = 1 << t;
+ d = (tsize - 1) / log(alink / offset);
+ d *= log((double)f / (f - 1));
+ }
+ printf(" /* RDF %u: 1/%u: %f */\n", t, 1 << t, d);
+ val = 0;
+ for (i = 0; i < tsize; i++) {
+ if (i < d)
+ diff = d2ifp(i);
+ else
+ diff = d2ifp(d);
+ if (i % 2) {
+ val |= diff << 16;
+ if (verbose)
+ printf(" 0x%08x,\t", val);
+ else
+ printf("0x%08x,\n", val);
+ } else {
+ val = diff;
+ if (verbose)
+ printf("\t\t");
+ }
+ if (verbose)
+ printf("/* %3u: %f */\n", i, ifp2d(diff));
+ }
+ }
+}
+
+/*
+ * Create all the tables for a given link cell rate and link bit rate.
+ * The link bit rate is only used to name the table.
+ */
+static void
+gen_tables(u_int alink, u_int mbps)
+{
+ printf("\n");
+ printf("/*\n");
+ printf(" * Tables for %ucps and %uMbps\n", alink, mbps);
+ printf(" */\n");
+ printf("const uint32_t patm_rtables%u[128 * (4 + 2 * %u)] = {\n",
+ mbps, ndtables);
+
+ gen_log2rate(alink);
+ gen_rate2log(alink);
+ gen_glob(alink);
+ gen_air(alink);
+ gen_rdf(alink);
+
+ printf("};\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "v")) != -1)
+ switch (opt) {
+
+ case 'v':
+ verbose = 1;
+ break;
+ }
+
+ printf("/*\n");
+ printf(" * This file was generated by `%s'\n", argv[0]);
+ printf(" */\n");
+ printf("\n");
+ printf("#include <sys/cdefs.h>\n");
+ printf("__FBSDID(\"$FreeBSD$\");\n");
+ printf("\n");
+ printf("#include <sys/types.h>\n");
+ printf("\n");
+ printf("const u_int patm_rtables_size = 128 * (4 + 2 * %u);\n",
+ ndtables);
+ printf("const u_int patm_rtables_ntab = %u;\n", ndtables);
+ gen_tables(352768, 155);
+ gen_tables( 59259, 25);
+ return (0);
+}
OpenPOWER on IntegriCloud