diff options
author | Chris Cappuccio <chris@cvs.openbsd.org> | 2000-10-13 16:22:09 +0000 |
---|---|---|
committer | Chris Cappuccio <chris@cvs.openbsd.org> | 2000-10-13 16:22:09 +0000 |
commit | 495c737e52c11c65e73e0c9c316388be53a79086 (patch) | |
tree | 3dede684821d44162757b0783b9bfa14be592bef /sbin/lmccontrol/lmccontrol.c | |
parent | 0377d74a469833622d0df1e898a34c70891ee6a2 (diff) |
utility to control lmc(4) interfaces
Diffstat (limited to 'sbin/lmccontrol/lmccontrol.c')
-rw-r--r-- | sbin/lmccontrol/lmccontrol.c | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/sbin/lmccontrol/lmccontrol.c b/sbin/lmccontrol/lmccontrol.c new file mode 100644 index 00000000000..e9f97029c4a --- /dev/null +++ b/sbin/lmccontrol/lmccontrol.c @@ -0,0 +1,382 @@ +/* $OpenBSD: lmccontrol.c,v 1.1 2000/10/13 16:22:08 chris Exp $ */ +/* $Id: lmccontrol.c,v 1.1 2000/10/13 16:22:08 chris Exp $ */ + +/*- + * Copyright (c) 1997-1999 LAN Media Corporation (LMC) + * All rights reserved. www.lanmedia.com + * + * This code is written by Michael Graff (explorer@vix.com) and + * Rob Braun (bbraun@vix.com) for LMC. + * The code is derived from permitted modifications to software created + * by Matt Thomas (matt@3am-software.com). + * + * 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. + * 3. All marketing or advertising materials mentioning features or use of this + * software must display the following acknowledgement: + * This product includes software developed by LAN Media Corporation + * and its contributors. + * 4. Neither the name of LAN Media Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY LAN MEDIA CORPORATION 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 CORPORATION 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 <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> + +typedef struct lmc___ctl lmc_ctl_t; +#include <dev/pci/if_lmcioctl.h> + +extern char *optarg; + +void lmc_av9110_freq(u_int32_t, lmc_av9110_t *); +static void dumpdata(char *, lmc_ctl_t *); +void usage(char *); + +#define DEFAULT_INTERFACE "lmc0" + +void +usage(char *s) +{ + fprintf(stderr, + "usage: lmccontrol [-i interface] [-l speed] [-cCeEsKkSoO]\n"); +} + +int +main(int argc, char **argv) +{ + lmc_ctl_t ctl; + int fd; + struct ifreq ifr; + int ch; + char *ifname = DEFAULT_INTERFACE; + lmc_ctl_t wanted; + int flag_c; /* clock source external, internal */ + int flag_l; /* line speed */ + int flag_s; /* Scrambler on, off */ + int flag_o; /* cable length < 100, > 100 */ + int flag_e; /* crc 16, 32 */ + int flag_k; /* HDLC keepalive */ + int just_print; + + flag_c = 0; + flag_l = 0; + flag_s = 0; + flag_o = 0; + flag_e = 0; + flag_k = 0; + just_print = 1; + + while ((ch = getopt(argc, argv, "i:l:cCsSoOeEkKpP")) != -1) { + switch (ch) { + case 'i': + ifname = optarg; + break; + case 'l': + flag_l = 1; + just_print = 0; + wanted.clock_rate = atoi(optarg); + break; + case 's': + flag_s = 1; + just_print = 0; + wanted.scrambler_onoff = LMC_CTL_OFF; + break; + case 'S': + flag_s = 1; + just_print = 0; + wanted.scrambler_onoff = LMC_CTL_ON; + break; + case 'c': + flag_c = 1; + just_print = 0; + wanted.clock_source = LMC_CTL_CLOCK_SOURCE_EXT; + break; + case 'C': + flag_c = 1; + just_print = 0; + wanted.clock_source = LMC_CTL_CLOCK_SOURCE_INT; + break; + case 'o': + flag_o = 1; + just_print = 0; + wanted.cable_length = LMC_CTL_CABLE_LENGTH_LT_100FT; + break; + case 'O': + flag_o = 1; + just_print = 0; + wanted.cable_length = LMC_CTL_CABLE_LENGTH_GT_100FT; + break; + case 'e': + flag_e = 1; + just_print = 0; + wanted.crc_length = LMC_CTL_CRC_LENGTH_16; + break; + case 'E': + flag_e = 1; + just_print = 0; + wanted.crc_length = LMC_CTL_CRC_LENGTH_32; + break; + case 'k': + flag_k = 1; + just_print = 0; + wanted.keepalive_onoff = LMC_CTL_ON; + break; + case 'K': + flag_k = 1; + just_print = 0; + wanted.keepalive_onoff = LMC_CTL_OFF; + break; + case 'p': +#if defined(linux) + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + fprintf(stderr, "socket: %s\n", strerror(errno)); + exit(1); + } + + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&ctl; + if (ioctl(fd, SPPPIOCCISCO, &ifr) < 0) { + fprintf(stderr, "ioctl %s SPPPIOCCISCO: %s\n", + ifr.ifr_name, strerror(errno)); + exit(1); + } + exit(0); +#else + fprintf (stderr, "This option is not yet supported\n"); +#endif + break; + case 'P': + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + fprintf(stderr, "socket: %s\n", strerror(errno)); + exit(1); + } + + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&ctl; +#if defined(linux) /* Linux IOCTL */ + if (ioctl(fd, SPPPIOCPPP, &ifr) < 0) { + fprintf(stderr, "ioctl %s SPPPIOCPPP: %s\n", + ifr.ifr_name, strerror(errno)); + exit(1); + } + exit(0); +#else + fprintf(stderr, "This option is not yet supported\n"); +#endif + break; + case 'h': + case '?': + usage(argv[0]); + exit(0); + } + } + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + fprintf(stderr, "socket: %s\n", strerror(errno)); + exit(1); + } + + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&ctl; + + /* + * Fetch current settings + */ + if (ioctl(fd, LMCIOCGINFO, &ifr) < 0) { + fprintf(stderr, "ioctl %s LMCIOCGINFO: %s\n", + ifr.ifr_name, strerror(errno)); + exit(1); + } + + /* + * If none of the flags are set, print status + */ + if (just_print) { + dumpdata(ifname, &ctl); + exit(0); + } + + if (flag_c) + ctl.clock_source = wanted.clock_source; + if (flag_l) { + lmc_av9110_freq(wanted.clock_rate, &wanted.cardspec.ssi); + if (wanted.cardspec.ssi.f == 0) { + printf("Unable to calculate requested rate.\n"); + exit(1); + } + if (wanted.cardspec.ssi.exact == 0) + printf("Unable to calculate exact frequency," + " using approximation %u\n", + wanted.cardspec.ssi.f); + ctl.clock_rate = wanted.clock_rate; + ctl.cardspec.ssi = wanted.cardspec.ssi; + printf("rate: %u\n", ctl.cardspec.ssi.f); +#if 0 + { + u_int32_t f; + lmc_av9110_t *av; + + av = &wanted.cardspec.ssi; + + printf("m == %u, v == %u, n == %u, r == %u, x == %u\n", + av->m, av->v, av->n, av->r, av->x); + + f = (20000000 / av->m) * (av->v ? 8 : 1) * av->n; + printf("fvco == %u\n", f); + if (av->r == 1) + f /= 2; + else if (av->r == 2) + f /= 4; + else if (av->r == 3) + f /= 8; + printf("fclk == %u (%u)\n", f, f/16); + if (av->x == 1) + f /= 2; + else if (av->x == 2) + f /= 4; + else if (av->x == 3) + f /= 8; + printf("fclkx == %u (%u)\n", f, f/16); + } +#endif + } + if (flag_s) + ctl.scrambler_onoff = wanted.scrambler_onoff; + if (flag_o) + ctl.cable_length = wanted.cable_length; + if (flag_e) + ctl.crc_length = wanted.crc_length; + if (flag_k) + ctl.keepalive_onoff = wanted.keepalive_onoff; + + if (ioctl(fd, LMCIOCSINFO, &ifr) < 0) { + fprintf(stderr, "ioctl %s LMCIOCSINFO: %s\n", + ifr.ifr_name, strerror(errno)); + exit(1); + } + + exit(0); +} + +char *clock_sources[] = { + "External/Line", + "Internal" +}; + +static void +print_clocking(lmc_ctl_t *ctl) +{ + char *source; + + if (ctl->clock_source > 1) + source = "Unknown Value"; + else + source = clock_sources[ctl->clock_source]; + + printf("\tClock source: %s\n", source); + + if (ctl->cardtype == LMC_CTL_CARDTYPE_LMC1000) + printf("\tClock rate: %u\n", ctl->clock_rate); + + printf("\tApproximate detected rate: %u\n", ctl->ticks * 4096); +} + +char *lmc_t1_cables[] = { + "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35", + "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL +}; + +static void +print_t1_cable(lmc_ctl_t *ctl) +{ + char *type; + + if (ctl->cable_type > 7) + type = "Invalid cable type"; + else + type = lmc_t1_cables[ctl->cable_type]; + + printf("\tCable type: %s\n", type); +} + +static void +print_protocol(lmc_ctl_t *ctl) +{ + printf("\tHDLC Keepalive: "); + if (ctl->keepalive_onoff) + printf("on\n"); + else + printf("off\n"); +} + +static void +dumpdata(char *name, lmc_ctl_t *ctl) +{ + /* + * Dump the data + */ + switch(ctl->cardtype) { + case LMC_CTL_CARDTYPE_LMC5200: + printf("%s: Lan Media Corporation LMC5200 (HSSI)\n", name); + print_clocking(ctl); + print_protocol(ctl); + break; + case LMC_CTL_CARDTYPE_LMC5245: + printf("%s: Lan Media Corporation LMC5245 (DS3)\n", name); + print_clocking(ctl); + printf("\tCable length: %s than 100 feet\n", + (ctl->cable_length == LMC_CTL_CABLE_LENGTH_LT_100FT + ? "less" : "more")); + printf("\tScrambler: %s\n", + (ctl->scrambler_onoff ? "on" : "off")); + print_protocol(ctl); + break; + case LMC_CTL_CARDTYPE_LMC1000: + printf("%s: Lan Media Corporation LMC1000 (T1/E1)\n", name); + print_clocking(ctl); + print_t1_cable(ctl); + print_protocol(ctl); + break; + case LMC_CTL_CARDTYPE_LMC1200: + printf("%s: Lan Media Corperation LMC1200 (T1)\n", name); + print_clocking(ctl); + print_protocol(ctl); + break; + default: + printf("%s: Unknown card type: %d\n", name, ctl->cardtype); + } + + printf("\tCRC length: %d\n", ctl->crc_length); +} |