1139749Simp/*- 2117632Sharti * Copyright (c) 2003 3117632Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4117632Sharti * All rights reserved. 5117632Sharti * 6117632Sharti * Redistribution and use in source and binary forms, with or without 7117632Sharti * modification, are permitted provided that the following conditions 8117632Sharti * are met: 9117632Sharti * 1. Redistributions of source code must retain the above copyright 10117632Sharti * notice, this list of conditions and the following disclaimer. 11117632Sharti * 2. Redistributions in binary form must reproduce the above copyright 12117632Sharti * notice, this list of conditions and the following disclaimer in the 13117632Sharti * documentation and/or other materials provided with the distribution. 14117632Sharti * 15117632Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16117632Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17117632Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18117632Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19117632Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20117632Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21117632Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22117632Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23117632Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24117632Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25117632Sharti * SUCH DAMAGE. 26117632Sharti * 27117632Sharti * Author: Hartmut Brandt <harti@freebsd.org> 28117632Sharti * 29117632Sharti * This program is used to generate the different rate tables for the IDT77252 30117632Sharti * driver. The generated tables are slightly different from those in the 31117632Sharti * IDT manual. 32117632Sharti */ 33117632Sharti#include <sys/cdefs.h> 34117632Sharti__FBSDID("$FreeBSD$"); 35117632Sharti 36117632Sharti#include <sys/types.h> 37117632Sharti#include <stdio.h> 38117632Sharti#include <unistd.h> 39117632Sharti#include <math.h> 40117632Sharti#include <ieeefp.h> 41117632Sharti 42117632Sharti/* verbosity flag */ 43117632Shartistatic int verbose; 44117632Sharti 45117632Sharti/* number of table entries */ 46117632Shartistatic const u_int tsize = 256; 47117632Sharti 48117632Sharti/* number of rate difference tables to create */ 49117632Shartistatic const u_int ndtables = 16; 50117632Sharti 51117632Sharti/* cell rate offset for log 0 */ 52117632Shartistatic const double offset = 10.0; 53117632Sharti 54117632Sharti/* 55117632Sharti * Make an internal form of the interval and be sure to round down. 56117632Sharti */ 57117632Shartistatic u_int 58117632Shartid2interval(double d) 59117632Sharti{ 60117632Sharti fp_rnd_t r; 61117632Sharti u_int s, id; 62117632Sharti 63117632Sharti r = fpsetround(FP_RZ); 64117632Sharti id = (u_int)rint(32 * d); 65117632Sharti fpsetround(r); 66117632Sharti 67117632Sharti s = 0; 68117632Sharti while (id >= 32 * 32) { 69117632Sharti s++; 70117632Sharti id >>= 1; 71117632Sharti } 72117632Sharti return ((s << 10) | (id)); 73117632Sharti} 74117632Sharti 75117632Sharti/* 76117632Sharti * Convert an internal interval back to a real one. 77117632Sharti */ 78117632Shartistatic double 79117632Shartiinterval2d(u_int id) 80117632Sharti{ 81117632Sharti return ((1 << ((id >> 10) & 0xf)) * ((id & 0x3ff) / 32.0)); 82117632Sharti} 83117632Sharti 84117632Sharti/* 85117632Sharti * Convert double to ATM-Forum format. Make sure to round up. 86117632Sharti */ 87117632Shartistatic u_int 88117632Sharticps2atmf(double cps) 89117632Sharti{ 90117632Sharti fp_rnd_t r; 91117632Sharti u_int s, id; 92117632Sharti 93117632Sharti if (cps < 1.0) 94117632Sharti return (0); 95117632Sharti 96117632Sharti s = 0; 97117632Sharti while (cps >= 2.0) { 98117632Sharti s++; 99117632Sharti cps /= 2; 100117632Sharti } 101117632Sharti r = fpsetround(FP_RP); 102117632Sharti id = (u_int)rint(512 * cps); 103117632Sharti fpsetround(r); 104117632Sharti 105117632Sharti return ((1 << 14) | (s << 9) | (id & 0x1ff)); 106117632Sharti} 107117632Sharti 108117632Sharti/* 109117632Sharti * Convert ATM forum format to double 110117632Sharti */ 111117632Shartistatic double 112117632Shartiatmf2cps(u_int atmf) 113117632Sharti{ 114117632Sharti return (((atmf >> 14) & 1) * (1 << ((atmf >> 9) & 0x1f)) * 115117632Sharti ((512 + (atmf & 0x1ff)) / 512.0)); 116117632Sharti} 117117632Sharti 118117632Sharti/* 119117632Sharti * A cell rate to the logarithmic one 120117632Sharti */ 121117632Shartistatic double 122117632Sharticps2log(u_int alink, double lg) 123117632Sharti{ 124117632Sharti if (lg <= offset) 125117632Sharti return (0); 126117632Sharti if (lg >= alink) 127117632Sharti return (tsize - 1); 128117632Sharti 129117632Sharti return ((tsize - 1) * (1 - log(alink / lg) / log(alink / offset))); 130117632Sharti} 131117632Sharti 132117632Sharti/* 133117632Sharti * Convert log to cell rate 134117632Sharti */ 135117632Shartistatic double 136117632Shartilog2cps(u_int alink, u_int lg) 137117632Sharti{ 138117632Sharti return (alink / pow(alink / offset, 139117632Sharti (double)(tsize - lg - 1) / (tsize - 1))); 140117632Sharti} 141117632Sharti 142117632Sharti/* 143117632Sharti * Convert a double to an internal scaled double 144117632Sharti */ 145117632Shartistatic u_int 146117632Shartid2ifp(double fp) 147117632Sharti{ 148117632Sharti fp_rnd_t r; 149117632Sharti u_int s, ifp; 150117632Sharti 151117632Sharti fp *= (1 << 16); 152117632Sharti 153117632Sharti r = fpsetround(FP_RN); 154117632Sharti ifp = (u_int)rint(fp); 155117632Sharti fpsetround(r); 156117632Sharti 157117632Sharti s = 0; 158117632Sharti while (ifp >= 1024) { 159117632Sharti s++; 160117632Sharti ifp >>= 1; 161117632Sharti } 162117632Sharti return ((s << 10) | (ifp)); 163117632Sharti} 164117632Sharti 165117632Sharti/* 166117632Sharti * Convert internal scaled float to double 167117632Sharti */ 168117632Shartistatic double 169117632Shartiifp2d(u_int p) 170117632Sharti{ 171117632Sharti return ((p & 0x3ff) * (1 << ((p >> 10) & 0xf)) / 65536.0); 172117632Sharti} 173117632Sharti 174117632Sharti/* 175117632Sharti * Generate log to rate conversion table 176117632Sharti */ 177117632Shartistatic void 178117632Shartigen_log2rate(u_int alink) 179117632Sharti{ 180117632Sharti u_int i, iinterval, atmf, n, nrm; 181117632Sharti double rate, interval, xinterval, cps, xcps; 182117632Sharti 183117632Sharti for (i = 0; i < 256; i++) { 184117632Sharti /* get the desired rate */ 185117632Sharti rate = alink / pow(alink / offset, 186117632Sharti (double)(tsize - i - 1) / (tsize - 1)); 187117632Sharti 188117632Sharti /* convert this to an interval */ 189117632Sharti interval = alink / rate; 190117632Sharti 191117632Sharti /* make the internal form of this interval, be sure to 192117632Sharti * round down */ 193117632Sharti iinterval = d2interval(interval); 194117632Sharti 195117632Sharti /* now convert back */ 196117632Sharti xinterval = interval2d(iinterval); 197117632Sharti 198117632Sharti /* make a cps from this interval */ 199117632Sharti cps = alink / xinterval; 200117632Sharti 201117632Sharti /* convert this to its ATM forum format */ 202117632Sharti atmf = cps2atmf(cps); 203117632Sharti 204117632Sharti /* and back */ 205117632Sharti xcps = atmf2cps(atmf); 206117632Sharti 207117632Sharti /* decide on NRM */ 208117632Sharti if (xcps < 40.0) { 209117632Sharti nrm = 0; 210117632Sharti n = 3; 211117632Sharti } else if (xcps < 80.0) { 212117632Sharti nrm = 1; 213117632Sharti n = 4; 214117632Sharti } else if (xcps < 160.0) { 215117632Sharti nrm = 2; 216117632Sharti n = 8; 217117632Sharti } else if (xcps < 320.0) { 218117632Sharti nrm = 3; 219117632Sharti n = 16; 220117632Sharti } else { 221117632Sharti nrm = 4; 222117632Sharti n = 32; 223117632Sharti } 224117632Sharti 225117632Sharti /* print */ 226117632Sharti if (verbose) 227117632Sharti printf(" 0x%08x, /* %03u: cps=%f nrm=%u int=%f */\n", 228117632Sharti (atmf << 17) | (nrm << 14) | iinterval, i, 229117632Sharti xcps, n, xinterval); 230117632Sharti else 231117632Sharti printf("0x%08x,\n", (atmf << 17) | (nrm << 14) | 232117632Sharti iinterval); 233117632Sharti } 234117632Sharti} 235117632Sharti 236117632Sharti/* 237117632Sharti * Generate rate to log conversion table 238117632Sharti */ 239117632Shartistatic void 240117632Shartigen_rate2log(u_int alink) 241117632Sharti{ 242117632Sharti u_int i, atmf, val, ilcr; 243117632Sharti double cps, lcr; 244117632Sharti fp_rnd_t r; 245117632Sharti 246117632Sharti val = 0; 247117632Sharti for (i = 0; i < 512; i++) { 248117632Sharti /* make ATM Forum CPS from index */ 249117632Sharti atmf = (((i & 0x1f0) >> 4) << 9) | 250117632Sharti ((i & 0xf) << 5) | (1 << 14); 251117632Sharti 252117632Sharti /* make cps */ 253117632Sharti cps = atmf2cps(atmf); 254117632Sharti 255117632Sharti /* convert to log */ 256117632Sharti lcr = cps2log(alink, cps); 257117632Sharti 258117632Sharti r = fpsetround(FP_RN); 259117632Sharti ilcr = (u_int)rint(lcr); 260117632Sharti fpsetround(r); 261117632Sharti 262117632Sharti /* put together */ 263117632Sharti val |= ilcr << (8 * (i % 4)); 264117632Sharti 265117632Sharti /* print */ 266117632Sharti if (i % 4 == 3) { 267117632Sharti if (verbose) 268117632Sharti printf(" 0x%08x,\t", val); 269117632Sharti else 270117632Sharti printf("0x%08x,\n", val); 271117632Sharti val = 0; 272117632Sharti } else if (verbose) 273117632Sharti printf("\t\t"); 274117632Sharti if (verbose) 275117632Sharti printf("/* %03u: %f -> %f */\n", i, 276117632Sharti cps, log2cps(alink, ilcr)); 277117632Sharti } 278117632Sharti} 279117632Sharti 280117632Sharti/* 281117632Sharti * Generate one entry into the global table 282117632Sharti */ 283117632Shartistatic void 284117632Shartigen_glob_entry(u_int alink, u_int fill, u_int ci, u_int ni) 285117632Sharti{ 286117632Sharti if (verbose) 287117632Sharti printf(" 0x%08x, /* %2u/32 %8.6f, %6u, ci=%u, ni=%u */\n", 288117632Sharti cps2atmf(alink * fill / 32.0) | (ci << 17) | (ni << 16), 289117632Sharti fill, fill / 32.0, alink * fill / 32, ci, ni); 290117632Sharti else 291117632Sharti printf("0x%08x,\n", 292117632Sharti cps2atmf(alink * fill / 32.0) | (ci << 17) | (ni << 16)); 293117632Sharti} 294117632Sharti 295117632Sharti/* 296117632Sharti * Generate global parameter table 297117632Sharti */ 298117632Shartistatic void 299117632Shartigen_glob(u_int alink) 300117632Sharti{ 301117632Sharti u_int i; 302117632Sharti 303117632Sharti gen_glob_entry(alink, 32, 0, 0); 304117632Sharti gen_glob_entry(alink, 16, 0, 0); 305117632Sharti gen_glob_entry(alink, 8, 0, 1); 306117632Sharti gen_glob_entry(alink, 4, 0, 1); 307117632Sharti gen_glob_entry(alink, 2, 1, 1); 308117632Sharti gen_glob_entry(alink, 1, 1, 1); 309117632Sharti gen_glob_entry(alink, 0, 1, 1); 310117632Sharti gen_glob_entry(alink, 0, 1, 1); 311117632Sharti 312117632Sharti for (i = 0; i < tsize/2 - 8; i++) { 313117632Sharti if (i % 16 == 0) 314117632Sharti printf(" "); 315117632Sharti printf(" 0,"); 316117632Sharti if (i % 16 == 15) 317117632Sharti printf("\n"); 318117632Sharti } 319117632Sharti printf("\n"); 320117632Sharti} 321117632Sharti 322117632Sharti/* 323117632Sharti * Generate additive rate increase tables 324117632Sharti */ 325117632Shartistatic void 326117632Shartigen_air(u_int alink) 327117632Sharti{ 328117632Sharti u_int t, i; 329117632Sharti double diff; /* cell rate to increase by */ 330117632Sharti double cps; 331117632Sharti double add; 332117632Sharti u_int val, a; 333117632Sharti 334117632Sharti for (t = 0; t < ndtables; t++) { 335117632Sharti diff = (double)alink / (1 << t); 336117632Sharti printf("/* AIR %u: diff=%f */\n", t, diff); 337117632Sharti val = 0; 338117632Sharti for (i = 0; i < tsize; i++) { 339117632Sharti cps = log2cps(alink, i); 340117632Sharti cps += diff; 341117632Sharti if (cps > alink) 342117632Sharti cps = alink; 343117632Sharti 344117632Sharti add = cps2log(alink, cps) - i; 345117632Sharti 346117632Sharti a = d2ifp(add); 347117632Sharti 348117632Sharti if (i % 2) { 349117632Sharti val |= a << 16; 350117632Sharti if (verbose) 351117632Sharti printf(" 0x%08x,\t", val); 352117632Sharti else 353117632Sharti printf("0x%08x,\n", val); 354117632Sharti } else { 355117632Sharti val = a; 356117632Sharti if (verbose) 357117632Sharti printf("\t\t"); 358117632Sharti } 359117632Sharti if (verbose) 360117632Sharti printf("/* %3u: %f */\n", i, ifp2d(add)); 361117632Sharti } 362117632Sharti } 363117632Sharti} 364117632Sharti 365117632Sharti/* 366117632Sharti * Generate rate decrease table 367117632Sharti */ 368117632Shartistatic void 369117632Shartigen_rdf(u_int alink) 370117632Sharti{ 371117632Sharti double d; 372117632Sharti u_int t, i, f, val, diff; 373117632Sharti 374117632Sharti for (t = 0; t < ndtables; t++) { 375117632Sharti /* compute the log index difference */ 376117632Sharti if (t == 0) { 377117632Sharti d = tsize - 1; 378117632Sharti } else { 379117632Sharti f = 1 << t; 380117632Sharti d = (tsize - 1) / log(alink / offset); 381117632Sharti d *= log((double)f / (f - 1)); 382117632Sharti } 383117632Sharti printf(" /* RDF %u: 1/%u: %f */\n", t, 1 << t, d); 384117632Sharti val = 0; 385117632Sharti for (i = 0; i < tsize; i++) { 386117632Sharti if (i < d) 387117632Sharti diff = d2ifp(i); 388117632Sharti else 389117632Sharti diff = d2ifp(d); 390117632Sharti if (i % 2) { 391117632Sharti val |= diff << 16; 392117632Sharti if (verbose) 393117632Sharti printf(" 0x%08x,\t", val); 394117632Sharti else 395117632Sharti printf("0x%08x,\n", val); 396117632Sharti } else { 397117632Sharti val = diff; 398117632Sharti if (verbose) 399117632Sharti printf("\t\t"); 400117632Sharti } 401117632Sharti if (verbose) 402117632Sharti printf("/* %3u: %f */\n", i, ifp2d(diff)); 403117632Sharti } 404117632Sharti } 405117632Sharti} 406117632Sharti 407117632Sharti/* 408117632Sharti * Create all the tables for a given link cell rate and link bit rate. 409117632Sharti * The link bit rate is only used to name the table. 410117632Sharti */ 411117632Shartistatic void 412117632Shartigen_tables(u_int alink, u_int mbps) 413117632Sharti{ 414117632Sharti printf("\n"); 415117632Sharti printf("/*\n"); 416117632Sharti printf(" * Tables for %ucps and %uMbps\n", alink, mbps); 417117632Sharti printf(" */\n"); 418117632Sharti printf("const uint32_t patm_rtables%u[128 * (4 + 2 * %u)] = {\n", 419117632Sharti mbps, ndtables); 420117632Sharti 421117632Sharti gen_log2rate(alink); 422117632Sharti gen_rate2log(alink); 423117632Sharti gen_glob(alink); 424117632Sharti gen_air(alink); 425117632Sharti gen_rdf(alink); 426117632Sharti 427117632Sharti printf("};\n"); 428117632Sharti} 429117632Sharti 430117632Shartiint 431117632Shartimain(int argc, char *argv[]) 432117632Sharti{ 433117632Sharti int opt; 434117632Sharti 435117632Sharti while ((opt = getopt(argc, argv, "v")) != -1) 436117632Sharti switch (opt) { 437117632Sharti 438117632Sharti case 'v': 439117632Sharti verbose = 1; 440117632Sharti break; 441117632Sharti } 442117632Sharti 443117632Sharti printf("/*\n"); 444117632Sharti printf(" * This file was generated by `%s'\n", argv[0]); 445117632Sharti printf(" */\n"); 446117632Sharti printf("\n"); 447117632Sharti printf("#include <sys/cdefs.h>\n"); 448117632Sharti printf("__FBSDID(\"$FreeBSD$\");\n"); 449117632Sharti printf("\n"); 450117632Sharti printf("#include <sys/types.h>\n"); 451117632Sharti printf("\n"); 452117632Sharti printf("const u_int patm_rtables_size = 128 * (4 + 2 * %u);\n", 453117632Sharti ndtables); 454117632Sharti printf("const u_int patm_rtables_ntab = %u;\n", ndtables); 455117632Sharti gen_tables(352768, 155); 456117632Sharti gen_tables( 59259, 25); 457117632Sharti return (0); 458117632Sharti} 459