summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2005-10-03 07:09:41 +0000
committerscottl <scottl@FreeBSD.org>2005-10-03 07:09:41 +0000
commit6026f74dcd180b8c501980ab3251934e5709a291 (patch)
tree1ee438b1f6d8eebaa45e9ee0ee94eb80c5d28132
parentd39a762fb7f3b6ea3df528e0ffc3259123d225cc (diff)
downloadFreeBSD-src-6026f74dcd180b8c501980ab3251934e5709a291.zip
FreeBSD-src-6026f74dcd180b8c501980ab3251934e5709a291.tar.gz
Add the lmcconfig tool for controlling the lmc driver. Add man pages and
glue. Submitted by: David Boggs
-rw-r--r--etc/mtree/BSD.include.dist2
-rw-r--r--include/Makefile2
-rw-r--r--share/man/man4/Makefile1
-rw-r--r--share/man/man4/lmc.41485
-rw-r--r--usr.sbin/Makefile1
-rw-r--r--usr.sbin/lmcconfig/Makefile9
-rw-r--r--usr.sbin/lmcconfig/lmcconfig.8716
-rw-r--r--usr.sbin/lmcconfig/lmcconfig.c2483
8 files changed, 4698 insertions, 1 deletions
diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index 6431303..ddd522c 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 59856c1..34fbd28 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 be91b5d..8551acc 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 0000000..fb08d6c
--- /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: <unknown card> (vendor=0x1011, dev=0x0009) at 18.0 irq 9"
+.br
+.Ic "freebsd-5: pci0: <network, ethernet> 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 "<M> SBE Inc. LMC1000/1200/5200/5245 support"
+.br
+.Ic "<M> Generic HDLC layer"
+.br
+.Ic "<M>\|"
+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<n>"
+if the generic HDLC code is used, or
+.Ic "lmc<n>"
+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: <SBE/LMC T3 Card> 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<n>"
+rather than
+.Ic "lmc<n>"
+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 c4556f5..a59ea00 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 0000000..df8b773
--- /dev/null
+++ b/usr.sbin/lmcconfig/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+MAN8= lmcconfig.8
+PROG= lmcconfig
+
+LDADD= -lnetgraph
+DPADD= ${LIBNETGRAPH}
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lmcconfig/lmcconfig.8 b/usr.sbin/lmcconfig/lmcconfig.8
new file mode 100644
index 0000000..5f48963
--- /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 0000000..f94c4d1
--- /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 <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#if defined(NETGRAPH)
+# include <netgraph.h>
+#endif
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <dev/lmc/if_lmc.h>
+
+/* 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 <number> 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 <number> 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 <number> 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 <addr> <data> Write MII reg\n");
+ fprintf(stderr, "\t-p Read and print PCI config regs\n");
+ fprintf(stderr, "\t-P <addr> <data> Write PCI config reg\n");
+ fprintf(stderr, "\t-s Read and print Tulip SROM\n");
+ fprintf(stderr, "\t-S <number> Initialize Tulip SROM\n");
+ fprintf(stderr, "\t-t Read and print Tulip Control/Status regs\n");
+ fprintf(stderr, "\t-T <addr> <data> 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 <filename> 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 <y|b|a> Stop sending Yellow|Blue|AIS signal\n");
+ fprintf(stderr, "\t-A <y|b|a> Start sending Yellow|Blue}AIS signal\n");
+ fprintf(stderr, "\t-B <number> Send BOP msg 25 times\n");
+ fprintf(stderr, "\t-c <number> Set cable length in meters\n");
+ fprintf(stderr, "\t-d Print status of T1 DSU/CSU\n");
+ fprintf(stderr, "\t-e <number> 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 <addr> <data> Write Framer/LIU register\n");
+ fprintf(stderr, "\t-g <number> 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 <number> 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 <number> 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 <number> 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 <y|b|a|i> Stop sending Yellow|Blue|AIS|Idle signal\n");
+ fprintf(stderr, "\t-A <y|b|a|i> Start sending Yellow|Blue|AIS|Idle signal\n");
+ fprintf(stderr, "\t-B <bopcode> Send BOP msg 10 times\n");
+ fprintf(stderr, "\t-c <number> Set cable length in meters\n");
+ fprintf(stderr, "\t-d Print status of T3 DSU/CSU\n");
+ fprintf(stderr, "\t-e <number> 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 <addr> <data> 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 <number> 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 <number> 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<<prescale;
+ for (n=3; n<=127; n++)
+ for (m=3; m<=127; m++)
+ for (v=0; v<=1; v++)
+ for (x=0; x<=3; x++)
+ for (r=0; r<=3; r++)
+ {
+ Fvco = (SYNTH_FREF * (n<<(3*v)))/m;
+ if (Fvco < SYNTH_FMIN || Fvco > 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<<i++;
+ if (c=='0') i++;
+ if (i==8) { i=0; length++; }
+ }
+ }
+ else if (c == 'S')
+ { /* Motarola S records (foo.exo) */
+ int blklen;
+ length = 0;
+ ungetc(c, f);
+ while ((c = fgetc(f)) != EOF)
+ {
+ if (c != 'S')
+ {
+ printf("I'm confused; I expected an 'S'\n");
+ exit(1);
+ }
+ c = fgetc(f);
+ if (c == '9') break;
+ else if (c == '1')
+ {
+ checksum = 0;
+ blklen = read_hex(f) -3;
+ read_hex(f); /* hi blkaddr */
+ read_hex(f); /* lo blkaddr */
+ for (i=0; i<blklen; i++)
+ ucode[length++] = read_hex(f);
+ read_hex(f); /* process but ignore checksum */
+ if (checksum != 0xFF)
+ {
+ printf("File checksum error\n");
+ exit(1);
+ }
+ c = fgetc(f); /* throw away eol */
+ c = fgetc(f); /* throw away eol */
+ }
+ else
+ {
+ printf("I'm confused; I expected a '1' or a '9'\n");
+ exit(1);
+ }
+ } /* while */
+ } /* Motorola S-Record */
+ else
+ {
+ printf("Unknown file type giving up\n");
+ exit(1);
+ }
+
+ load_xilinx_from_file(ucode, length);
+ }
+
+/* 32-bit CRC calculated right-to-left over 8-bit bytes */
+u_int32_t crc32(char *bufp, int len)
+ {
+ int bit, i;
+ u_int32_t data;
+ u_int32_t crc = 0xFFFFFFFFL;
+ u_int32_t poly = 0xEDB88320L;
+
+ for (i = 0; i < len; i++)
+ for (data = *bufp++, bit = 0; bit < 8; bit++, data >>= 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);
+ }
OpenPOWER on IntegriCloud