From 6fa40729c860d286d6b0cc1052c04ba87cd093d7 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Mon, 3 Oct 2005 07:09:41 +0000 Subject: [PATCH] Add the lmcconfig tool for controlling the lmc driver. Add man pages and glue. Submitted by: David Boggs --- etc/mtree/BSD.include.dist | 2 + include/Makefile | 2 +- share/man/man4/Makefile | 1 + share/man/man4/lmc.4 | 1485 +++++++++++++++++++ usr.sbin/Makefile | 1 + usr.sbin/lmcconfig/Makefile | 9 + usr.sbin/lmcconfig/lmcconfig.8 | 716 +++++++++ usr.sbin/lmcconfig/lmcconfig.c | 2483 ++++++++++++++++++++++++++++++++ 8 files changed, 4698 insertions(+), 1 deletion(-) create mode 100644 share/man/man4/lmc.4 create mode 100644 usr.sbin/lmcconfig/Makefile create mode 100644 usr.sbin/lmcconfig/lmcconfig.8 create mode 100644 usr.sbin/lmcconfig/lmcconfig.c diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 64313033c23c..ddd522cd0720 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -48,6 +48,8 @@ .. iicbus .. + lmc + .. ofw .. pbio diff --git a/include/Makefile b/include/Makefile index 59856c1e765b..34fbd2857f8c 100644 --- a/include/Makefile +++ b/include/Makefile @@ -37,7 +37,7 @@ LDIRS= bsm cam geom net net80211 netatalk netatm netgraph netinet netinet6 \ LSUBDIRS= cam/scsi \ dev/acpica dev/an dev/bktr dev/firewire dev/hwpmc \ - dev/ic dev/iicbus ${_dev_ieee488} dev/ofw \ + dev/ic dev/iicbus ${_dev_ieee488} dev/lmc dev/ofw \ dev/pbio dev/ppbus dev/smbus dev/usb dev/wi dev/utopia \ fs/devfs fs/fdescfs fs/fifofs fs/msdosfs fs/ntfs fs/nullfs \ fs/nwfs fs/portalfs fs/procfs fs/smbfs fs/udf fs/umapfs \ diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index be91b5dc6867..8551acc4f59d 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -128,6 +128,7 @@ MAN= aac.4 \ kue.4 \ led.4 \ lge.4 \ + lmc.4 \ lo.4 \ lp.4 \ lpbb.4 \ diff --git a/share/man/man4/lmc.4 b/share/man/man4/lmc.4 new file mode 100644 index 000000000000..fb08d6c56aa1 --- /dev/null +++ b/share/man/man4/lmc.4 @@ -0,0 +1,1485 @@ +.\" +.\" $FreeBSD$ +.\" +.\" Copyright (c) 2002-2005 David Boggs. (boggs@boggs.palo-alto.ca.us) +.\" All rights reserved. +.\" +.\" BSD License: +.\" +.\" 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. +.\" +.\" GNU General Public License: +.\" +.\" This program is free software; you can redistribute it and/or modify it +.\" under the terms of the GNU General Public License as published by the Free +.\" Software Foundation; either version 2 of the License, or (at your option) +.\" any later version. +.\" +.\" This program is distributed in the hope that it will be useful, but WITHOUT +.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +.\" more details. +.\" +.\" You should have received a copy of the GNU General Public License along with +.\" this program; if not, write to the Free Software Foundation, Inc., 59 +.\" Temple Place - Suite 330, Boston, MA 02111-1307, USA. +.\" +.\" I forget these things: +.\" groff -Tascii -mdoc lmc.4 > lmc.0 +.\" groff -Tps -mdoc lmc.4 > lmc.ps +.\" groff -Thtml -mdoc lmc.4 > lmc.html (buggy) +.\" +.Dd June 2005 +.Dt LMC 4 +.Os \" sets \*(oS or \*[operating-system] +. +.\" substring works differently before minor version 19 +.ie (\n(.y < 19) .nr ssfix 1 +.el .nr ssfix 0 +. +.ie "\*[operating-system]"" .ds aa \*(oS +.el .ds aa \*[operating-system] +.substring aa (0+\n[ssfix] (6+\n[ssfix]) +.ie "\*(aa"FreeBSD" .nr fbsd 1 +.el .nr fbsd 0 +. +.ie "\*[operating-system]"" .ds aa \*(oS +.el .ds aa \*[operating-system] +.substring aa (0+\n[ssfix]) (5+\n[ssfix]) +.ie "\*(aa"NetBSD" .nr nbsd 1 +.el .nr nbsd 0 +. +.ie "\*[operating-system]"" .ds aa \*(oS +.el .ds aa \*[operating-system] +.substring aa (0+\n[ssfix]) (7+\n[ssfix]) +.ie "\*(aa"OpenBSD" .nr obsd 1 +.el .nr obsd 0 +. +.ie "\*[operating-system]"" .ds aa \*(oS +.el .ds aa \*[operating-system] +.substring aa (0+\n[ssfix]) (4+\n[ssfix]) +.ie "\*(aa"BSDI" .nr bsdi 1 +.el .nr bsdi 0 +. +.ie "\*[operating-system]"" .ds aa \*(oS +.el .ds aa \*[operating-system] +.ie "\*(aa"BSD" .nr linux 1 +.el .nr linux 0 +. +.\" if no operating system matched, select all OSs +.if !(\n[fbsd] : \n[nbsd] : \n[obsd] : \n[bsdi] : \n[linux]) \{\ +.nr fbsd 1 +.nr nbsd 1 +.nr obsd 1 +.nr bsdi 1 +.nr linux 1 \} +. +.Sp +.Sh NAME +.Sp +.Nm lmc +.Nd device driver for +.Tn LMC +(now +.Tn SBE ) +wide-area network interface cards. +.Sp +.Sh SYNOPSIS +.Sp +.if \n[fbsd] \{\ +.Cd "device lmc" \} +.if (\n[nbsd] : \n[obsd] : \n[bsdi]) \{\ +.Cd "lmc* at pci?" \} +.if \n[linux] \{\ +.Cd "CONFIG_LANMEDIA=m" \} +.Sp +.Sh DESCRIPTION +.Sp +This is an open-source Unix device driver for PCI-bus WAN interface cards. +It sends and receives packets in HDLC frames over synchronous circuits. +A generic PC plus Unix plus some +.Tn "LMC" / +.Tn "SBE" +cards makes an +.Em open +router. +This driver works with FreeBSD, NetBSD, OpenBSD, BSD/OS and Linux OSs. +It has been tested on i386 (SMP 32-bit little-end), Sparc (64-bit big-end), +and Alpha (64-bit little-end) architectures. +.Pp +The +.Nm +driver works with the following cards: +.Bd -literal -offset 2m +SBE wanADAPT-HSSI High Speed Serial Interface, + (LMC5200) EIA612/613, 50-pin connector, + 0 to 52 Mb/s, DTE only. +SBE wanADAPT-T3 T3: two 75-ohm BNC connectors, + (LMC5245) C-Parity or M13 Framing, + 44.736 Mb/s, up to 950 ft. +SBE wanADAPT-SSI Synchronous Serial Interface, + (LMC1000) V.35, X.21, EIA449, EIA530(A), EIA232, + 0 to 10 Mb/s, DTE or DCE. +SBE wanADAPT-T1E1 T1 or E1: RJ45 conn, 100 or 120 ohms, + (LMC1200) T1-ESF-B8ZS, T1-SF-AMI, E1-(many)-HDB3, + 1.544 Mb/s or 2.048 Mb/s, up to 6 Kft. +.Ed +.Pp +Cards contain a high-performance +.Sy "PCI" +interface, an +.Sy "HDLC" +function and +either integrated +.Sy "modems" +(T1, T3) or +.Sy "modem" +interfaces (HSSI and SSI). +.Bl -tag -width "Modem" +.It Sy "PCI" +The PCI interface is a DEC 21140A "Tulip" Fast Ethernet chip. +This chip has an efficient PCI implementation with scatter/gather DMA, +and can run at 100 Mb/s full duplex (twice as fast as needed here). +.It Sy "HDLC" +The HDLC functions (ISO-3309: flags, bit-stuffing, CRC) are implemented +in a Field Programmable Gate Array (FPGA) which talks to the Ethernet +chip through a Media Independent Interface (MII). +The hardware in the FPGA translates between Ethernet packets and +HDLC frames on-the-fly; think it as a WAN PHY chip for Ethernet. +.It Sy "Modem" +The modem chips are the main differences between cards. +HSSI cards use ECL10K chips to implement the EIA-612/613 interface. +T3 cards use a TranSwitch TXC-03401 framer chip. +SSI cards use Linear Technology LTC1343 modem interface chips. +T1 cards use a BrookTree/Conexant/Mindspeed Bt8370 framer +and line interface chip. +.El +.Pp +Line protocols exist above device drivers and below internet protocols. +They typically encapsulate packets in HDLC frames and deal with +higher-level issues like protocol multiplexing and security. +This driver is compatible with several line protocol packages: +.Bl -tag -width "Generic HDLC" +.if (\n[fbsd] : \n[nbsd]) \{\ +.It Sy "Netgraph" +.Xr Netgraph 4 +implements many basic packet-handling functions as kernel loadable modules. +They can be interconnected in a graph to implement many protocols. +Configuration is done from userland without rebuilding the kernel. +Packets are sent and received through this interface if the driver's +.Em rawdata +hook is connected, otherwise the ifnet interface (SPPP and RawIP) is used. +ASCII configuration control messages are +.Em not +currently supported. \} +.if (\n[fbsd]) \{\ +.It Sy "SPPP" +.Xr sppp 4 +implements Synchronous-PPP, Frame-Relay and Cisco-HDLC in the kernel. \} +.if (\n[nbsd] : \n[obsd]) \{\ +.It Sy "SPPP" +.Xr sppp 4 +implements Synchronous-PPP and Cisco-HDLC in the kernel. \} +.if \n[bsdi] \{\ +.It Sy "P2P" +.Xr p2p 4 +implements Synchronous-PPP, Frame-Relay and Cisco-HDLC in the kernel. \} +.if \n[linux] \{\ +.It Sy "Generic HDLC" +implements Synchronous-PPP, Frame-Relay, Cisco-HDLC, +Ether-in-HDLC, and IP-in-HDLC (aka RAWIP) in the kernel. \} +.It Sy "RawIP" +This null line protocol, built into the driver, sends and receives +raw IPv4 and IPv6 packets in HDLC frames (aka IP-in-HDLC) with +no extra bytes of overhead and no state at the end points. +.El +.Sp +.Sh EXAMPLES +.Sp +.Ss ifconfig and lmcconfig +.Sp +The program +.Xr lmcconfig 8 +manipulates interface parameters beyond the scope of +.Xr ifconfig 8 . +In normal operation only a few arguments are needed: +.Bl -inset -offset 4n -compact +.It Sy "-X\0\0" +selects the external +.if (\n[fbsd] : \n[nbsd] : \n[obsd]) SPPP +.if \n[bsdi] P2P +.if \n[linus] Generic-HDLC +line protocol package. +.It Sy "-x\0\0" +selects the built-in RawIP line protocol package. +.if (\n[fbsd] : \n[nbsd] : \n[obsd]) \{\ +.It Sy "-Z\0\0" +selects PPP line protocol. +.It Sy "-z\0\0" +selects Cisco-HDLC line protocol. +.It Sy "-F\0\0" +selects Frame-Relay line protocol.\} +.El +.Pp +.Ic "lmcconfig lmc0" +.br +displays interface configuration and status. +.if \n[obsd] \{\ +.Pp +Some configuration options are available through +.Ic "ifconfig" +as well as +.Ic "lmcconfig" . +.Pp +.Ic "ifconfig lmc0 media e1 timeslot all +.br +selects E1 format using all 32 timeslots. +.br +.Ic "ifconfig -m lmc0" +.br +lists the available media options. +.Pp +.Ic "ifconfig lmc0 -mediaopt hdlc-crc16" +.br +deselects 16-bit CRCs, thereby selecting 32-bit CRCs. +.br +.Ic "ifconfig lmc0 mediaopt loopback" +.br +loops the interface transmitter to the receiver for testing. +Some cards have up to six loopback paths through the hardware. +.Ic "ifconfig" +selects a simple loopback present in every card type, but +.Ic "lmcconfig" +can select them all.\} +.Pp +.Ic "lmcconfig lmc0 -D" +.br +enables debugging output from the device driver only. +.br +.Ic "ifconfig lmc0 debug" +.br +enables debugging output from the device driver and from +the line protocol module above it. +Debugging messages that appear on the console are also +written to file +.Ic "/var/log/messages" . +.Em Caution : +when things go very wrong, a torrent of debugging messages +can swamp the console and bring a machine to its knees. +.if (\n[fbsd] : \n[nbsd] : \n[obsd] : \n[bsdi]) \{\ +.Sp +.Ss Patching Ethernet Drivers +.Sp +Since these cards use DEC 21140A Tulip Ethernet chips, +be aware that an Ethernet driver may mistake one for an +Ethernet card and try to drive it. +For some versions of some operating systems, it is +sufficient to list the +.Nm +cards before any Ethernet cards in the kernel configuration. +Another solution is to unplug all 21140-based Ethernet cards +and remove their device drivers from the kernel configuration. +Finally, one can patch the Ethernet drivers to ignore +.Nm +cards. +In any case, you must make a custom kernel. +.if \n[fbsd] \{\ +Chapter 9 of the FreeBSD Handbook \} +.if \n[nbsd] \{\ +Chapter 6 of the NetBSD Guide \} +.if \n[obsd] \{\ +Chapter 5 of the OpenBSD FAQ \} +.if \n[bsdi] \{\ +"Rebuilding the Kernel" in the BSD/OS Administrator's Guide \} +explains how to configure and build custom kernels. +.Pp +To patch an Ethernet device driver: +.if \n[fbsd] \{\ +.br +add this line to +.Ic "tulip_pci_probe()" +in +.Ic "sys/pci/if_de.c" : \} +.if (\n[nbsd] : \n[obsd]) \{\ +.br +add this line to +.Ic "tulip_pci_probe()" +in +.Ic "/sys/dev/pci/if_de.c" : +.br +add this line to +.Ic "dc_pci_match() " +in +.Ic "/sys/dev/pci/if_dc_pci.c" : +.if \n[nbsd] \{\ +.br +add this line to +.Ic "tlp_pci_match() " +in +.Ic "/sys/dev/pci/if_tlp_pci.c" : \} \} +.if \n[bsdi] \{\ +.br +add this line to +.Ic "tulip_pci_match()" +in +.Ic "/sys/i386/pci/if_de.c" : \} +.br +.if \n[fbsd] \{\ +.Ic "if (pci_get_subvendor(dev)==0x1376)" +.br +.Ic " return ENXIO;" +.br +This driver should already be patched. \} +.if (\n[nbsd] : \n[obsd]) \{\ +.Ic "if ((pci_conf_read(pa->pa_pc, pa->pa_tag, 0x2C) & 0xFFFF)==0x1376)" +.br +.Ic " return 0;" +.br \} +.if \n[bsdi] \{\ +.Ic "if ((pci_inl(pa, 0x2C) & 0xFFFF)==0x1376)" +.br +.Ic " return 0;" +.br \} +Make sure you patch the correct routine: many Ethernet drivers +contain probe/match routines for several operating systems inside +.Ic "#ifdefs" . +.Pp +.Ic "/var/log/messages" +should contain a boot message like this: +.br +.if \n[fbsd] \{\ +.Ic "freebsd-4: pci0: (vendor=0x1011, dev=0x0009) at 18.0 irq 9" +.br +.Ic "freebsd-5: pci0: at device 18.0 (no driver attached)" \} +.if \n[nbsd] \{\ +.Ic "vendor 0x1011 product 0x0009 (ethernet network, revision 0x22) +.br +.Ic "at pci0 dev 18 function 0 not configured" \} +.if \n[obsd] \{\ +.Ic "DEC 21140 rev 0x22 at pci0 dev 18 function 0 not configured" \} +.if \n[bsdi] \{\ +.Ic "lmc0 at pci0 iobase 0xe880 irq 10 maddr 0xfebeff00-0xfebeff7f" \} +.if (\n[nbsd] : \n[obsd] : \n[bsdi]) \{\ +.Pp +If the boot message looks like this: +.br +.if \n[obsd] \{\ +.Ic "de1 at pci0 dev 18 function 0 DEC 21140 rev 0x22:" +.br +.Ic "de1: can't read ENET ROM (why=-4) (76130600000 ..." +.br +.Ic "de1: 21140A [10-100Mb/s] pass 2.2 address unknown" +.br \} +.if \n[nbsd] \{\ +.Ic "tlp0 at pci0 dev 18 function 0: DECchip 21140A Ethernet, pass 2.2" +.br +.Ic "tlp0: sorry, unable to handle your board" +.br \} +.if \n[bsdi] \{\ +.Ic "stray interrupt on irq 9" +.br \} +then the Ethernet driver needs patching. \} \} +.if \n[fbsd] \{\ +.Sp +.Ss FreeBSD Configuration +.Sp +Put the source files in +.Ic "/sys/dev/lmc" . +You may need to create the directory. +.Pp +Add the following line to +.Ic "/sys/conf/files" : +.br +.Ic "dev/lmc/if_lmc.c optional lmc pci" +.br +Put it near other +.Ic "dev/l*" +entries. +.br +For FreeBSD-5, change +.Ic optional +to +.Ic count +in the entry for sppp: +.br +.Ic "net/if_spppsubr.c count sppp" +.Pp +To wire this driver into your kernel: +Add the following line to +.Ic "/sys/ARCH/conf/YOURKERNEL" : +.br +.Ic "device lmc # LMC/SBE WAN cards" +.br +Put this line near lines for other network devices. +To load the driver into a running kernel, see KLD below. +.Pp +To wire a line protocol into your kernel, add: +.br +.Ic "options netgraph # wired into the kernel" +.br +.Ic "pseudo-device sppp # FreeBSD-4" +.br +.Ic "device sppp # FreeBSD-5" +.br +It is not necessary to wire line protocols into your kernel. +This driver and line protocols can be loaded later with kldload(8). +The driver can send and receive raw IP packets even if neither +SPPP nor Netgraph are configured into the kernel. +Netgraph and SPPP can both be enabled; netgraph will be used if the +.Em "rawdata" +hook is connected. \} +.if \n[fbsd] \{\ +.Sp +.Ss FreeBSD Kernel Loadable Modules ("KLD" mechanism) +.Sp +To make this driver into a standard kernel loadable module: +.br +Make a directory named +.Ic "/sys/modules/lmc" . +.br +Copy +.Ic "/sys/dev/lmc/Makefile" +to +.Ic "/sys/modules/lmc/Makefile" . +.br +Add +.Ic "lmc" +to +.Ic "/sys/modules/Makefile" +for your machine architecture. +.Pp +While standing in +.Ic /sys/ARCH/compile/YOURKERNEL: +.br +.Ic "make modules-depend" +generates all module dependencies. +.br +.Ic "make modules" +creates all modules. +.br +.Ic "make modules-install" +installs all modules. +.Pp +To make this driver into a kernel loadable module "by hand": +.br +While standing in +.Ic "/sys/dev/lmc" : +.br +.Ic "make depend" +generates lmc module dependencies. +.br +.Ic "make all" +creates the lmc module. +.br +.Ic "make install" +installs the lmc module. +.br +.Ic "make depend all install" +does everything. +.Pp +While standing anywhere (as root): +.br +.Ic "kldload if_lmc" +loads the driver and starts it. +.br +.Ic "kldunload if_lmc" +stops the driver and unloads it. +.br +.Ic "kldstat" +displays status of loaded modules. +.Pp +.Ic "securelevel" +must be 0 to load modules; see +.Xr init 8 . +.Pp +To load this module at boot time, add +.br +.Ic "if_lmc_load=""YES""" +.br +to +.Ic "/boot/loader.conf"; see +.Xr loader.conf 5 . \} +.if \n[fbsd] \{\ +.Sp +.Ss FreeBSD Operation +.Sp +Activate a PPP link using SPPP and Netgraph with: +.br +.Ic "ngctl mkpeer lmc0: sppp rawdata downstream" +.br +.Ic "ifconfig sppp0 10.0.0.1 10.0.0.2" +.Pp +Activate a PPP link using only SPPP with: +.br +.Ic "lmcconfig lmc0 -XYZ" +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2" +.Pp +Activate a Cisco-HDLC link using SPPP and Netgraph with: +.br +.Ic "ngctl mkpeer lmc0: sppp rawdata downstream" +.br +.Ic "ifconfig sppp0 10.0.0.1 10.0.0.2 link2" +.Pp +Activate a Cisco-HDLC link using only SPPP with: +.br +.Ic "lmcconfig lmc0 -XYz" +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2" +.Pp +Activate a Cisco-HDLC link using only Netgraph with: +.br +.Ic "ngctl mkpeer lmc0: cisco rawdata downstream" +.br +.Ic "ngctl mkpeer lmc0:rawdata iface inet inet" +.br +.Ic "ifconfig ng0 10.0.0.1 10.0.0.2" +.Pp +Activate a Frame-Relay DTE link using SPPP with: +.br +.Ic "lmcconfig lmc0 -XYF" +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2" +.br +SPPP implements the ANSI T1.617 annex D LMI. +.Pp +Activate a Frame-Relay DTE link using Netgraph with: +.br +.Ic "ngctl mkpeer lmc0: frame_relay rawdata downstream" +.br +.Ic "ngctl mkpeer lmc0:rawdata lmi dlci0 auto0" +.br +.Ic "ngctl connect lmc0:rawdata dlci0 dlci1023 auto1023" +.br +.Ic "ngctl mkpeer lmc0:rawdata rfc1490 dlci500 downstream" +.br +.Ic "ngctl mkpeer lmc0:rawdata.dlci500 iface inet inet" +.br +.Ic "ifconfig ng0 10.0.0.1 10.0.0.2" +.br +This is +.Em "ONE" +possible Frame Relay configuration; there are many. +.Pp +Activate a RAWIP link using only the driver with: +.br +.Ic "lmcconfig lmc0 -x" +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2" +.Pp +Activate a RAWIP link using Netgraph with: +.br +.Ic "ngctl mkpeer lmc0: iface rawdata inet" +.br +.Ic "ifconfig ng0 10.0.0.1 10.0.0.2" +.br +If the driver is kldunloaded and then kldloaded, reconnect hooks by: +.br +.Ic "ngctl connect lmc0: ng0: rawdata inet" \} +.if (\n[nbsd] : \n[obsd]) \{\ +.Sp +.if \n[nbsd] .Ss NetBSD Configuration +.if \n[obsd] .Ss OpenBSD Configuration +.Sp +Put the source files in +.Ic "/sys/dev/pci/" . +.Pp +Add the following lines to +.Ic "/sys/dev/pci/files.pci" : +.br +.Ic "device lmc: ifnet, sppp" +.if \n[obsd] .Ic ", ifmedia" +.br +.Ic "attach lmc at pci" +.br +.Ic "file dev/pci/if_lmc.c lmc" +.br +Put them near other +.Ic "dev/pci/if_*.c" +entries. +.Pp +In file +.Ic "/sys/conf/files" , +append +.Ic "needs-count" +to the end of this line: +.br +.Ic "file net/if_spppsubr.c sppp needs-count" +.Pp +To wire this driver into your kernel, +add the following line to +.Ic "/sys/arch/ARCH/conf/YOURKERNEL" : +.br +.Ic "lmc* at pci? # LMC/SBE WAN cards" +.br +Put this line near lines for other network devices. +To load the driver into a running kernel, see LKM below. +.Pp +To wire SPPP into your kernel: +.br +.Ic "pseudo-device sppp 1 # wired into the kernel" +.br +The driver can send and receive raw IP packets even if +SPPP is not configured into the kernel. \} +.if (\n[nbsd] : \n[obsd]) \{\ +.Sp +.if \n[nbsd] .Ss NetBSD Loadable Kernel Modules ("LKM" mechanism) +.if \n[obsd] .Ss OpenBSD Loadable Kernel Modules ("LKM" mechanism) +.Sp +Add the following line to +.Ic "/sys/arch/ARCH/conf/YOURKERNEL" : +.br +.Ic "options LKM # loadable kernel modules" +.Pp +Install symbolic links from the kernel compilation directory +to the source directory: +.br +.Ic "ln -s /sys/dev/pci/if_lmc.c" +.br +.Ic "ln -s /sys/dev/pci/if_lmc.h" +.Pp +While standing in +.Ic "/sys/arch/ARCH/compile/YOURKENEL" : +.br +.Ic "make if_lmc.o" +compiles the driver module. +.br +.Ic "modload if_lmc.o" +loads the driver and starts it. +.Pp +while standing anywhere (as root): +.br +.Ic "modunload -n if_lmc.o" +stops the driver and unloads it. +.br +.Ic "modstat" +displays status of loaded modules. +.Pp +When the driver module is loaded, if you get a message like this: +.br +.Ic lmc1: bus_space_map failed; error 35 +.br +then the Ethernet device driver needs patching. +.Pp +.Ic "securelevel" +must be 0 to load modules; see +.Xr init 8 . +.br +One way is to include in +.Ic "/sys/arch/ARCH/conf/YOURKERNEL" : +.br +.Ic "options INSECURE # disable kernel security levels" +.if \n[obsd] \{\ +.Pp +LKM only works for PCI bus 0 on an i386 machine. \} \} +.Sp +.if \n[nbsd] .Ss NetBSD Operation +.if \n[obsd] .Ss OpenBSD Operation +.Sp +.if (\n[nbsd] : \n[obsd]) \{\ +Activate a PPP link using SPPP with: +.br +.Ic "lmcconfig lmc0 -XYZ" +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2" +.Pp +Activate a Cisco-HDLC link using SPPP with: +.br +.Ic "lmcconfig lmc0 -XYz" +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2" +.Pp +Activate a RAWIP link with: +.br +.Ic "lmcconfig lmc0 -x" +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2" \} +.if \n[bsdi] \{\ +.Sp +.Ss BSD/OS Configuration +.Sp +Put the source files in +.Ic "/sys/i386/pci/" . +.Pp +Add the following lines to +.Ic "/sys/i386/conf/files.i386" : +.br +.Ic "device lmc at pci: pcisubr, p2p" +.br +.Ic "file i386/pci/if_lmc.c lmc device-driver" +.br +Put them near other +.Ic "i386/pci/if_*.c entries" . +.Pp +Add the following lines to +.Ic "/sys/i386/conf/YOURKERNEL" : +.br +.Ic "lmc* at pci? # LMC/SBE WAN cards" +.br +Put the above line before any Ethernet devices. +.br +.Ic "options PPP # include PPP code" +.br +.Ic "options FR # include Frame-Relay code" +.br +.Ic "options CISCO_HDLC # include Cisco-HDLC code" +.br \} +.if \n[bsdi] \{\ +.Sp +.Ss BSD/OS Operation +.Sp +To activate a PPP link, create file +.Ic "/etc/ppp.sys" +containing: +.br +.Ic "Plmc0: :device=lmc0:\e" +.br +.Ic " :local-addr=10.0.0.1:\e" +.br +.Ic " :remote-addr=10.0.0.2:\e" +.br +.Ic " :immediate:dialout:direct:\e" +.br +.Ic " :-pfc:-acfc:-tcpc:" +.br +Then run +.Xr ppp 8 : +.Ic "ppp -bd Plmc0" . +.br +Add +.Ic "-X debug-all" +to watch protocol events happen. +.Pp +Activate a Cisco-HDLC link by setting LINKTYPE with ifconfig: +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2 linktype chdlc" +.Pp +Activate a Fame-Relay link with: +.br +.Ic "ifconfig lmc0 linktype fr" +.br +By default the port is a DTE; add the next line to make it a DCE: +.br +.Ic "frconfig lmc0 type dce" +.br +.Ic "frconfig lmc0 lmi ansi" +.br +.Ic "frconfig lmc0 dlci 500 10.0.0.2" +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2" +.Pp +Activate a RAWIP link with: +.br +.Ic "ifconfig lmc0 down -remove" +.br +.Ic "lmcconfig lmc0 -x" +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.2" +.br \} +.if \n[linux] \{\ +.Sp +.Ss Linux Configuration +.Sp +The source files are in +.Ic "/usr/src/linux/drivers/net/wan/lmc/" . +.Pp +Configure the driver and line protocol into your kernel with +.Ic make menuconfig , +navigating through the menus, select this device driver and the +generic HDLC layer as loadable kernel modules or wired into the kernel: +.br +.Ic "Device Drivers --->" +.br +.Ic "Networking Support --->" +.br +.Ic "Wan interfaces --->" +.br +.Ic " SBE Inc. LMC1000/1200/5200/5245 support" +.br +.Ic " Generic HDLC layer" +.br +.Ic "\|" +configures code as a module and +.Ic "<*>" +wires it into the kernel. +.Pp +Selecting the Generic HDLC layer selects all available protocols. +Raw, Cisco and Frame-Relay are in the generic-hdlc module; +PPP is a separate module. +.br +.Ic "[*] Raw HDLC support" +.br +.Ic "[*] Raw HDLC Ethernet device support" +.br +.Ic "[*] Cisco HDLC support" +.br +.Ic "[*] Frame Relay support" +.br +.Ic "[*] Synchronous Point-to-Point Protocol (PPP) support" +.br +.Ic "[*]\|" +includes support for a protocol and +.Ic "[\0]" +excludes it. +.Pp +The driver can send and receive raw IP packets even if +Generic-HDLC is not configured into the kernel. +The device name will be +.Ic "hdlc" +if the generic HDLC code is used, or +.Ic "lmc" +otherwise. \} +.if \n[linux] \{\ +.Sp +.Ss Linux Loadable Kernel Modules +.Sp +If configured as above, the kernel will recognize an LMC/SBE card +when it boots and load this driver and the Generic-HDLC code. +Messages similar to the following will appear in /var/log/messages: +.br +.Ic "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994" +.br +.Ic "Linux port (c) 1998 Building Number Three Ltd & Jan 'Yenya' Kasprzak." +.br +.Ic "HDLC support module revision 1.16" +.br +.Ic "hdlc0: io 0xe880/9 mem 0xfebeff00/25" +.Ic "rom 0xfeb40000/14 irq 11 pci 0000:00:13.0" +.br +The driver registers itself under the name +.Ic "hdlc" +rather than +.Ic "lmc" +because the generic-HDLC code requires it. +.Pp +When the card and line protocol are configured these messages will appear: +.br +.Ic "hdlc0: PCI rev 2.2, MII rev 3.5, +.Ic "IEEE addr 00:60:99:00:13:c4, TXC03401 rev B" +.br +.Ic "hdlc0: Driver rev 2004.6.17, Options IO_CSR LITTLE_END" +.br +.Ic "hdlc0: protocol up" +.Pp +While standing in /usr/src/linux/drivers/net/wan/lmc: +.br +.Ic "make -C /usr/src/linux SUBDIRS=/usr/src/linux/drivers/net/wan/lmc \e" +.br +.Ic " modules modules-install " +compiles and installs the driver. +.br +.Ic "modprobe if_lmc " +loads the module into the kernel. +.br +.Ic "modprobe -r if_lmc " +removes the module from the kernel. +.br +.Ic "lsmod " +displays status of loaded modules. +.br \} +.if \n[linux] \{\ +.Sp +.Ss Linux Operation +.Sp +The program +.Ic "sethdlc" +configures the generic-HDLC code. +.br +.Ic "sethdlc hdlc0 (or pvc0 for frame relay)" +.br +displays the current settings of a given device. +Note that +.Ic "sethdlc" +must be run before +.Ic "ifconfig" . +.Ic "Sethdlc" +and the generic-hdlc kernel code are documented in +.Ic "/usr/src/linux/Documentation/networking/generic-hdlc.txt" +and at +.Ic "http://hq.pm.waw.pl/hdlc" +.Pp +Activate a PPP link with: +.br +.Ic "sethdlc hdlc0 ppp" +.br +.Ic "ifconfig hdlc0 10.0.0.1 pointopoint 10.0.0.2" +.Pp +Activate a Cisco-HDLC link with: +.br +.Ic "sethdlc hdlc0 cisco" +.br +.Ic "ifconfig hdlc0 10.0.0.1 pointopoint 10.0.0.2" +.Pp +Activate a Frame-Relay DTE link with: +.br +.Ic "sethdlc hdlc0 fr lmi ansi [dce]" +.br +.Ic "sethdlc hdlc0 create 500" +.br +.Ic "ifconfig hdlc0 up" +.br +.Ic "ifconfig pvc0 10.0.0.1 pointopoint 10.0.0.2" +.br +This is +.Em "ONE" +possible Frame Relay configuration; there are many. +Adding "dce" after "ansi" configures it as a DCE (switch). +.Pp +Activate a RAWIP link with: +.br +.Ic "sethdlc hdlc0 hdlc" +.br +.Ic "ifconfig hdlc0 10.0.0.1 pointopoint 10.0.0.2" +.br \} +.Sp +.Sh TESTING +.Sp +.Ss Testing with Loopbacks +.Sp +Testing with loopbacks requires only one card. +Packets can be looped back at many points: in the PCI chip, +in the modem chips, through a loopback plug, in the +local external equipment, or at the far end of a circuit. +.if \n[linux] \{\ +Testing with loopbacks does not work on Linux because the +kernel detects that an outgoing packet is destined for "self" +and loops it back without ever giving it to the hardware. \} +.Pp +Activate the card with ifconfig: +.br +.Ic "ifconfig lmc0 10.0.0.1 10.0.0.1" +.Pp +All cards can be looped through the PCI chip. +Cards with internal modems can be looped through +the modem framer and the modem line interface. +Cards for external modems can be looped through +the driver/receiver chips. +See +.Xr lmcconfig 8 +for details. +.Pp +Loopback plugs test everything on the card. +.Bl -tag -width "T1/E1" -offset 2m -compact +.It Sy "HSSI" +Loopback plugs can be ordered from SBE (and others). +Transmit clock is normally supplied by the external modem. +When an HSSI card is operated with a loopback plug, the PCI bus +clock must be used as the transmit clock, typically 33 MHz. +When testing an HSSI card with a loopback plug, +configure it with lmcconfig: +.br +.Ic "lmcconfig lmc0 -a 2 +.br +.Ic "-a 2 " +selects the PCI bus clock as the transmit clock. +.It Sy "T3" +Connect the two BNC jacks with a short coax cable. +.It Sy "SSI" +Loopback plugs can be ordered from SBE (only). +Transmit clock is normally supplied by the external modem. +When an SSI card is operated with a loopback plug, +the on-board clock synthesizer must be used. +When testing an SSI card with a loopback plug, +configure it with lmcconfig: +.br +.Ic "lmcconfig lmc0 -E -f 10000000" +.br +.Ic "-E " +puts the card in DCE mode to source a transmit clock. +.br +.Ic "-f 10000000 " +sets the internal clock source to 10 Mb/s. +.br +.It Sy "T1/E1" +A loopback plug is a modular plug with two wires +connecting pin 1 to pin 4 and pin 2 to pin 5. +.El +.Pp +One can also test by connecting to a local modem (HSSI and SSI) +or NI (T1 and T3) configured to loop back. +Cards can generate signals to loopback remote equipment +so that complete circuits can be tested; see +.Xr lmcconfig 8 +for details. +.Sp +.Ss Testing with a Modem +.Sp +Testing with a modem requires two cards of different types. +.Bl -tag -width "T3/HSSI" +.It Sy "T3/HSSI" +If you have a T3 modem with an HSSI interface +(made by Digital Link, Larscom, Kentrox etc.) +then use an HSSI card in one machine and a T3 card in the other machine. +The T3 coax cables must use the null modem configuration (see below). +.It Sy "T1/V.35" +If you have a T1 (or E1) modem with a V.35, X.21 or EIA530 interface, +then use an SSI card in one machine and a T1 card in the other machine. +Use a T1 null modem cable (see below). +.El +.Sp +.Ss Testing with a Null Modem Cable +.Sp +Testing with a null modem cable requires two cards of the same type. +.Bl -tag -width "T1/E1" +.It Sy "HSSI" +Three-meter HSSI null-modem cables can be ordered from SBE. +In a pinch, a 50-pin SCSI-II cable up to a few meters will +work as a straight HSSI cable (not a null modem cable). +Longer cables should be purpose-built HSSI cables because +the cable impedance is different. +Transmit clock is normally supplied by the external modem. +When an HSSI card is connected by a null modem cable, the PCI bus +clock can be used as the transmit clock, typically 33 MHz. +When testing an HSSI card with a null modem cable, configure it +with lmcconfig: +.br +.Ic "lmcconfig lmc0 -a 2 +.br +.Ic "-a 2 " +selects the PCI bus clock as the transmit clock. +.It Sy "T3" +T3 null modem cables are just 75-ohm coax cables with BNC connectors. +TX OUT on one card should be connected to RX IN on the other card. +In a pinch, 50-ohm thin Ethernet cables +.Em usually +work up to a few meters, but they will +.Em not +work for longer runs -- 75-ohm coax is +.Em required . +.It Sy "SSI" +Three-meter SSI null modem cables can be ordered from SBE. +An SSI null modem cable reports a cable type of V.36/EIA449. +Transmit clock is normally supplied by the external modem. +When an SSI card is connected by a null modem cable, +an on-board clock synthesizer is used. +When testing an SSI card with a null modem cable, configure it +with lmcconfig: +.br +.Ic "lmcconfig lmc0 -E -f 10000000" +.br +.Ic "-E " +puts the card in DCE mode to source a transmit clock. +.br +.Ic "-f 10000000 " +sets the internal clock source to 10 Mb/s. +.br +.Pp +.It Sy "T1/E1" +A T1 null modem cable has two twisted pairs that connect +pins 1 and 2 on one plug to pins 4 and 5 on the other plug. +Looking into the cable entry hole of a plug, +with the locking tab oriented down, +pin 1 is on the left. +A twisted pair Ethernet cable makes an excellent straight T1 cable. +Alas, Ethernet cross-over cables do not work as T1 null modem cables. +.El +.Sp +.Sh OPERATION NOTES +.Sp +.Ss Packet Lengths +Maximum transmit and receive packet length is unlimited. +.br +Minimum transmit and receive packet length is one byte. +.Pp +Cleaning up after one packet and setting up for the next +packet involves making several DMA references. +This can take longer than the duration of a short packet, +causing the adapter to fall behind. +For typical PCI bus traffic levels and memory system latencies, +back-to-back packets longer than about 20 bytes will always +work (53 byte cells work), but a burst of several hundred +back-to-back packets shorter than 20 bytes will cause packets +to be dropped. +This usually isn't a problem since an IPv4 packet header is +at least 20 bytes long. +.Pp +This device driver imposes no constraints on packet size. +Most operating systems set the default Maximum Transmission +Unit (MTU) to 1500 bytes; the legal range is usually (72..65535). +This can be changed with +.br +.Ic "ifconfig lmc0 mtu 2000" . +.br +.if (\n[fbsd] : \n[nbsd] : \n[obsd]) \{\ +SPPP enforces an MTU of (128..far-end-MRU) for PPP +and 1500 bytes for Cisco-HDLC. \} +.if \n[bsdi] \{\ +P2P enforces an MTU of 1500 bytes for PPP and Cisco-HDLC +and 4000 bytes for Frame Relay. \} +.if \n[linux] \{\ +Generic-HDLC enforces an MTU range of (68..1500) bytes. \} +RAWIP sets the default MTU to 4032 bytes, +but it can be changed to anything. +.if (\n[fbsd] : \n[nbsd] : \n[obsd]) \{\ +.Sp +.Ss ALTQ - Alternate Output Queue Disciplines +.Sp +This driver has hooks for +.Xr altq 4 , +the Alternate Queueing package. +To see Altq in action, use your favorite traffic generation +program to generate three flows sending down one T3 circuit. +Without Altq, the speeds of the three connections will vary chaotically. +Turn on Altq and two of the connections will run at 21 Mb/s and +the third will run at 1.5 Mb/s. +.Pp +To include ALTQ in your kernel, +add the following line to +.Ic "conf/YOURKERNEL" : +.br +.Ic "options ALTQ # ALTQ enabled" +.br +The example below requires the Hierarchical +Fair Service Curve (HSFC) queue discipline: +.br +.Ic "options ALTQ_HFSC # queue discipline" +.Pp +Enable +.Xr altqd 8 +and create file +.Ic "/etc/altq.conf" +containing: +.br +.Bd -literal -offset 2m -compact +.Ic "interface lmc0 bandwidth 44M hfsc" +.br +.Ic "class hfsc lmc0 a root pshare 49" +.br +.Ic "filter lmc0 a 10.0.0.2 12345 10.0.0.1 0 6" +.br +.Ic "filter lmc0 a 10.0.0.1 0 10.0.0.2 12345 6" +.br +.Ic "class hfsc lmc0 b root pshare 49" +.br +.Ic "filter lmc0 b 10.0.0.2 12346 10.0.0.1 0 6" +.br +.Ic "filter lmc0 b 10.0.0.1 0 10.0.0.2 12346 6" +.br +.Ic "class hfsc lmc0 c root pshare 2 default" +.br +.Ic "filter lmc0 c 10.0.0.2 12347 10.0.0.1 0 6" +.br +.Ic "filter lmc0 c 10.0.0.1 0 10.0.0.2 12347 6" +.br +.Ed \} +.if (\n[fbsd] : \n[nbsd] : \n[obsd] : \n[bsdi]) \{\ +.Sp +.Ss BPF - Berkeley Packet Filter +.Sp +This driver has hooks for +.Xr bpf 4 , +the Berkeley Packet Filter. +The line protocol header length reported to BPF is four bytes +for SPPP and P2P line protocols and zero bytes for RawIP. +.Pp +To include BPF for ifnet in your kernel, +add the following line to +.Ic "conf/YOURKERNEL" : +.br +.Ic "pseudo-device bpf # FreeBSD-4, NetBSD, OpenBSD, BSD/OS" +.br +.Ic "device bpf # FreeBSD-5" +.Pp +To test the BPF kernel interface, +bring up a link between two machines, then run +.Xr ping 8 +and +.Xr tcpdump 1 : +.br +.Ic "ping 10.0.0.1" +.br +and in a different window: +.br +.Ic "tcpdump -i lmc0" +.br +The output from tcpdump should look like this: +.br +.Ic "03:54:35.979965 10.0.0.2 > 10.0.0.1: icmp: echo request" +.br +.Ic "03:54:35.981423 10.0.0.1 > 10.0.0.2: icmp: echo reply" +.br +Line protocol control packets will appear among the +ping packets occasionally. \} +.if (\n[fbsd] : \n[linux]) \{\ +.Sp +.Ss Device Polling +.Sp +A T3 receiver can generate over 100K interrupts per second, +This can cause a system to "live-lock": spend all of its +time servicing interrupts. +Linux and FreeBSD have polling mechanisms to prevent live-lock. +.if \n[linux] \{\ +.Pp +Linux's mechanism disables a card's interrupt when it interrupts, +calls the card's interrupt service routine with kernel interrupts +enabled, and then reenables the card's interrupt. +The driver is permitted to process a limited number of packets each +time it is called by the kernel. +Card interrupts are left disabled if more packets arrive than are +permitted to be processed, which in extreme cases will result in +packets being dropped in hardware at no cost to software. \} +.if \n[fbsd] \{\ +.Pp +FreeBSD's mechanism permanently disables interrupts from the card +and instead the card's interrupt service routine is called each +time the kernel is entered (syscall, timer interrupt, etc) and +from the kernel idle loop; this adds some latency. +The driver is permitted to process a limited number of packets. +The percentage of the CPU that can be consumed this way is settable. +.Pp +FreeBSD's +.Xr polling 4 +mechanism is enabled with: +.br +.Ic "sysctl kern.polling.enable=1" +.br +The kernel must be built with polling enabled: +.br +.Ic "options DEVICE_POLLING" +.br +.Ic "options HZ=1000" \} \} +.Sp +.Ss SNMP: Simple Network Management Protocol +.Sp +This driver is aware of what is required to be a Network Interface +Object managed by an Agent of the Simple Network Management Protocol. +The driver exports SNMP-formatted configuration and status +information sufficient for an SNMP Agent to create MIBs for: +.Bl -inset -compact -offset 2m +.It RFC-2233: Interfaces group, +.It RFC-2496: DS3 interfaces, +.It RFC-2495: DS1/E1 interfaces, +.It RFC-1659: RS232-like interfaces. +.El +.Pp +An SNMP Agent is a user program, not a kernel function. +Agents can retrieve configuration and status information +by using +.if \n[fbsd] \{\ +Netgraph control messages or \} +.Xr ioctl 2 +system calls. +User programs should poll +.Ic sc->cfg.ticks +which increments once per second after the SNMP state has been updated. +.Sp +.Ss HSSI and SSI LEDs +.Sp +The card should be operational if all three green LEDs are on +(the upper-left one should be blinking) and the red LED is off. +All four LEDs turn on at power-on and module-unload. +.Bl -column -compact -offset 2m "YELLOW" "upper-right" "Software" +.It "RED" Ta "upper-right" Ta "No Transmit clock" +.It "GREEN" Ta "upper-left" Ta "Device driver is alive if blinking" +.It "GREEN" Ta "lower-right" Ta "Modem signals are good" +.It "GREEN" Ta "lower-left" Ta "Cable is plugged in (SSI only)" +.El +.Sp +.Ss T1E1 and T3 LEDs +.Sp +The card should be operational if the upper-left green LED is blinking +and all other LEDs are off. For the T3 card, if other LEDs are on or +blinking, try swapping the coax cables! +All four LEDs turn on at power-on and module-unload. +.Bl -column -compact -offset 2m "YELLOW" "upper-right" "Received" +.It "RED" Ta "upper-right" Ta "Received signal is wrong" +.It "GREEN" Ta "upper-left" Ta "Device driver is alive if blinking" +.It "BLUE" Ta "lower-right" Ta "Alarm Information Signal (AIS)" +.It "YELLOW" Ta "lower-left" Ta "Remote Alarm Indication (RAI)" +.El \" YELLOW +.Bl -column -compact "The yellow" "LED" +.It "The green" Ta "LED blinks if the device driver is alive." +.It "The red" Ta "LED blinks if an outward loopback is active." +.It "The blue" Ta "LED blinks if sending AIS, on solid if receiving AIS." +.It "The yellow" Ta "LED blinks if sending RAI, on solid if receiving RAI." +.El \" LED +.Sp +.Ss E1 Framing +.Sp +Phone companies usually insist that customers put a +.Em Frame Alignment Signal +(FAS) in time slot 0. +A Cyclic Redundancy Checksum (CRC) can also ride in time slot 0. +.Em Channel Associated Signalling +(CAS) uses Time Slot 16. +In telco-speak +.Em signalling +is on/off hook, ringing, busy, etc. +Signalling is not needed here and consumes 64 Kb/s. +Only use E1-CAS formats if the other end insists on it! +Use E1-FAS+CRC framing format on a public circuit. +Depending on the equipment installed in a private circuit, +it may be possible to use all 32 time slots for data (E1-NONE). +.Sp +.Ss T3 Framing +.Sp +M13 is a technique for multiplexing 28 T1s into a T3. +Muxes use the C-bits for speed-matching the tributaries. +Muxing is not needed here and usurps the FEBE and FEAC bits. +Only use T3-M13 format if the other end insists on it! +Use T3-CParity framing format if possible. +Loop Timing, Fractional T3, and HDLC packets in +the Facility Data Link are +.Em not +supported. +.Sp +.Ss T1 & T3 Frame Overhead Functions +.Sp +Performance Report Messages (PRMs) are enabled in T1-ESF. +.br +Bit Oriented Protocol (BOP) messages are enabled in T1-ESF. +.br +In-band loopback control (framed or not) is enabled in T1-SF. +.br +Far End Alarm and Control (FEAC) msgs are enabled in T3-CPar. +.br +Far End Block Error (FEBE) reports are enabled in T3-CPar. +.br +Remote Alarm Indication (RAI) is enabled in T3-Any. +.br +Loopbacks initiated remotely time out after 300 seconds. +.Sp +.Ss T1/E1 'Fractional' 64 kb/s Time Slots +.Sp +T1 uses time slots 24..1; E1 uses time slots 31..0. +E1 uses TS0 for FAS overhead and TS16 for CAS overhead. +E1-NONE has +.Em no +overhead, so all 32 TSs are available for data. +Enable/disable time slots by setting 32 1s/0s in a config param. +Enabling an E1 overhead time slot, +or enabling TS0 or TS25-TS31 for T1, +is ignored by the driver, which knows better. +The default TS param, 0xFFFFFFFF, enables the maximum number +of time slots for whatever frame format is selected. +56 Kb/s time slots are +.Em not +supported. +.Sp +.Ss T1 Raw Mode +.Sp +Special gate array microcode exists for the T1/E1 card. +Each T1 frame of 24 bytes is treated as a packet. +A raw T1 byte stream can be delivered to main memory +and transmitted from main memory. +The T1 card adds or deletes framing bits but does not +touch the data. +ATM cells can be transmitted and received this way, with +the software doing all the work. +But that's not hard; after all it's only 1.5 Mb/s second! +.Sp +.Ss T3 Circuit Emulation Mode +.Sp +Special gate array microcode exists for the T3 card. +Each T3 frame of 595 bytes is treated as a packet. +A raw T3 signal can be +.Em packetized , +transported through a +packet network (using some protocol) and then +.Em reconstituted +as a T3 signal at the far end. The output transmitter's +bit rate can be controlled from software so that it can be +.Em frequency locked +to the distant input signal. +.Sp +.Ss HSSI and SSI Transmit Clocks +.Sp +Synchronous interfaces use two transmit clocks to eliminate +.Em skew +caused by speed-of-light delays in the modem cable. +DCEs (modems) drive ST, Send Timing. the first transmit clock. +DTEs (hosts) receive ST and use it to clock transmit data, TD, +onto the modem cable. +DTEs also drive a copy of ST back towards the DCE and call it TT, +Transmit Timing. the second trasmit clock. +DCEs receive TT and TD and use TT to clock TD into a flip flop. +TT experiences the same delay as (and has no +.Em skew +relative to) TD. +Thus, cable length does not affect data/clock timing. +.Sp +.Sh SEE ALSO +.Sp +.Xr tcpdump 1 , +.Xr ioctl 2 , +.if (\n[fbsd] : \n[nbsd] : \n[obsd]) \{\ +.Xr altq 4 , \} +.if (\n[fbsd] : \n[nbsd] : \n[obsd] : \n[bsdi]) \{\ +.Xr bpf 4 , \} +.if \n[fbsd] \{\ +.Xr kld 4 , +.Xr loader.conf 5 , +.Xr netgraph 4 , \} +.if \n[bsdi] \{\ +.Xr p2p 4 , \} +.if \n[fbsd] \{\ +.Xr polling 4 , \} +.if (\n[fbsd] : \n[nbsd] : \n[obsd]) \{\ +.Xr sppp 4 , +.Xr altqd 8 , \} +.if \n[bsdi] \{\ +.Xr frconfig 8 , \} +.Xr ifconfig 8 , +.if (\n[fbsd] : \n[nbsd] : \n[obsd]) \{\ +.Xr init 8 , \} +.if (\n[nbsd] : \n[obsd]) \{\ +.Xr lkm 8 , \} +.if \n[fbsd] \{\ +.Xr mpd 8 , +.Xr ngctl 8 , \} +.Xr ping 8 , +.if \n[bsdi] \{\ +.Xr ppp 8 , \} +.Xr lmcconfig 8 , +.if (\n[fbsd] : \n[nbsd] : \n[obsd] : \n[bsdi]) \{\ +.Xr ifnet 9 . \} +.if \n[fbsd] \{\ +.Pp +.Pa /usr/ports/net/mpd . \} +.if \n[linux] \{\ +.Pp +.Pa http://hq.pm.waw.pl/hdlc . \} +.Pp +.Pa http://www.sbei.com . +.Sp +.Sh HISTORY +.Sp +Ron Crane had the idea to use a Fast Ethernet chip as a PCI interface +and add an Ethernet-to-HDLC gate array to make a WAN card. +David Boggs designed the Ethernet-to-HDLC gate array and PC cards. +We did this at our company, LAN Media Corporation +.Tn (LMC) . +.Tn SBE +Corp aquired +.Tn LMC +and continues to make the cards. +.Pp +Since the cards use Tulip Ethernet chips, we started with Matt Thomas' +ubiquitous "de" driver. Michael Graff stripped out the Ethernet stuff +and added HSSI stuff. Basil Gunn ported it to Solaris (lost) and +Rob Braun ported it to Linux. Andrew Stanley-Jones added support +for three more cards and wrote the first version of lmcconfig. +David Boggs rewrote everything and now feels responsible for it. +.Sp +.Sh AUTHOR +.Sp +.An "David Boggs" Aq boggs@boggs.palo-alto.ca.us . diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index c4556f577d64..a59ea002031d 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -72,6 +72,7 @@ SUBDIR= ac \ lastlogin \ ${_lpr} \ ${_lptcontrol} \ + lmcconfig \ ${_mailstats} \ mailwrapper \ ${_makemap} \ diff --git a/usr.sbin/lmcconfig/Makefile b/usr.sbin/lmcconfig/Makefile new file mode 100644 index 000000000000..df8b773e4e34 --- /dev/null +++ b/usr.sbin/lmcconfig/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +MAN8= lmcconfig.8 +PROG= lmcconfig + +LDADD= -lnetgraph +DPADD= ${LIBNETGRAPH} + +.include diff --git a/usr.sbin/lmcconfig/lmcconfig.8 b/usr.sbin/lmcconfig/lmcconfig.8 new file mode 100644 index 000000000000..5f48963e5232 --- /dev/null +++ b/usr.sbin/lmcconfig/lmcconfig.8 @@ -0,0 +1,716 @@ +.\" +.\" $FreeBSD$ +.\" +.\" Copyright (c) 2003 David Boggs. (boggs@boggs.palo-alto.ca.us) +.\" All rights reserved. +.\" +.\" BSD License: +.\" +.\" 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. +.\" +.\" GNU General Public License: +.\" +.\" This program is free software; you can redistribute it and/or modify it +.\" under the terms of the GNU General Public License as published by the Free +.\" Software Foundation; either version 2 of the License, or (at your option) +.\" any later version. +.\" +.\" This program is distributed in the hope that it will be useful, but WITHOUT +.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +.\" more details. +.\" +.\" You should have received a copy of the GNU General Public License along with +.\" this program; if not, write to the Free Software Foundation, Inc., 59 +.\" Temple Place - Suite 330, Boston, MA 02111-1307, USA. +.\" +.\" I forget these things: +.\" groff -Tascii -mdoc lmcconfig.8 > lmcconfig.txt +.\" groff -Tps -mdoc lmcconfig.8 > lmcconfig.ps +.\" groff -Thtml -mdoc lmcconfig.8 > lmcconfig.html (buggy) +.\" +.Dd June 2005 +.Dt LMCCONFIG 8 +.Os +.Sp +.Sh NAME +.Sp +.Nm lmcconfig +.Nd configuration program for +.Tn SBE +(formerly +.Tn LMC ) +wide-area network interface cards. +.Sp +.Sh SYNOPSIS +.Sp +.Nm +.Ar interface +.Op Fl abBcCdDeEfhLmMpPrsStTuwxXyYzZ? +.br +.Nm +.Ar interface +.Fl 1 +.Op Fl aABceEfFgiIlLpPstTuUxX +.br +.Nm +.Ar interface +.Fl 3 +.Op Fl aABcefFlLsSv +.Sp +.Sh DESCRIPTION +.Sp +.Nm +is the configuration program for the +.Xr lmc 4 +wide-area network device driver. +It sets control values, such as T3 framing format, +and it displays status, such as that of integrated modems, +that are beyond the scope of +.Xr ifconfig 8 . +.Pp +.Nm +displays the interface status when no parameters are specified; +see example below. +For this case only, if no +.Ar interface +is specified, it defaults to +.Ic lmc0 . +.Pp +Only the super-user may modify the configuration of a network interface. +.Pp +The following options are available: +.Bl -tag -width indent +.It Ar interface +This is the name of the interface; the default is +.Cm lmc0 . +If +.Xr netgraph 4 +is present and the interface name ends with a colon +then netgraph control messages are used, +otherwise the +.Xr ifnet 9 +kernel interface and socket +.Xr ioctl 2 +system calls are used. +.It Fl 1 +All parameters after this apply to the T1E1 card. +.It Fl 3 +All parameters after this apply to the T3 card. +.El +.Sp +.Ss Commands for all cards +.Sp +The following parameters apply to more then one card type. +.Bl -tag -width indent +.It Fl a Ar number +Set Transmitter clock source to +.Ar number . +.Bl -column "1" "External connector" "T1E1, HSSIc" -offset 2m -compact +.It "1" Ta "TxClk from modem" Ta "T1E1, HSSI" Ta "default" +.It "2" Ta "Internal source" Ta "T1E1, HSSI" +.It "3" Ta "RxClk from modem" Ta "T1E1, HSSIc" Ta "loop timed" +.It "4" Ta "External connector" Ta "T1E1, HSSIc" +.El +.Pp +An HSSI card normally takes its Tx clock from the modem connector +(it is a DTE) but can use the PCI bus clock (typically 33 MHz) +for loopback and null modem testing; values 3 and 4 are only +applicable to a few rare CompactPCI/HSSI cards. +.Pp +A T1E1 card uses an on-board synthesized oscillator +if the value is 1 or 2; it +.Em loop times +(uses the clock recovered by the receiver as the transmitter clock) +if the value is 3; and it uses a clock from a header connector on +the card if the value is 4. +.Pp +TxClk source is not applicable to other card types. +.It Fl b +Read BIOS rom. +Print the first 256 locations. +The BIOS rom is not used and not present on some cards. +.It Fl B +Write BIOS rom. +Write the first 256 locations with an address pattern. +.It Fl c +Use HDLC's 16-bit CRC polynomial: X^16+X^12+X^5+1 (default) +.Bd -ragged -compact +.It Fl C +Use HDLC's 32-bit CRC polynomial: +X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X+1 +.Ed +.It Fl d +Clear the driver-level debug flag. Non-critical log messages are suppressed. +.It Fl D +Set the driver-level debug flag. The driver generates more log messages. +The driver also generates more log messages if the interface-level debug +flag is set by +.Xr ifconfig 8 . +.It Fl e +Set DTE (Data Terminal Equipment) mode (default). +An SSI card transmitter uses the Tx clock signal from the modem connector +and receives the Data Carrier Detect pin (DCD). +DTE/DCE is not applicable to other card types except +a few rare CompactPCI/HSSI cards. +.It Fl E +Set DCE (Data Communication Equipment) mode. +An SSI card transmitter uses an on-board synthesized oscillator +and drives the Data Carrier Detect pin (DCD). +.It Fl f Ar number +Set the frequency of the built-in synthesized oscillator to +.Ar number +bits/second. +The nearest frequency that the synthesizer can generate will be used. +Only SSI cards and a few rare CompactPCI/HSSI cards have synthesizers. +.It Fl F +Set SPPP line protocol to Frame-Relay. +Only works for FreeBSD-5.4 and later. +Not applicable to Linux, NetBSD, OpenBSD. or BSD/OS. +.It Fl h +Print help (usage message). +.It Fl i +Set interface name (eg. 'lmc0'). +.It Fl L Ar number +Set loopback mode to +.Ar number . +.Bl -column "99" "payload" "inward thru drvrs/rcvrsxxx" "HSSI, SSI" -offset 1m -compact +.It "1" Ta "none" Ta "default" +.It "2" Ta "payload" Ta "outward thru framer" Ta "T1E1. T3" +.It "3" Ta "line" Ta "outward thru line if" Ta "T1E1, T3, HSSIc" +.It "4" Ta "other" Ta "inward thru line if" Ta "T1E1, T3" +.It "5" Ta "inward" Ta "inward thru framer" Ta "T1E1, T3" +.It "6" Ta "dual" Ta "inward and outward" Ta "T1E1, T3" +.It "16" Ta "tulip" Ta "inward thru Tulip chip" Ta "all cards" +.It "17" Ta "pins" Ta "inward thru drvrs/rcvrs" Ta "SSI" +.It "18" Ta "LA/LL" Ta "assert LA/LL modem pin" Ta "HSSI, SSI" +.It "19" Ta "LB/RL" Ta "assert LB/RL modem pin" Ta "HSSI, SSI" +.El +.It Fl m +Read Tulip MII registers. +Print the 32 16-bit registers in the Media Independent Interface. +.It Fl M Ar addr Ar data +Write Tulip MII register. +Write +.Ar data +into register +.Ar addr . +.It Fl p +Read Tulip PCI configuration registers. +Print the first 16 32-bit registers in the PCI configuration space. +.It Fl P Ar addr Ar data +Write Tulip PCI configuration register. +Write +.Ar data +into register +.Ar addr . +.It Fl s +Read Tulip SROM. +Print the 64 16-bit locations. +The PCI subsystem vendor and device IDs are kept here. +.It Fl S Ar number +Write Tulip SROM. +Initializes the Tulip SROM to card type +.Ar number . +.Bl -tag -width 1m -offset 1m -compact +.It 3 Ta HSSI +.It 4 Ta T3 +.It 5 Ta SSI +.It 6 Ta T1E1 +.It 7 Ta HSSIc +.It 8 Ta SDSL +.It 0 Ta auto-set from MII PHYID +.El +If +.Ar number +is zero, then the card type is computed from the gate array +microcode version field in the MII PHYID register. +.Em CAUTION : +if the SROM is incorrect, the card will be unusable! +This command is +.Em so +dangerous that lmcconfig must be edited and recompiled to enable it. +.It Fl t +Read Tulip CSRs. +Print the 16 32-bit control and status registers. +.It Fl T Ar addr Ar data +Write Tulip CSR. +Write +.Ar data +into csr number +.Ar addr . +Note that addr is a CSR number (0-15) not a byte offset into CSR space. +.It Fl u +Reset event counters to zero. +The driver counts events like packets in and out, errors, discards, etc. +The time when the counters are reset is remembered. +.It Fl U +Reset gate array. +Not needed during normal operation; just for testing. +.It Fl v +Set verbose mode: print more stuff. +.It Fl V +Print the card configuration -- see the EXAMPLES section. +.It Fl w +Load gate array from on-board rom. +Not needed during normal operation; just for testing. +.It Fl W Ar filename +Load gate array microcode from +.Ar filename . +.It Fl x +Select RAWIP mode -- bypass line protocol code. +.It Fl X +Select line protocol code rather than RAWIP mode. +.It Fl y +Disable SPPP keep-alive packets, +Only works for FreeBSD, NetBSD and OpenBSD. +Not applicable to Linux or BSD/OS. +.It Fl Y +Enable SPPP keep-alive packets. +Only works for FreeBSD, NetBSD and OpenBSD. +Not applicable to Linux or BSD/OS. +.It Fl z +Set SPPP line protocol to Cisco-HDLC. +Only works for FreeBSD, NetBSD and OpenBSD. +Not applicable to Linux or BSD/OS. +.It Fl Z +Set SPPP line protocol to PPP. +Only works for FreeBSD, NetBSD and OpenBSD. +Not applicable to Linux or BSD/OS. +.It Fl ? +Print help (usage message). +.El +.Sp +.Ss Commands for T1E1 cards +.Sp +The following parameters apply to the T1E1 card type: +.Bl -tag -width indent +.It Fl a Ar y|a|b +Stop sending alarm signal. +.Bl -column "y" "Yellow Alarm" "unframed all ones; aka AIS" -offset 1m -compact +.It "y" Ta "Yellow Alarm" Ta "varies with framing" +.It "a" Ta "Red Alarm" Ta "unframed all ones; aka AIS" +.It "b" Ta "Blue Alarm" Ta "unframed all ones" +.El +Red alarm, also known as AIS (Alarm Indication Signal), +and Blue alarm are identical in T1. +.It Fl A Ar y|a|b +Start sending alarm signal (see table above). +.It Fl B Ar number +Send a Bit Oriented Protocol (BOP) message with code +.Ar number. +BOP codes are six bits. +.It Fl c Ar number +Set cable length to +.Ar number +meters (default: 10 meters). +This is used to set receiver sensitivity +and transmitter line build-out. +.It Fl d +Print the status of the on-board DSU/CSU -- see the EXAMPLES section. +.It Fl e Ar number +Set the framing format to +.Ar number : +.Bl -tag -width 1m -offset 1m -compact +.It 9 Ta T1-SF/AMI +.It 27 Ta T1-ESF/B8ZS (default) +.It 0 Ta E1-FAS +.It 8 Ta E1-FAS+CRC +.It 16 Ta E1-FAS+CAS +.It 24 Ta E1-FAS+CRC+CAS +.It 32 Ta E1-NO-framing +.El +.It Fl E Ar number +Enable 64Kb time slots (TSs) for the T1E1 card. +.Ar number +is a 32-bit hex number (default 0xFFFFFFFF). +The LSB is TS0 and the MSB is TS31. +TS0 and TS25-31 are ignored in T1 mode. +TS0 and TS16 are determined by the framing format in E1 mode. +.It Fl f +Read framer registers. +Print the 512 8-bit registers in the framer chip. +.It Fl F Ar addr Ar data +Write framer register. +Write +.Ar data +into register +.Ar addr . +.It Fl g Ar number +Set receiver gain range to +.Ar number : +.Bl -column "0x00" "Medium" "auto-set based on cable length (default)" -offset 1m -compact +.It "0x24" Ta "Short" Ta "0 to 20 dB of equalized gain" +.It "0x2C" Ta "Medium" Ta "0 to 30 dB of equalized gain" +.It "0x34" Ta "Long" Ta "0 to 40 dB of equalized gain" +.It "0x3F" Ta "Extend" Ta "0 to 64 dB of equalized gain (wide open)" +.It "0xFF" Ta "Auto" Ta "auto-set based on cable length (default)" +.El +This sets the level at which +.Em Loss-Of-Signal +is declared. +.It Fl i +Send a +.Em CSU loopback deactivate +inband command (T1-SF only). +.It Fl I +Send a +.Em CSU loopback activate +inband command (T1-SF only). +.It Fl l +Send a +.Em line loopback deactivate +BOP message (T1-ESF only). +.It Fl L +Send a +.Em line loopback activate +BOP message (T1-ESF only). +.It Fl p +Send a +.Em payload loopback deactivate +BOP message (T1-ESF only). +.It Fl P +Send a +.Em payload loopback activate +BOP message (T1-ESF only). +.It Fl s +Print the status of the on-board DSU/CSU -- see the EXAMPLES section. +.It Fl t +Stop sending test pattern. +.It Fl T Ar number +Start sending test pattern +.Ar number : +.Bl -tag -width 1m -offset 1m -compact +.It 0 Ta unframed X^11+X^9+1 +.It 1 Ta unframed X^15+X^14+1 +.It 2 Ta unframed X^20+X^17+1 +.It 3 Ta unframed X^23+X^18+1 +.It 4 Ta unframed X^11+X^9+1 with 7ZS +.It 5 Ta unframed X^15+X^14+1 with 7ZS +.It 6 Ta unframed X^20+X^17+1 with 14ZS (QRSS) +.It 7 Ta unframed X^23+X^18+1 with 14ZS +.It 8 Ta framed X^11+X^9+1 +.It 9 Ta framed X^15+X^14+1 +.It 10 Ta framed X^20+X^17+1 +.It 11 Ta framed X^23+X^18+1 +.It 12 Ta framed X^11+X^9+1 with 7ZS +.It 13 Ta framed X^15+X^14+1 with 7ZS +.It 14 Ta framed X^20+X^17+1 with 14ZS (QRSS) +.It 15 Ta framed X^23+X^18+1 with 14ZS +.El +.It Fl u Ar number +Set transmit pulse shape to +.Ar number : +.Bl -tag -width 1m -offset 1m -compact +.It 0 Ta T1 DSX 0 to 40 meters +.It 2 Ta T1 DSX 40 to 80 meters +.It 4 Ta T1 DSX 80 to 120 meters +.It 6 Ta T1 DSX 120 to 160 meters +.It 8 Ta T1 DSX 160 to 200 meters +.It 10 Ta E1 75-ohm coax pair +.It 12 Ta E1 120-ohm twisted pairs +.It 14 Ta T1 CSU 200 to 2000 meters; set LBO +.It 255 Ta auto-set based on cable length and framing format (default) +.El +.It Fl U Ar number +Set transmit line build-out to +.Ar number : +.Bl -column "255" "22.5 dB" "FCC option A" -offset 1m -compact +.It " 0" Ta "0 dB" Ta "FCC option A" +.It " 16" Ta "7.5 dB" Ta "FCC option B" +.It " 32" Ta "15 dB" Ta "FCC option C" +.It " 48" Ta "22.5 dB" Ta "final span" +.It "255" Ta "auto-set based on cable length (default)" +.El +This is only applicable if the pulse shape is T1-CSU. +.It Fl v +Set verbose mode: print more stuff. +.It Fl x +Disable transmitter outputs. +.It Fl X +Enable transmitter outputs. +.El +.Sp +.Ss Commands for T3 cards +.Sp +The following parameters apply to the T3 card type: +.Bl -tag -width indent +.It Fl a Ar y|a|b|i +Stop sending alarm signal. +.Bl -column "y" "Yellow Alarm" "framed 1010... aka AIS" -offset 1m -compact +.It "y" Ta "Yellow Alarm" Ta "X-bits set to 0" +.It "a" Ta "Red Alarm" Ta "framed 1010... aka AIS" +.It "b" Ta "Blue Alarm" Ta "unframed all-ones" +.It "i" Ta "Idle signal" Ta "framed 11001100..." +.El +.It Fl A Ar y|a|b|i +Start sending alarm signal (see table above). +.It Fl B Ar number +Send a BOP (Bit Oriented Protocol) message with code +.Ar number . +BOP codes are six bits. +.It Fl c Ar number +Set cable length to +.Ar number +meters (default: 10 meters). +This is used to set receiver sensitivity +and transmitter line build-out. +.It Fl d +Print the status of the on-board T3 DSU -- see the EXAMPLES section. +.It Fl e Ar number +Set the framing format to +.Ar number : +.Bl -tag -width 1m -offset 1m -compact +.It 100 Ta T3-C-bit parity +.It 101 Ta T3-M13 format +.El +.It Fl f +Read framer registers. +Print the 22 8-bit registers in the framer chip. +.It Fl F Ar addr Ar data +Write framer register. +Write +.Ar data +into register +.Ar addr . +.It Fl l +Send a +.Em line loopback deactivate +BOP message. +.It Fl L +Send a +.Em line loopback activate +BOP message. +.It Fl s +Print the status of the on-board T3 DSU -- see the EXAMPLES section. +.It Fl S Ar number +Set payload scrambler polynominal to +.Ar number : +.Bl -tag -width 1m -offset 1m -compact +.It 1 Ta payload scrambler disabled +.It 2 Ta X^43+1: DigitalLink and Kentrox +.It 3 Ta X^20+X^17+1 w/28ZS: Larscom +.El +Payload scrambler polynomials are not standardized. +.It Fl v +Set verbose mode: print more stuff. +.It Fl V Ar number +Set transmit frequency offset to +.Ar number . +Some T3 cards can offset the transmitter frequency from 44.736 MHz. +.Ar Number +is in the range (0..4095); 2048 is zero offset; step size is about 3 Hz. +.Ar Number +is written to a Digital-Analog Converter (DAC) which connects +to a Voltage Controlled Crystal Oscillator (VCXO). +.El +.Sp +.Ss Event Counters +.Sp +The device driver counts many interesting events such as +packets in and out, errors and discards. +The table below lists the event counters and describes what they count. +.Bl -tag -width "underruns" +.It ibytes +Bytes received in packets with good ending status. +.It obytes +Bytes transmitted. +.It ipackets +Packets received with good ending status. +.It opackets +Packets transmitted. +.It ierrors +Packets received with bad ending status. +.It oerrors +Packets transmitted with bad ending status. +.It idiscards +Packets received but discarded because +the input queue was full or the interface was down. +.It odiscards +Packets presented for transmission but discarded because +the output queue was full or the interface was down. +.It txdma +Packets presented for transmission but queued and retried later +because no DMA descriptors were available. +This can happen during normal operation and is not an indication of trouble. +.It fifo-overrun +Packets that started to arrive, but were aborted because +the card was unable to DMA data to memory fast enough +to prevent the receiver fifo from overflowing. +.It fifo-underrun +Packets that started to transmit but were aborted because +the card was unable to DMA data from the memory fast enough +to prevent the transmitter fifo from underflowing. +When this happens, the transmitter threshold is increased, +so that more bytes are required to be in the fifo +before the transmitter is started. +.It missed +Packets that are missed because the receiver is stopped. +.It overruns +Packets that are missed because the receiver +had no DMA descriptors available. +.It fdl_pkts +Packets received on the T1 Facility Data Link. +.It crc-errs +Cyclic Redundancy Checksum errors detected by the CRC-6 in +T1 Extended SuperFrames (ESF) or the CRC-4 in E1 frames. +.It lcv-errs +Line Coding Violation errors: +Alternate Mark Inversion (AMI) errors for T1-SF, +Bipolar 8-Zero Substitution (B8ZS) errors for T1-ESF, or +High Density Bipolar with 3-Zero Substitution (HDB3) errors for E1 or +Bipolar 3-Zero Substitution (B3ZS) errors for T3. +.It frm-errs +T1 or T3 bit errors in the frame alignment signal. +.It febe-errs +Far End Block Errors: +T1 or T3 bit errors detected by the device at the far end of the link. +.It par-errs +T3 bit errors detected by the hop-by-hop parity mechanism. +.It cpar-errs +T3 bit errors detected by the end-to-end parity mechanism. +.It mfrm-errs +T3 bit errors in the multi-frame alignment signal. +.El +.Sp +.Ss Transmit Speed +.Sp +The hardware counts transmit clocks divided by 2048. +The software computes "Tx speed" from this (see examples below). +The transmit clock is the bit rate of the circuit divided by two if the +circuit is idle and divided by four if the circuit is carrying a packet. +So an idle circuit reports a Tx speed equal to its bit rate, +and a busy circuit reports a Tx speed equal to half its bit rate. +.Pp +This "bit rate" does not include circuit-level overhead bits +(such as T1 or T3 frame bits) but does include HDLC stuff bits. +An idle T1 circuit with a raw bit rate of 1544000 and a +bit-rate-minus-overhead of 1536000 will report a "Tx speed" +of ((1536000 bitand 4095) plus or minus 4096). +Sometimes it will even get the correct answer of 1536000, and +if the link is fully loaded it will report about 768000 bits/sec. +.Pp +It's not a perfect bit rate meter (the circuit must be idle), +but it is a useful circuit utilization meter if you know the +circuit bit rate and do some arithmetic. Software recalculates +Tx speed once a second; the measurement period has some jitter. +.Sp +.Sh EXAMPLES +.Sp +.Bd -unfilled -compact +When lmc0 is a T1E1 card, +.br +.Ic lmcconfig lmc0 +generates the following output: +.Ed +.Bd -literal -offset 2m -compact +Card name: lmc0 +Card type: SBE/LMC T1E1 card +Link status: Up +Tx Speed: 1548288 +Line Prot/Pkg: Frame-Relay/SPPP +SPPP Keep-alives: OFF +CRC length: 16 bits +Loopback: None +Tx Clk src: Internal source +Format-Frame/Code: T1-ESF/B8ZS +TimeSlot [31-0]: 0x01FFFFFE +Cable length: 10 meters +Tx pulse shape: auto-set to T1-DSX: 0 to 40 meters +Rx gain max: auto-set to 20.0 dB +Current time: Thu Sep 29 21:48:51 2005 +Cntrs reset: Thu Sep 29 16:21:05 2005 +RX bytes: 15053836 +RX packets: 23271 +TX bytes: 1732169 +TX packets: 20526 +Rx fdl pkts: 5443 +.Ed +.Bd -unfilled +When lmc0 is a T1E1 card, +.br +.Ic lmcconfig lmc0 -1 -d +generates the following output: +.Ed +.Bd -literal -offset 2m -compact +Format-Frame/Code: T1-ESF/B8ZS +TimeSlot [31-0]: 0x01FFFFFE +Tx Clk src: Internal source +Tx Speed: 1548288 +Tx pulse shape: T1-DSX: 0 to 40 meters +Tx outputs: Enabled +Line impedance: 100 ohms +Max line loss: 20.0 dB +Cur line loss: 3.1 dB +Invert data: No +Line loop: No +Payload loop: No +Framer loop: No +Analog loop: No +Tx AIS: No +Rx AIS: No +Tx BOP RAI: No +Rx BOP RAI: No +Rx LOS analog: No +Rx LOS digital: No +Rx LOF: No +Tx QRS: No +Rx QRS: No +LCV errors: 0 +CRC errors: 0 +Frame errors: 0 +Sev Err Frms: 0 +Change of Frm align: 0 +Loss of Frame events: 0 +Last Tx BOP msg: 0x00 (Yellow Alarm (far end LOF)) +Last Rx BOP msg: 0x00 (Yellow Alarm (far end LOF)) +SNMP Near-end performance data: + LCV=0 LOS=0 FE=0 CRC=0 AIS=0 SEF=0 OOF=0 RAI=0 +ANSI Far-end performance reports: + SEQ=1 CRC=0 SE=0 FE=0 LV=0 SL=0 LB=0 + SEQ=0 CRC=0 SE=0 FE=0 LV=0 SL=0 LB=0 + SEQ=3 CRC=0 SE=0 FE=0 LV=0 SL=0 LB=0 + SEQ=2 CRC=0 SE=0 FE=0 LV=0 SL=0 LB=0 +.Ed +.Sp +.Sh DIAGNOSTICS +.Sp +Messages indicating the specified interface does not exist, or +the user is not privileged and tried to alter an interface's configuration. +.Sp +.Sh SEE ALSO +.Sp +.Xr ioctl 2 , +.Xr netgraph 4 , +.Xr lmc 4 , +.Xr ifconfig 8 , +.Xr ifnet 9 . +.Pp +.Pa http://www.sbei.com . +.Sp +.Sh HISTORY +.Sp +This is a total rewrite of the program lmcctl by Andrew Stanley-Jones. +.Sp +.Sh AUTHOR +.Sp +.An "David Boggs" Aq boggs@boggs.palo-alto.ca.us . diff --git a/usr.sbin/lmcconfig/lmcconfig.c b/usr.sbin/lmcconfig/lmcconfig.c new file mode 100644 index 000000000000..f94c4d1bb6cc --- /dev/null +++ b/usr.sbin/lmcconfig/lmcconfig.c @@ -0,0 +1,2483 @@ +/* + * First author: Michael Graff. + * Copyright (c) 1997-2000 Lan Media Corp. (www.lanmedia.com). + * All rights reserved. + * + * Second author: Andrew Stanley-Jones. + * Copyright (c) 2000-2002 SBE Corp. (www.sbei.com). + * All rights reserved. + * + * Third author: David Boggs. + * Copyright (c) 2002-2004 David Boggs. (boggs@boggs.palo-alto.ca.us). + * All rights reserved. + * + * BSD License: + * + * 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. + * + * GNU General Public License: + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Description: + * + * This program configures the Unix/Linux device driver for SBE Corp's + * wanADAPT and wanPMC series of Wide Area Network Interface Cards. + * There is a man page for this program; go find it. + * + * If Netgraph is present (FreeBSD only): + * cc -o lmcconfig -l netgraph -D NETGRAPH lmcconfig.c + * If Netgraph is NOT present: + * cc -o lmcconfig lmcconfig.c + * Install the executable program in /usr/local/sbin/lmcconfig. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#if defined(NETGRAPH) +# include +#endif +#include +#include +#include +#include +#include +#include + +#include + +/* program global variables */ +char * progname; /* name of this program */ +char * ifname; /* interface name */ +int fdcs; /* ifnet File Desc or ng Ctl Socket */ +struct status status; /* card status (read only) */ +struct config config; /* card configuration (read/write) */ +int netgraph = 0; /* non-zero if netgraph present */ +int summary = 0; /* print summary at end */ +int update = 0; /* update driver config */ +int verbose = 0; /* verbose output */ +u_int8_t checksum; /* gate array ucode file checksum */ + +void usage() + { + fprintf(stderr, "Usage: %s interface [-abBcCdDeEfhiLmMpPsStTuUvVwWxXyYzZ?]\n", progname); + fprintf(stderr, "or\n"); + fprintf(stderr, "Usage: %s interface -1 [-aABcdeEfFgiIlLpPstTuUvxX]\n", progname); + fprintf(stderr, "or\n"); + fprintf(stderr, "Usage: %s interface -3 [-aABcdefFlLsSvV]\n\n", progname); + fprintf(stderr, "\tInterface is the interface name, e.g. '%s'\n", ifname); +#if defined(NETGRAPH) + fprintf(stderr, "\tIf interface name ends with ':' then use netgraph\n"); +#endif + fprintf(stderr, "\t-1 following parameters apply to T1E1 cards\n"); + fprintf(stderr, "\t-3 following parameters apply to T3 cards\n"); + fprintf(stderr, "\t-a Set Tx clock source, where:\n"); + fprintf(stderr, "\t 1:modem Tx clk 2:int src 3:modem Rx Clk 4:ext conn\n"); + fprintf(stderr, "\t-b Read and print bios rom addrs 0-255\n"); + fprintf(stderr, "\t-B Write bios rom with address pattern\n"); + fprintf(stderr, "\t-c Set 16-bit CRC (default)\n"); + fprintf(stderr, "\t-C Set 32-bit CRC\n"); + fprintf(stderr, "\t-d Clear driver DEBUG flag\n"); + fprintf(stderr, "\t-D Set driver DEBUG flag (more log msgs)\n"); + fprintf(stderr, "\t-e Set DTE mode (default)\n"); + fprintf(stderr, "\t-E Set DCE mode\n"); + fprintf(stderr, "\t-f Set synth osc freq in bits/sec\n"); + fprintf(stderr, "\t-F Set SPPP line protocol to Frame-Relay\n"); + fprintf(stderr, "\t-h Help: this usage message\n"); + fprintf(stderr, "\t-i Interface name (eg, lmc0)\n"); + fprintf(stderr, "\t-L Set loopback: 1:none 2:payload 3:line 4:other\n"); + fprintf(stderr, "\t 5:inward 6:dual 16:Tulip 17:pins 18:LA/LL 19:LB/RL\n"); + fprintf(stderr, "\t-m Read and print MII regs\n"); + fprintf(stderr, "\t-M Write MII reg\n"); + fprintf(stderr, "\t-p Read and print PCI config regs\n"); + fprintf(stderr, "\t-P Write PCI config reg\n"); + fprintf(stderr, "\t-s Read and print Tulip SROM\n"); + fprintf(stderr, "\t-S Initialize Tulip SROM\n"); + fprintf(stderr, "\t-t Read and print Tulip Control/Status regs\n"); + fprintf(stderr, "\t-T Write Tulip Control/status reg\n"); + fprintf(stderr, "\t-u Reset event counters\n"); + fprintf(stderr, "\t-U Reset gate array\n"); + fprintf(stderr, "\t-v Set verbose printout mode\n"); + fprintf(stderr, "\t-V Print card configuration\n"); + fprintf(stderr, "\t-w Load gate array from ROM\n"); + fprintf(stderr, "\t-W Load gate array from file\n"); + fprintf(stderr, "\t-x select RAWIP mode and bypass line protocols\n"); + fprintf(stderr, "\t-X Select line protocols: SPPP, P2P or HDLC\n"); + fprintf(stderr, "\t-y disable SPPP keep-alive packets\n"); + fprintf(stderr, "\t-Y enable SPPP keep-alive packets\n"); + fprintf(stderr, "\t-z Set SPPP line protocol to Cisco-HDLC\n"); + fprintf(stderr, "\t-Z Set SPPP line protocol to PPP\n"); + + fprintf(stderr, "The -1 switch precedes T1/E1 commands.\n"); + fprintf(stderr, "\t-a Stop sending Yellow|Blue|AIS signal\n"); + fprintf(stderr, "\t-A Start sending Yellow|Blue}AIS signal\n"); + fprintf(stderr, "\t-B Send BOP msg 25 times\n"); + fprintf(stderr, "\t-c Set cable length in meters\n"); + fprintf(stderr, "\t-d Print status of T1 DSU/CSU\n"); + fprintf(stderr, "\t-e Set framing format, where:\n"); + fprintf(stderr, "\t 27:T1-ESF 9:T1-SF 0:E1-FAS 8:E1-FAS+CRC\n"); + fprintf(stderr, "\t 16:E1-FAS+CAS 24:E1-FAS+CRC+CAS 32:E1-NO-FRAMING\n"); + fprintf(stderr, "\t-E <32-bit hex number> 1 activates a channel and 0 deactivates it.\n"); + fprintf(stderr, "\t Use this to config a link in fractional T1/E1 mode\n"); + fprintf(stderr, "\t-f Read and print Framer/LIU registers\n"); + fprintf(stderr, "\t-F Write Framer/LIU register\n"); + fprintf(stderr, "\t-g Set receiver gain, where:\n"); + fprintf(stderr, "\t 0:short range 1:medium range\n"); + fprintf(stderr, "\t 2:long range 3:extended range\n"); + fprintf(stderr, "\t 4:auto-set based on cable length\n"); + fprintf(stderr, "\t-i Send 'CSU Loop Down' inband msg\n"); + fprintf(stderr, "\t-I Send 'CSU Loop Up' inband msg\n"); + fprintf(stderr, "\t-l Send 'Line Loop Down' BOP msg\n"); + fprintf(stderr, "\t-L Send 'Line Loop Up' BOP msg\n"); + fprintf(stderr, "\t-p Send 'Payload Loop Down' BOP msg\n"); + fprintf(stderr, "\t-P Send 'Payload Loop Up' BOP msg\n"); + fprintf(stderr, "\t-s Print status of T1 DSU/CSU\n"); + fprintf(stderr, "\t-t Stop sending test pattern\n"); + fprintf(stderr, "\t-T Start sending test pattern, where:\n"); + fprintf(stderr, "\t 0:unframed 2^11 1:unframed 2^15\n"); + fprintf(stderr, "\t 2:unframed 2^20 3:unframed 2^23\n"); + fprintf(stderr, "\t 4:unframed 2^11 w/ZS 5:unframed 2^15 w/ZS\n"); + fprintf(stderr, "\t 6:unframed QRSS 7:unframed 2^23 w/ZS\n"); + fprintf(stderr, "\t 8: framed 2^11 9: framed 2^15\n"); + fprintf(stderr, "\t 10: framed 2^20 11: framed 2^23\n"); + fprintf(stderr, "\t 12: framed 2^11 w/ZS 13: framed 2^15 w/ZS\n"); + fprintf(stderr, "\t 14: framed QRSS 15: framed 2^23 w/ZS\n"); + fprintf(stderr, "\t-u Set transmitter pulse shape, where:\n"); + fprintf(stderr, "\t 0:T1-DSX 0-40m 1:T1-DSX 40-80m\n"); + fprintf(stderr, "\t 2:T1-DSX 80-120m 3:T1-DSX 120-160m\n"); + fprintf(stderr, "\t 4:T1-DSX 160-200m 5:E1-G.703 75ohm coax\n"); + fprintf(stderr, "\t 6:E1-G.703 120ohm TP 7:T1-CSU Long range\n"); + fprintf(stderr, "\t 8:auto-set based on cable length (T1 only)\n"); + fprintf(stderr, "\t-U Set line build out where:\n"); + fprintf(stderr, "\t 0:0dB 1:7.5dB 2:15dB 3:22.5dB\n"); + fprintf(stderr, "\t 4:auto-set based on cable length\n"); + fprintf(stderr, "\t-v Set verbose printout mode\n"); + fprintf(stderr, "\t-x disable Transmitter outputs\n"); + fprintf(stderr, "\t-X enable Transmitter outputs\n"); + + fprintf(stderr, "The -3 switch precedes T3 commands.\n"); + fprintf(stderr, "\t-a Stop sending Yellow|Blue|AIS|Idle signal\n"); + fprintf(stderr, "\t-A Start sending Yellow|Blue|AIS|Idle signal\n"); + fprintf(stderr, "\t-B Send BOP msg 10 times\n"); + fprintf(stderr, "\t-c Set cable length in meters\n"); + fprintf(stderr, "\t-d Print status of T3 DSU/CSU\n"); + fprintf(stderr, "\t-e Set T3 frame format, where:\n"); + fprintf(stderr, "\t 100:C-Bit Parity 101:M13\n"); + fprintf(stderr, "\t-f Read and print Framer registers\n"); + fprintf(stderr, "\t-F Write Framer register\n"); + fprintf(stderr, "\t-l Send 'Line Loop Down' BOP msg\n"); + fprintf(stderr, "\t-L Send 'Line Loop Up' BOP msg\n"); + fprintf(stderr, "\t-s Print status of T3 DSU/CSU\n"); + fprintf(stderr, "\t-S Set DS3 scrambler mode, where:\n"); + fprintf(stderr, "\t 1:OFF 2:DigitalLink|Kentrox 3:Larse\n"); + fprintf(stderr, "\t-v Set verbose printout mode\n"); + fprintf(stderr, "\t-V Write to T3 VCXO freq control DAC\n"); + } + +void call_driver(unsigned long cmd, struct iohdr *iohdr) + { + int error = 0; + + strncpy(iohdr->ifname, ifname, sizeof(iohdr->ifname)); + iohdr->cookie = NGM_LMC_COOKIE; + iohdr->iohdr = iohdr; + + /* Exchange data with a running device driver. */ +#if defined(NETGRAPH) + if (netgraph) + { + NgSendMsg(fdcs, ifname, NGM_LMC_COOKIE, cmd, iohdr, IOCPARM_LEN(cmd)); + if (cmd & IOC_OUT) + { + int replen = sizeof(struct ng_mesg) + IOCPARM_LEN(cmd); + char rep[replen]; /* storage for the reply */ + struct ng_mesg *reply = (struct ng_mesg *)rep; + int rl = NgRecvMsg(fdcs, reply, replen, NULL); + if (rl == replen) + bcopy(&reply->data, iohdr, IOCPARM_LEN(cmd)); + else + { + fprintf(stderr, "%s: NgRecvMsg returned %d bytes, expected %d\n", + progname, rl, replen); + exit(1); + } + } + } + else +#endif + { + if ((error = ioctl(fdcs, cmd, (caddr_t)iohdr)) < 0) + { + fprintf(stderr, "%s: ioctl() returned error code %d: %s\n", + progname, errno, strerror(errno)); + if (errno == ENETDOWN) + printf("Type: 'ifconfig %s up' then try again.\n", ifname); + exit(1); + } + } + + if (iohdr->cookie != NGM_LMC_COOKIE) + { + fprintf(stderr, "%s: cookie = 0x%08X, expected 0x%08X\n", progname, iohdr->cookie, NGM_LMC_COOKIE); + fprintf(stderr, "%s: This version of %s is incompatible with the device driver\n", progname, progname); + exit(1); + } + } + +u_int32_t read_pci_config(u_int8_t addr) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_PCI; + ioctl.address = addr; + + call_driver(LMCIOCREAD, &ioctl.iohdr); + + return ioctl.data; + } + +void write_pci_config(u_int8_t addr, u_int32_t data) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOW; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_PCI; + ioctl.address = addr; + ioctl.data = data; + + call_driver(LMCIOCWRITE, &ioctl.iohdr); + } + +u_int32_t read_csr(u_int8_t addr) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_CSR; + ioctl.address = addr; + + call_driver(LMCIOCREAD, &ioctl.iohdr); + + return ioctl.data; + } + +void write_csr(u_int8_t addr, u_int32_t data) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOW; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_CSR; + ioctl.address = addr; + ioctl.data = data; + + call_driver(LMCIOCWRITE, &ioctl.iohdr); + } + +u_int16_t read_srom(u_int8_t addr) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_SROM; + ioctl.address = addr; + + call_driver(LMCIOCREAD, &ioctl.iohdr); + + return ioctl.data; + } + +void write_srom(u_int8_t addr, u_int16_t data) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOW; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_SROM; + ioctl.address = addr; + ioctl.data = data; + + call_driver(LMCIOCWRITE, &ioctl.iohdr); + } + +u_int8_t read_bios_rom(u_int32_t addr) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_BIOS; + ioctl.address = addr; + + call_driver(LMCIOCREAD, &ioctl.iohdr); + + return ioctl.data; + } + +void write_bios_rom(u_int32_t addr, u_int8_t data) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOW; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_BIOS; + ioctl.address = addr; + ioctl.data = data; + + call_driver(LMCIOCWRITE, &ioctl.iohdr); + } + +u_int16_t read_mii(u_int8_t addr) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_MII; + ioctl.address = addr; + + call_driver(LMCIOCREAD, &ioctl.iohdr); + + return ioctl.data; + } + +void write_mii(u_int8_t addr, u_int16_t data) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOW; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_MII; + ioctl.address = addr; + ioctl.data = data; + + call_driver(LMCIOCWRITE, &ioctl.iohdr); + } + +unsigned char read_framer(u_int16_t addr) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_FRAME; + ioctl.address = addr; + + call_driver(LMCIOCREAD, &ioctl.iohdr); + + return ioctl.data; + } + +void write_framer(u_int16_t addr, u_int8_t data) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOW; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RW_FRAME; + ioctl.address = addr; + ioctl.data = data; + + call_driver(LMCIOCWRITE, &ioctl.iohdr); + } + +void write_synth(struct synth synth) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOW; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_WO_SYNTH; + bcopy(&synth, &ioctl.data, sizeof(synth)); + + call_driver(LMCIOCWRITE, &ioctl.iohdr); + } + +void write_dac(u_int16_t data) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOW; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_WO_DAC; + ioctl.data = data; + + call_driver(LMCIOCWRITE, &ioctl.iohdr); + } + +void reset_xilinx() + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_XILINX_RESET; + + call_driver(LMCIOCTL, &ioctl.iohdr); + } + +void load_xilinx_from_rom() + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_XILINX_ROM; + + call_driver(LMCIOCTL, &ioctl.iohdr); + } + +void load_xilinx_from_file(char *ucode, u_int32_t len) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_XILINX_FILE; + ioctl.data = len; + ioctl.ucode = ucode; + + call_driver(LMCIOCTL, &ioctl.iohdr); + } + +void ioctl_snmp_send(u_int32_t send) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_SNMP_SEND; + ioctl.data = send; + + call_driver(LMCIOCTL, &ioctl.iohdr); + } + +void ioctl_snmp_loop(u_int32_t loop) + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_SNMP_LOOP; + ioctl.data = loop; + + call_driver(LMCIOCTL, &ioctl.iohdr); + } + +void ioctl_reset_cntrs() + { + struct ioctl ioctl; + + ioctl.iohdr.direction = DIR_IOWR; + ioctl.iohdr.length = sizeof(struct ioctl); + ioctl.cmd = IOCTL_RESET_CNTRS; + + call_driver(LMCIOCTL, &ioctl.iohdr); + } + +void ioctl_read_config() + { + config.iohdr.direction = DIR_IOWR; + config.iohdr.length = sizeof(struct config); + + call_driver(LMCIOCGCFG, &config.iohdr); + } + +void ioctl_write_config() + { + config.iohdr.direction = DIR_IOW; + config.iohdr.length = sizeof(struct config); + + call_driver(LMCIOCSCFG, &config.iohdr); + } + +void ioctl_read_status() + { + status.iohdr.direction = DIR_IOWR; + status.iohdr.length = sizeof(struct status); + + call_driver(LMCIOCGSTAT, &status.iohdr); + } + +void print_card_name() + { + printf("Card name:\t\t%s\n", ifname); + } + +void print_card_type() + { + printf("Card type:\t\t"); + switch(status.card_type) + { + case TLP_CSID_HSSI: + printf("HSSI (lmc5200)\n"); + break; + case TLP_CSID_T3: + printf("T3 (lmc5245)\n"); + break; + case TLP_CSID_SSI: + printf("SSI (lmc1000)\n"); + break; + case TLP_CSID_T1E1: + printf("T1E1 (lmc1200)\n"); + break; + case TLP_CSID_HSSIc: + printf("HSSI (lmc5200C)\n"); + break; + default: + printf("unknown card_type: %d\n", status.card_type); + break; + } + } + +void print_status() + { + char *status_string; + + if (status.oper_status == STATUS_UP) + status_string = "Up"; + else if (status.oper_status == STATUS_DOWN) + status_string = "Down"; + else if (status.oper_status == STATUS_TEST) + status_string = "Test"; + else + status_string = "Unknown"; + printf("Link status:\t\t%s\n", status_string); + } + +void print_tx_speed() + { + printf("Tx Speed:\t\t%u\n", status.tx_speed); + } + +void print_debug() + { + if (config.debug != 0) + printf("Debug:\t\t\t%s\n", "On"); + } + +void print_line_prot() + { + char *on = "On", *off = "Off"; + + printf("Line Prot/Pkg:\t\t"); + switch (status.line_prot) + { + case 0: + printf("NotSet/"); + break; + case PROT_PPP: + printf("PPP/"); + break; + case PROT_C_HDLC: + printf("Cisco-HDLC/"); + break; + case PROT_FRM_RLY: + printf("Frame-Relay/"); + break; + case PROT_IP_HDLC: + printf("IP-in-HDLC/"); + break; + case PROT_ETH_HDLC: + printf("Ether-in-HDLC/"); + break; + case PROT_X25: + printf("X25+LAPB/"); + break; + default: + printf("unknown line_prot: %d/", status.line_prot); + break; + } + + switch (status.line_pkg) + { + case 0: + printf("NotSet\n"); + break; + case PKG_RAWIP: + printf("Driver\n"); + break; + case PKG_NG: + printf("Netgraph\n"); + break; + case PKG_GEN_HDLC: + printf("GenHDLC\n"); + break; + case PKG_SPPP: + printf("SPPP\n"); + break; + case PKG_P2P: + printf("P2P\n"); + break; + default: + printf("unknown line_pkg: %d\n", status.line_pkg); + break; + } + + if (status.line_pkg == PKG_SPPP) + printf("SPPP Keep-alives:\t%s\n", + config.keep_alive ? on : off); + } + +void print_crc_len() + { + printf("CRC length:\t\t"); + if (config.crc_len == CFG_CRC_0) + printf("no CRC\n"); + else if (config.crc_len == CFG_CRC_16) + printf("16 bits\n"); + else if (config.crc_len == CFG_CRC_32) + printf("32 bits\n"); + else + printf("bad crc_len: %d\n", config.crc_len); + } + +void print_loop_back() + { + printf("Loopback:\t\t"); + switch (config.loop_back) + { + case CFG_LOOP_NONE: + printf("None\n"); + break; + case CFG_LOOP_PAYLOAD: + printf("Outward thru framer (payload loop)\n"); + break; + case CFG_LOOP_LINE: + printf("Outward thru line interface (line loop)\n"); + break; + case CFG_LOOP_OTHER: + printf("Inward thru line interface\n"); + break; + case CFG_LOOP_INWARD: + printf("Inward thru framer\n"); + break; + case CFG_LOOP_DUAL: + printf("Inward & outward (dual loop)\n"); + break; + case CFG_LOOP_TULIP: + printf("Inward thru Tulip chip\n"); + break; + case CFG_LOOP_PINS: + printf("Inward thru drvrs/rcvrs\n"); + break; + case CFG_LOOP_LL: + printf("LA/LL asserted\n"); + break; + case CFG_LOOP_RL: + printf("LB/RL asserted\n"); + break; + default: + printf("unknown loop_back: %d\n", config.loop_back); + break; + } + } + +void print_tx_clk_src() + { + printf("Tx Clk src:\t\t"); + switch (config.tx_clk_src) + { + case CFG_CLKMUX_ST: + printf("Tx Clk from modem\n"); + break; + case CFG_CLKMUX_INT: + printf("Internal source\n"); + break; + case CFG_CLKMUX_RT: + printf("Rx Clk from modem (loop timed)\n"); + break; + case CFG_CLKMUX_EXT: + printf("External connector\n"); + break; + default: + printf("unknown tx_clk_src: %d\n", config.tx_clk_src); + break; + } + } + +void print_format() + { + printf("Format-Frame/Code:\t"); + switch (config.format) + { + case CFG_FORMAT_T1SF: + printf("T1-SF/AMI\n"); + break; + case CFG_FORMAT_T1ESF: + printf("T1-ESF/B8ZS\n"); + break; + case CFG_FORMAT_E1FAS: + printf("E1-FAS/HDB3\n"); + break; + case CFG_FORMAT_E1FASCRC: + printf("E1-FAS+CRC/HDB3\n"); + break; + case CFG_FORMAT_E1FASCAS: + printf("E1-FAS+CAS/HDB3\n"); + break; + case CFG_FORMAT_E1FASCRCCAS: + printf("E1-FAS+CRC+CAS/HDB3\n"); + break; + case CFG_FORMAT_E1NONE: + printf("E1-NOFRAMING/HDB3\n"); + break; + case CFG_FORMAT_T3CPAR: + printf("T3-CParity/B3ZS\n"); + break; + case CFG_FORMAT_T3M13: + printf("T3-M13/B3ZS\n"); + break; + default: + printf("unknown format: %d\n", config.format); + break; + } + } + +void print_dte_dce() + { + printf("DTE or DCE:\t\t"); + switch(config.dte_dce) + { + case CFG_DTE: + printf("DTE (receiving TxClk)\n"); + break; + case CFG_DCE: + printf("DCE (driving TxClk)\n"); + break; + default: + printf("unknown dte_dce: %d\n", config.dte_dce); + break; + } + } + +void print_synth_freq() + { + double Fref = 20e6; + double Fout, Fvco; + + /* decode the synthesizer params */ + Fvco = (Fref * (config.synth.n<<(3*config.synth.v)))/config.synth.m; + Fout = Fvco / (1<<(config.synth.x+config.synth.r+config.synth.prescale)); + + printf("Synth freq:\t\t%.0f\n", Fout); + } + +void synth_freq(unsigned long target) + { + unsigned int n, m, v, x, r; + double Fout, Fvco, Ftarg; + double newdiff, olddiff; + double bestF=0.0, bestV=0.0; + unsigned prescale = (target < 50000) ? 9:4; + + Ftarg = target< SYNTH_FMAX) continue; + Fout = Fvco / (1<<(x+r)); + if (Fout >= Ftarg) + newdiff = Fout - Ftarg; + else + newdiff = Ftarg - Fout; + if (bestF >= Ftarg) + olddiff = bestF - Ftarg; + else + olddiff = Ftarg - bestF; + if ((newdiff < olddiff) || + ((newdiff == olddiff) && (Fvco < bestV))) + { + config.synth.n = n; + config.synth.m = m; + config.synth.v = v; + config.synth.x = x; + config.synth.r = r; + config.synth.prescale = prescale; + bestF = Fout; + bestV = Fvco; + } + } +#if 0 + printf("Fbest=%.0f, Ftarg=%u, Fout=%.0f\n", bestF>>prescale, target, bestF); + printf("N=%u, M=%u, V=%u, X=%u, R=%u\n", config.synth.n, + config.synth.m, config.synth.v, config.synth.x, config.synth.r); +#endif + } + +void print_cable_len() + { + printf("Cable length:\t\t%d meters\n", config.cable_len); + } + +void print_cable_type() + { + printf("Cable type:\t\t"); + if (status.cable_type > 7) + printf("unknown cable_type: %d\n", status.cable_type); + else + printf("%s\n", ssi_cables[status.cable_type]); + } + +void print_time_slots() + { + printf("TimeSlot [31-0]:\t0x%08X\n", config.time_slots); + } + +void print_scrambler() + { + printf("Scrambler:\t\t"); + if (config.scrambler == CFG_SCRAM_OFF) + printf("off\n"); + else if (config.scrambler == CFG_SCRAM_DL_KEN) + printf("DigLink/Kentrox: X^43+1\n"); + else if (config.scrambler == CFG_SCRAM_LARS) + printf("Larse: X^20+X^17+1 w/28ZS\n"); + else + printf("unknown scrambler: %d\n", config.scrambler); + } + +double vga_dbs(u_int8_t vga) + { + if (vga < 0x0F) return 0.0; + if ((vga >= 0x0F) && (vga <= 0x1B)) return 0.0 + 0.77 * (vga - 0x0F); + if ((vga >= 0x1C) && (vga <= 0x33)) return 10.0 + 1.25 * (vga - 0x1C); + if ((vga >= 0x34) && (vga <= 0x39)) return 40.0 + 1.67 * (vga - 0x34); + if ((vga >= 0x3A) && (vga <= 0x3F)) return 50.0 + 2.80 * (vga - 0x3A); + if (vga > 0x3F) return 64.0; + return 0.0; /* suppress compiler warning */ + } + +void print_rx_gain() + { + printf("Rx gain max:\t\t"); + + if (config.rx_gain == CFG_GAIN_AUTO) + printf("auto-set to %02.1f dB\n", + vga_dbs(read_framer(Bt8370_VGA_MAX) & 0x3F)); + else + printf("up to %02.1f dB\n", vga_dbs(config.rx_gain)); + } + +void print_tx_lbo() + { + u_int8_t saved_lbo = config.tx_lbo; + + printf("LBO = "); + if (config.tx_lbo == CFG_LBO_AUTO) + { + config.tx_lbo = read_framer(Bt8370_TLIU_CR) & 0x30; + printf("auto-set to "); + } + + switch (config.tx_lbo) + { + case CFG_LBO_0DB: + printf("0 dB\n"); + break; + case CFG_LBO_7DB: + printf("7.5 dB\n"); + break; + case CFG_LBO_15DB: + printf("15 dB\n"); + break; + case CFG_LBO_22DB: + printf("22.5 dB\n"); + break; + default: + printf("unknown tx_lbo: %d\n", config.tx_lbo); + break; + } + + if (saved_lbo == CFG_LBO_AUTO) + config.tx_lbo = saved_lbo; + } + +void print_tx_pulse() + { + u_int8_t saved_pulse = config.tx_pulse; + + printf("Tx pulse shape:\t\t"); + if (config.tx_pulse == CFG_PULSE_AUTO) + { + config.tx_pulse = read_framer(Bt8370_TLIU_CR) & 0x0E; + printf("auto-set to "); + } + + switch (config.tx_pulse) + { + case CFG_PULSE_T1DSX0: + printf("T1-DSX: 0 to 40 meters\n"); + break; + case CFG_PULSE_T1DSX1: + printf("T1-DSX: 40 to 80 meters\n"); + break; + case CFG_PULSE_T1DSX2: + printf("T1-DSX: 80 to 120 meters\n"); + break; + case CFG_PULSE_T1DSX3: + printf("T1-DSX: 120 to 160 meters\n"); + break; + case CFG_PULSE_T1DSX4: + printf("T1-DSX: 160 to 200 meters\n"); + break; + case CFG_PULSE_E1COAX: + printf("E1: Twin Coax\n"); + break; + case CFG_PULSE_E1TWIST: + printf("E1: Twisted Pairs\n"); + break; + case CFG_PULSE_T1CSU: + printf("T1-CSU; "); + print_tx_lbo(); + break; + default: + printf("unknown tx_pulse: %d\n", config.tx_pulse); + break; + } + + if (saved_pulse == CFG_PULSE_AUTO) + config.tx_pulse = saved_pulse; + } + +void print_ssi_sigs() + { + u_int32_t mii16 = status.snmp.ssi.sigs; + char *on = "On", *off = "Off"; + + printf("Modem signals:\t\tDTR=%s DSR=%s RTS=%s CTS=%s\n", + (mii16 & MII16_SSI_DTR) ? on : off, + (mii16 & MII16_SSI_DSR) ? on : off, + (mii16 & MII16_SSI_RTS) ? on : off, + (mii16 & MII16_SSI_CTS) ? on : off); + printf("Modem signals:\t\tDCD=%s RI=%s LL=%s RL=%s TM=%s\n", + (mii16 & MII16_SSI_DCD) ? on : off, + (mii16 & MII16_SSI_RI) ? on : off, + (mii16 & MII16_SSI_LL) ? on : off, + (mii16 & MII16_SSI_RL) ? on : off, + (mii16 & MII16_SSI_TM) ? on : off); + } + +void print_hssi_sigs() + { + u_int32_t mii16 = status.snmp.hssi.sigs; + char *on = "On", *off = "Off"; + + printf("Modem signals:\t\tTA=%s CA=%s\n", + (mii16 & MII16_HSSI_TA) ? on : off, + (mii16 & MII16_HSSI_CA) ? on : off); + printf("Modem signals:\t\tLA=%s LB=%s LC=%s TM=%s\n", + (mii16 & MII16_HSSI_LA) ? on : off, + (mii16 & MII16_HSSI_LB) ? on : off, + (mii16 & MII16_HSSI_LC) ? on : off, + (mii16 & MII16_HSSI_TM) ? on : off); + } + +void print_events() + { + char *time; + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + time = (char *)ctime((time_t *)&tv); + printf("Current time:\t\t%s", time); + if (status.cntrs.reset_time.tv_sec < 1000) + time = "Never\n"; + else + time = (char *)ctime((time_t *)&status.cntrs.reset_time.tv_sec); + printf("Cntrs reset:\t\t%s", time); + + if (status.cntrs.ibytes) printf("Rx bytes:\t\t%qu\n", status.cntrs.ibytes); + if (status.cntrs.obytes) printf("Tx bytes:\t\t%qu\n", status.cntrs.obytes); + if (status.cntrs.ipackets) printf("Rx packets:\t\t%qu\n", status.cntrs.ipackets); + if (status.cntrs.opackets) printf("Tx packets:\t\t%qu\n", status.cntrs.opackets); + if (status.cntrs.ierrors) printf("Rx errors:\t\t%u\n", status.cntrs.ierrors); + if (status.cntrs.oerrors) printf("Tx errors:\t\t%u\n", status.cntrs.oerrors); + if (status.cntrs.idiscards) printf("Rx discards:\t\t%u\n", status.cntrs.idiscards); + if (status.cntrs.odiscards) printf("Tx discards:\t\t%u\n", status.cntrs.odiscards); + if (status.cntrs.fifo_over) printf("Rx fifo overruns:\t%u\n", status.cntrs.fifo_over); + if (status.cntrs.fifo_under) printf("Tx fifo underruns:\t%u\n", status.cntrs.fifo_under); + if (status.cntrs.missed) printf("Rx missed:\t\t%u\n", status.cntrs.missed); + if (status.cntrs.overruns) printf("Rx overruns:\t\t%u\n", status.cntrs.overruns); + if (status.cntrs.fdl_pkts) printf("Rx FDL pkts:\t\t%u\n", status.cntrs.fdl_pkts); + if (status.cntrs.crc_errs) printf("Rx CRC:\t\t\t%u\n", status.cntrs.crc_errs); + if (status.cntrs.lcv_errs) printf("Rx line code:\t\t%u\n", status.cntrs.lcv_errs); + if (status.cntrs.frm_errs) printf("Rx F-bits:\t\t%u\n", status.cntrs.frm_errs); + if (status.cntrs.febe_errs) printf("Rx FEBE:\t\t%u\n", status.cntrs.febe_errs); + if (status.cntrs.par_errs) printf("Rx P-parity:\t\t%u\n", status.cntrs.par_errs); + if (status.cntrs.cpar_errs) printf("Rx C-parity:\t\t%u\n", status.cntrs.cpar_errs); + if (status.cntrs.mfrm_errs) printf("Rx M-bits:\t\t%u\n", status.cntrs.mfrm_errs); + if (config.debug) + { /* These events are hard to explain and may worry users, */ + if (status.cntrs.rxdma) printf("Rx no buffs:\t\t%u\n", status.cntrs.rxdma); + if (status.cntrs.txdma) printf("Tx no descs:\t\t%u\n", status.cntrs.txdma); + if (status.cntrs.lck_watch) printf("Lck watch:\t\t%u\n", status.cntrs.lck_watch); + if (status.cntrs.lck_ioctl) printf("Lck ioctl:\t\t%u\n", status.cntrs.lck_ioctl); + if (status.cntrs.lck_intr) printf("Lck intr:\t\t%u\n", status.cntrs.lck_intr); + } + } + +void print_summary() + { + switch(status.card_type) + { + case TLP_CSID_HSSI: + { + print_card_name(); + print_card_type(); + print_debug(); + print_status(); + print_tx_speed(); + print_line_prot(); + print_crc_len(); + print_loop_back(); + print_tx_clk_src(); + print_hssi_sigs(); + print_events(); + break; + } + case TLP_CSID_T3: + { + print_card_name(); + print_card_type(); + print_debug(); + print_status(); + print_tx_speed(); + print_line_prot(); + print_crc_len(); + print_loop_back(); + print_format(); + print_cable_len(); + print_scrambler(); + print_events(); + break; + } + case TLP_CSID_SSI: + { + print_card_name(); + print_card_type(); + print_debug(); + print_status(); + print_tx_speed(); + print_line_prot(); + print_crc_len(); + print_loop_back(); + print_dte_dce(); + print_synth_freq(); + print_cable_type(); + print_ssi_sigs(); + print_events(); + break; + } + case TLP_CSID_T1E1: + { + print_card_name(); + print_card_type(); + print_debug(); + print_status(); + print_tx_speed(); + print_line_prot(); + print_crc_len(); + print_loop_back(); + print_tx_clk_src(); + print_format(); + print_time_slots(); + print_cable_len(); + print_tx_pulse(); + print_rx_gain(); + print_events(); + break; + } + case TLP_CSID_HSSIc: + { + print_card_name(); + print_card_type(); + print_debug(); + print_status(); + print_line_prot(); + print_tx_speed(); + print_crc_len(); + print_loop_back(); + print_tx_clk_src(); + print_dte_dce(); + print_synth_freq(); + print_hssi_sigs(); + print_events(); + break; + } + default: + { + printf("%s: Unknown card type: %d\n", ifname, status.card_type); + break; + } + } + } + +char *print_t3_bop(int bop_code) + { + switch(bop_code) + { + case 0x00: + return "far end LOF"; + case 0x0E: + return "far end LOS"; + case 0x16: + return "far end AIS"; + case 0x1A: + return "far end IDL"; + case 0x07: + return "Line Loopback activate"; + case 0x1C: + return "Line Loopback deactivate"; + case 0x1B: + return "Entire DS3 line"; + default: + return "Unknown BOP code"; + } + } + +void print_t3_snmp() + { + printf("SNMP performance data:\n"); + printf(" LCV=%d", status.snmp.t3.lcv); + printf(" LOS=%d", (status.snmp.t3.line & TLINE_LOS) ? 1 : 0); + printf(" PCV=%d", status.snmp.t3.pcv); + printf(" CCV=%d", status.snmp.t3.ccv); + printf(" AIS=%d", (status.snmp.t3.line & TLINE_RX_AIS) ? 1 : 0); + printf(" SEF=%d", (status.snmp.t3.line & T1LINE_SEF) ? 1 : 0); + printf(" OOF=%d", (status.snmp.t3.line & TLINE_LOF) ? 1 : 0); + printf(" FEBE=%d", status.snmp.t3.febe); + printf(" RAI=%d", (status.snmp.t3.line & TLINE_RX_RAI) ? 1 : 0); + printf("\n"); + } + +void print_t3_dsu() + { + char *no = "No", *yes = "Yes"; + u_int16_t mii16 = read_mii(16); + u_int8_t ctl1 = read_framer(T3CSR_CTL1); + u_int8_t ctl8 = read_framer(T3CSR_CTL8); + u_int8_t stat9 = read_framer(T3CSR_STAT9); + u_int8_t ctl12 = read_framer(T3CSR_CTL12); + u_int8_t stat16 = read_framer(T3CSR_STAT16); + + printf("Framing: \t\t%s\n", ctl1 & CTL1_M13MODE ? "M13" : "CPAR"); + print_tx_speed(); + printf("Scrambler: \t\t%s\n", mii16 & MII16_DS3_SCRAM ? yes : no); + printf("Scram poly: \t\t%s\n", mii16 & MII16_DS3_POLY ? "X^20" : "X^43"); + printf("Cable length \t\t%s\n", mii16 & MII16_DS3_ZERO ? "Short" : "Long"); + printf("Line loop: \t\t%s\n", mii16 & MII16_DS3_LNLBK ? yes : no); + printf("Payload loop: \t\t%s\n", ctl12 & CTL12_RTPLOOP ? yes : no); + printf("Frame loop: \t\t%s\n", ctl1 & CTL1_3LOOP ? yes : no); + printf("Host loop: \t\t%s\n", mii16 & MII16_DS3_TRLBK ? yes : no); + printf("Transmit RAI: \t\t%s\n", ctl1 & CTL1_XTX ? no : yes); + printf("Receive RAI \t\t%s\n", stat16 & STAT16_XERR ? yes : no); + printf("Transmit AIS: \t\t%s\n", ctl1 & CTL1_TXAIS ? yes : no); + printf("Receive AIS: \t\t%s\n", stat16 & STAT16_RAIS ? yes : no); + printf("Transmit IDLE: \t\t%s\n", ctl1 & CTL1_TXIDL ? yes : no); + printf("Receive IDLE: \t\t%s\n", stat16 & STAT16_RIDL ? yes : no); + printf("Transmit BLUE: \t\t%s\n", ctl8 & CTL8_TBLU ? yes : no); + printf("Receive BLUE: \t\t%s\n", stat9 & STAT9_RBLU ? yes : no); + printf("Loss of Signal:\t\t%s\n", stat16 & STAT16_RLOS ? yes : no); + printf("Loss of Frame: \t\t%s\n", stat16 & STAT16_ROOF ? yes : no); + printf("Sev Err Frms: \t\t%s\n", stat16 & STAT16_SEF ? yes : no); + printf("Code errors: \t\t%d\n", read_framer(T3CSR_CVLO) + (read_framer(T3CSR_CVHI)<<8)); + printf("C-Par errors: \t\t%d\n", read_framer(T3CSR_CERR)); + printf("P-Par errors: \t\t%d\n", read_framer(T3CSR_PERR)); + printf("F-Bit errors: \t\t%d\n", read_framer(T3CSR_FERR)); + printf("M-Bit errors: \t\t%d\n", read_framer(T3CSR_MERR)); + printf("FarEndBitErrs: \t\t%d\n", read_framer(T3CSR_FEBE)); + printf("Last Tx FEAC msg:\t0x%02X (%s)\n", + read_framer(T3CSR_TX_FEAC) & 0x3F, + print_t3_bop(read_framer(T3CSR_TX_FEAC) & 0x3F)); + printf("Last dbl FEAC msg;\t0x%02X (%s)\n", + read_framer(T3CSR_DBL_FEAC) & 0x3F, + print_t3_bop(read_framer(T3CSR_DBL_FEAC) & 0x3F)); + printf("Last Rx FEAC msg:\t0x%02X (%s)\n", + read_framer(T3CSR_RX_FEAC) & 0x3F, + print_t3_bop(read_framer(T3CSR_RX_FEAC) & 0x3F)); + print_t3_snmp(); + } + +void t3_cmd(int argc, char **argv) + { + int ch; + + while ((ch = getopt(argc, argv, "a:A:B:c:de:fF:lLsS:vV:")) != -1) + { + switch (ch) + { + case 'a': /* stop alarms */ + { + switch (optarg[0]) + { + case 'a': /* Stop sending AIS Signal */ + { + write_mii(16, + read_mii(16) & ~MII16_DS3_FRAME); + write_framer(T3CSR_CTL1, + read_framer(T3CSR_CTL1) & ~CTL1_TXAIS); + if (verbose) printf("Stop sending Alarm Indication Signal (AIS)\n"); + break; + } + case 'b': /* Stop sending Blue signal */ + { + write_mii(16, + read_mii(16) & ~MII16_DS3_FRAME); + write_framer(T3CSR_CTL8, + read_framer(T3CSR_CTL8) & ~CTL8_TBLU); + if (verbose) printf("Stop sending Blue signal\n"); + break; + } + case 'i': /* Stop sending IDLE signal */ + { + write_framer(T3CSR_CTL1, + read_framer(T3CSR_CTL1) & ~CTL1_TXIDL); + if (verbose) printf("Stop sending IDLE signal\n"); + break; + } + case 'y': /* Stop sending Yellow alarm */ + { + write_framer(T3CSR_CTL1, + read_framer(T3CSR_CTL1) | CTL1_XTX); + if (verbose) printf("Stop sending Yellow alarm\n"); + break; + } + default: + printf("Unknown alarm: %c\n", optarg[0]); + break; + } + break; + } + case 'A': /* start alarms */ + { + switch (optarg[0]) + { + case 'a': /* Start sending AIS Signal */ + { + write_mii(16, + read_mii(16) | MII16_DS3_FRAME); + write_framer(T3CSR_CTL1, + read_framer(T3CSR_CTL1) | CTL1_TXAIS); + if (verbose) printf("Sending AIS signal (framed 1010..)\n"); + break; + } + case 'b': /* Start sending Blue signal */ + { + write_mii(16, + read_mii(16) | MII16_DS3_FRAME); + write_framer(T3CSR_CTL8, + read_framer(T3CSR_CTL8) | CTL8_TBLU); + if (verbose) printf("Sending Blue signal (unframed all 1s)\n"); + break; + } + case 'i': /* Start sending IDLE signal */ + { + write_framer(T3CSR_CTL1, + read_framer(T3CSR_CTL1) | CTL1_TXIDL); + if (verbose) printf("Sending IDLE signal (framed 1100..)\n"); + break; + } + case 'y': /* Start sending Yellow alarm */ + { + write_framer(T3CSR_CTL1, + read_framer(T3CSR_CTL1) & ~CTL1_XTX); + if (verbose) printf("Sending Yellow alarm (X-bits=0)\n"); + break; + } + default: + printf("Unknown alarm: %c\n", optarg[0]); + break; + } + break; + } + case 'B': /* send BOP msg */ + { + u_int8_t bop = strtoul(optarg, NULL, 0); + write_framer(T3CSR_TX_FEAC, 0xC0 + bop); + if (verbose) printf("Sent '0x%02X' BOP msg 10 times\n", bop); + break; + } + case 'c': /* set cable length */ + { + config.cable_len = strtoul(optarg, NULL, 0); + if (verbose) print_cable_len(); + update = 1; + break; + } + case 'd': /* DSU status */ + case 's': /* deprecated */ + { + print_t3_dsu(); + break; + } + case 'e': /* set framimg format */ + { + config.format = strtoul(optarg, NULL, 0); + if (verbose) print_format(); + update = 1; + break; + } + case 'f': /* read and print framer regs */ + { + int i; + printf("TXC03401 regs:\n"); + printf(" 0 1 2 3 4 5 6 7"); + for (i=0; i<21; i++) + { + if (i%8 == 0) printf("\n%02X: ", i); + printf("%02X ", read_framer(i)); + } + printf("\n\n"); + break; + } + case 'F': /* write framer reg */ + { + u_int32_t addr = strtoul(optarg, NULL, 0); + u_int32_t data = strtoul(argv[optind++], NULL, 0); + write_framer(addr, data); + if (verbose) + { + data = read_framer(addr); + printf("Write framer register: addr = 0x%02X data = 0x%02X\n", addr, data); + } + break; + } + case 'l': /* send DS3 line loopback deactivate BOP cmd */ + { + ioctl_snmp_send(TSEND_RESET); + if (verbose) printf("Sent 'DS3 Line Loopback deactivate' BOP cmd\n"); + break; + } + case 'L': /* send DS3 line loopback activate BOP cmd */ + { + ioctl_snmp_send(TSEND_LINE); + if (verbose) printf("Sent 'DS3 Line Loopback activate' BOP cmd\n"); + break; + } + case 'S': /* set scrambler */ + { + config.scrambler = strtoul(optarg, NULL, 0); + if (verbose) print_scrambler(); + update = 1; + break; + } + case 'v': /* set verbose mode */ + { + verbose = 1; + break; + } + case 'V': /* set T3 freq control DAC */ + { + u_int32_t dac = strtoul(optarg, NULL, 0); + write_dac(dac); + if (verbose) printf("VCXO DAC value is %d\n", dac); + break; + } + default: + { + printf("Unknown command char: %c\n", ch); + exit(1); + } /* case */ + } /* switch */ + } /* while */ + } /* proc */ + +void print_test_pattern(int patt) + { + printf("Test Pattern:\t\t"); + switch (patt) + { + case 0: + printf("unframed X^11+X^9+1\n"); + break; + case 1: + printf("unframed X^15+X^14+1\n"); + break; + case 2: + printf("unframed X^20+X^17+1\n"); + break; + case 3: + printf("unframed X^23+X^18+1\n"); + break; + case 4: + printf("unframed X^11+X^9+1 w/7ZS\n"); + break; + case 5: + printf("unframed X^15+X^14+1 w/7ZS\n"); + break; + case 6: + printf("unframed X^20+X^17+1 w/14ZS (QRSS)\n"); + break; + case 7: + printf("unframed X^23+X^18+1 w/14ZS\n"); + break; + case 8: + printf("framed X^11+X^9+1\n"); + break; + case 9: + printf("framed X^15+X^14+1\n"); + break; + case 10: + printf("framed X^20+X^17+1\n"); + break; + case 11: + printf("framed X^23+X^18+1\n"); + break; + case 12:; + printf("framed X^11+X^9+1 w/7ZS\n"); + break; + case 13: + printf("framed X^15+X^14+1 w/7ZS\n"); + break; + case 14: + printf("framed X^20+X^17+1 w/14ZS (QRSS)\n"); + break; + case 15: + printf("framed X^23+X^18+1 w/14ZS\n"); + break; + } + } + +char *print_t1_bop(int bop_code) + { + switch(bop_code) + { + case 0x00: + return "Yellow Alarm (far end LOF)"; + case 0x07: + return "Line Loop up"; + case 0x1C: + return "Line Loop down"; + case 0x0A: + return "Payload Loop up"; + case 0x19: + return "Payload Loop down"; + case 0x09: + return "Network Loop up"; + case 0x12: + return "Network Loop down"; + default: + return "Unknown BOP code"; + } + } + +void print_far_report(int index) + { + u_int16_t far = status.snmp.t1.prm[index]; + + printf(" SEQ=%d ", (far & T1PRM_SEQ)>>8); + if (far & T1PRM_G1) printf("CRC=1"); + else if (far & T1PRM_G2) printf("CRC=1 to 5"); + else if (far & T1PRM_G3) printf("CRC=5 to 10"); + else if (far & T1PRM_G4) printf("CRC=10 to 100"); + else if (far & T1PRM_G5) printf("CRC=100 to 319"); + else if (far & T1PRM_G6) printf("CRC>=320"); + else printf("CRC=0"); + printf(" SE=%d", (far & T1PRM_SE) ? 1 : 0); + printf(" FE=%d", (far & T1PRM_FE) ? 1 : 0); + printf(" LV=%d", (far & T1PRM_LV) ? 1 : 0); + printf(" SL=%d", (far & T1PRM_SL) ? 1 : 0); + printf(" LB=%d", (far & T1PRM_LB) ? 1 : 0); + printf("\n"); + } + +void print_t1_snmp() + { + printf("SNMP Near-end performance data:\n"); + printf(" LCV=%d", status.snmp.t1.lcv); + printf(" LOS=%d", (status.snmp.t1.line & TLINE_LOS) ? 1 : 0); + printf(" FE=%d", status.snmp.t1.fe); + printf(" CRC=%d", status.snmp.t1.crc); + printf(" AIS=%d", (status.snmp.t1.line & TLINE_RX_AIS) ? 1 : 0); + printf(" SEF=%d", (status.snmp.t1.line & T1LINE_SEF) ? 1 : 0); + printf(" OOF=%d", (status.snmp.t1.line & TLINE_LOF) ? 1 : 0); + printf(" RAI=%d",(status.snmp.t1.line & TLINE_RX_RAI) ? 1 : 0); + printf("\n"); + if (config.format == CFG_FORMAT_T1ESF) + { + printf("ANSI Far-end performance reports:\n"); + print_far_report(0); + print_far_report(1); + print_far_report(2); + print_far_report(3); + } + } + +void print_t1_dsu() + { + char *no = "No", *yes = "Yes"; + u_int16_t mii16 = read_mii(16); + u_int8_t isr0 = read_framer(Bt8370_ISR0); + u_int8_t loop = read_framer(Bt8370_LOOP); + u_int8_t vga_max = read_framer(Bt8370_VGA_MAX) & 0x3F; + u_int8_t alm1 = read_framer(Bt8370_ALM1); + u_int8_t alm3 = read_framer(Bt8370_ALM3); + u_int8_t talm = read_framer(Bt8370_TALM); + u_int8_t tpatt = read_framer(Bt8370_TPATT); + u_int8_t tpulse = read_framer(Bt8370_TLIU_CR); + u_int8_t vga; + u_int8_t saved_pulse, saved_lbo; + + /* d/c write required before read */ + write_framer(Bt8370_VGA, 0); + vga = read_framer(Bt8370_VGA) & 0x3F; + + print_format(); + print_time_slots(); + print_tx_clk_src(); + print_tx_speed(); + + saved_pulse = config.tx_pulse; + config.tx_pulse = tpulse & 0x0E; + saved_lbo = config.tx_lbo; + config.tx_lbo = tpulse & 0x30; + print_tx_pulse(); + config.tx_pulse = saved_pulse; + config.tx_lbo = saved_lbo; + + printf("Tx outputs: \t\t%sabled\n", (mii16 & MII16_T1_XOE) ? "En" : "Dis"); + printf("Line impedance:\t\t%s ohms\n", (mii16 & MII16_T1_Z) ? "120" : "100"); + printf("Max line loss: \t\t%4.1f dB\n", vga_dbs(vga_max)); + printf("Cur line loss: \t\t%4.1f dB\n", vga_dbs(vga)); + printf("Invert data: \t\t%s\n", (mii16 & MII16_T1_INVERT) ? yes : no); + printf("Line loop: \t\t%s\n", (loop & LOOP_LINE) ? yes : no); + printf("Payload loop: \t\t%s\n", (loop & LOOP_PAYLOAD) ? yes : no); + printf("Framer loop: \t\t%s\n", (loop & LOOP_FRAMER) ? yes : no); + printf("Analog loop: \t\t%s\n", (loop & LOOP_ANALOG) ? yes : no); + printf("Tx AIS: \t\t%s\n", ((talm & TALM_TAIS) || + ((talm & TALM_AUTO_AIS) && (alm1 & ALM1_RLOS))) ? yes : no); + printf("Rx AIS: \t\t%s\n", (alm1 & ALM1_RAIS) ? yes : no); + if (((config.format & 1)==0) && (config.format != CFG_FORMAT_E1NONE)) + { + printf("Tx RAI: \t\t%s\n", ((talm & TALM_TYEL) || + ((talm & TALM_AUTO_YEL) && (alm3 & ALM3_FRED))) ? yes : no); + printf("Rx RAI: \t\t%s\n", (alm1 & ALM1_RYEL) ? yes : no); + } + if (config.format == CFG_FORMAT_T1ESF) + { + printf("Tx BOP RAI: \t\t%s\n", (alm1 & ALM1_RLOF) ? yes : no); + printf("Rx BOP RAI: \t\t%s\n", (alm1 & ALM1_RMYEL) ? yes : no); + } + if ((config.format & 0x11) == 0x10) /* E1CAS */ + { + printf("Rx TS16 AIS: \t\t%s\n", (alm3 & ALM3_RMAIS) ? yes : no); + printf("Tx TS16 RAI; \t\t%s\n", + ((talm & TALM_AUTO_MYEL) && (alm3 & ALM3_SRED)) ? yes : no); + } + printf("Rx LOS analog: \t\t%s\n", (alm1 & ALM1_RALOS) ? yes : no); + printf("Rx LOS digital:\t\t%s\n", (alm1 & ALM1_RLOS) ? yes : no); + printf("Rx LOF: \t\t%s\n", (alm1 & ALM1_RLOF) ? yes : no); + printf("Tx QRS: \t\t%s\n", (tpatt & 0x10) ? yes : no); + printf("Rx QRS: \t\t%s\n", (isr0 & 0x10) ? yes : no); + printf("LCV errors: \t\t%d\n", + read_framer(Bt8370_LCV_LO) + (read_framer(Bt8370_LCV_HI)<<8)); + if (config.format != CFG_FORMAT_E1NONE) + { + if ((config.format & 1)==0) printf("Far End Block Errors:\t%d\n", + read_framer(Bt8370_FEBE_LO) + (read_framer(Bt8370_FEBE_HI)<<8)); + printf("CRC errors: \t\t%d\n", + read_framer(Bt8370_CRC_LO) + (read_framer(Bt8370_CRC_HI)<<8)); + printf("Frame errors: \t\t%d\n", + read_framer(Bt8370_FERR_LO) + (read_framer(Bt8370_FERR_HI)<<8)); + printf("Sev Err Frms: \t\t%d\n", read_framer(Bt8370_AERR) & 0x03); + printf("Change of Frm align:\t%d\n", (read_framer(Bt8370_AERR) & 0x0C)>>2); + printf("Loss of Frame events:\t%d\n", (read_framer(Bt8370_AERR) & 0xF0)>>4); + } + if (config.format == CFG_FORMAT_T1ESF) + { + printf("Last Tx BOP msg:\t0x%02X (%s)\n", + read_framer(Bt8370_TBOP), print_t1_bop(read_framer(Bt8370_TBOP))); + printf("Last Rx BOP msg:\t0x%02X (%s)\n", + read_framer(Bt8370_RBOP), print_t1_bop(read_framer(Bt8370_RBOP)&0x3F)); + } + print_t1_snmp(); + } + +void t1_cmd(int argc, char **argv) + { + int ch; + + while ((ch = getopt(argc, argv, "a:A:B:c:de:E:fF:g:iIlLpPstT:u:U:vxX")) != -1) + { + switch (ch) + { + case 'a': /* stop alarms */ + { + switch (optarg[0]) + { + case 'y': /* Stop sending Yellow Alarm */ + { + if ((config.format == CFG_FORMAT_T1SF) || + (config.format == CFG_FORMAT_E1NONE)) + printf("No Yellow alarm for this frame format\n"); + else if (config.format == CFG_FORMAT_T1ESF) + write_framer(Bt8370_BOP, 0xE0); /* rbop 25, tbop off */ + else + { + u_int8_t talm = read_framer(Bt8370_TALM); + write_framer(Bt8370_TALM, talm & ~TALM_TYEL); + } + if (verbose) printf("Stop sending Yellow alarm\n"); + break; + } + case 'a': /* Stop sending AIS */ + case 'b': /* Stop sending Blue Alarm */ + { + u_int8_t talm = read_framer(Bt8370_TALM); + write_framer(Bt8370_TALM, talm & ~TALM_TAIS); + if (verbose) printf("Stop sending AIS/Blue signal\n"); + break; + } + default: + printf("Unknown alarm: %c\n", optarg[0]); + } + break; + } + case 'A': /* start alarms */ + { + switch (optarg[0]) + { + case 'y': /* Start sending Yellow Alarm */ + { + if ((config.format == CFG_FORMAT_T1SF) || + (config.format == CFG_FORMAT_E1NONE)) + printf("No Yellow alarm for this frame format\n"); + else if (config.format == CFG_FORMAT_T1ESF) + { + write_framer(Bt8370_BOP, 0x0F); /* rbop off, tbop cont */ + write_framer(Bt8370_TBOP, T1BOP_OOF); + } + else + { + u_int8_t talm = read_framer(Bt8370_TALM); + write_framer(Bt8370_TALM, talm | TALM_TYEL); + } + if (verbose) printf("Sending Yellow alarm\n"); + break; + } + case 'a': /* Start sending AIS */ + case 'b': /* Start sending Blue Alarm */ + { + u_int8_t talm = read_framer(Bt8370_TALM); + write_framer(Bt8370_TALM, talm | TALM_TAIS); + if (verbose) printf("Sending AIS/Blue signal\n"); + break; + } + default: + printf("Unknown alarm: %c\n", optarg[0]); + } + break; + } + case 'B': /* send BOP msg */ + { + u_int8_t bop = strtoul(optarg, NULL, 0); + if (config.format == CFG_FORMAT_T1ESF) + { + write_framer(Bt8370_BOP, 0x0B); /* rbop off, tbop 25 */ + write_framer(Bt8370_TBOP, bop); /* start sending BOP msg */ + sleep(1); /* sending 25 BOP msgs takes about 100 ms. */ + write_framer(Bt8370_BOP, 0xE0); /* rbop 25, tbop off */ + if (verbose) printf("Sent '0x%02X' BOP msg 25 times\n", bop); + } + else + printf("BOP msgs only work in T1-ESF format\n"); + break; + } + case 'c': /* set cable length */ + { + config.cable_len = strtoul(optarg, NULL, 0); + if (verbose) print_cable_len(); + update = 1; + break; + } + case 'd': /* DSU status */ + case 's': /* deprecated */ + { + print_t1_dsu(); + break; + } + case 'e': /* set framimg format */ + { + config.format = strtoul(optarg, NULL, 0); + if (verbose) print_format(); + update = 1; + break; + } + case 'E': /* set time slots */ + { + config.time_slots = strtoul(optarg, NULL, 16); + if (verbose) print_time_slots(); + update = 1; + break; + } + case 'f': /* read and print framer regs */ + { + int i; + printf("Bt8370 regs:\n"); + printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F"); + for (i=0; i<512; i++) + { + if (i%16 == 0) printf("\n%03X: ", i); + printf("%02X ", read_framer(i)); + } + printf("\n\n"); + break; + } + case 'F': /* write framer reg */ + { + u_int32_t addr = strtoul(optarg, NULL, 0); + u_int32_t data = strtoul(argv[optind++], NULL, 0); + write_framer(addr, data); + if (verbose) + { + data = read_framer(addr); + printf("Write framer register: addr = 0x%02X data = 0x%02X\n", addr, data); + } + break; + } + case 'g': /* set receiver gain */ + { + config.rx_gain = strtoul(optarg, NULL, 0); + if (verbose) print_rx_gain(); + update = 1; + break; + } + case 'i': /* send CSU loopback deactivate inband cmd */ + { + if (config.format == CFG_FORMAT_T1SF) + { + if (verbose) printf("Sending 'CSU loop down' inband cmd for 10 secs..."); + ioctl_snmp_send(TSEND_RESET); + sleep(10); + ioctl_snmp_send(TSEND_NORMAL); + if (verbose) printf("done\n"); + } + else + printf("Inband loopback cmds only work in T1-SF format"); + break; + } + case 'I': /* send CSU loopback activate inband cmd */ + { + if (config.format == CFG_FORMAT_T1SF) + { + if (verbose) printf("Sending 'CSU loop up' inband cmd for 10 secs..."); + ioctl_snmp_send(TSEND_LINE); + sleep(10); + ioctl_snmp_send(TSEND_NORMAL); + if (verbose) printf("done\n"); + } + else + printf("Inband loopback cmds only work in T1-SF format"); + break; + } + case 'l': /* send line loopback deactivate BOP msg */ + { + if (config.format == CFG_FORMAT_T1ESF) + { + ioctl_snmp_send(TSEND_RESET); + if (verbose) printf("Sent 'Line Loop Down' BOP cmd\n"); + } + else + printf("BOP msgs only work in T1-ESF format\n"); + break; + } + case 'L': /* send line loopback activate BOP msg */ + { + if (config.format == CFG_FORMAT_T1ESF) + { + ioctl_snmp_send(TSEND_LINE); + if (verbose) printf("Sent 'Line Loop Up' BOP cmd\n"); + } + else + printf("BOP msgs only work in T1-ESF format\n"); + break; + } + case 'p': /* send payload loopback deactivate BOP msg */ + { + if (config.format == CFG_FORMAT_T1ESF) + { + ioctl_snmp_send(TSEND_RESET); + if (verbose) printf("Sent 'Payload Loop Down' BOP cmd\n"); + } + else + printf("BOP msgs only work in T1-ESF format\n"); + break; + } + case 'P': /* send payload loopback activate BOP msg */ + { + if (config.format == CFG_FORMAT_T1ESF) + { + ioctl_snmp_send(TSEND_PAYLOAD); + if (verbose) printf("Sent 'Payload Loop Up' BOP cmd\n"); + } + else + printf("BOP msgs only work in T1-ESF format\n"); + break; + } + case 't': /* stop sending test pattern */ + { + ioctl_snmp_send(TSEND_NORMAL); + if (verbose) printf("Stop sending test pattern\n"); + break; + } + case 'T': /* start sending test pattern */ + { + u_int8_t patt = strtoul(optarg, NULL, 0); + write_framer(Bt8370_TPATT, 0x10 + patt); + write_framer(Bt8370_RPATT, 0x30 + patt); + if (verbose) print_test_pattern(patt); + break; + } + case 'u': /* set transmit pulse shape */ + { + config.tx_pulse = strtoul(optarg, NULL, 0); + if (verbose) print_tx_pulse(); + update = 1; + break; + } + case 'U': /* set tx line build-out */ + { + if (config.tx_pulse == CFG_PULSE_T1CSU) + { + config.tx_lbo = strtoul(optarg, NULL, 0); + if (verbose) print_tx_pulse(); + update = 1; + } + else + printf("LBO only meaningful if Tx Pulse is T1CSU\n"); + break; + } + case 'v': /* set verbose mode */ + { + verbose = 1; + break; + } + case 'x': /* disable transmitter outputs */ + { + write_mii(16, read_mii(16) & ~MII16_T1_XOE); + if (verbose) printf("Transmitter outputs disabled\n"); + break; + } + case 'X': /* enable transmitter outputs */ + { + write_mii(16, read_mii(16) | MII16_T1_XOE); + if (verbose) printf("Transmitter outputs enabled\n"); + break; + } + default: + { + printf("Unknown command char: %c\n", ch); + exit(1); + } /* case */ + } /* switch */ + } /* while */ + } /* proc */ + +/* used when reading Motorola S-Record format ROM files */ +unsigned char read_hex(FILE *f) + { + unsigned char a, b, c; + for (a=0, b=0; a<2; a++) + { + c = fgetc(f); + c -= 48; + if (c > 9) c -= 7; + b = (b<<4) | (c & 0xF); + } + checksum += b; + return b; + } + +static void load_xilinx(char *name) + { + FILE *f; + char *ucode; + int i, length; + char c; + + if (verbose) printf("Load firmware from file %s...\n", name); + if ((f = fopen(name, "r")) == 0) + { + perror("Failed to open file"); + exit(1); + } + + ucode = (char *)malloc(8192); bzero(ucode, 8192); + + c = fgetc(f); + if (c == 'X') + { /* Xilinx raw bits file (foo.rbt) */ + /* skip seven lines of boiler plate */ + for (i=0; i<7;) if ((c=fgetc(f))=='\n') i++; + /* build a dense bit array */ + i = length = 0; + while ((c=fgetc(f))!=EOF) + { /* LSB first */ + if (c=='1') ucode[length] |= 1<>= 1) + crc = (crc >> 1) ^ (((crc ^ data) & 1) ? poly : 0); + + return crc; + } + +/* 8-bit CRC calculated left-to-right over 16-bit words */ +u_int8_t crc8(u_int16_t *bufp, int len) + { + int bit, i; + u_int16_t data; + u_int8_t crc = 0xFF; + u_int8_t poly = 0x07; + + for (i = 0; i < len; i++) + for (data = *bufp++, bit = 15; bit >= 0; bit--) + { + if ((i==8) && (bit==7)) break; + crc = (crc << 1) ^ ((((crc >> 7) ^ (data >> bit)) & 1) ? poly : 0); + } + return crc; + } + +/* HSSI=3, DS3=4, SSI=5, T1E1=6, HSSIc=7, SDSL=8 */ +void init_srom(int board) + { + int i; + u_int16_t srom[64]; + + /* zero the entire rom */ + for (i=0; i<64; i++) srom[i] = 0; + + srom[0] = 0x1376; /* subsys vendor id */ + srom[1] = board ? board : (read_mii(3)>>4 & 0xF) +1; + srom[8] = crc8(srom, 9); + /* Tulip hardware checks this checksum */ + srom[10] = 0x6000; /* ethernet address */ + srom[11] = 0x0099; /* ethernet address */ + srom[12] = 0x0000; /* ethernet address */ + /* srom checksum is low 16 bits of Ethernet CRC-32 */ + srom[63] = crc32((char *)srom, 126) ^ 0xFFFFFFFFL; + + /* write the SROM */ +#if 1 /* really write it */ + for (i=0; i<64; i++) write_srom(i, srom[i]); +#else /* print what would be written */ + printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F"); + for (i=0; i<64; i++) + { + if (i%8 == 0) printf("\n%02X: ", i<<1); + printf("%02X %02X ", srom[i] & 0xFF, srom[i]>>8); + } + printf("\n\n"); +#endif + } + +int main(int argc, char **argv) + { + int i, error, ch; + char *optstring = "13a:bBcCdDeEf:Fhi:L:mM:pP:sS:tT:uUvVwW:xXyYzZ?"; + + progname = (char *)argv[0]; + + /* Here is the overall plan: + * 1) Read the interface name from the command line. + * 2) Open the device; decide if netgraph is being used. + * 3) Read the current interface configuration from the driver. + * 4) Read the command line args and carry out their actions. + * 5) Write the modified interface configuration to the driver. + */ + + /* 1) Read the interface name from the command line. */ +#if __linux__ + ifname = (argc==1) ? "hdlc0" : (char *) argv[1]; +#else + ifname = (argc==1) ? DEVICE_NAME"0" : (char *) argv[1]; +#endif + + /* 2) Open the device; decide if netgraph is being used, */ + /* use netgraph if ifname ends with ":" */ + for (i=0; i<16; i++) if (ifname[i] == 0) break; + + /* Get a socket type file descriptor. */ +#if defined(NETGRAPH) + if ((netgraph = (ifname[i-1] == ':'))) + error = NgMkSockNode(NULL, &fdcs, NULL); + else +#endif + error = fdcs = socket(AF_INET, SOCK_DGRAM, 0); + if (error < 0) + { + fprintf(stderr, "%s: %s() failed: %s\n", progname, + netgraph? "NgMkSockNode" : "socket", strerror(errno)); + exit(1); + } + + /* 3) Read the current interface configuration from the driver. */ + ioctl_read_config(); + ioctl_read_status(); + + summary = (argc <= 2); /* print summary at end */ + update = 0; /* write to card at end */ + + /* 4) Read the command line args and carry out their actions. */ + optind = 2; + while (((ch = getopt(argc, argv, optstring)) != -1) && (argc > 2)) + { + switch (ch) + { + case '1': /* T1 commands */ + { + if (verbose) printf("Doing T1 settings\n"); + if (status.card_type != TLP_CSID_T1E1) + { + printf("T1 settings only apply to T1E1 cards\n"); + exit(1); + } + t1_cmd(argc, argv); + break; + } + case '3': /* T3 commands */ + { + if (verbose) printf("Doing T3 settings\n"); + if (status.card_type != TLP_CSID_T3) + { + printf("T3 settings only apply to T3 cards\n"); + exit(1); + } + t3_cmd(argc, argv); + break; + } + case 'a': /* clock source */ + { + if ((status.card_type != TLP_CSID_T1E1) || + (status.card_type != TLP_CSID_HSSI) || + (status.card_type != TLP_CSID_HSSIc)) + { + if (verbose) print_tx_clk_src(); + config.tx_clk_src = strtoul(optarg, NULL, 0); + update = 1; + } + else + printf("txclksrc only applies to T1E1 and HSSI card types\n"); + break; + } + case 'b': /* read bios rom */ + { + int i; + printf("Bios ROM:\n"); + printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F"); + for (i=0; i<256; i++) + { + if (i%16 == 0) printf("\n%02X: ", i); + printf("%02X ", read_bios_rom(i)); + } + printf("\n\n"); + break; + } + case 'B': /* write bios rom */ + { + int i; + for (i=0; i<256; i++) write_bios_rom(i, 255-i); + if (verbose) printf("wrote (0..255) to bios rom addrs (0..255)\n"); + break; + } + case 'c': /* set crc_len = 16 */ + { + config.crc_len = CFG_CRC_16; + if (verbose) print_crc_len(); + update = 1; + break; + } + case 'C': /* set crc_len = 32 */ + { + config.crc_len = CFG_CRC_32; + if (verbose) print_crc_len(); + update = 1; + break; + } + case 'd': /* clear DEBUG flag */ + { + config.debug = 0; + if (verbose) printf("DEBUG flag cleared\n"); + update = 1; + break; + } + case 'D': /* set DEBUG flag */ + { + config.debug = 1; + if (verbose) printf("DEBUG flag set\n"); + update = 1; + break; + } + case 'e': /* set DTE (default) */ + { + if ((status.card_type == TLP_CSID_SSI) || + (status.card_type == TLP_CSID_HSSIc)) + { + config.dte_dce = CFG_DTE; + if (verbose) print_dte_dce(); + update = 1; + } + else + printf("DTE cmd only applies to SSI & HSSIc cards\n"); + break; + } + case 'E': /* set DCE */ + { + if ((status.card_type == TLP_CSID_SSI) || + (status.card_type == TLP_CSID_HSSIc)) + { + config.dte_dce = CFG_DCE; + if (verbose) print_dte_dce(); + update = 1; + } + else + printf("DCE cmd only applies to SSI & HSSIc cards\n"); + break; + } + case 'f': /* set synth osc freq */ + { + if ((status.card_type == TLP_CSID_SSI) || + (status.card_type == TLP_CSID_HSSIc)) + { + synth_freq(strtoul(optarg, NULL, 0)); + write_synth(config.synth); + if (verbose) print_synth_freq(); + } + else + printf("synth osc freq only applies to SSI & HSSIc cards\n"); + break; + } + case 'F': /* set SPPP line protocol to Frame-Relay */ + { + config.line_prot = PROT_FRM_RLY; + config.keep_alive = 1; /* required for LMI operation */ + if (verbose) printf("SPPP line protocol set to Frame-Relay\n"); + update = 1; + break; + } + case 'h': /* help */ + case '?': + { + usage(); + exit(0); + } + case 'i': /* interface name */ + { + /* already scanned this */ + break; + } + case 'L': /* set loopback modes */ + { + config.loop_back = strtoul(optarg, NULL, 0); + if (verbose) print_loop_back(); + update = 1; + break; + } + case 'm': /* read and print MII regs */ + { + printf("MII regs:\n"); + printf(" 0 1 2 3 4 5 6 7"); + for (i=0; i<32; i++) + { + u_int16_t mii = read_mii(i); + if (i%8 == 0) printf("\n%02X: ", i); + printf("%04X ", mii); + } + printf("\n\n"); + break; + } + case 'M': /* write MII reg */ + { + u_int32_t addr = strtoul(optarg, NULL, 0); + u_int32_t data = strtoul(argv[optind++], NULL, 0); + write_mii(addr, data); + if (verbose) + { + data = read_mii(addr); + printf("Write mii register: addr = 0x%02X data = 0x%04X\n", addr, data); + } + break; + } + case 'p': /* read and print PCI config regs */ + { + int i; + printf("21140A PCI Config regs:\n"); + printf(" 0 1 2 3"); + for (i=0; i<16; i++) + { + if (i%4 == 0) printf("\n%X: ", i); + printf("%08X ", read_pci_config(i<<2)); + } + printf("\n\n"); + break; + } + case 'P': /* write PCI config reg */ + { + u_int32_t addr = strtoul(optarg, NULL, 0); + u_int32_t data = strtoul(argv[optind++], NULL, 0); + write_pci_config(addr, data); + if (verbose) + { + data = read_pci_config(addr); + printf("Write PCI config reg: addr = 0x%02X data = 0x%08X\n", addr, data); + } + break; + } + case 's': /* read and print Tulip SROM */ + { + int i; + printf("21140A SROM:\n"); + printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F"); + for (i=0; i<64; i++) + { + u_int16_t srom = read_srom(i); + if (i%8 == 0) printf("\n%02X: ", i<<1); + printf("%02X %02X ", srom & 0xFF, srom>>8); + } + printf("\n\n"); + break; + } + case 'S': /* write Tulip SROM loc */ + { +#if 0 /* write a single location -- not too useful */ + u_int32_t addr = strtoul(optarg, NULL, 0); + u_int32_t data = strtoul(argv[optind++], NULL, 0); + write_mii(addr, data); + data = read_mii(addr); + printf("Write SROM: addr = 0x%02X data = 0x%04X\n", addr, data); +#endif +#if 0 /* write the whole SROM -- very dangerous */ + init_srom(strtoul(optarg, NULL, 0)); +#endif + printf("Caution! Recompile %s to enable this.\n", progname); + break; + } + case 't': /* read and print Tulip CSRs */ + { + int i; + printf("21140A CSRs:\n"); + printf(" 0 1 2 3"); + for (i=0; i<16; i++) + { + if (i%4 == 0) printf("\n%X: ", i); + printf("%08X ", read_csr(i)); + } + printf("\n\n"); + break; + } + case 'T': /* write Tulip CSR */ + { + u_int32_t addr = strtoul(optarg, NULL, 0); + u_int32_t data = strtoul(argv[optind++], NULL, 0); + write_csr(addr, data); + if (verbose) + { + data = read_csr(addr); + printf("Write 21140A CSR: addr = 0x%02X data = 0x%08X\n", addr, data); + } + break; + } + case 'u': /* reset event counters */ + { + ioctl_reset_cntrs(); + if (verbose) printf("Event counters reset\n"); + break; + } + case 'U': /* reset gate array */ + { + reset_xilinx(); + if (verbose) printf("gate array reset\n"); + break; + } + case 'v': /* set verbose mode */ + { + verbose = 1; + break; + } + case 'V': /* print card configuration */ + { + summary = 1; + break; + } + case 'w': /* load gate array microcode from ROM */ + { + load_xilinx_from_rom(); + if (verbose) printf("gate array configured from on-board ROM\n"); + break; + } + case 'W': /* load gate array microcode from file */ + { + load_xilinx(optarg); + if (verbose) printf("gate array configured from file %s\n", optarg); + break; + } + case 'x': /* select RAWIP protocol */ + { + config.line_pkg = PKG_RAWIP; + if (verbose) printf("RAWIP mode selected\n"); + update = 1; + break; + } + case 'X': /* Select in-kernel line protocol packages */ + { + config.line_pkg = 0; + if (verbose) printf("line protocol mode selected\n"); + update = 1; + break; + } + case 'y': /* disable SPPP keep-alive packets */ + { + if ((config.line_pkg == PKG_SPPP) && + (config.line_prot == PROT_FRM_RLY)) + printf("keep-alives must be ON for Frame-Relay/SPPP\n"); + else + { + config.keep_alive = 0; + if (verbose) printf("SPPP keep-alive packets disabled\n"); + update = 1; + } + break; + } + case 'Y': /* enable SPPP keep-alive packets */ + { + config.keep_alive = 1; + if (verbose) printf("SPPP keep-alive packets enabled\n"); + update = 1; + break; + } + case 'z': /* set SPPP line protocol to Cisco HDLC */ + { + config.line_prot = PROT_C_HDLC; + config.keep_alive = 1; + if (verbose) printf("SPPP line protocol set to Cisco-HDLC\n"); + update = 1; + break; + } + case 'Z': /* set SPPP line protocol to PPP */ + { + config.line_prot = PROT_PPP; + config.keep_alive = 0; + if (verbose) printf("SPPP line protocol set to PPP\n"); + update = 1; + break; + } + default: + { + printf("Unknown command char: %c\n", ch); + exit(1); + } + } /* switch */ + } /* while */ + + if (summary) print_summary(); + + /* 5) Write the modified interface configuration to the driver. */ + if (update) ioctl_write_config(); + + exit(0); + }