Index: ObsoleteFiles.inc =================================================================== --- ObsoleteFiles.inc +++ ObsoleteFiles.inc @@ -38,6 +38,11 @@ # xargs -n1 | sort | uniq -d; # done +# 2018xxxx: retire lmc +OLD_FILES+=usr/sbin/lmcconfig +OLD_FILES+=usr/share/man/man4/lmc.4.gz +OLD_FILES+=usr/share/man/man4/if_lmc.4.gz +OLD_FILES+=usr/share/man/man8/lmcconfig.8.gz # 20180417: remove fuswintr and suswintr OLD_FILES+=usr/share/man/man9/fuswintr.9.gz OLD_FILES+=usr/share/man/man9/suswintr.9.gz Index: UPDATING =================================================================== --- UPDATING +++ UPDATING @@ -34,6 +34,12 @@ ****************************** SPECIAL WARNING: ****************************** +2018xxxx: + The lmc(4) driver has been removed. This was a WAN interface + card that was already reportedly rare in 2003, and had an ambiguous + license. If you have device lmc in your kernel config file it must + be removed. + 20180413: Support for Arcnet networks has been removed. If you have device arcnet or device cm in your kernel config file they must be Index: lib/libsysdecode/Makefile =================================================================== --- lib/libsysdecode/Makefile +++ lib/libsysdecode/Makefile @@ -120,9 +120,6 @@ # Workaround duplicate declarations in CFLAGS.gcc.ioctl.c+= -Wno-redundant-decls -# Workaround warning for unused ssi_cables[] in -CFLAGS.gcc.ioctl.c+= -Wno-unused - CFLAGS.gcc+= ${CFLAGS.gcc.${.IMPSRC}} DEPENDOBJS+= tables.h Index: share/man/man4/Makefile =================================================================== --- share/man/man4/Makefile +++ share/man/man4/Makefile @@ -266,7 +266,6 @@ ${_linux.4} \ liquidio.4 \ lm75.4 \ - lmc.4 \ lo.4 \ lp.4 \ lpbb.4 \ @@ -688,7 +687,6 @@ MLINKS+=lagg.4 if_lagg.4 MLINKS+=le.4 if_le.4 MLINKS+=lge.4 if_lge.4 -MLINKS+=lmc.4 if_lmc.4 MLINKS+=lo.4 loop.4 MLINKS+=lp.4 plip.4 MLINKS+=malo.4 if_malo.4 Index: share/man/man4/lmc.4 =================================================================== --- share/man/man4/lmc.4 +++ /dev/null @@ -1,771 +0,0 @@ -.\" -.\" $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. -.\" -.Dd April 24, 2018 -.Dt LMC 4 -.Os -.\" -.Sh NAME -.\" -.Nm lmc -.Nd device driver for -.Tn LMC -(now -.Tn SBE ) -wide-area network interface cards -.\" -.Sh SYNOPSIS -.\" -To wire this driver into your kernel, -add the following line to your kernel configuration file: -.Bd -ragged -offset indent -.Cd "device lmc" -.Ed -.Pp -Alternatively, to load this module at boot time, add -.Bd -literal -offset indent -if_lmc_load="YES" -.Ed -.Pp -to -.Pa /boot/loader.conf ; -see -.Xr loader.conf 5 . -.Pp -To wire a line protocol into your kernel, add: -.Bd -ragged -offset indent -.Cd "options NETGRAPH" -.Cd "device sppp" -.Ed -.Pp -It is not necessary to wire line protocols into your kernel, -they can be loaded later with -.Xr 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 -.Va rawdata -hook is connected. -.\" -.Sh DEPRECATION NOTICE -The -.Nm -driver is not present in -.Fx 12.0 -and later. -.\" -.Sh DESCRIPTION -.\" -This is an open-source -.Ux -device driver for PCI-bus WAN interface cards. -It sends and receives packets in HDLC frames over synchronous circuits. -A generic PC plus -.Ux -plus some -.Tn LMC / SBE -cards makes an -.Em open -router. -This driver works with -.Fx , -.Nx , -.Ox , -.Bsx -and -.Tn Linux -OSs. -It has been tested on i386 (SMP 32-bit little-endian) and Sparc (64-bit big-endian) -architectures. -.Pp -The -.Nm -driver works with the following cards: -.Bl -bullet -.It -SBE wanADAPT-HSSI (LMC5200) -.Pp -High Speed Serial Interface, -EIA612/613, 50-pin connector, -0 to 52 Mb/s, DTE only. -.It -SBE wanADAPT-T3 (LMC5245) -.Pp -T3: two 75-ohm BNC connectors, -C-Parity or M13 Framing, -44.736 Mb/s, up to 950 ft. -.It -SBE wanADAPT-SSI (LMC1000) -.Pp -Synchronous Serial Interface, -V.35, X.21, EIA449, EIA530(A), EIA232, -0 to 10 Mb/s, DTE or DCE. -.It -SBE wanADAPT-T1E1 (LMC1200) -.Pp -T1 or E1: RJ45 conn, 100 or 120 ohms, -T1-ESF-B8ZS, T1-SF-AMI, E1-(many)-HDB3, -1.544 Mb/s or 2.048 Mb/s, up to 6 Kft. -.El -.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" -.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. -.It Sy "SPPP" -.Xr sppp 4 -implements Synchronous-PPP, Frame-Relay and Cisco-HDLC 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 -.\" -.Sh EXAMPLES -.\" -.Ss "ifconfig and lmcconfig" -.\" -The program -.Xr lmcconfig 8 -manipulates interface parameters beyond the scope of -.Xr ifconfig 8 . -In normal operation only a few arguments are needed: -.Pp -.Bl -tag -width ".Fl X" -offset indent -compact -.It Fl X -selects the external -SPPP -line protocol package. -.It Fl x -selects the built-in RawIP line protocol package. -.It Fl Z -selects PPP line protocol. -.It Fl z -selects Cisco-HDLC line protocol. -.It Fl F -selects Frame-Relay line protocol. -.El -.Bl -tag -width indent -.It Li "lmcconfig lmc0" -displays interface configuration and status. -.It Li "lmcconfig lmc0 -D" -enables debugging output from the device driver only. -.It Li "ifconfig lmc0 debug" -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 -.Pa "/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. -.El -.\" -.Ss Operation -.\" -Activate a PPP link using SPPP and Netgraph with: -.Bd -literal -offset indent -ngctl mkpeer lmc0: sppp rawdata downstream -ifconfig sppp0 10.0.0.1 10.0.0.2 -.Ed -.Pp -Activate a PPP link using only SPPP with: -.Bd -literal -offset indent -lmcconfig lmc0 -XYZ -ifconfig lmc0 10.0.0.1 10.0.0.2 -.Ed -.Pp -Activate a Cisco-HDLC link using SPPP and Netgraph with: -.Bd -literal -offset indent -ngctl mkpeer lmc0: sppp rawdata downstream -ifconfig sppp0 10.0.0.1 10.0.0.2 link2 -.Ed -.Pp -Activate a Cisco-HDLC link using only SPPP with: -.Bd -literal -offset indent -lmcconfig lmc0 -XYz -ifconfig lmc0 10.0.0.1 10.0.0.2 -.Ed -.Pp -Activate a Cisco-HDLC link using only Netgraph with: -.Bd -literal -offset indent -ngctl mkpeer lmc0: cisco rawdata downstream -ngctl mkpeer lmc0:rawdata iface inet inet -ifconfig ng0 10.0.0.1 10.0.0.2 -.Ed -.Pp -Activate a Frame-Relay DTE link using SPPP with: -.Bd -literal -offset indent -lmcconfig lmc0 -XYF -ifconfig lmc0 10.0.0.1 10.0.0.2 -.Ed -.Pp -(SPPP implements the ANSI T1.617 annex D LMI.) -.Pp -Activate a Frame-Relay DTE link using Netgraph with: -.Bd -literal -offset indent -ngctl mkpeer lmc0: frame_relay rawdata downstream -ngctl mkpeer lmc0:rawdata lmi dlci0 auto0 -ngctl connect lmc0:rawdata dlci0 dlci1023 auto1023 -ngctl mkpeer lmc0:rawdata rfc1490 dlci500 downstream -ngctl mkpeer lmc0:rawdata.dlci500 iface inet inet -ifconfig ng0 10.0.0.1 10.0.0.2 -.Ed -This is -.Em ONE -possible Frame Relay configuration; there are many. -.Pp -Activate a RAWIP link using only the driver with: -.Bd -literal -offset indent -lmcconfig lmc0 -x -ifconfig lmc0 10.0.0.1 10.0.0.2 -.Ed -.Pp -Activate a RAWIP link using Netgraph with: -.Bd -literal -offset indent -ngctl mkpeer lmc0: iface rawdata inet -ifconfig ng0 10.0.0.1 10.0.0.2 -.Ed -.Pp -If the driver is unloaded and then loaded, reconnect hooks by: -.Pp -.Dl "ngctl connect lmc0: ng0: rawdata inet" -.\" -.Sh TESTING -.\" -.Ss Testing with Loopbacks -.\" -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. -.Pp -Activate the card with -.Xr ifconfig 8 : -.Pp -.Dl "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 ".Sy T1/E1" -.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 -.Xr lmcconfig 8 : -.Pp -.Dl "lmcconfig lmc0 -a 2" -.Pp -.Dq Fl a Li 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 -.Xr lmcconfig 8 : -.Pp -.Dl "lmcconfig lmc0 -E -f 10000000" -.Pp -.Fl E -puts the card in DCE mode to source a transmit clock. -.Dq Fl f Li 10000000 -sets the internal clock source to 10 Mb/s. -.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. -.\" -.Ss Testing with a Modem -.\" -Testing with a modem requires two cards of different types. -.Bl -tag -width ".Sy 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 -.\" -.Ss Testing with a Null Modem Cable -.\" -Testing with a null modem cable requires two cards of the same type. -.Bl -tag -width ".Sy 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 -.Xr lmcconfig 8 : -.Pp -.Dl "lmcconfig lmc0 -a 2" -.Pp -.Dq Fl a Li 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 \[em] 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 -.Xr lmcconfig 8 : -.Pp -.Dl "lmcconfig lmc0 -E -f 10000000" -.Pp -.Fl E -puts the card in DCE mode to source a transmit clock. -.Dq Fl f Li 10000000 -sets the internal clock source to 10 Mb/s. -.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 -.\" -.Sh OPERATION NOTES -.\" -.Ss Packet Lengths -Maximum transmit and receive packet length is unlimited. -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 is not 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 -.Pp -.Dl "ifconfig lmc0 mtu 2000" -.Pp -SPPP enforces an MTU of (128..far-end-MRU) for PPP -and 1500 bytes for Cisco-HDLC. -RAWIP sets the default MTU to 4032 bytes, -but it can be changed to anything. -.\" -.Ss BPF - Berkeley Packet Filter -.\" -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 support into your kernel, -add the following line to -.Pa conf/YOURKERNEL : -.Pp -.Dl "device bpf" -.Pp -To test the BPF kernel interface, -bring up a link between two machines, then run -.Xr ping 8 -and -.Xr tcpdump 1 : -.Pp -.Dl "ping 10.0.0.1" -.Pp -and in a different window: -.Pp -.Dl "tcpdump -i lmc0" -.Pp -The output from -.Xr tcpdump 1 -should look like this: -.Bd -literal -offset indent -03:54:35.979965 10.0.0.2 > 10.0.0.1: icmp: echo request -03:54:35.981423 10.0.0.1 > 10.0.0.2: icmp: echo reply -.Ed -.Pp -Line protocol control packets will appear among the -.Xr ping 8 -packets occasionally. -.\" -.Ss Device Polling -.\" -A T3 receiver can generate over 100K interrupts per second, -this can cause a system to -.Dq live-lock : -spend all of its -time servicing interrupts. -.Fx -has a polling mechanism to prevent live-lock. -.Pp -.Fx Ns '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 -See the -.Xr polling 4 -manpage for details on how to enable the polling mode. -.\" -.Ss SNMP: Simple Network Management Protocol -.\" -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: -.Pp -.Bl -item -offset indent -compact -.It -.%T "RFC-2233: Interfaces group" , -.It -.%T "RFC-2496: DS3 interfaces" , -.It -.%T "RFC-2495: DS1/E1 interfaces" , -.It -.%T "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 -Netgraph control messages or -.Xr ioctl 2 -system calls. -User programs should poll -.Va sc->cfg.ticks -which increments once per second after the SNMP state has been updated. -.\" -.Ss HSSI and SSI LEDs -.\" -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. -.Pp -.Bl -column -compact -offset indent "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 -.\" -.Ss T1E1 and T3 LEDs -.\" -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. -.Pp -.Bl -column -compact -offset indent "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 -.Pp -.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 -.\" -.Ss E1 Framing -.\" -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). -.\" -.Ss T3 Framing -.\" -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. -.\" -.Ss T1 & T3 Frame Overhead Functions -.\" -.Bl -item -compact -.It -Performance Report Messages (PRMs) are enabled in T1-ESF. -.It -Bit Oriented Protocol (BOP) messages are enabled in T1-ESF. -.It -In-band loopback control (framed or not) is enabled in T1-SF. -.It -Far End Alarm and Control (FEAC) msgs are enabled in T3-CPar. -.It -Far End Block Error (FEBE) reports are enabled in T3-CPar. -.It -Remote Alarm Indication (RAI) is enabled in T3-Any. -.It -Loopbacks initiated remotely time out after 300 seconds. -.El -.\" -.Ss T1/E1 'Fractional' 64 kb/s Time Slots -.\" -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. -.\" -.Ss T1 Raw Mode -.\" -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 is not hard; after all it is only 1.5 Mb/s second! -.\" -.Ss T3 Circuit Emulation Mode -.\" -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. -.\" -.Ss HSSI and SSI Transmit Clocks -.\" -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 transmit 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. -.\" -.Sh SEE ALSO -.\" -.Xr tcpdump 1 , -.Xr ioctl 2 , -.Xr bpf 4 , -.Xr kld 4 , -.Xr netgraph 4 , -.Xr polling 4 , -.Xr sppp 4 , -.Xr loader.conf 5 , -.Xr ifconfig 8 , -.Xr lmcconfig 8 , -.Xr mpd 8 Pq Pa ports/net/mpd , -.Xr ngctl 8 , -.Xr ping 8 , -.Xr ifnet 9 -.\" -.Sh HISTORY -.\" -.An 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. -.An 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.\& acquired -.Tn LMC -and continues to make the cards. -.Pp -Since the cards use Tulip Ethernet chips, we started with -.An Matt Thomas Ns ' -ubiquitous -.Xr de 4 -driver. -.An Michael Graff -stripped out the Ethernet stuff and added HSSI stuff. -.An Basil Gunn -ported it to -.Tn Solaris -(lost) and -.Tn Rob Braun -ported it to -.Tn Linux . -.An Andrew Stanley-Jones -added support -for three more cards and wrote the first version of -.Xr lmcconfig 8 . -.An David Boggs -rewrote everything and now feels responsible for it. -.\" -.Sh AUTHORS -.\" -.An David Boggs Aq Mt boggs@boggs.palo-alto.ca.us Index: sys/conf/NOTES =================================================================== --- sys/conf/NOTES +++ sys/conf/NOTES @@ -1982,7 +1982,6 @@ # Yukon II Gigabit controllers, including 88E8021, 88E8022, 88E8061, # 88E8062, 88E8035, 88E8036, 88E8038, 88E8050, 88E8052, 88E8053, # 88E8055, 88E8056 and D-Link 560T/550SX. -# lmc: Support for the LMC/SBE wide-area network interface cards. # mlx5: Mellanox ConnectX-4 and ConnectX-4 LX IB and Eth shared code module. # mlx5en:Mellanox ConnectX-4 and ConnectX-4 LX PCIe Ethernet adapters. # my: Myson Fast Ethernet (MTD80X, MTD89X) @@ -2136,9 +2135,6 @@ device vx # 3Com 3c590, 3c595 (``Vortex'') device vxge # Exar/Neterion XFrame 3100 10GbE -# PCI WAN adapters. -device lmc - # PCI IEEE 802.11 Wireless NICs device ath # Atheros pci/cardbus NIC's device ath_hal # pci/cardbus chip support Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -2373,7 +2373,6 @@ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "lio_23xx_nic.bin.fw" -dev/lmc/if_lmc.c optional lmc dev/malo/if_malo.c optional malo dev/malo/if_malohal.c optional malo dev/malo/if_malo_pci.c optional malo pci Index: sys/dev/lmc/if_lmc.h =================================================================== --- sys/dev/lmc/if_lmc.h +++ /dev/null @@ -1,1325 +0,0 @@ -/*- - * $FreeBSD$ - * - * 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. - */ - -#ifndef IF_LMC_H -#define IF_LMC_H - -#define DEVICE_NAME "lmc" - -/* Linux RPM-style version information */ -#define DRIVER_MAJOR_VERSION 2005 /* year */ -#define DRIVER_MINOR_VERSION 9 /* month */ -#define DRIVER_SUB_VERSION 29 /* day */ - -/* netgraph stuff */ -#define NG_LMC_NODE_TYPE DEVICE_NAME -#define NGM_LMC_COOKIE 1128054761 /* date -u +'%s' */ - -/* Tulip PCI configuration registers */ -#define TLP_CFID 0x00 /* 0: CFg ID register */ -#define TLP_CFCS 0x04 /* 1: CFg Command/Status */ -#define TLP_CFRV 0x08 /* 2: CFg ReVision */ -#define TLP_CFLT 0x0C /* 3: CFg Latency Timer */ -#define TLP_CBIO 0x10 /* 4: Cfg Base IO address */ -#define TLP_CBMA 0x14 /* 5: Cfg Base Mem Addr */ -#define TLP_CSID 0x2C /* 11: Cfg Subsys ID reg */ -#define TLP_CFIT 0x3C /* 15: CFg InTerrupt */ -#define TLP_CFDD 0x40 /* 16: CFg Driver Data */ - -#define TLP_CFID_TULIP 0x00091011 /* DEC 21140A Ethernet chip */ - -#define TLP_CFCS_MSTR_ABORT 0x20000000 -#define TLP_CFCS_TARG_ABORT 0x10000000 -#define TLP_CFCS_SYS_ERROR 0x00000100 -#define TLP_CFCS_PAR_ERROR 0x00000040 -#define TLP_CFCS_MWI_ENABLE 0x00000010 -#define TLP_CFCS_BUS_MASTER 0x00000004 -#define TLP_CFCS_MEM_ENABLE 0x00000002 -#define TLP_CFCS_IO_ENABLE 0x00000001 - -#define TLP_CFLT_LATENCY 0x0000FF00 -#define TLP_CFLT_CACHE 0x000000FF - -#define TLP_CSID_HSSI 0x00031376 /* LMC 5200 HSSI card */ -#define TLP_CSID_T3 0x00041376 /* LMC 5245 T3 card */ -#define TLP_CSID_SSI 0x00051376 /* LMC 1000 SSI card */ -#define TLP_CSID_T1E1 0x00061376 /* LMC 1200 T1E1 card */ -#define TLP_CSID_HSSIc 0x00071376 /* LMC 5200 HSSI cPCI */ -#define TLP_CSID_SDSL 0x00081376 /* LMC 1168 SDSL card */ - -#define TLP_CFIT_MAX_LAT 0xFF000000 - -#define TLP_CFDD_SLEEP 0x80000000 -#define TLP_CFDD_SNOOZE 0x40000000 - -/* Tulip Control and Status Registers */ -#define TLP_CSR_STRIDE 8 /* 64 bits */ -#define TLP_BUS_MODE 0 * TLP_CSR_STRIDE -#define TLP_TX_POLL 1 * TLP_CSR_STRIDE -#define TLP_RX_POLL 2 * TLP_CSR_STRIDE -#define TLP_RX_LIST 3 * TLP_CSR_STRIDE -#define TLP_TX_LIST 4 * TLP_CSR_STRIDE -#define TLP_STATUS 5 * TLP_CSR_STRIDE -#define TLP_OP_MODE 6 * TLP_CSR_STRIDE -#define TLP_INT_ENBL 7 * TLP_CSR_STRIDE -#define TLP_MISSED 8 * TLP_CSR_STRIDE -#define TLP_SROM_MII 9 * TLP_CSR_STRIDE -#define TLP_BIOS_ROM 10 * TLP_CSR_STRIDE -#define TLP_TIMER 11 * TLP_CSR_STRIDE -#define TLP_GPIO 12 * TLP_CSR_STRIDE -#define TLP_CSR13 13 * TLP_CSR_STRIDE -#define TLP_CSR14 14 * TLP_CSR_STRIDE -#define TLP_WDOG 15 * TLP_CSR_STRIDE -#define TLP_CSR_SIZE 128 /* IO bus space size */ - -/* CSR 0 - PCI Bus Mode Register */ -#define TLP_BUS_WRITE_INVAL 0x01000000 /* DONT USE! */ -#define TLP_BUS_READ_LINE 0x00800000 -#define TLP_BUS_READ_MULT 0x00200000 -#define TLP_BUS_DESC_BIGEND 0x00100000 -#define TLP_BUS_TAP 0x000E0000 -#define TLP_BUS_CAL 0x0000C000 -#define TLP_BUS_PBL 0x00003F00 -#define TLP_BUS_DATA_BIGEND 0x00000080 -#define TLP_BUS_DSL 0x0000007C -#define TLP_BUS_ARB 0x00000002 -#define TLP_BUS_RESET 0x00000001 -#define TLP_BUS_CAL_SHIFT 14 -#define TLP_BUS_PBL_SHIFT 8 - -/* CSR 5 - Status Register */ -#define TLP_STAT_FATAL_BITS 0x03800000 -#define TLP_STAT_TX_FSM 0x00700000 -#define TLP_STAT_RX_FSM 0x000E0000 -#define TLP_STAT_FATAL_ERROR 0x00002000 -#define TLP_STAT_TX_UNDERRUN 0x00000020 -#define TLP_STAT_FATAL_SHIFT 23 - -/* CSR 6 - Operating Mode Register */ -#define TLP_OP_RECEIVE_ALL 0x40000000 -#define TLP_OP_MUST_BE_ONE 0x02000000 -#define TLP_OP_NO_HEART_BEAT 0x00080000 -#define TLP_OP_PORT_SELECT 0x00040000 -#define TLP_OP_TX_THRESH 0x0000C000 -#define TLP_OP_TX_RUN 0x00002000 -#define TLP_OP_LOOP_MODE 0x00000C00 -#define TLP_OP_EXT_LOOP 0x00000800 -#define TLP_OP_INT_LOOP 0x00000400 -#define TLP_OP_FULL_DUPLEX 0x00000200 -#define TLP_OP_PROMISCUOUS 0x00000040 -#define TLP_OP_PASS_BAD_PKT 0x00000008 -#define TLP_OP_RX_RUN 0x00000002 -#define TLP_OP_TR_SHIFT 14 -#define TLP_OP_INIT (TLP_OP_PORT_SELECT | \ - TLP_OP_FULL_DUPLEX | \ - TLP_OP_MUST_BE_ONE | \ - TLP_OP_NO_HEART_BEAT | \ - TLP_OP_RECEIVE_ALL | \ - TLP_OP_PROMISCUOUS | \ - TLP_OP_PASS_BAD_PKT | \ - TLP_OP_RX_RUN | \ - TLP_OP_TX_RUN) - -/* CSR 7 - Interrupt Enable Register */ -#define TLP_INT_NORMAL_INTR 0x00010000 -#define TLP_INT_ABNRML_INTR 0x00008000 -#define TLP_INT_FATAL_ERROR 0x00002000 -#define TLP_INT_RX_NO_BUFS 0x00000080 -#define TLP_INT_RX_INTR 0x00000040 -#define TLP_INT_TX_UNDERRUN 0x00000020 -#define TLP_INT_TX_INTR 0x00000001 -#define TLP_INT_DISABLE 0 -#define TLP_INT_TX (TLP_INT_NORMAL_INTR | \ - TLP_INT_ABNRML_INTR | \ - TLP_INT_FATAL_ERROR | \ - TLP_INT_TX_UNDERRUN | \ - TLP_INT_TX_INTR) -#define TLP_INT_RX (TLP_INT_NORMAL_INTR | \ - TLP_INT_ABNRML_INTR | \ - TLP_INT_FATAL_ERROR | \ - TLP_INT_RX_NO_BUFS | \ - TLP_INT_RX_INTR) -#define TLP_INT_TXRX (TLP_INT_TX | TLP_INT_RX) - -/* CSR 8 - RX Missed Frames & Overrun Register */ -#define TLP_MISS_OCO 0x10000000 -#define TLP_MISS_OVERRUN 0x0FFE0000 -#define TLP_MISS_MFO 0x00010000 -#define TLP_MISS_MISSED 0x0000FFFF -#define TLP_OVERRUN_SHIFT 17 - -/* CSR 9 - SROM & MII & Boot ROM Register */ -#define TLP_MII_MDIN 0x00080000 -#define TLP_MII_MDOE 0x00040000 -#define TLP_MII_MDOUT 0x00020000 -#define TLP_MII_MDC 0x00010000 - -#define TLP_BIOS_RD 0x00004000 -#define TLP_BIOS_WR 0x00002000 -#define TLP_BIOS_SEL 0x00001000 - -#define TLP_SROM_RD 0x00004000 -#define TLP_SROM_SEL 0x00000800 -#define TLP_SROM_DOUT 0x00000008 -#define TLP_SROM_DIN 0x00000004 -#define TLP_SROM_CLK 0x00000002 -#define TLP_SROM_CS 0x00000001 - -/* CSR 12 - General Purpose IO register */ -#define TLP_GPIO_DIR 0x00000100 - -/* CSR 15 - Watchdog Timer Register */ -#define TLP_WDOG_RX_OFF 0x00000010 -#define TLP_WDOG_TX_OFF 0x00000001 -#define TLP_WDOG_INIT (TLP_WDOG_TX_OFF | \ - TLP_WDOG_RX_OFF) - -/* GPIO bits common to all cards */ -#define GPIO_INIT 0x01 /* from Xilinx */ -#define GPIO_RESET 0x02 /* to Xilinx */ -/* bits 2 and 3 vary with board type -- see below */ -#define GPIO_MODE 0x10 /* to Xilinx */ -#define GPIO_DP 0x20 /* to/from Xilinx */ -#define GPIO_DATA 0x40 /* serial data */ -#define GPIO_CLK 0x80 /* serial clock */ - -/* HSSI GPIO bits */ -#define GPIO_HSSI_ST 0x04 /* send timing sense (deprecated) */ -#define GPIO_HSSI_TXCLK 0x08 /* clock source */ - -/* HSSIc GPIO bits */ -#define GPIO_HSSI_SYNTH 0x04 /* Synth osc chip select */ -#define GPIO_HSSI_DCE 0x08 /* provide clock on TXCLOCK output */ - -/* T3 GPIO bits */ -#define GPIO_T3_DAC 0x04 /* DAC chip select */ -#define GPIO_T3_INTEN 0x08 /* Framer Interrupt enable */ - -/* SSI GPIO bits */ -#define GPIO_SSI_SYNTH 0x04 /* Synth osc chip select */ -#define GPIO_SSI_DCE 0x08 /* provide clock on TXCLOCK output */ - -/* T1E1 GPIO bits */ -#define GPIO_T1_INTEN 0x08 /* Framer Interrupt enable */ - -/* MII register 16 bits common to all cards */ -/* NB: LEDs for HSSI & SSI are in DIFFERENT bits than for T1E1 & T3; oops */ -/* NB: CRC32 for HSSI & SSI is in DIFFERENT bit than for T1E1 & T3; oops */ -#define MII16_LED_ALL 0x0780 /* RW: LED bit mask */ -#define MII16_FIFO 0x0800 /* RW: 1=reset, 0=not reset */ - -/* MII register 16 bits for HSSI */ -#define MII16_HSSI_TA 0x0001 /* RW: host ready; host->modem */ -#define MII16_HSSI_CA 0x0002 /* RO: modem ready; modem->host */ -#define MII16_HSSI_LA 0x0004 /* RW: loopback A; host->modem */ -#define MII16_HSSI_LB 0x0008 /* RW: loopback B; host->modem */ -#define MII16_HSSI_LC 0x0010 /* RO: loopback C; modem->host */ -#define MII16_HSSI_TM 0x0020 /* RO: test mode; modem->host */ -#define MII16_HSSI_CRC32 0x0040 /* RW: CRC length 16/32 */ -#define MII16_HSSI_LED_LL 0x0080 /* RW: lower left - green */ -#define MII16_HSSI_LED_LR 0x0100 /* RW: lower right - green */ -#define MII16_HSSI_LED_UL 0x0200 /* RW: upper left - green */ -#define MII16_HSSI_LED_UR 0x0400 /* RW: upper right - red */ -#define MII16_HSSI_FIFO 0x0800 /* RW: reset fifos */ -#define MII16_HSSI_FORCECA 0x1000 /* RW: [cPCI] force CA on */ -#define MII16_HSSI_CLKMUX 0x6000 /* RW: [cPCI] TX clock selection */ -#define MII16_HSSI_LOOP 0x8000 /* RW: [cPCI] LOOP TX into RX */ -#define MII16_HSSI_MODEM 0x003F /* TA+CA+LA+LB+LC+TM */ - -/* MII register 16 bits for DS3 */ -#define MII16_DS3_ZERO 0x0001 /* RW: short/long cables */ -#define MII16_DS3_TRLBK 0x0002 /* RW: loop towards host */ -#define MII16_DS3_LNLBK 0x0004 /* RW: loop towards net */ -#define MII16_DS3_RAIS 0x0008 /* RO: LIU receive AIS (depr) */ -#define MII16_DS3_TAIS 0x0010 /* RW: LIU transmit AIS (depr) */ -#define MII16_DS3_BIST 0x0020 /* RO: LIU QRSS patt match (depr) */ -#define MII16_DS3_DLOS 0x0040 /* RO: LIU Digital LOS (depr) */ -#define MII16_DS3_LED_BLU 0x0080 /* RW: lower right - blue */ -#define MII16_DS3_LED_YEL 0x0100 /* RW: lower left - yellow */ -#define MII16_DS3_LED_RED 0x0200 /* RW: upper right - red */ -#define MII16_DS3_LED_GRN 0x0400 /* RW: upper left - green */ -#define MII16_DS3_FIFO 0x0800 /* RW: reset fifos */ -#define MII16_DS3_CRC32 0x1000 /* RW: CRC length 16/32 */ -#define MII16_DS3_SCRAM 0x2000 /* RW: payload scrambler */ -#define MII16_DS3_POLY 0x4000 /* RW: 1=Larse, 0=DigLink|Kentrox */ -#define MII16_DS3_FRAME 0x8000 /* RW: 1=stop txframe pulses */ - -/* MII register 16 bits for SSI */ -#define MII16_SSI_DTR 0x0001 /* RW: DTR host->modem */ -#define MII16_SSI_DSR 0x0002 /* RO: DSR modem->host */ -#define MII16_SSI_RTS 0x0004 /* RW: RTS host->modem */ -#define MII16_SSI_CTS 0x0008 /* RO: CTS modem->host */ -#define MII16_SSI_DCD 0x0010 /* RW: DCD modem<->host */ -#define MII16_SSI_RI 0x0020 /* RO: RI modem->host */ -#define MII16_SSI_CRC32 0x0040 /* RW: CRC length 16/32 */ -#define MII16_SSI_LED_LL 0x0080 /* RW: lower left - green */ -#define MII16_SSI_LED_LR 0x0100 /* RW: lower right - green */ -#define MII16_SSI_LED_UL 0x0200 /* RW: upper left - green */ -#define MII16_SSI_LED_UR 0x0400 /* RW: upper right - red */ -#define MII16_SSI_FIFO 0x0800 /* RW: reset fifos */ -#define MII16_SSI_LL 0x1000 /* RW: LL: host->modem */ -#define MII16_SSI_RL 0x2000 /* RW: RL: host->modem */ -#define MII16_SSI_TM 0x4000 /* RO: TM: modem->host */ -#define MII16_SSI_LOOP 0x8000 /* RW: Loop at ext conn */ -#define MII16_SSI_MODEM 0x703F /* DTR+DSR+RTS+CTS+DCD+RI+LL+RL+TM */ - -/* Mii register 17 has the SSI cable bits */ -#define MII17_SSI_CABLE_SHIFT 3 /* shift to get cable type */ -#define MII17_SSI_CABLE_MASK 0x0038 /* RO: mask to get cable type */ -#define MII17_SSI_PRESCALE 0x0040 /* RW: divide by: 0=16; 1=512 */ -#define MII17_SSI_ITF 0x0100 /* RW: fill with: 0=flags; 1=ones */ -#define MII17_SSI_NRZI 0x0400 /* RW: coding: NRZ= 0; NRZI=1 */ - -/* MII register 16 bits for T1/E1 */ -#define MII16_T1_UNUSED1 0x0001 -#define MII16_T1_INVERT 0x0002 /* RW: invert data (for SF/AMI) */ -#define MII16_T1_XOE 0x0004 /* RW: TX Output Enable; 0=disable */ -#define MII16_T1_RST 0x0008 /* RW: Bt8370 chip reset */ -#define MII16_T1_Z 0x0010 /* RW: output impedance T1=1 E1=0 */ -#define MII16_T1_INTR 0x0020 /* RO: interrupt from Bt8370 */ -#define MII16_T1_ONESEC 0x0040 /* RO: one second square wave */ -#define MII16_T1_LED_BLU 0x0080 /* RW: lower right - blue */ -#define MII16_T1_LED_YEL 0x0100 /* RW: lower left - yellow */ -#define MII16_T1_LED_RED 0x0200 /* RW: upper right - red */ -#define MII16_T1_LED_GRN 0x0400 /* RW: upper left - green */ -#define MII16_T1_FIFO 0x0800 /* RW: reset fifos */ -#define MII16_T1_CRC32 0x1000 /* RW: CRC length 16/32 */ -#define MII16_T1_UNUSED2 0xE000 - -/* T3 framer: RW=Read/Write; RO=Read-Only; RC=Read/Clr; WO=Write-Only */ -#define T3CSR_STAT0 0x00 /* RO: real-time status */ -#define T3CSR_CTL1 0x01 /* RW: global control bits */ -#define T3CSR_FEBE 0x02 /* RC: Far End Block Error Counter */ -#define T3CSR_CERR 0x03 /* RC: C-bit Parity Error Counter */ -#define T3CSR_PERR 0x04 /* RC: P-bit Parity Error Counter */ -#define T3CSR_TX_FEAC 0x05 /* RW: Far End Alarm & Control */ -#define T3CSR_RX_FEAC 0x06 /* RO: Far End Alarm & Control */ -#define T3CSR_STAT7 0x07 /* RL: latched real-time status */ -#define T3CSR_CTL8 0x08 /* RW: extended global ctl bits */ -#define T3CSR_STAT9 0x09 /* RL: extended status bits */ -#define T3CSR_FERR 0x0A /* RC: F-bit Error Counter */ -#define T3CSR_MERR 0x0B /* RC: M-bit Error Counter */ -#define T3CSR_CTL12 0x0C /* RW: more extended ctl bits */ -#define T3CSR_DBL_FEAC 0x0D /* RW: TX double FEAC */ -#define T3CSR_CTL14 0x0E /* RW: even more extended ctl bits */ -#define T3CSR_FEAC_STK 0x0F /* RO: RX FEAC stack */ -#define T3CSR_STAT16 0x10 /* RL: extended latched status */ -#define T3CSR_INTEN 0x11 /* RW: interrupt enable */ -#define T3CSR_CVLO 0x12 /* RC: coding violation cntr LSB */ -#define T3CSR_CVHI 0x13 /* RC: coding violation cntr MSB */ -#define T3CSR_CTL20 0x14 /* RW: yet more extended ctl bits */ - -#define CTL1_XTX 0x01 /* Transmit X-bit value */ -#define CTL1_3LOOP 0x02 /* framer loop back */ -#define CTL1_SER 0x04 /* SERial interface selected */ -#define CTL1_M13MODE 0x08 /* M13 frame format */ -#define CTL1_TXIDL 0x10 /* Transmit Idle signal */ -#define CTL1_ENAIS 0x20 /* Enable AIS upon LOS */ -#define CTL1_TXAIS 0x40 /* Transmit Alarm Indication Sig */ -#define CTL1_NOFEBE 0x80 /* No Far End Block Errors */ - -#define CTL5_EMODE 0x80 /* rev B Extended features enabled */ -#define CTL5_START 0x40 /* transmit the FEAC msg now */ - -#define CTL8_FBEC 0x80 /* F-Bit Error Count control */ -#define CTL8_TBLU 0x20 /* Transmit Blue signal */ - -#define STAT9_SEF 0x80 /* Severely Errored Frame */ -#define STAT9_RBLU 0x20 /* Receive Blue signal */ - -#define CTL12_RTPLLEN 0x80 /* Rx-to-Tx Payload Lpbk Lock ENbl */ -#define CTL12_RTPLOOP 0x40 /* Rx-to-Tx Payload Loopback */ -#define CTL12_DLCB1 0x08 /* Data Link C-Bits forced to 1 */ -#define CTL12_C21 0x04 /* C2 forced to 1 */ -#define CTL12_MCB1 0x02 /* Most C-Bits forced to 1 */ - -#define CTL13_DFEXEC 0x40 /* Execute Double FEAC */ - -#define CTL14_FEAC10 0x80 /* Transmit FEAC word 10 times */ -#define CTL14_RGCEN 0x20 /* Receive Gapped Clock Out Enbl */ -#define CTL14_TGCEN 0x10 /* Timing Gen Gapped Clk Out Enbl */ - -#define FEAC_STK_MORE 0x80 /* FEAC stack has more FEACs */ -#define FEAC_STK_VALID 0x40 /* FEAC stack is valid */ -#define FEAC_STK_FEAC 0x3F /* FEAC stack FEAC data */ - -#define STAT16_XERR 0x01 /* X-bit Error */ -#define STAT16_SEF 0x02 /* Severely Errored Frame */ -#define STAT16_RTLOC 0x04 /* Rx/Tx Loss Of Clock */ -#define STAT16_FEAC 0x08 /* new FEAC msg */ -#define STAT16_RIDL 0x10 /* channel IDLe signal */ -#define STAT16_RAIS 0x20 /* Alarm Indication Signal */ -#define STAT16_ROOF 0x40 /* Out Of Frame sync */ -#define STAT16_RLOS 0x80 /* Loss Of Signal */ - -#define CTL20_CVEN 0x01 /* Coding Violation Counter Enbl */ - -/* T1.107 Bit Oriented C-Bit Parity Far End Alarm Control and Status codes */ -#define T3BOP_OOF 0x00 /* Yellow alarm status */ -#define T3BOP_LINE_UP 0x07 /* line loopback activate */ -#define T3BOP_LINE_DOWN 0x1C /* line loopback deactivate */ -#define T3BOP_LOOP_DS3 0x1B /* loopback full DS3 */ -#define T3BOP_IDLE 0x1A /* IDLE alarm status */ -#define T3BOP_AIS 0x16 /* AIS alarm status */ -#define T3BOP_LOS 0x0E /* LOS alarm status */ - -/* T1E1 regs; RW=Read/Write; RO=Read-Only; RC=Read/Clr; WO=Write-Only */ -#define Bt8370_DID 0x000 /* RO: Device ID */ -#define Bt8370_CR0 0x001 /* RW; Primary Control Register */ -#define Bt8370_JAT_CR 0x002 /* RW: Jitter Attenuator CR */ -#define Bt8370_IRR 0x003 /* RO: Interrupt Request Reg */ -#define Bt8370_ISR7 0x004 /* RC: Alarm 1 Interrupt Status */ -#define Bt8370_ISR6 0x005 /* RC: Alarm 2 Interrupt Status */ -#define Bt8370_ISR5 0x006 /* RC: Error Interrupt Status */ -#define Bt8370_ISR4 0x007 /* RC; Cntr Ovfl Interrupt Status */ -#define Bt8370_ISR3 0x008 /* RC: Timer Interrupt Status */ -#define Bt8370_ISR2 0x009 /* RC: Data Link 1 Int Status */ -#define Bt8370_ISR1 0x00A /* RC: Data Link 2 Int Status */ -#define Bt8370_ISR0 0x00B /* RC: Pattrn Interrupt Status */ -#define Bt8370_IER7 0x00C /* RW: Alarm 1 Interrupt Enable */ -#define Bt8370_IER6 0x00D /* RW: Alarm 2 Interrupt Enable */ -#define Bt8370_IER5 0x00E /* RW: Error Interrupt Enable */ -#define Bt8370_IER4 0x00F /* RW: Cntr Ovfl Interrupt Enable */ - -#define Bt8370_IER3 0x010 /* RW: Timer Interrupt Enable */ -#define Bt8370_IER2 0x011 /* RW: Data Link 1 Int Enable */ -#define Bt8370_IER1 0x012 /* RW: Data Link 2 Int Enable */ -#define Bt8370_IER0 0x013 /* RW: Pattern Interrupt Enable */ -#define Bt8370_LOOP 0x014 /* RW: Loopback Config Reg */ -#define Bt8370_DL3_TS 0x015 /* RW: External Data Link Channel */ -#define Bt8370_DL3_BIT 0x016 /* RW: External Data Link Bit */ -#define Bt8370_FSTAT 0x017 /* RO: Offline Framer Status */ -#define Bt8370_PIO 0x018 /* RW: Programmable Input/Output */ -#define Bt8370_POE 0x019 /* RW: Programmable Output Enable */ -#define Bt8370_CMUX 0x01A /* RW: Clock Input Mux */ -#define Bt8370_TMUX 0x01B /* RW: Test Mux Config */ -#define Bt8370_TEST 0x01C /* RW: Test Config */ - -#define Bt8370_LIU_CR 0x020 /* RW: Line Intf Unit Config Reg */ -#define Bt8370_RSTAT 0x021 /* RO; Receive LIU Status */ -#define Bt8370_RLIU_CR 0x022 /* RW: Receive LIU Config */ -#define Bt8370_LPF 0x023 /* RW: RPLL Low Pass Filter */ -#define Bt8370_VGA_MAX 0x024 /* RW: Variable Gain Amplifier Max */ -#define Bt8370_EQ_DAT 0x025 /* RW: Equalizer Coeff Data Reg */ -#define Bt8370_EQ_PTR 0x026 /* RW: Equzlizer Coeff Table Ptr */ -#define Bt8370_DSLICE 0x027 /* RW: Data Slicer Threshold */ -#define Bt8370_EQ_OUT 0x028 /* RW: Equalizer Output Levels */ -#define Bt8370_VGA 0x029 /* RO: Variable Gain Ampl Status */ -#define Bt8370_PRE_EQ 0x02A /* RW: Pre-Equalizer */ - -#define Bt8370_COEFF0 0x030 /* RO: LMS Adj Eq Coeff Status */ -#define Bt8370_GAIN0 0x038 /* RW: Equalizer Gain Thresh */ -#define Bt8370_GAIN1 0x039 /* RW: Equalizer Gain Thresh */ -#define Bt8370_GAIN2 0x03A /* RW: Equalizer Gain Thresh */ -#define Bt8370_GAIN3 0x03B /* RW: Equalizer Gain Thresh */ -#define Bt8370_GAIN4 0x03C /* RW: Equalizer Gain Thresh */ - -#define Bt8370_RCR0 0x040 /* RW: Rx Configuration */ -#define Bt8370_RPATT 0x041 /* RW: Rx Test Pattern Config */ -#define Bt8370_RLB 0x042 /* RW: Rx Loopback Code Detr Conf */ -#define Bt8370_LBA 0x043 /* RW: Loopback Activate Code Patt */ -#define Bt8370_LBD 0x044 /* RW: Loopback Deact Code Patt */ -#define Bt8370_RALM 0x045 /* RW: Rx Alarm Signal Config */ -#define Bt8370_LATCH 0x046 /* RW: Alarm/Err/Cntr Latch Config */ -#define Bt8370_ALM1 0x047 /* RO: Alarm 1 Status */ -#define Bt8370_ALM2 0x048 /* RO: Alarm 2 Status */ -#define Bt8370_ALM3 0x049 /* RO: Alarm 3 Status */ - -#define Bt8370_FERR_LO 0x050 /* RC: Framing Bit Error Cntr LSB */ -#define Bt8370_FERR_HI 0x051 /* RC: Framing Bit Error Cntr MSB */ -#define Bt8370_CRC_LO 0x052 /* RC: CRC Error Counter LSB */ -#define Bt8370_CRC_HI 0x053 /* RC: CRC Error Counter MSB */ -#define Bt8370_LCV_LO 0x054 /* RC: Line Code Viol Counter LSB */ -#define Bt8370_LCV_HI 0x055 /* RC: Line Code Viol Counter MSB */ -#define Bt8370_FEBE_LO 0x056 /* RC: Far End Block Err Cntr LSB */ -#define Bt8370_FEBE_HI 0x057 /* RC: Far End Block Err Cntr MSB */ -#define Bt8370_BERR_LO 0x058 /* RC: PRBS Bit Error Counter LSB */ -#define Bt8370_BERR_HI 0x059 /* RC: PRBS Bit Error Counter MSB */ -#define Bt8370_AERR 0x05A /* RC: SEF/LOF/COFA counter */ -#define Bt8370_RSA4 0x05B /* RO: Rx Sa4 Byte Buffer */ -#define Bt8370_RSA5 0x05C /* RO: Rx Sa5 Byte Buffer */ -#define Bt8370_RSA6 0x05D /* RO: Rx Sa6 Byte Buffer */ -#define Bt8370_RSA7 0x05E /* RO: Rx Sa7 Byte Buffer */ -#define Bt8370_RSA8 0x05F /* RO: Rx Sa8 Byte Buffer */ - -#define Bt8370_SHAPE0 0x060 /* RW: Tx Pulse Shape Config */ -#define Bt8370_TLIU_CR 0x068 /* RW: Tx LIU Config Reg */ - -#define Bt8370_TCR0 0x070 /* RW: Tx Framer Config */ -#define Bt8370_TCR1 0x071 /* RW: Txter Configuration */ -#define Bt8370_TFRM 0x072 /* RW: Tx Frame Format */ -#define Bt8370_TERROR 0x073 /* RW: Tx Error Insert */ -#define Bt8370_TMAN 0x074 /* RW: Tx Manual Sa/FEBE Config */ -#define Bt8370_TALM 0x075 /* RW: Tx Alarm Signal Config */ -#define Bt8370_TPATT 0x076 /* RW: Tx Test Pattern Config */ -#define Bt8370_TLB 0x077 /* RW: Tx Inband Loopback Config */ -#define Bt8370_LBP 0x078 /* RW: Tx Inband Loopback Patt */ -#define Bt8370_TSA4 0x07B /* RW: Tx Sa4 Byte Buffer */ -#define Bt8370_TSA5 0x07C /* RW: Tx Sa5 Byte Buffer */ -#define Bt8370_TSA6 0x07D /* RW: Tx Sa6 Byte Buffer */ -#define Bt8370_TSA7 0x07E /* RW: Tx Sa7 Byte Buffer */ -#define Bt8370_TSA8 0x07F /* RW: Tx Sa8 Byte Buffer */ - -#define Bt8370_CLAD_CR 0x090 /* RW: Clock Rate Adapter Config */ -#define Bt8370_CSEL 0x091 /* RW: CLAD Frequency Select */ -#define Bt8370_CPHASE 0x092 /* RW: CLAD Phase Det Scale Factor */ -#define Bt8370_CTEST 0x093 /* RW: CLAD Test */ - -#define Bt8370_BOP 0x0A0 /* RW: Bit Oriented Protocol Xcvr */ -#define Bt8370_TBOP 0x0A1 /* RW: Tx BOP Codeword */ -#define Bt8370_RBOP 0x0A2 /* RO; Rx BOP Codeword */ -#define Bt8370_BOP_STAT 0x0A3 /* RO: BOP Status */ -#define Bt8370_DL1_TS 0x0A4 /* RW: DL1 Time Slot Enable */ -#define Bt8370_DL1_BIT 0x0A5 /* RW: DL1 Bit Enable */ -#define Bt8370_DL1_CTL 0x0A6 /* RW: DL1 Control */ -#define Bt8370_RDL1_FFC 0x0A7 /* RW: RDL1 FIFO Fill Control */ -#define Bt8370_RDL1 0x0A8 /* RO: RDL1 FIFO */ -#define Bt8370_RDL1_STAT 0x0A9 /* RO: RDL1 Status */ -#define Bt8370_PRM 0x0AA /* RW: Performance Report Message */ -#define Bt8370_TDL1_FEC 0x0AB /* RW: TDL1 FIFO Empty Control */ -#define Bt8370_TDL1_EOM 0x0AC /* WO: TDL1 End Of Message Control */ -#define Bt8370_TDL1 0x0AD /* RW: TDL1 FIFO */ -#define Bt8370_TDL1_STAT 0x0AE /* RO: TDL1 Status */ -#define Bt8370_DL2_TS 0x0AF /* RW: DL2 Time Slot Enable */ - -#define Bt8370_DL2_BIT 0x0B0 /* RW: DL2 Bit Enable */ -#define Bt8370_DL2_CTL 0x0B1 /* RW: DL2 Control */ -#define Bt8370_RDL2_FFC 0x0B2 /* RW: RDL2 FIFO Fill Control */ -#define Bt8370_RDL2 0x0B3 /* RO: RDL2 FIFO */ -#define Bt8370_RDL2_STAT 0x0B4 /* RO: RDL2 Status */ -#define Bt8370_TDL2_FEC 0x0B6 /* RW: TDL2 FIFO Empty Control */ -#define Bt8370_TDL2_EOM 0x0B7 /* WO; TDL2 End Of Message Control */ -#define Bt8370_TDL2 0x0B8 /* RW: TDL2 FIFO */ -#define Bt8370_TDL2_STAT 0x0B9 /* RO: TDL2 Status */ -#define Bt8370_DL_TEST1 0x0BA /* RW: DLINK Test Config */ -#define Bt8370_DL_TEST2 0x0BB /* RW: DLINK Test Status */ -#define Bt8370_DL_TEST3 0x0BC /* RW: DLINK Test Status */ -#define Bt8370_DL_TEST4 0x0BD /* RW: DLINK Test Control */ -#define Bt8370_DL_TEST5 0x0BE /* RW: DLINK Test Control */ - -#define Bt8370_SBI_CR 0x0D0 /* RW: System Bus Interface Config */ -#define Bt8370_RSB_CR 0x0D1 /* RW: Rx System Bus Config */ -#define Bt8370_RSYNC_BIT 0x0D2 /* RW: Rx System Bus Sync Bit Offs */ -#define Bt8370_RSYNC_TS 0x0D3 /* RW: Rx System Bus Sync TS Offs */ -#define Bt8370_TSB_CR 0x0D4 /* RW: Tx System Bus Config */ -#define Bt8370_TSYNC_BIT 0x0D5 /* RW: Tx System Bus Sync Bit OFfs */ -#define Bt8370_TSYNC_TS 0x0D6 /* RW: Tx System Bus Sync TS Offs */ -#define Bt8370_RSIG_CR 0x0D7 /* RW: Rx Siganalling Config */ -#define Bt8370_RSYNC_FRM 0x0D8 /* RW: Sig Reinsertion Frame Offs */ -#define Bt8370_SSTAT 0x0D9 /* RO: Slip Buffer Status */ -#define Bt8370_STACK 0x0DA /* RO: Rx Signalling Stack */ -#define Bt8370_RPHASE 0x0DB /* RO: RSLIP Phase Status */ -#define Bt8370_TPHASE 0x0DC /* RO: TSLIP Phase Status */ -#define Bt8370_PERR 0x0DD /* RO: RAM Parity Status */ - -#define Bt8370_SBCn 0x0E0 /* RW: System Bus Per-Channel Ctl */ -#define Bt8370_TPCn 0x100 /* RW: Tx Per-Channel Control */ -#define Bt8370_TSIGn 0x120 /* RW: Tx Signalling Buffer */ -#define Bt8370_TSLIP_LOn 0x140 /* RW: Tx PCM Slip Buffer Lo */ -#define Bt8370_TSLIP_HIn 0x160 /* RW: Tx PCM Slip Buffer Hi */ -#define Bt8370_RPCn 0x180 /* RW: Rx Per-Channel Control */ -#define Bt8370_RSIGn 0x1A0 /* RW: Rx Signalling Buffer */ -#define Bt8370_RSLIP_LOn 0x1C0 /* RW: Rx PCM Slip Buffer Lo */ -#define Bt8370_RSLIP_HIn 0x1E0 /* RW: Rx PCM Slip Buffer Hi */ - -/* Bt8370_LOOP (0x14) framer loopback control register bits */ -#define LOOP_ANALOG 0x01 /* inward loop thru LIU */ -#define LOOP_FRAMER 0x02 /* inward loop thru framer */ -#define LOOP_LINE 0x04 /* outward loop thru LIU */ -#define LOOP_PAYLOAD 0x08 /* outward loop of payload */ -#define LOOP_DUAL 0x06 /* inward framer + outward line */ - -/* Bt8370_ALM1 (0x47) receiver alarm status register bits */ -#define ALM1_SIGFRZ 0x01 /* Rx Signalling Freeze */ -#define ALM1_RLOF 0x02 /* Rx loss of frame alignment */ -#define ALM1_RLOS 0x04 /* Rx digital loss of signal */ -#define ALM1_RALOS 0x08 /* Rx analog loss of signal */ -#define ALM1_RAIS 0x10 /* Rx Alarm Indication Signal */ -#define ALM1_RYEL 0x40 /* Rx Yellow alarm indication */ -#define ALM1_RMYEL 0x80 /* Rx multiframe YELLOW alarm */ - -/* Bt8370_ALM3 (0x49) receive framer status register bits */ -#define ALM3_FRED 0x04 /* Rx Out Of T1/FAS alignment */ -#define ALM3_MRED 0x08 /* Rx Out Of MFAS alignment */ -#define ALM3_SRED 0x10 /* Rx Out Of CAS alignment */ -#define ALM3_SEF 0x20 /* Rx Severely Errored Frame */ -#define ALM3_RMAIS 0x40 /* Rx TS16 AIS (CAS) */ - -/* Bt8370_TALM (0x75) transmit alarm control register bits */ -#define TALM_TAIS 0x01 /* Tx Alarm Indication Signal */ -#define TALM_TYEL 0x02 /* Tx Yellow alarm */ -#define TALM_TMYEL 0x04 /* Tx Multiframe Yellow alarm */ -#define TALM_AUTO_AIS 0x08 /* auto send AIS on LOS */ -#define TALM_AUTO_YEL 0x10 /* auto send YEL on LOF */ -#define TALM_AUTO_MYEL 0x20 /* auto send E1-Y16 on loss-of-CAS */ - -/* 8370 BOP (Bit Oriented Protocol) command fragments */ -#define RBOP_OFF 0x00 /* BOP Rx disabled */ -#define RBOP_25 0xE0 /* BOP Rx requires 25 BOPs */ -#define TBOP_OFF 0x00 /* BOP Tx disabled */ -#define TBOP_25 0x0B /* BOP Tx sends 25 BOPs */ -#define TBOP_CONT 0x0F /* BOP Tx sends continuously */ - -/* T1.403 Bit-Oriented ESF Data-Link Message codes */ -#define T1BOP_OOF 0x00 /* Yellow alarm status */ -#define T1BOP_LINE_UP 0x07 /* line loopback activate */ -#define T1BOP_LINE_DOWN 0x1C /* line loopback deactivate */ -#define T1BOP_PAY_UP 0x0A /* payload loopback activate */ -#define T1BOP_PAY_DOWN 0x19 /* payload loopback deactivate */ -#define T1BOP_NET_UP 0x09 /* network loopback activate */ -#define T1BOP_NET_DOWN 0x12 /* network loopback deactivate */ - -/* Unix & Linux reserve 16 device-private IOCTLs */ -#if BSD -# define LMCIOCGSTAT _IOWR('i', 240, struct status) -# define LMCIOCGCFG _IOWR('i', 241, struct config) -# define LMCIOCSCFG _IOW('i', 242, struct config) -# define LMCIOCREAD _IOWR('i', 243, struct ioctl) -# define LMCIOCWRITE _IOW('i', 244, struct ioctl) -# define LMCIOCTL _IOWR('i', 245, struct ioctl) -#endif - -struct iohdr /* all LMCIOCs begin with this */ - { - char ifname[IFNAMSIZ]; /* interface name, e.g. "lmc0" */ - u_int32_t cookie; /* interface version number */ - u_int16_t direction; /* missing in Linux IOCTL */ - u_int16_t length; /* missing in Linux IOCTL */ - struct iohdr *iohdr; /* missing in Linux IOCTL */ - u_int32_t spare; /* pad this struct to **32 bytes** */ - }; - -#define DIR_IO 0 -#define DIR_IOW 1 /* copy data user->kernel */ -#define DIR_IOR 2 /* copy data kernel->user */ -#define DIR_IOWR 3 /* copy data kernel<->user */ - -struct hssi_snmp - { - u_int16_t sigs; /* MII16_HSSI & MII16_HSSI_MODEM */ - }; - -struct ssi_snmp - { - u_int16_t sigs; /* MII16_SSI & MII16_SSI_MODEM */ - }; - -struct t3_snmp - { - u_int16_t febe; /* 8 bits - Far End Block err cnt */ - u_int16_t lcv; /* 16 bits - BPV err cnt */ - u_int16_t pcv; /* 8 bits - P-bit err cnt */ - u_int16_t ccv; /* 8 bits - C-bit err cnt */ - u_int16_t line; /* line status bit vector */ - u_int16_t loop; /* loop status bit vector */ - }; - -struct t1_snmp - { - u_int16_t prm[4]; /* T1.403 Performance Report Msg */ - u_int16_t febe; /* 10 bits - E1 FAR CRC err cnt */ - u_int16_t lcv; /* 16 bits - BPV + EXZ err cnt */ - u_int16_t fe; /* 12 bits - Ft/Fs/FPS/FAS err cnt */ - u_int16_t crc; /* 10 bits - CRC6/CRC4 err cnt */ - u_int16_t line; /* line status bit vector */ - u_int16_t loop; /* loop status bit vector */ - }; - -/* SNMP trunk MIB Send codes */ -#define TSEND_NORMAL 1 /* Send data (normal or looped) */ -#define TSEND_LINE 2 /* Send 'line loopback activate' */ -#define TSEND_PAYLOAD 3 /* Send 'payload loop activate' */ -#define TSEND_RESET 4 /* Send 'loopback deactivate' */ -#define TSEND_QRS 5 /* Send Quasi Random Signal */ - -/* ANSI T1.403 Performance Report Msg -- once a second from the far end */ -#define T1PRM_FE 0x8000 /* Frame Sync Bit Error Event >= 1 */ -#define T1PRM_SE 0x4000 /* Severely Err Framing Event >= 1 */ -#define T1PRM_LB 0x2000 /* Payload Loopback Activated */ -#define T1PRM_G1 0x1000 /* CRC Error Event = 1 */ -#define T1PRM_R 0x0800 /* Reserved */ -#define T1PRM_G2 0x0400 /* 1 < CRC Error Event <= 5 */ -#define T1PRM_SEQ 0x0300 /* modulo 4 counter */ -#define T1PRM_G3 0x0080 /* 5 < CRC Error Event <= 10 */ -#define T1PRM_LV 0x0040 /* Line Code Violation Event >= 1 */ -#define T1PRM_G4 0x0020 /* 10 < CRC Error Event <= 100 */ -#define T1PRM_U 0x0018 /* Under study for synchronization */ -#define T1PRM_G5 0x0004 /* 100 < CRC Error Event <= 319 */ -#define T1PRM_SL 0x0002 /* Slip Event >= 1 */ -#define T1PRM_G6 0x0001 /* CRC Error Event >= 320 */ - -/* SNMP Line Status */ -#define TLINE_NORM 0x0001 /* no alarm present */ -#define TLINE_RX_RAI 0x0002 /* receiving RAI = Yellow alarm */ -#define TLINE_TX_RAI 0x0004 /* sending RAI = Yellow alarm */ -#define TLINE_RX_AIS 0x0008 /* receiving AIS = blue alarm */ -#define TLINE_TX_AIS 0x0010 /* sending AIS = blue alarm */ -#define TLINE_LOF 0x0020 /* near end LOF = red alarm */ -#define TLINE_LOS 0x0040 /* near end loss of Signal */ -#define TLINE_LOOP 0x0080 /* near end is looped */ -#define T1LINE_RX_TS16_AIS 0x0100 /* near end receiving TS16 AIS */ -#define T1LINE_RX_TS16_LOMF 0x0200 /* near end sending TS16 LOMF */ -#define T1LINE_TX_TS16_LOMF 0x0400 /* near end receiving TS16 LOMF */ -#define T1LINE_RX_TEST 0x0800 /* near end receiving QRS Signal */ -#define T1LINE_SEF 0x1000 /* near end severely errored frame */ -#define T3LINE_RX_IDLE 0x0100 /* near end receiving IDLE signal */ -#define T3LINE_SEF 0x0200 /* near end severely errored frame */ - -/* SNMP Loopback Status */ -#define TLOOP_NONE 0x01 /* no loopback */ -#define TLOOP_NEAR_PAYLOAD 0x02 /* near end payload loopback */ -#define TLOOP_NEAR_LINE 0x04 /* near end line loopback */ -#define TLOOP_NEAR_OTHER 0x08 /* near end looped somehow */ -#define TLOOP_NEAR_INWARD 0x10 /* near end looped inward */ -#define TLOOP_FAR_PAYLOAD 0x20 /* far end payload loopback */ -#define TLOOP_FAR_LINE 0x40 /* far end line loopback */ - -/* event counters record interesting statistics */ -struct event_cntrs - { - struct timeval reset_time; /* time when cntrs were reset */ - u_int64_t ibytes; /* Rx bytes with good status */ - u_int64_t obytes; /* Tx bytes */ - u_int64_t ipackets; /* Rx packets with good status */ - u_int64_t opackets; /* Tx packets */ - u_int32_t ierrors; /* Rx packets with bad status */ - u_int32_t oerrors; /* Tx packets with bad status */ - u_int32_t idiscards; /* Rx packets discarded */ - u_int32_t odiscards; /* Tx packets discarded */ - u_int32_t fifo_over; /* Rx fifo overruns */ - u_int32_t fifo_under; /* Tx fifo underruns */ - u_int32_t missed; /* Rx pkts missed: no DMA descs */ - u_int32_t overruns; /* Rx pkts missed: fifo overrun */ - u_int32_t fdl_pkts; /* Rx T1 Facility Data Link pkts */ - u_int32_t crc_errs; /* Rx T1 frame CRC errors */ - u_int32_t lcv_errs; /* Rx T1 T3 Line Coding Violation */ - u_int32_t frm_errs; /* Rx T1 T3 Frame bit errors */ - u_int32_t febe_errs; /* Rx T1 T3 Far End Bit Errors */ - u_int32_t par_errs; /* Rx T3 P-bit parity errors */ - u_int32_t cpar_errs; /* Rx T3 C-bit parity errors */ - u_int32_t mfrm_errs; /* Rx T3 Multi-frame bit errors */ - u_int32_t rxdma; /* Rx out of kernel buffers */ - u_int32_t txdma; /* Tx out of DMA desciptors */ - u_int32_t lck_watch; /* try_lock conflict in watchdog */ - u_int32_t lck_ioctl; /* try_lock conflict in ioctl */ - u_int32_t lck_intr; /* try_lock conflict in interrupt */ - }; - -/* sc->status is the READ ONLY status of the card. */ -/* Accessed using socket IO control calls or netgraph control messages. */ -struct status - { - struct iohdr iohdr; /* common ioctl header */ - u_int32_t card_type; /* PCI device number */ - u_int16_t ieee[3]; /* IEEE MAC-addr from Tulip SROM */ - u_int16_t oper_status; /* actual state: up, down, test */ - u_int32_t tx_speed; /* measured TX bits/sec */ - u_int32_t cable_type; /* SSI only: cable type */ - u_int32_t line_pkg; /* actual line pkg in use */ - u_int32_t line_prot; /* actual line proto in use */ - u_int32_t ticks; /* incremented by watchdog @ 1 Hz */ - struct event_cntrs cntrs; /* event counters */ - union - { - struct hssi_snmp hssi; /* data for RFC-???? HSSI MIB */ - struct t3_snmp t3; /* data for RFC-2496 T3 MIB */ - struct ssi_snmp ssi; /* data for RFC-1659 RS232 MIB */ - struct t1_snmp t1; /* data for RFC-2495 T1 MIB */ - } snmp; - }; - -/* line protocol package codes fnobl */ -#define PKG_RAWIP 1 /* driver yyyyy */ -#define PKG_SPPP 2 /* fbsd, nbsd, obsd yyynn */ -#define PKG_P2P 3 /* bsd/os nnnyn */ -#define PKG_NG 4 /* fbsd ynnnn */ -#define PKG_GEN_HDLC 5 /* linux nnnny */ - -/* line protocol codes fnobl */ -#define PROT_PPP 1 /* Point-to-Point Protocol yyyyy */ -#define PROT_C_HDLC 2 /* Cisco HDLC Protocol yyyyy */ -#define PROT_FRM_RLY 3 /* Frame Relay Protocol ynnyy */ -#define PROT_X25 4 /* X.25/LAPB Protocol nnnny */ -#define PROT_ETH_HDLC 5 /* raw Ether pkts in HDLC nnnny */ -#define PROT_IP_HDLC 6 /* raw IP4/6 pkts in HDLC yyyyy */ - -/* oper_status codes (same as SNMP status codes) */ -#define STATUS_UP 1 /* may/will tx/rx pkts */ -#define STATUS_DOWN 2 /* can't/won't tx/rx pkts */ -#define STATUS_TEST 3 /* currently not used */ - -struct synth /* programmable oscillator params */ - { - unsigned n :7; /* numerator (3..127) */ - unsigned m :7; /* denominator (3..127) */ - unsigned v :1; /* mul by 1|8 */ - unsigned x :2; /* div by 1|2|4|8 */ - unsigned r :2; /* div by 1|2|4|8 */ - unsigned prescale :13; /* log(final divisor): 2, 4 or 9 */ - } __attribute__ ((packed)); - -#define SYNTH_FREF 20e6 /* reference xtal = 20 MHz */ -#define SYNTH_FMIN 50e6 /* internal VCO min 50 MHz */ -#define SYNTH_FMAX 250e6 /* internal VCO max 250 MHz */ - -/* sc->config is the READ/WRITE configuration of the card. */ -/* Accessed using socket IO control calls or netgraph control messages. */ -struct config - { - struct iohdr iohdr; /* common ioctl header */ - u_int32_t crc_len; /* ALL: CRC-16 or CRC-32 or none */ - u_int32_t loop_back; /* ALL: many kinds of loopbacks */ - u_int32_t tx_clk_src; /* T1, HSSI: ST, RT, int, ext */ - u_int32_t format; /* T3, T1: ckt framing format */ - u_int32_t time_slots; /* T1: 64Kb time slot config */ - u_int32_t cable_len; /* T3, T1: cable length in meters */ - u_int32_t scrambler; /* T3: payload scrambler config */ - u_int32_t dte_dce; /* SSI, HSSIc: drive TXCLK */ - struct synth synth; /* SSI, HSSIc: synth oscil params */ - u_int32_t rx_gain; /* T1: receiver gain limit 0-50 dB */ - u_int32_t tx_pulse; /* T1: transmitter pulse shape */ - u_int32_t tx_lbo; /* T1: transmitter atten 0-22.5 dB */ - u_int32_t debug; /* ALL: extra printout */ - u_int32_t line_pkg; /* ALL: use this line pkg */ - u_int32_t line_prot; /* SPPP: use this line proto */ - u_int32_t keep_alive; /* SPPP: use keep-alive packets */ - }; - -#define CFG_CRC_0 0 /* no CRC */ -#define CFG_CRC_16 2 /* X^16+X^12+X^5+1 (default) */ -#define CFG_CRC_32 4 /* 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 */ -#define CFG_LOOP_NONE 1 /* SNMP don't loop back anything */ -#define CFG_LOOP_PAYLOAD 2 /* SNMP loop outward thru framer */ -#define CFG_LOOP_LINE 3 /* SNMP loop outward thru LIU */ -#define CFG_LOOP_OTHER 4 /* SNMP loop inward thru LIU */ -#define CFG_LOOP_INWARD 5 /* SNMP loop inward thru framer */ -#define CFG_LOOP_DUAL 6 /* SNMP loop inward & outward */ -#define CFG_LOOP_TULIP 16 /* ALL: loop inward thru Tulip */ -#define CFG_LOOP_PINS 17 /* HSSIc, SSI: loop inward-pins */ -#define CFG_LOOP_LL 18 /* HSSI, SSI: assert LA/LL mdm pin */ -#define CFG_LOOP_RL 19 /* HSSI, SSI: assert LB/RL mdm pin */ - -#define CFG_CLKMUX_ST 1 /* TX clk <- Send timing */ -#define CFG_CLKMUX_INT 2 /* TX clk <- internal source */ -#define CFG_CLKMUX_RT 3 /* TX clk <- Receive (loop) timing */ -#define CFG_CLKMUX_EXT 4 /* TX clk <- ext connector */ - -/* values 0-31 are Bt8370 CR0 register values (LSB is zero if E1). */ -/* values 32-99 are reserved for other T1E1 formats, (even number if E1) */ -/* values 100 and up are used for T3 frame formats. */ -#define CFG_FORMAT_T1SF 9 /* T1-SF AMI */ -#define CFG_FORMAT_T1ESF 27 /* T1-ESF+CRC B8ZS X^6+X+1 */ -#define CFG_FORMAT_E1FAS 0 /* E1-FAS HDB3 TS0 */ -#define CFG_FORMAT_E1FASCRC 8 /* E1-FAS+CRC HDB3 TS0 X^4+X+1 */ -#define CFG_FORMAT_E1FASCAS 16 /* E1-FAS +CAS HDB3 TS0 & TS16 */ -#define CFG_FORMAT_E1FASCRCCAS 24 /* E1-FAS+CRC+CAS HDB3 TS0 & TS16 */ -#define CFG_FORMAT_E1NONE 32 /* E1-NO framing HDB3 */ -#define CFG_FORMAT_T3CPAR 100 /* T3-C-Bit par B3ZS */ -#define CFG_FORMAT_T3M13 101 /* T3-M13 format B3ZS */ - -/* format aliases that improve code readability */ -#define FORMAT_T1ANY ((sc->config.format & 1)==1) -#define FORMAT_E1ANY ((sc->config.format & 1)==0) -#define FORMAT_E1CAS ((sc->config.format & 0x11)==0x10) -#define FORMAT_E1CRC ((sc->config.format & 0x09)==0x08) -#define FORMAT_E1NONE (sc->config.format == CFG_FORMAT_E1NONE) -#define FORMAT_T1ESF (sc->config.format == CFG_FORMAT_T1ESF) -#define FORMAT_T1SF (sc->config.format == CFG_FORMAT_T1SF) -#define FORMAT_T3CPAR (sc->config.format == CFG_FORMAT_T3CPAR) - -#define CFG_SCRAM_OFF 1 /* DS3 payload scrambler off */ -#define CFG_SCRAM_DL_KEN 2 /* DS3 DigitalLink/Kentrox X^43+1 */ -#define CFG_SCRAM_LARS 3 /* DS3 Larscom X^20+X^17+1 w/28ZS */ - -#define CFG_DTE 1 /* HSSIc, SSI: rcv TXCLK; rcv DCD */ -#define CFG_DCE 2 /* HSSIc, SSI: drv TXCLK; drv DCD */ - -#define CFG_GAIN_SHORT 0x24 /* 0-20 dB of equalized gain */ -#define CFG_GAIN_MEDIUM 0x2C /* 0-30 dB of equalized gain */ -#define CFG_GAIN_LONG 0x34 /* 0-40 dB of equalized gain */ -#define CFG_GAIN_EXTEND 0x3F /* 0-64 dB of equalized gain */ -#define CFG_GAIN_AUTO 0xFF /* auto-set based on cable length */ - -#define CFG_PULSE_T1DSX0 0 /* T1 DSX 0- 40 meters */ -#define CFG_PULSE_T1DSX1 2 /* T1 DSX 40- 80 meters */ -#define CFG_PULSE_T1DSX2 4 /* T1 DSX 80-120 meters */ -#define CFG_PULSE_T1DSX3 6 /* T1 DSX 120-160 meters */ -#define CFG_PULSE_T1DSX4 8 /* T1 DSX 160-200 meters */ -#define CFG_PULSE_E1COAX 10 /* E1 75 ohm coax pair */ -#define CFG_PULSE_E1TWIST 12 /* E1 120 ohm twisted pairs */ -#define CFG_PULSE_T1CSU 14 /* T1 CSU 200-2000 meters; set LBO */ -#define CFG_PULSE_AUTO 0xFF /* auto-set based on cable length */ - -#define CFG_LBO_0DB 0 /* T1CSU LBO = 0.0 dB; FCC opt A */ -#define CFG_LBO_7DB 16 /* T1CSU LBO = 7.5 dB; FCC opt B */ -#define CFG_LBO_15DB 32 /* T1CSU LBO = 15.0 dB; FCC opt C */ -#define CFG_LBO_22DB 48 /* T1CSU LBO = 22.5 dB; final span */ -#define CFG_LBO_AUTO 0xFF /* auto-set based on cable length */ - -struct ioctl - { - struct iohdr iohdr; /* common ioctl header */ - u_int32_t cmd; /* command */ - u_int32_t address; /* command address */ - u_int32_t data; /* command data */ - char *ucode; /* user-land address of ucode */ - }; - -#define IOCTL_RW_PCI 1 /* RW: Tulip PCI config registers */ -#define IOCTL_RW_CSR 2 /* RW: Tulip Control & Status Regs */ -#define IOCTL_RW_SROM 3 /* RW: Tulip Serial Rom */ -#define IOCTL_RW_BIOS 4 /* RW: Tulip Boot rom */ -#define IOCTL_RW_MII 5 /* RW: MII registers */ -#define IOCTL_RW_FRAME 6 /* RW: Framer registers */ -#define IOCTL_WO_SYNTH 7 /* WO: Synthesized oscillator */ -#define IOCTL_WO_DAC 8 /* WO: Digital/Analog Converter */ - -#define IOCTL_XILINX_RESET 16 /* reset Xilinx: all FFs set to 0 */ -#define IOCTL_XILINX_ROM 17 /* load Xilinx program from ROM */ -#define IOCTL_XILINX_FILE 18 /* load Xilinx program from file */ - -#define IOCTL_SET_STATUS 50 /* set mdm ctrl bits (internal use)*/ -#define IOCTL_SNMP_SEND 51 /* trunk MIB send code */ -#define IOCTL_SNMP_LOOP 52 /* trunk MIB loop configuration */ -#define IOCTL_SNMP_SIGS 53 /* RS232-like modem control sigs */ -#define IOCTL_RESET_CNTRS 54 /* reset event counters */ - -/* storage for these strings is allocated here! */ -static const char *ssi_cables[] = - { - "V.10/EIA423", - "V.11/EIA530A", - "RESERVED", - "X.21", - "V.35", - "V.36/EIA449", - "V.28/EIA232", - "NO CABLE", - NULL, - }; - -/***************************************************************************/ -/* Declarations above here are shared with the user lmcconfig program. */ -/* Declarations below here are private to the kernel device driver. */ -/***************************************************************************/ - -#if (_KERNEL || KERNEL || __KERNEL__) - -#define SNDQ_MAXLEN 32 /* packets awaiting transmission */ -#define DESCS_PER_PKT 4 /* DMA descriptors per TX pkt */ -#define NUM_TX_DESCS (DESCS_PER_PKT * SNDQ_MAXLEN) -/* Increase DESCS_PER_PKT if status.cntrs.txdma increments. */ - -/* A Tulip DMA descriptor can point to two chunks of memory. - * Each chunk has a max length of 2047 bytes (ask the VMS guys...). - * 2047 isn't a multiple of a cache line size (32 bytes typically). - * So back off to 2048-32 = 2016 bytes per chunk (2 chunks per descr). - */ -#define MAX_CHUNK_LEN 2016 -#define MAX_DESC_LEN (2 * MAX_CHUNK_LEN) - -/* Tulip DMA descriptor; THIS STRUCT MUST MATCH THE HARDWARE */ -struct dma_desc - { - u_int32_t status; /* hardware->to->software */ -#if (BYTE_ORDER == LITTLE_ENDIAN) /* left-to-right packing by compiler */ - unsigned length1:11; /* buffer1 length */ - unsigned length2:11; /* buffer2 length */ - unsigned control:10; /* software->to->hardware */ -#else /* right-to-left packing by compiler */ - unsigned control:10; /* software->to->hardware */ - unsigned length2:11; /* buffer2 length */ - unsigned length1:11; /* buffer1 length */ -#endif - u_int32_t address1; /* buffer1 bus address */ - u_int32_t address2; /* buffer2 bus address */ - bus_dmamap_t map; /* bus dmamap for this descriptor */ -# define TLP_BUS_DSL_VAL (sizeof(bus_dmamap_t) & TLP_BUS_DSL) - } __attribute__ ((packed)); - -/* Tulip DMA descriptor status bits */ -#define TLP_DSTS_OWNER 0x80000000 -#define TLP_DSTS_RX_DESC_ERR 0x00004000 -#define TLP_DSTS_RX_FIRST_DESC 0x00000200 -#define TLP_DSTS_RX_LAST_DESC 0x00000100 -#define TLP_DSTS_RX_MII_ERR 0x00000008 -#define TLP_DSTS_RX_DRIBBLE 0x00000004 -#define TLP_DSTS_TX_UNDERRUN 0x00000002 -#define TLP_DSTS_RX_OVERRUN 0x00000001 /* not documented in rev AF */ -#define TLP_DSTS_RX_BAD (TLP_DSTS_RX_MII_ERR | \ - TLP_DSTS_RX_DRIBBLE | \ - TLP_DSTS_RX_DESC_ERR | \ - TLP_DSTS_RX_OVERRUN) - -/* Tulip DMA descriptor control bits */ -#define TLP_DCTL_TX_INTERRUPT 0x0200 -#define TLP_DCTL_TX_LAST_SEG 0x0100 -#define TLP_DCTL_TX_FIRST_SEG 0x0080 -#define TLP_DCTL_TX_NO_CRC 0x0010 -#define TLP_DCTL_END_RING 0x0008 -#define TLP_DCTL_TX_NO_PAD 0x0002 - -/* DMA descriptors are kept in a ring. - * Ring is empty when (read == write). - * Ring is full when (read == wrap(write+1)), - * The ring also contains a tailq of data buffers. - */ -struct desc_ring - { - struct dma_desc *read; /* next descriptor to be read */ - struct dma_desc *write; /* next descriptor to be written */ - struct dma_desc *first; /* first descriptor in ring */ - struct dma_desc *last; /* last descriptor in ring */ - struct dma_desc *temp; /* temporary write pointer for tx */ - u_int32_t dma_addr; /* bus address for desc array */ - int size_descs; /* bus_dmamap_sync needs this */ - int num_descs; /* used to set rx quota */ -#if BSD - struct mbuf *head; /* tail-queue of mbufs */ - struct mbuf *tail; - bus_dma_tag_t tag; /* bus_dma tag for desc array */ - bus_dmamap_t map; /* bus_dma map for desc array */ - bus_dma_segment_t segs[2]; /* bus_dmamap_load() or bus_dmamem_alloc() */ - int nsegs; /* bus_dmamap_load() or bus_dmamem_alloc() */ -#endif - }; - -/* break circular definition */ -typedef struct softc softc_t; - -/* card-dependent methods */ -struct card - { - void (* config)(softc_t *); - void (* ident)(softc_t *); - int (* watchdog)(softc_t *); /* must not sleep */ - int (* ioctl)(softc_t *, struct ioctl *); /* can sleep */ - }; - -/* flag bits in sc->flags */ -#define FLAG_IFNET 0x00000002 /* IFNET is attached */ -#define FLAG_NETDEV 0x00000004 /* NETDEV is registered */ -#define FLAG_NETGRAPH 0x00000008 /* NETGRAPH is attached */ - -/* Accessing Tulip CSRs: - * There are two ways: IO instruction (default) and memory reference. - * IO refs are used if IOREF_CSR is defined; otherwise memory refs are used. - * MEMORY REFERENCES DO NOT WORK in BSD/OS: page faults happen. - */ -#define IOREF_CSR 1 /* access Tulip CSRs with IO cycles if 1 */ - -#if defined(DEVICE_POLLING) -# define DEV_POLL 1 -#else -# define DEV_POLL 0 -#endif - -#if defined(ALTQ) && ALTQ -# define ALTQ_PRESENT 1 -#else -# define ALTQ_PRESENT 0 -#endif - -/* This is the instance data, or "software context" for the device driver. */ -/* NetBSD, OpenBSD and BSD/OS want struct device first in the softc. */ -/* FreeBSD wants struct ifnet first in the softc. */ -struct softc - { - - - /* State for kernel-resident Line Protocols */ -#if IFNET - struct ifnet *ifp; - struct ifmedia ifm; /* hooks for ifconfig(8) */ -# if NSPPP - struct sppp *sppp; -# elif P2P - struct p2pcom p2pcom; - struct p2pcom *p2p; -# endif -#endif - - -#if NETGRAPH - node_p ng_node; /* pointer to our node struct */ - hook_p ng_hook; /* non-zero means NETGRAPH owns device */ - struct ifaltq ng_sndq; - struct ifaltq ng_fastq; -#endif - - struct callout callout; /* watchdog needs this */ - device_t dev; /* base device pointer */ - bus_space_tag_t csr_tag; /* bus_space needs this */ - bus_space_handle_t csr_handle;/* bus_space_needs this */ - void *irq_cookie; /* bus_teardown_intr needs this */ - struct resource *irq_res; /* bus_release_resource needs this */ - int irq_res_id; /* bus_release_resource needs this */ - struct resource *csr_res; /* bus_release_resource needs this */ - int csr_res_id; /* bus_release resource needs this */ - int csr_res_type; /* bus_release resource needs this */ - struct mbuf *tx_mbuf; /* hang mbuf here while building dma descs */ -# ifdef DEVICE_POLLING - int quota; /* used for incoming packet flow control */ -# endif - struct mtx top_mtx; /* lock card->watchdog vs core_ioctl */ - struct mtx bottom_mtx; /* lock for buf queues & descriptor rings */ - - - /* Top-half state used by all card types; lock with top_lock, */ - const char *dev_desc; /* string describing type of board */ - struct status status; /* driver status lmcconfig can read */ - struct config config; /* driver config lmcconfig can read/write */ - struct card *card; /* card methods: config, ioctl, watchdog */ - u_int32_t gpio_dir; /* s/w copy of GPIO direction register */ - u_int16_t led_state; /* last value written to mii16 */ - u_int32_t flags; /* driver-global flags */ - - /* Top-half state used by card-specific watchdogs; lock with top_lock. */ - u_int32_t last_mii16; /* SSI, HSSI: MII reg 16 one second ago */ - u_int32_t last_stat16; /* T3: framer reg 16 one second ago */ - u_int32_t last_alm1; /* T1E1: framer reg 47 one second ago */ - u_int32_t last_FEAC; /* last FEAC msg code received */ - u_int32_t loop_timer; /* seconds until loopback expires */ - - /* Bottom-half state used by the interrupt code; lock with bottom_lock. */ - struct desc_ring txring; /* tx descriptor ring state */ - struct desc_ring rxring; /* rx descriptor ring state */ - }; /* end of softc */ - -/* Hide the minor differences between OS versions */ - - typedef void intr_return_t; -# define READ_PCI_CFG(sc, addr) pci_read_config ((sc)->dev, addr, 4) -# define WRITE_PCI_CFG(sc, addr, data) pci_write_config((sc)->dev, addr, data, 4) -# define READ_CSR(csr) bus_space_read_4 (sc->csr_tag, sc->csr_handle, csr) -# define WRITE_CSR(csr, val) bus_space_write_4(sc->csr_tag, sc->csr_handle, csr, val) -# define NAME_UNIT device_get_nameunit(sc->dev) -# define DRIVER_DEBUG ((sc->config.debug) || (sc->ifp->if_flags & IFF_DEBUG)) -# define TOP_TRYLOCK mtx_trylock(&sc->top_mtx) -# define TOP_UNLOCK mtx_unlock (&sc->top_mtx) -# define BOTTOM_TRYLOCK mtx_trylock(&sc->bottom_mtx) -# define BOTTOM_UNLOCK mtx_unlock (&sc->bottom_mtx) -# define CHECK_CAP priv_check(curthread, PRIV_DRIVER) -# define DISABLE_INTR /* nothing */ -# define ENABLE_INTR /* nothing */ -# define IRQ_NONE /* nothing */ -# define IRQ_HANDLED /* nothing */ -# define IFP2SC(ifp) (ifp)->if_softc -# define COPY_BREAK MHLEN -# define SLEEP(usecs) tsleep(sc, PCATCH | PZERO, DEVICE_NAME, 1+(usecs/tick)) -# define DMA_SYNC(map, size, flags) bus_dmamap_sync(ring->tag, map, flags) -# define DMA_LOAD(map, addr, size) bus_dmamap_load(ring->tag, map, addr, size, fbsd_dmamap_load, ring, 0) -# if (NBPFILTER != 0) -# define LMC_BPF_MTAP(mbuf) BPF_MTAP(sc->ifp, mbuf) -# define LMC_BPF_ATTACH(dlt, len) bpfattach(sc->ifp, dlt, len) -# define LMC_BPF_DETACH bpfdetach(sc->ifp) -# endif -# define IF_DROP(ifq) _IF_DROP(ifq) -# define IF_QFULL(ifq) _IF_QFULL(ifq) -# define IFF_RUNNING IFF_DRV_RUNNING - - -#if (NBPFILTER == 0) -# define LMC_BPF_MTAP(mbuf) /* nothing */ -# define LMC_BPF_ATTACH(dlt, len) /* nothing */ -# define LMC_BPF_DETACH /* nothing */ -#endif - -#define HSSI_DESC "SBE/LMC HSSI Card" -#define T3_DESC "SBE/LMC T3 Card" -#define SSI_DESC "SBE/LMC SSI Card" -#define T1E1_DESC "SBE/LMC T1E1 Card" - -/* procedure prototypes */ - -static void shift_srom_bits(softc_t *, u_int32_t, u_int32_t); -static u_int16_t read_srom(softc_t *, u_int8_t); -static void write_srom(softc_t *, u_int8_t, u_int16_t); - -static u_int8_t read_bios(softc_t *, u_int32_t); -static void write_bios_phys(softc_t *, u_int32_t, u_int8_t); -static void write_bios(softc_t *, u_int32_t, u_int8_t); -static void erase_bios(softc_t *); - -static void shift_mii_bits(softc_t *, u_int32_t, u_int32_t); -static u_int16_t read_mii(softc_t *, u_int8_t); -static void write_mii(softc_t *, u_int8_t, u_int16_t); - -static void set_mii16_bits(softc_t *, u_int16_t); -static void clr_mii16_bits(softc_t *, u_int16_t); -static void set_mii17_bits(softc_t *, u_int16_t); -static void clr_mii17_bits(softc_t *, u_int16_t); - -static void led_off(softc_t *, u_int16_t); -static void led_on(softc_t *, u_int16_t); -static void led_inv(softc_t *, u_int16_t); - -static void write_framer(softc_t *, u_int16_t, u_int8_t); -static u_int8_t read_framer(softc_t *, u_int16_t); - -static void make_gpio_input(softc_t *, u_int32_t); -static void make_gpio_output(softc_t *, u_int32_t); -static u_int32_t read_gpio(softc_t *); -static void set_gpio_bits(softc_t *, u_int32_t); -static void clr_gpio_bits(softc_t *, u_int32_t); - -static void reset_xilinx(softc_t *); -static void load_xilinx_from_rom(softc_t *); -static int load_xilinx_from_file(softc_t *, char *, u_int32_t); - -static void shift_synth_bits(softc_t *, u_int32_t, u_int32_t); -static void write_synth(softc_t *, struct synth *); - -static void write_dac(softc_t *, u_int16_t); - -static void hssi_config(softc_t *); -static void hssi_ident(softc_t *); -static int hssi_watchdog(softc_t *); -static int hssi_ioctl(softc_t *, struct ioctl *); - -static void t3_config(softc_t *); -static void t3_ident(softc_t *); -static int t3_watchdog(softc_t *); -static void t3_send_dbl_feac(softc_t *, int, int); -static int t3_ioctl(softc_t *, struct ioctl *); - -static void ssi_config(softc_t *); -static void ssi_ident(softc_t *); -static int ssi_watchdog(softc_t *); -static int ssi_ioctl(softc_t *, struct ioctl *); - -static void t1_config(softc_t *); -static void t1_ident(softc_t *); -static int t1_watchdog(softc_t *); -static void t1_send_bop(softc_t *, int); -static int t1_ioctl(softc_t *, struct ioctl *); - -#if IFNET -static void lmc_raw_input(struct ifnet *, struct mbuf *); -#endif /* IFNET */ - -#if BSD -static void mbuf_enqueue(struct desc_ring *, struct mbuf *); -static struct mbuf* mbuf_dequeue(struct desc_ring *); -static void fbsd_dmamap_load(void *, bus_dma_segment_t *, int, int); -static int create_ring(softc_t *, struct desc_ring *, int); -static void destroy_ring(softc_t *, struct desc_ring *); -static int rxintr_cleanup(softc_t *); -static int rxintr_setup(softc_t *); -static int txintr_cleanup(softc_t *); -static int txintr_setup_mbuf(softc_t *, struct mbuf *); -static int txintr_setup(softc_t *); -#endif /* BSD */ - - -static void check_intr_status(softc_t *); -static void core_interrupt(void *, int); -static void user_interrupt(softc_t *, int); -#if BSD -# if (defined(__FreeBSD__) && defined(DEVICE_POLLING)) -static int fbsd_poll(struct ifnet *, enum poll_cmd, int); -# endif -static intr_return_t bsd_interrupt(void *); -#endif /* BSD */ - -static void set_status(softc_t *, int); -#if P2P -static int p2p_getmdm(struct p2pcom *, caddr_t); -static int p2p_mdmctl(struct p2pcom *, int); -#endif -#if NSPPP -static void sppp_tls(struct sppp *); -static void sppp_tlf(struct sppp *); -#endif - -static void config_proto(softc_t *, struct config *); -static int core_ioctl(softc_t *, u_long, caddr_t); -static void core_watchdog(softc_t *); - -#if IFNET -static int lmc_raw_ioctl(struct ifnet *, u_long, caddr_t); -static int lmc_ifnet_ioctl(struct ifnet *, u_long, caddr_t); -static void lmc_ifnet_start(struct ifnet *); -static int lmc_raw_output(struct ifnet *, struct mbuf *, - const struct sockaddr *, struct route *); -static void setup_ifnet(struct ifnet *); -static int lmc_ifnet_attach(softc_t *); -static void lmc_ifnet_detach(softc_t *); -#endif /* IFNET */ - -#if NETGRAPH -static int ng_constructor(node_p); -static int ng_rcvmsg(node_p, item_p, hook_p); -static int ng_shutdown(node_p); -static int ng_newhook(node_p, hook_p, const char *); -static int ng_connect(hook_p); -static int ng_rcvdata(hook_p, item_p); -static int ng_disconnect(hook_p); -# if (IFNET == 0) -static void ng_watchdog(void *); -# endif -static int ng_attach(softc_t *); -static void ng_detach(softc_t *); -#endif /* NETGRAPH */ - -static int startup_card(softc_t *); -static void shutdown_card(void *); -static int attach_card(softc_t *, const char *); -static void detach_card(softc_t *); - -static int fbsd_probe(device_t); -static int fbsd_detach(device_t); -static int fbsd_shutdown(device_t); -static int fbsd_attach(device_t); - - - - - -#endif /* KERNEL */ - -#endif /* IF_LMC_H */ Index: sys/dev/lmc/if_lmc.c =================================================================== --- sys/dev/lmc/if_lmc.c +++ /dev/null @@ -1,4592 +0,0 @@ -/*- - * $FreeBSD$ - * - * Copyright (c) 2002-2004 David Boggs. - * 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 is an open-source Unix device driver for PCI-bus WAN interface cards. - * It sends and receives packets in HDLC frames over synchronous links. - * A generic PC plus Unix plus some SBE/LMC cards makes an OPEN router. - * This driver works with FreeBSD, NetBSD, OpenBSD, BSD/OS and Linux. - * It has been tested on i386 (32-bit little-end), Sparc (64-bit big-end), - * and Alpha (64-bit little-end) architectures. - * - * History and Authors: - * - * Ron Crane had the neat 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 arrays and PC cards. - * We did this at our company, LAN Media Corporation (LMC). - * SBE Corp acquired LMC and continues to make the cards. - * - * 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. - * During 2002-5 David Boggs rewrote it and now feels responsible for it. - * - * Responsible Individual: - * - * Send bug reports and improvements to . - */ -# include /* OS version */ -# define IFNET 1 -# include "opt_inet.h" /* INET */ -# include "opt_inet6.h" /* INET6 */ -# include "opt_netgraph.h" /* NETGRAPH */ -# ifdef HAVE_KERNEL_OPTION_HEADERS -# include "opt_device_polling.h" /* DEVICE_POLLING */ -# endif -# ifndef INET -# define INET 0 -# endif -# ifndef INET6 -# define INET6 0 -# endif -# ifndef NETGRAPH -# define NETGRAPH 0 -# endif -# define P2P 0 /* not in FreeBSD */ -# define NSPPP 1 /* No count devices in FreeBSD 5 */ -# include "opt_bpf.h" /* DEV_BPF */ -# ifdef DEV_BPF -# define NBPFILTER 1 -# else -# define NBPFILTER 0 -# endif -# define GEN_HDLC 0 /* not in FreeBSD */ -# -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# if NETGRAPH -# include -# include -# endif -# if (INET || INET6) -# include -# include -# endif -# if NSPPP -# include -# endif -# if NBPFILTER -# include -# endif -/* and finally... */ -# include - - - - - -/* The SROM is a generic 93C46 serial EEPROM (64 words by 16 bits). */ -/* Data is set up before the RISING edge of CLK; CLK is parked low. */ -static void -shift_srom_bits(softc_t *sc, u_int32_t data, u_int32_t len) - { - u_int32_t csr = READ_CSR(TLP_SROM_MII); - for (; len>0; len--) - { /* MSB first */ - if (data & (1<<(len-1))) - csr |= TLP_SROM_DIN; /* DIN setup */ - else - csr &= ~TLP_SROM_DIN; /* DIN setup */ - WRITE_CSR(TLP_SROM_MII, csr); - csr |= TLP_SROM_CLK; /* CLK rising edge */ - WRITE_CSR(TLP_SROM_MII, csr); - csr &= ~TLP_SROM_CLK; /* CLK falling edge */ - WRITE_CSR(TLP_SROM_MII, csr); - } - } - -/* Data is sampled on the RISING edge of CLK; CLK is parked low. */ -static u_int16_t -read_srom(softc_t *sc, u_int8_t addr) - { - int i; - u_int32_t csr; - u_int16_t data; - - /* Enable SROM access. */ - csr = (TLP_SROM_SEL | TLP_SROM_RD | TLP_MII_MDOE); - WRITE_CSR(TLP_SROM_MII, csr); - /* CS rising edge prepares SROM for a new cycle. */ - csr |= TLP_SROM_CS; - WRITE_CSR(TLP_SROM_MII, csr); /* assert CS */ - shift_srom_bits(sc, 6, 4); /* issue read cmd */ - shift_srom_bits(sc, addr, 6); /* issue address */ - for (data=0, i=16; i>=0; i--) /* read ->17<- bits of data */ - { /* MSB first */ - csr = READ_CSR(TLP_SROM_MII); /* DOUT sampled */ - data = (data<<1) | ((csr & TLP_SROM_DOUT) ? 1:0); - csr |= TLP_SROM_CLK; /* CLK rising edge */ - WRITE_CSR(TLP_SROM_MII, csr); - csr &= ~TLP_SROM_CLK; /* CLK falling edge */ - WRITE_CSR(TLP_SROM_MII, csr); - } - /* Disable SROM access. */ - WRITE_CSR(TLP_SROM_MII, TLP_MII_MDOE); - - return data; - } - -/* The SROM is formatted by the mfgr and should NOT be written! */ -/* But lmcconfig can rewrite it in case it gets overwritten somehow. */ -/* IOCTL SYSCALL: can sleep. */ -static void -write_srom(softc_t *sc, u_int8_t addr, u_int16_t data) - { - u_int32_t csr; - int i; - - /* Enable SROM access. */ - csr = (TLP_SROM_SEL | TLP_SROM_RD | TLP_MII_MDOE); - WRITE_CSR(TLP_SROM_MII, csr); - - /* Issue write-enable command. */ - csr |= TLP_SROM_CS; - WRITE_CSR(TLP_SROM_MII, csr); /* assert CS */ - shift_srom_bits(sc, 4, 4); /* issue write enable cmd */ - shift_srom_bits(sc, 63, 6); /* issue address */ - csr &= ~TLP_SROM_CS; - WRITE_CSR(TLP_SROM_MII, csr); /* deassert CS */ - - /* Issue erase command. */ - csr |= TLP_SROM_CS; - WRITE_CSR(TLP_SROM_MII, csr); /* assert CS */ - shift_srom_bits(sc, 7, 4); /* issue erase cmd */ - shift_srom_bits(sc, addr, 6); /* issue address */ - csr &= ~TLP_SROM_CS; - WRITE_CSR(TLP_SROM_MII, csr); /* deassert CS */ - - /* Issue write command. */ - csr |= TLP_SROM_CS; - WRITE_CSR(TLP_SROM_MII, csr); /* assert CS */ - for (i=0; i<10; i++) /* 100 ms max wait */ - if ((READ_CSR(TLP_SROM_MII) & TLP_SROM_DOUT)==0) SLEEP(10000); - shift_srom_bits(sc, 5, 4); /* issue write cmd */ - shift_srom_bits(sc, addr, 6); /* issue address */ - shift_srom_bits(sc, data, 16); /* issue data */ - csr &= ~TLP_SROM_CS; - WRITE_CSR(TLP_SROM_MII, csr); /* deassert CS */ - - /* Issue write-disable command. */ - csr |= TLP_SROM_CS; - WRITE_CSR(TLP_SROM_MII, csr); /* assert CS */ - for (i=0; i<10; i++) /* 100 ms max wait */ - if ((READ_CSR(TLP_SROM_MII) & TLP_SROM_DOUT)==0) SLEEP(10000); - shift_srom_bits(sc, 4, 4); /* issue write disable cmd */ - shift_srom_bits(sc, 0, 6); /* issue address */ - csr &= ~TLP_SROM_CS; - WRITE_CSR(TLP_SROM_MII, csr); /* deassert CS */ - - /* Disable SROM access. */ - WRITE_CSR(TLP_SROM_MII, TLP_MII_MDOE); - } - -/* Not all boards have BIOS roms. */ -/* The BIOS ROM is an AMD 29F010 1Mbit (128K by 8) EEPROM. */ -static u_int8_t -read_bios(softc_t *sc, u_int32_t addr) - { - u_int32_t srom_mii; - - /* Load the BIOS rom address register. */ - WRITE_CSR(TLP_BIOS_ROM, addr); - - /* Enable the BIOS rom. */ - srom_mii = TLP_BIOS_SEL | TLP_BIOS_RD | TLP_MII_MDOE; - WRITE_CSR(TLP_SROM_MII, srom_mii); - - /* Wait at least 20 PCI cycles. */ - DELAY(20); - - /* Read the BIOS rom data. */ - srom_mii = READ_CSR(TLP_SROM_MII); - - /* Disable the BIOS rom. */ - WRITE_CSR(TLP_SROM_MII, TLP_MII_MDOE); - - return (u_int8_t)srom_mii & 0xFF; - } - -static void -write_bios_phys(softc_t *sc, u_int32_t addr, u_int8_t data) - { - u_int32_t srom_mii; - - /* Load the BIOS rom address register. */ - WRITE_CSR(TLP_BIOS_ROM, addr); - - /* Enable the BIOS rom. */ - srom_mii = TLP_BIOS_SEL | TLP_BIOS_WR | TLP_MII_MDOE; - - /* Load the data into the data register. */ - srom_mii = (srom_mii & 0xFFFFFF00) | (data & 0xFF); - WRITE_CSR(TLP_SROM_MII, srom_mii); - - /* Wait at least 20 PCI cycles. */ - DELAY(20); - - /* Disable the BIOS rom. */ - WRITE_CSR(TLP_SROM_MII, TLP_MII_MDOE); - } - -/* IOCTL SYSCALL: can sleep. */ -static void -write_bios(softc_t *sc, u_int32_t addr, u_int8_t data) - { - u_int8_t read_data; - - /* this sequence enables writing */ - write_bios_phys(sc, 0x5555, 0xAA); - write_bios_phys(sc, 0x2AAA, 0x55); - write_bios_phys(sc, 0x5555, 0xA0); - write_bios_phys(sc, addr, data); - - /* Wait for the write operation to complete. */ - for (;;) /* interruptable syscall */ - { - for (;;) - { - read_data = read_bios(sc, addr); - if ((read_data & 0x80) == (data & 0x80)) break; - if (read_data & 0x20) - { /* Data sheet says read it again. */ - read_data = read_bios(sc, addr); - if ((read_data & 0x80) == (data & 0x80)) break; - if (DRIVER_DEBUG) - printf("%s: write_bios() failed; rom addr=0x%x\n", - NAME_UNIT, addr); - return; - } - } - read_data = read_bios(sc, addr); - if (read_data == data) break; - } - } - -/* IOCTL SYSCALL: can sleep. */ -static void -erase_bios(softc_t *sc) - { - unsigned char read_data; - - /* This sequence enables erasing: */ - write_bios_phys(sc, 0x5555, 0xAA); - write_bios_phys(sc, 0x2AAA, 0x55); - write_bios_phys(sc, 0x5555, 0x80); - write_bios_phys(sc, 0x5555, 0xAA); - write_bios_phys(sc, 0x2AAA, 0x55); - write_bios_phys(sc, 0x5555, 0x10); - - /* Wait for the erase operation to complete. */ - for (;;) /* interruptable syscall */ - { - for (;;) - { - read_data = read_bios(sc, 0); - if (read_data & 0x80) break; - if (read_data & 0x20) - { /* Data sheet says read it again. */ - read_data = read_bios(sc, 0); - if (read_data & 0x80) break; - if (DRIVER_DEBUG) - printf("%s: erase_bios() failed\n", NAME_UNIT); - return; - } - } - read_data = read_bios(sc, 0); - if (read_data == 0xFF) break; - } - } - -/* MDIO is 3-stated between tranactions. */ -/* MDIO is set up before the RISING edge of MDC; MDC is parked low. */ -static void -shift_mii_bits(softc_t *sc, u_int32_t data, u_int32_t len) - { - u_int32_t csr = READ_CSR(TLP_SROM_MII); - for (; len>0; len--) - { /* MSB first */ - if (data & (1<<(len-1))) - csr |= TLP_MII_MDOUT; /* MDOUT setup */ - else - csr &= ~TLP_MII_MDOUT; /* MDOUT setup */ - WRITE_CSR(TLP_SROM_MII, csr); - csr |= TLP_MII_MDC; /* MDC rising edge */ - WRITE_CSR(TLP_SROM_MII, csr); - csr &= ~TLP_MII_MDC; /* MDC falling edge */ - WRITE_CSR(TLP_SROM_MII, csr); - } - } - -/* The specification for the MII is IEEE Std 802.3 clause 22. */ -/* MDIO is sampled on the RISING edge of MDC; MDC is parked low. */ -static u_int16_t -read_mii(softc_t *sc, u_int8_t regad) - { - int i; - u_int32_t csr; - u_int16_t data = 0; - - WRITE_CSR(TLP_SROM_MII, TLP_MII_MDOUT); - - shift_mii_bits(sc, 0xFFFFF, 20); /* preamble */ - shift_mii_bits(sc, 0xFFFFF, 20); /* preamble */ - shift_mii_bits(sc, 1, 2); /* start symbol */ - shift_mii_bits(sc, 2, 2); /* read op */ - shift_mii_bits(sc, 0, 5); /* phyad=0 */ - shift_mii_bits(sc, regad, 5); /* regad */ - csr = READ_CSR(TLP_SROM_MII); - csr |= TLP_MII_MDOE; - WRITE_CSR(TLP_SROM_MII, csr); - shift_mii_bits(sc, 0, 2); /* turn-around */ - for (i=15; i>=0; i--) /* data */ - { /* MSB first */ - csr = READ_CSR(TLP_SROM_MII); /* MDIN sampled */ - data = (data<<1) | ((csr & TLP_MII_MDIN) ? 1:0); - csr |= TLP_MII_MDC; /* MDC rising edge */ - WRITE_CSR(TLP_SROM_MII, csr); - csr &= ~TLP_MII_MDC; /* MDC falling edge */ - WRITE_CSR(TLP_SROM_MII, csr); - } - return data; - } - -static void -write_mii(softc_t *sc, u_int8_t regad, u_int16_t data) - { - WRITE_CSR(TLP_SROM_MII, TLP_MII_MDOUT); - shift_mii_bits(sc, 0xFFFFF, 20); /* preamble */ - shift_mii_bits(sc, 0xFFFFF, 20); /* preamble */ - shift_mii_bits(sc, 1, 2); /* start symbol */ - shift_mii_bits(sc, 1, 2); /* write op */ - shift_mii_bits(sc, 0, 5); /* phyad=0 */ - shift_mii_bits(sc, regad, 5); /* regad */ - shift_mii_bits(sc, 2, 2); /* turn-around */ - shift_mii_bits(sc, data, 16); /* data */ - WRITE_CSR(TLP_SROM_MII, TLP_MII_MDOE); - if (regad == 16) sc->led_state = data; /* a small optimization */ - } - -static void -set_mii16_bits(softc_t *sc, u_int16_t bits) - { - u_int16_t mii16 = read_mii(sc, 16); - mii16 |= bits; - write_mii(sc, 16, mii16); - } - -static void -clr_mii16_bits(softc_t *sc, u_int16_t bits) - { - u_int16_t mii16 = read_mii(sc, 16); - mii16 &= ~bits; - write_mii(sc, 16, mii16); - } - -static void -set_mii17_bits(softc_t *sc, u_int16_t bits) - { - u_int16_t mii17 = read_mii(sc, 17); - mii17 |= bits; - write_mii(sc, 17, mii17); - } - -static void -clr_mii17_bits(softc_t *sc, u_int16_t bits) - { - u_int16_t mii17 = read_mii(sc, 17); - mii17 &= ~bits; - write_mii(sc, 17, mii17); - } - -/* - * Watchdog code is more readable if it refreshes LEDs - * once a second whether they need it or not. - * But MII refs take 150 uSecs each, so remember the last value - * written to MII16 and avoid LED writes that do nothing. - */ - -static void -led_off(softc_t *sc, u_int16_t led) - { - if ((led & sc->led_state) == led) return; - set_mii16_bits(sc, led); - } - -static void -led_on(softc_t *sc, u_int16_t led) - { - if ((led & sc->led_state) == 0) return; - clr_mii16_bits(sc, led); - } - -static void -led_inv(softc_t *sc, u_int16_t led) - { - u_int16_t mii16 = read_mii(sc, 16); - mii16 ^= led; - write_mii(sc, 16, mii16); - } - -/* - * T1 & T3 framer registers are accessed through MII regs 17 & 18. - * Write the address to MII reg 17 then R/W data through MII reg 18. - * The hardware interface is an Intel-style 8-bit muxed A/D bus. - */ -static void -write_framer(softc_t *sc, u_int16_t addr, u_int8_t data) - { - write_mii(sc, 17, addr); - write_mii(sc, 18, data); - } - -static u_int8_t -read_framer(softc_t *sc, u_int16_t addr) - { - write_mii(sc, 17, addr); - return (u_int8_t)read_mii(sc, 18); - } - -/* Tulip's hardware implementation of General Purpose IO - * (GPIO) pins makes life difficult for software. - * Bits 7-0 in the Tulip GPIO CSR are used for two purposes - * depending on the state of bit 8. - * If bit 8 is 0 then bits 7-0 are "data" bits. - * If bit 8 is 1 then bits 7-0 are "direction" bits. - * If a direction bit is one, the data bit is an output. - * The problem is that the direction bits are WRITE-ONLY. - * Software must remember the direction bits in a shadow copy. - * (sc->gpio_dir) in order to change some but not all of the bits. - * All accesses to the Tulip GPIO register use these five procedures. - */ - -static void -make_gpio_input(softc_t *sc, u_int32_t bits) - { - sc->gpio_dir &= ~bits; - WRITE_CSR(TLP_GPIO, TLP_GPIO_DIR | (sc->gpio_dir)); - } - -static void -make_gpio_output(softc_t *sc, u_int32_t bits) - { - sc->gpio_dir |= bits; - WRITE_CSR(TLP_GPIO, TLP_GPIO_DIR | (sc->gpio_dir)); - } - -static u_int32_t -read_gpio(softc_t *sc) - { - return READ_CSR(TLP_GPIO); - } - -static void -set_gpio_bits(softc_t *sc, u_int32_t bits) - { - WRITE_CSR(TLP_GPIO, (read_gpio(sc) | bits) & 0xFF); - } - -static void -clr_gpio_bits(softc_t *sc, u_int32_t bits) - { - WRITE_CSR(TLP_GPIO, (read_gpio(sc) & ~bits) & 0xFF); - } - -/* Reset ALL of the flip-flops in the gate array to zero. */ -/* This does NOT change the gate array programming. */ -/* Called during initialization so it must not sleep. */ -static void -reset_xilinx(softc_t *sc) - { - /* Drive RESET low to force initialization. */ - clr_gpio_bits(sc, GPIO_RESET); - make_gpio_output(sc, GPIO_RESET); - - /* Hold RESET low for more than 10 uSec. */ - DELAY(50); - - /* Done with RESET; make it an input. */ - make_gpio_input(sc, GPIO_RESET); - } - -/* Load Xilinx gate array program from on-board rom. */ -/* This changes the gate array programming. */ -/* IOCTL SYSCALL: can sleep. */ -static void -load_xilinx_from_rom(softc_t *sc) - { - int i; - - /* Drive MODE low to load from ROM rather than GPIO. */ - clr_gpio_bits(sc, GPIO_MODE); - make_gpio_output(sc, GPIO_MODE); - - /* Drive DP & RESET low to force configuration. */ - clr_gpio_bits(sc, GPIO_RESET | GPIO_DP); - make_gpio_output(sc, GPIO_RESET | GPIO_DP); - - /* Hold RESET & DP low for more than 10 uSec. */ - DELAY(50); - - /* Done with RESET & DP; make them inputs. */ - make_gpio_input(sc, GPIO_DP | GPIO_RESET); - - /* BUSY-WAIT for Xilinx chip to configure itself from ROM bits. */ - for (i=0; i<100; i++) /* 1 sec max delay */ - if ((read_gpio(sc) & GPIO_DP) == 0) SLEEP(10000); - - /* Done with MODE; make it an input. */ - make_gpio_input(sc, GPIO_MODE); - } - -/* Load the Xilinx gate array program from userland bits. */ -/* This changes the gate array programming. */ -/* IOCTL SYSCALL: can sleep. */ -static int -load_xilinx_from_file(softc_t *sc, char *addr, u_int32_t len) - { - char *data; - int i, j, error; - - /* Get some pages to hold the Xilinx bits; biggest file is < 6 KB. */ - if (len > 8192) return EFBIG; /* too big */ - data = malloc(len, M_DEVBUF, M_WAITOK); - if (data == NULL) return ENOMEM; - - /* Copy the Xilinx bits from userland. */ - if ((error = copyin(addr, data, len))) - { - free(data, M_DEVBUF); - return error; - } - - /* Drive MODE high to load from GPIO rather than ROM. */ - set_gpio_bits(sc, GPIO_MODE); - make_gpio_output(sc, GPIO_MODE); - - /* Drive DP & RESET low to force configuration. */ - clr_gpio_bits(sc, GPIO_RESET | GPIO_DP); - make_gpio_output(sc, GPIO_RESET | GPIO_DP); - - /* Hold RESET & DP low for more than 10 uSec. */ - DELAY(50); - - /* Done with RESET & DP; make them inputs. */ - make_gpio_input(sc, GPIO_RESET | GPIO_DP); - - /* BUSY-WAIT for Xilinx chip to clear its config memory. */ - make_gpio_input(sc, GPIO_INIT); - for (i=0; i<10000; i++) /* 1 sec max delay */ - if ((read_gpio(sc) & GPIO_INIT)==0) SLEEP(10000); - - /* Configure CLK and DATA as outputs. */ - set_gpio_bits(sc, GPIO_CLK); /* park CLK high */ - make_gpio_output(sc, GPIO_CLK | GPIO_DATA); - - /* Write bits to Xilinx; CLK is parked HIGH. */ - /* DATA is set up before the RISING edge of CLK. */ - for (i=0; istatus.card_type == TLP_CSID_SSI) - { - if (synth->prescale == 9) /* divide by 512 */ - set_mii17_bits(sc, MII17_SSI_PRESCALE); - else /* divide by 32 */ - clr_mii17_bits(sc, MII17_SSI_PRESCALE); - } - - clr_gpio_bits(sc, GPIO_DATA | GPIO_CLK); - make_gpio_output(sc, GPIO_DATA | GPIO_CLK); - - /* SYNTH is a low-true chip enable for the AV9110 chip. */ - set_gpio_bits(sc, GPIO_SSI_SYNTH); - make_gpio_output(sc, GPIO_SSI_SYNTH); - clr_gpio_bits(sc, GPIO_SSI_SYNTH); - - /* Serially shift the command into the AV9110 chip. */ - shift_synth_bits(sc, synth->n, 7); - shift_synth_bits(sc, synth->m, 7); - shift_synth_bits(sc, synth->v, 1); - shift_synth_bits(sc, synth->x, 2); - shift_synth_bits(sc, synth->r, 2); - shift_synth_bits(sc, 0x16, 5); /* enable clk/x output */ - - /* SYNTH (chip enable) going high ends the command. */ - set_gpio_bits(sc, GPIO_SSI_SYNTH); - make_gpio_input(sc, GPIO_SSI_SYNTH); - - /* Stop driving serial-related signals; pullups/pulldowns take over. */ - make_gpio_input(sc, GPIO_DATA | GPIO_CLK); - - /* remember the new synthesizer parameters */ - if (&sc->config.synth != synth) sc->config.synth = *synth; - } - -/* Write a command to the DAC controlling the VCXO on some T3 adapters. */ -/* The DAC is a TI-TLV5636: 12-bit resolution and a serial interface. */ -/* DATA is set up before the FALLING edge of CLK. CLK is parked HIGH. */ -static void -write_dac(softc_t *sc, u_int16_t data) - { - int i; - - /* Prepare to use DATA and CLK. */ - set_gpio_bits(sc, GPIO_DATA | GPIO_CLK); - make_gpio_output(sc, GPIO_DATA | GPIO_CLK); - - /* High-to-low transition prepares DAC for new value. */ - set_gpio_bits(sc, GPIO_T3_DAC); - make_gpio_output(sc, GPIO_T3_DAC); - clr_gpio_bits(sc, GPIO_T3_DAC); - - /* Serially shift command bits into DAC. */ - for (i=0; i<16; i++) - { /* MSB first */ - if ((data & (1<<(15-i))) != 0) - set_gpio_bits(sc, GPIO_DATA); /* DATA setup */ - else - clr_gpio_bits(sc, GPIO_DATA); /* DATA setup */ - clr_gpio_bits(sc, GPIO_CLK); /* CLK falling edge */ - set_gpio_bits(sc, GPIO_CLK); /* CLK rising edge */ - } - - /* Done with DAC; make it an input; loads new value into DAC. */ - set_gpio_bits(sc, GPIO_T3_DAC); - make_gpio_input(sc, GPIO_T3_DAC); - - /* Stop driving serial-related signals; pullups/pulldowns take over. */ - make_gpio_input(sc, GPIO_DATA | GPIO_CLK); - } - -/* begin HSSI card code */ - -/* Must not sleep. */ -static void -hssi_config(softc_t *sc) - { - if (sc->status.card_type == 0) - { /* defaults */ - sc->status.card_type = READ_PCI_CFG(sc, TLP_CSID); - sc->config.crc_len = CFG_CRC_16; - sc->config.loop_back = CFG_LOOP_NONE; - sc->config.tx_clk_src = CFG_CLKMUX_ST; - sc->config.dte_dce = CFG_DTE; - sc->config.synth.n = 52; /* 52.000 Mbs */ - sc->config.synth.m = 5; - sc->config.synth.v = 0; - sc->config.synth.x = 0; - sc->config.synth.r = 0; - sc->config.synth.prescale = 2; - } - - /* set CRC length */ - if (sc->config.crc_len == CFG_CRC_32) - set_mii16_bits(sc, MII16_HSSI_CRC32); - else - clr_mii16_bits(sc, MII16_HSSI_CRC32); - - /* Assert pin LA in HSSI conn: ask modem for local loop. */ - if (sc->config.loop_back == CFG_LOOP_LL) - set_mii16_bits(sc, MII16_HSSI_LA); - else - clr_mii16_bits(sc, MII16_HSSI_LA); - - /* Assert pin LB in HSSI conn: ask modem for remote loop. */ - if (sc->config.loop_back == CFG_LOOP_RL) - set_mii16_bits(sc, MII16_HSSI_LB); - else - clr_mii16_bits(sc, MII16_HSSI_LB); - - if (sc->status.card_type == TLP_CSID_HSSI) - { - /* set TXCLK src */ - if (sc->config.tx_clk_src == CFG_CLKMUX_ST) - set_gpio_bits(sc, GPIO_HSSI_TXCLK); - else - clr_gpio_bits(sc, GPIO_HSSI_TXCLK); - make_gpio_output(sc, GPIO_HSSI_TXCLK); - } - else if (sc->status.card_type == TLP_CSID_HSSIc) - { /* cPCI HSSI rev C has extra features */ - /* Set TXCLK source. */ - u_int16_t mii16 = read_mii(sc, 16); - mii16 &= ~MII16_HSSI_CLKMUX; - mii16 |= (sc->config.tx_clk_src&3)<<13; - write_mii(sc, 16, mii16); - - /* cPCI HSSI implements loopback towards the net. */ - if (sc->config.loop_back == CFG_LOOP_LINE) - set_mii16_bits(sc, MII16_HSSI_LOOP); - else - clr_mii16_bits(sc, MII16_HSSI_LOOP); - - /* Set DTE/DCE mode. */ - if (sc->config.dte_dce == CFG_DCE) - set_gpio_bits(sc, GPIO_HSSI_DCE); - else - clr_gpio_bits(sc, GPIO_HSSI_DCE); - make_gpio_output(sc, GPIO_HSSI_DCE); - - /* Program the synthesized oscillator. */ - write_synth(sc, &sc->config.synth); - } - } - -static void -hssi_ident(softc_t *sc) - { - } - -/* Called once a second; must not sleep. */ -static int -hssi_watchdog(softc_t *sc) - { - u_int16_t mii16 = read_mii(sc, 16) & MII16_HSSI_MODEM; - int link_status = STATUS_UP; - - led_inv(sc, MII16_HSSI_LED_UL); /* Software is alive. */ - led_on(sc, MII16_HSSI_LED_LL); /* always on (SSI cable) */ - - /* Check the transmit clock. */ - if (sc->status.tx_speed == 0) - { - led_on(sc, MII16_HSSI_LED_UR); - link_status = STATUS_DOWN; - } - else - led_off(sc, MII16_HSSI_LED_UR); - - /* Is the modem ready? */ - if ((mii16 & MII16_HSSI_CA) == 0) - { - led_off(sc, MII16_HSSI_LED_LR); - link_status = STATUS_DOWN; - } - else - led_on(sc, MII16_HSSI_LED_LR); - - /* Print the modem control signals if they changed. */ - if ((DRIVER_DEBUG) && (mii16 != sc->last_mii16)) - { - char *on = "ON ", *off = "OFF"; - printf("%s: TA=%s CA=%s LA=%s LB=%s LC=%s TM=%s\n", NAME_UNIT, - (mii16 & MII16_HSSI_TA) ? on : off, - (mii16 & MII16_HSSI_CA) ? on : off, - (mii16 & MII16_HSSI_LA) ? on : off, - (mii16 & MII16_HSSI_LB) ? on : off, - (mii16 & MII16_HSSI_LC) ? on : off, - (mii16 & MII16_HSSI_TM) ? on : off); - } - - /* SNMP one-second-report */ - sc->status.snmp.hssi.sigs = mii16 & MII16_HSSI_MODEM; - - /* Remember this state until next time. */ - sc->last_mii16 = mii16; - - /* If a loop back is in effect, link status is UP */ - if (sc->config.loop_back != CFG_LOOP_NONE) - link_status = STATUS_UP; - - return link_status; - } - -/* IOCTL SYSCALL: can sleep (but doesn't). */ -static int -hssi_ioctl(softc_t *sc, struct ioctl *ioctl) - { - int error = 0; - - if (ioctl->cmd == IOCTL_SNMP_SIGS) - { - u_int16_t mii16 = read_mii(sc, 16); - mii16 &= ~MII16_HSSI_MODEM; - mii16 |= (MII16_HSSI_MODEM & ioctl->data); - write_mii(sc, 16, mii16); - } - else if (ioctl->cmd == IOCTL_SET_STATUS) - { - if (ioctl->data != 0) - set_mii16_bits(sc, MII16_HSSI_TA); - else - clr_mii16_bits(sc, MII16_HSSI_TA); - } - else - error = EINVAL; - - return error; - } - -/* begin DS3 card code */ - -/* Must not sleep. */ -static void -t3_config(softc_t *sc) - { - int i; - u_int8_t ctl1; - - if (sc->status.card_type == 0) - { /* defaults */ - sc->status.card_type = TLP_CSID_T3; - sc->config.crc_len = CFG_CRC_16; - sc->config.loop_back = CFG_LOOP_NONE; - sc->config.format = CFG_FORMAT_T3CPAR; - sc->config.cable_len = 10; /* meters */ - sc->config.scrambler = CFG_SCRAM_DL_KEN; - sc->config.tx_clk_src = CFG_CLKMUX_INT; - - /* Center the VCXO -- get within 20 PPM of 44736000. */ - write_dac(sc, 0x9002); /* set Vref = 2.048 volts */ - write_dac(sc, 2048); /* range is 0..4095 */ - } - - /* Set cable length. */ - if (sc->config.cable_len > 30) - clr_mii16_bits(sc, MII16_DS3_ZERO); - else - set_mii16_bits(sc, MII16_DS3_ZERO); - - /* Set payload scrambler polynomial. */ - if (sc->config.scrambler == CFG_SCRAM_LARS) - set_mii16_bits(sc, MII16_DS3_POLY); - else - clr_mii16_bits(sc, MII16_DS3_POLY); - - /* Set payload scrambler on/off. */ - if (sc->config.scrambler == CFG_SCRAM_OFF) - clr_mii16_bits(sc, MII16_DS3_SCRAM); - else - set_mii16_bits(sc, MII16_DS3_SCRAM); - - /* Set CRC length. */ - if (sc->config.crc_len == CFG_CRC_32) - set_mii16_bits(sc, MII16_DS3_CRC32); - else - clr_mii16_bits(sc, MII16_DS3_CRC32); - - /* Loopback towards host thru the line interface. */ - if (sc->config.loop_back == CFG_LOOP_OTHER) - set_mii16_bits(sc, MII16_DS3_TRLBK); - else - clr_mii16_bits(sc, MII16_DS3_TRLBK); - - /* Loopback towards network thru the line interface. */ - if (sc->config.loop_back == CFG_LOOP_LINE) - set_mii16_bits(sc, MII16_DS3_LNLBK); - else if (sc->config.loop_back == CFG_LOOP_DUAL) - set_mii16_bits(sc, MII16_DS3_LNLBK); - else - clr_mii16_bits(sc, MII16_DS3_LNLBK); - - /* Configure T3 framer chip; write EVERY writeable register. */ - ctl1 = CTL1_SER | CTL1_XTX; - if (sc->config.loop_back == CFG_LOOP_INWARD) ctl1 |= CTL1_3LOOP; - if (sc->config.loop_back == CFG_LOOP_DUAL) ctl1 |= CTL1_3LOOP; - if (sc->config.format == CFG_FORMAT_T3M13) ctl1 |= CTL1_M13MODE; - write_framer(sc, T3CSR_CTL1, ctl1); - write_framer(sc, T3CSR_TX_FEAC, CTL5_EMODE); - write_framer(sc, T3CSR_CTL8, CTL8_FBEC); - write_framer(sc, T3CSR_CTL12, CTL12_DLCB1 | CTL12_C21 | CTL12_MCB1); - write_framer(sc, T3CSR_DBL_FEAC, 0); - write_framer(sc, T3CSR_CTL14, CTL14_RGCEN | CTL14_TGCEN); - write_framer(sc, T3CSR_INTEN, 0); - write_framer(sc, T3CSR_CTL20, CTL20_CVEN); - - /* Clear error counters and latched error bits */ - /* that may have happened while initializing. */ - for (i=0; i<21; i++) read_framer(sc, i); - } - -static void -t3_ident(softc_t *sc) - { - printf(", TXC03401 rev B"); - } - -/* Called once a second; must not sleep. */ -static int -t3_watchdog(softc_t *sc) - { - u_int16_t CV; - u_int8_t CERR, PERR, MERR, FERR, FEBE; - u_int8_t ctl1, stat16, feac; - int link_status = STATUS_UP; - u_int16_t mii16; - - /* Read the alarm registers. */ - ctl1 = read_framer(sc, T3CSR_CTL1); - stat16 = read_framer(sc, T3CSR_STAT16); - mii16 = read_mii(sc, 16); - - /* Always ignore the RTLOC alarm bit. */ - stat16 &= ~STAT16_RTLOC; - - /* Software is alive. */ - led_inv(sc, MII16_DS3_LED_GRN); - - /* Receiving Alarm Indication Signal (AIS). */ - if ((stat16 & STAT16_RAIS) != 0) /* receiving ais */ - led_on(sc, MII16_DS3_LED_BLU); - else if (ctl1 & CTL1_TXAIS) /* sending ais */ - led_inv(sc, MII16_DS3_LED_BLU); - else - led_off(sc, MII16_DS3_LED_BLU); - - /* Receiving Remote Alarm Indication (RAI). */ - if ((stat16 & STAT16_XERR) != 0) /* receiving rai */ - led_on(sc, MII16_DS3_LED_YEL); - else if ((ctl1 & CTL1_XTX) == 0) /* sending rai */ - led_inv(sc, MII16_DS3_LED_YEL); - else - led_off(sc, MII16_DS3_LED_YEL); - - /* If certain status bits are set then the link is 'down'. */ - /* The bad bits are: rxlos rxoof rxais rxidl xerr. */ - if ((stat16 & ~(STAT16_FEAC | STAT16_SEF)) != 0) - link_status = STATUS_DOWN; - - /* Declare local Red Alarm if the link is down. */ - if (link_status == STATUS_DOWN) - led_on(sc, MII16_DS3_LED_RED); - else if (sc->loop_timer != 0) /* loopback is active */ - led_inv(sc, MII16_DS3_LED_RED); - else - led_off(sc, MII16_DS3_LED_RED); - - /* Print latched error bits if they changed. */ - if ((DRIVER_DEBUG) && ((stat16 & ~STAT16_FEAC) != sc->last_stat16)) - { - char *on = "ON ", *off = "OFF"; - printf("%s: RLOS=%s ROOF=%s RAIS=%s RIDL=%s SEF=%s XERR=%s\n", - NAME_UNIT, - (stat16 & STAT16_RLOS) ? on : off, - (stat16 & STAT16_ROOF) ? on : off, - (stat16 & STAT16_RAIS) ? on : off, - (stat16 & STAT16_RIDL) ? on : off, - (stat16 & STAT16_SEF) ? on : off, - (stat16 & STAT16_XERR) ? on : off); - } - - /* Check and print error counters if non-zero. */ - CV = read_framer(sc, T3CSR_CVHI)<<8; - CV += read_framer(sc, T3CSR_CVLO); - PERR = read_framer(sc, T3CSR_PERR); - CERR = read_framer(sc, T3CSR_CERR); - FERR = read_framer(sc, T3CSR_FERR); - MERR = read_framer(sc, T3CSR_MERR); - FEBE = read_framer(sc, T3CSR_FEBE); - - /* CV is invalid during LOS. */ - if ((stat16 & STAT16_RLOS)!=0) CV = 0; - /* CERR & FEBE are invalid in M13 mode */ - if (sc->config.format == CFG_FORMAT_T3M13) CERR = FEBE = 0; - /* FEBE is invalid during AIS. */ - if ((stat16 & STAT16_RAIS)!=0) FEBE = 0; - if (DRIVER_DEBUG && (CV || PERR || CERR || FERR || MERR || FEBE)) - printf("%s: CV=%u PERR=%u CERR=%u FERR=%u MERR=%u FEBE=%u\n", - NAME_UNIT, CV, PERR, CERR, FERR, MERR, FEBE); - - /* Driver keeps crude link-level error counters (SNMP is better). */ - sc->status.cntrs.lcv_errs += CV; - sc->status.cntrs.par_errs += PERR; - sc->status.cntrs.cpar_errs += CERR; - sc->status.cntrs.frm_errs += FERR; - sc->status.cntrs.mfrm_errs += MERR; - sc->status.cntrs.febe_errs += FEBE; - - /* Check for FEAC messages (FEAC not defined in M13 mode). */ - if (FORMAT_T3CPAR && (stat16 & STAT16_FEAC)) do - { - feac = read_framer(sc, T3CSR_FEAC_STK); - if ((feac & FEAC_STK_VALID)==0) break; - /* Ignore RxFEACs while a far end loopback has been requested. */ - if ((sc->status.snmp.t3.line & TLOOP_FAR_LINE)!=0) continue; - switch (feac & FEAC_STK_FEAC) - { - case T3BOP_LINE_UP: break; - case T3BOP_LINE_DOWN: break; - case T3BOP_LOOP_DS3: - { - if (sc->last_FEAC == T3BOP_LINE_DOWN) - { - if (DRIVER_DEBUG) - printf("%s: Received a 'line loopback deactivate' FEAC msg\n", NAME_UNIT); - clr_mii16_bits(sc, MII16_DS3_LNLBK); - sc->loop_timer = 0; - } - if (sc->last_FEAC == T3BOP_LINE_UP) - { - if (DRIVER_DEBUG) - printf("%s: Received a 'line loopback activate' FEAC msg\n", NAME_UNIT); - set_mii16_bits(sc, MII16_DS3_LNLBK); - sc->loop_timer = 300; - } - break; - } - case T3BOP_OOF: - { - if (DRIVER_DEBUG) - printf("%s: Received a 'far end LOF' FEAC msg\n", NAME_UNIT); - break; - } - case T3BOP_IDLE: - { - if (DRIVER_DEBUG) - printf("%s: Received a 'far end IDL' FEAC msg\n", NAME_UNIT); - break; - } - case T3BOP_AIS: - { - if (DRIVER_DEBUG) - printf("%s: Received a 'far end AIS' FEAC msg\n", NAME_UNIT); - break; - } - case T3BOP_LOS: - { - if (DRIVER_DEBUG) - printf("%s: Received a 'far end LOS' FEAC msg\n", NAME_UNIT); - break; - } - default: - { - if (DRIVER_DEBUG) - printf("%s: Received a 'type 0x%02X' FEAC msg\n", NAME_UNIT, feac & FEAC_STK_FEAC); - break; - } - } - sc->last_FEAC = feac & FEAC_STK_FEAC; - } while ((feac & FEAC_STK_MORE) != 0); - stat16 &= ~STAT16_FEAC; - - /* Send Service-Affecting priority FEAC messages */ - if (((sc->last_stat16 ^ stat16) & 0xF0) && (FORMAT_T3CPAR)) - { - /* Transmit continuous FEACs */ - write_framer(sc, T3CSR_CTL14, - read_framer(sc, T3CSR_CTL14) & ~CTL14_FEAC10); - if ((stat16 & STAT16_RLOS)!=0) - write_framer(sc, T3CSR_TX_FEAC, 0xC0 + T3BOP_LOS); - else if ((stat16 & STAT16_ROOF)!=0) - write_framer(sc, T3CSR_TX_FEAC, 0xC0 + T3BOP_OOF); - else if ((stat16 & STAT16_RAIS)!=0) - write_framer(sc, T3CSR_TX_FEAC, 0xC0 + T3BOP_AIS); - else if ((stat16 & STAT16_RIDL)!=0) - write_framer(sc, T3CSR_TX_FEAC, 0xC0 + T3BOP_IDLE); - else - write_framer(sc, T3CSR_TX_FEAC, CTL5_EMODE); - } - - /* Start sending RAI, Remote Alarm Indication. */ - if (((stat16 & STAT16_ROOF)!=0) && ((stat16 & STAT16_RLOS)==0) && - ((sc->last_stat16 & STAT16_ROOF)==0)) - write_framer(sc, T3CSR_CTL1, ctl1 &= ~CTL1_XTX); - /* Stop sending RAI, Remote Alarm Indication. */ - else if (((stat16 & STAT16_ROOF)==0) && ((sc->last_stat16 & STAT16_ROOF)!=0)) - write_framer(sc, T3CSR_CTL1, ctl1 |= CTL1_XTX); - - /* Start sending AIS, Alarm Indication Signal */ - if (((stat16 & STAT16_RLOS)!=0) && ((sc->last_stat16 & STAT16_RLOS)==0)) - { - set_mii16_bits(sc, MII16_DS3_FRAME); - write_framer(sc, T3CSR_CTL1, ctl1 | CTL1_TXAIS); - } - /* Stop sending AIS, Alarm Indication Signal */ - else if (((stat16 & STAT16_RLOS)==0) && ((sc->last_stat16 & STAT16_RLOS)!=0)) - { - clr_mii16_bits(sc, MII16_DS3_FRAME); - write_framer(sc, T3CSR_CTL1, ctl1 & ~CTL1_TXAIS); - } - - /* Time out loopback requests. */ - if (sc->loop_timer != 0) - if (--sc->loop_timer == 0) - if ((mii16 & MII16_DS3_LNLBK)!=0) - { - if (DRIVER_DEBUG) - printf("%s: Timeout: Loop Down after 300 seconds\n", NAME_UNIT); - clr_mii16_bits(sc, MII16_DS3_LNLBK); /* line loopback off */ - } - - /* SNMP error counters */ - sc->status.snmp.t3.lcv = CV; - sc->status.snmp.t3.pcv = PERR; - sc->status.snmp.t3.ccv = CERR; - sc->status.snmp.t3.febe = FEBE; - - /* SNMP Line Status */ - sc->status.snmp.t3.line = 0; - if ((ctl1 & CTL1_XTX)==0) sc->status.snmp.t3.line |= TLINE_TX_RAI; - if (stat16 & STAT16_XERR) sc->status.snmp.t3.line |= TLINE_RX_RAI; - if (ctl1 & CTL1_TXAIS) sc->status.snmp.t3.line |= TLINE_TX_AIS; - if (stat16 & STAT16_RAIS) sc->status.snmp.t3.line |= TLINE_RX_AIS; - if (stat16 & STAT16_ROOF) sc->status.snmp.t3.line |= TLINE_LOF; - if (stat16 & STAT16_RLOS) sc->status.snmp.t3.line |= TLINE_LOS; - if (stat16 & STAT16_SEF) sc->status.snmp.t3.line |= T3LINE_SEF; - - /* SNMP Loopback Status */ - sc->status.snmp.t3.loop &= ~TLOOP_FAR_LINE; - if (sc->config.loop_back == CFG_LOOP_TULIP) - sc->status.snmp.t3.loop |= TLOOP_NEAR_OTHER; - if (ctl1 & CTL1_3LOOP) sc->status.snmp.t3.loop |= TLOOP_NEAR_INWARD; - if (mii16 & MII16_DS3_TRLBK) sc->status.snmp.t3.loop |= TLOOP_NEAR_OTHER; - if (mii16 & MII16_DS3_LNLBK) sc->status.snmp.t3.loop |= TLOOP_NEAR_LINE; -/*if (ctl12 & CTL12_RTPLOOP) sc->status.snmp.t3.loop |= TLOOP_NEAR_PAYLOAD; */ - - /* Remember this state until next time. */ - sc->last_stat16 = stat16; - - /* If an INWARD loopback is in effect, link status is UP */ - if (sc->config.loop_back != CFG_LOOP_NONE) /* XXX INWARD ONLY */ - link_status = STATUS_UP; - - return link_status; - } - -/* IOCTL SYSCALL: can sleep. */ -static void -t3_send_dbl_feac(softc_t *sc, int feac1, int feac2) - { - u_int8_t tx_feac; - int i; - - /* The FEAC transmitter could be sending a continuous */ - /* FEAC msg when told to send a double FEAC message. */ - /* So save the current state of the FEAC transmitter. */ - tx_feac = read_framer(sc, T3CSR_TX_FEAC); - /* Load second FEAC code and stop FEAC transmitter. */ - write_framer(sc, T3CSR_TX_FEAC, CTL5_EMODE + feac2); - /* FEAC transmitter sends 10 more FEACs and then stops. */ - SLEEP(20000); /* sending one FEAC takes 1700 uSecs */ - /* Load first FEAC code and start FEAC transmitter. */ - write_framer(sc, T3CSR_DBL_FEAC, CTL13_DFEXEC + feac1); - /* Wait for double FEAC sequence to complete -- about 70 ms. */ - for (i=0; i<10; i++) /* max delay 100 ms */ - if (read_framer(sc, T3CSR_DBL_FEAC) & CTL13_DFEXEC) SLEEP(10000); - /* Flush received FEACS; don't respond to our own loop cmd! */ - while (read_framer(sc, T3CSR_FEAC_STK) & FEAC_STK_VALID) DELAY(1); /* XXX HANG */ - /* Restore previous state of the FEAC transmitter. */ - /* If it was sending a continuous FEAC, it will resume. */ - write_framer(sc, T3CSR_TX_FEAC, tx_feac); - } - -/* IOCTL SYSCALL: can sleep. */ -static int -t3_ioctl(softc_t *sc, struct ioctl *ioctl) - { - int error = 0; - - switch (ioctl->cmd) - { - case IOCTL_SNMP_SEND: /* set opstatus? */ - { - if (sc->config.format != CFG_FORMAT_T3CPAR) - error = EINVAL; - else if (ioctl->data == TSEND_LINE) - { - sc->status.snmp.t3.loop |= TLOOP_FAR_LINE; - t3_send_dbl_feac(sc, T3BOP_LINE_UP, T3BOP_LOOP_DS3); - } - else if (ioctl->data == TSEND_RESET) - { - t3_send_dbl_feac(sc, T3BOP_LINE_DOWN, T3BOP_LOOP_DS3); - sc->status.snmp.t3.loop &= ~TLOOP_FAR_LINE; - } - else - error = EINVAL; - break; - } - case IOCTL_SNMP_LOOP: /* set opstatus = test? */ - { - if (ioctl->data == CFG_LOOP_NONE) - { - clr_mii16_bits(sc, MII16_DS3_FRAME); - clr_mii16_bits(sc, MII16_DS3_TRLBK); - clr_mii16_bits(sc, MII16_DS3_LNLBK); - write_framer(sc, T3CSR_CTL1, - read_framer(sc, T3CSR_CTL1) & ~CTL1_3LOOP); - write_framer(sc, T3CSR_CTL12, - read_framer(sc, T3CSR_CTL12) & ~(CTL12_RTPLOOP | CTL12_RTPLLEN)); - } - else if (ioctl->data == CFG_LOOP_LINE) - set_mii16_bits(sc, MII16_DS3_LNLBK); - else if (ioctl->data == CFG_LOOP_OTHER) - set_mii16_bits(sc, MII16_DS3_TRLBK); - else if (ioctl->data == CFG_LOOP_INWARD) - write_framer(sc, T3CSR_CTL1, - read_framer(sc, T3CSR_CTL1) | CTL1_3LOOP); - else if (ioctl->data == CFG_LOOP_DUAL) - { - set_mii16_bits(sc, MII16_DS3_LNLBK); - write_framer(sc, T3CSR_CTL1, - read_framer(sc, T3CSR_CTL1) | CTL1_3LOOP); - } - else if (ioctl->data == CFG_LOOP_PAYLOAD) - { - set_mii16_bits(sc, MII16_DS3_FRAME); - write_framer(sc, T3CSR_CTL12, - read_framer(sc, T3CSR_CTL12) | CTL12_RTPLOOP); - write_framer(sc, T3CSR_CTL12, - read_framer(sc, T3CSR_CTL12) | CTL12_RTPLLEN); - DELAY(25); /* at least two frames (22 uS) */ - write_framer(sc, T3CSR_CTL12, - read_framer(sc, T3CSR_CTL12) & ~CTL12_RTPLLEN); - } - else - error = EINVAL; - break; - } - default: - error = EINVAL; - break; - } - - return error; - } - -/* begin SSI card code */ - -/* Must not sleep. */ -static void -ssi_config(softc_t *sc) - { - if (sc->status.card_type == 0) - { /* defaults */ - sc->status.card_type = TLP_CSID_SSI; - sc->config.crc_len = CFG_CRC_16; - sc->config.loop_back = CFG_LOOP_NONE; - sc->config.tx_clk_src = CFG_CLKMUX_ST; - sc->config.dte_dce = CFG_DTE; - sc->config.synth.n = 51; /* 1.536 MHz */ - sc->config.synth.m = 83; - sc->config.synth.v = 1; - sc->config.synth.x = 1; - sc->config.synth.r = 1; - sc->config.synth.prescale = 4; - } - - /* Disable the TX clock driver while programming the oscillator. */ - clr_gpio_bits(sc, GPIO_SSI_DCE); - make_gpio_output(sc, GPIO_SSI_DCE); - - /* Program the synthesized oscillator. */ - write_synth(sc, &sc->config.synth); - - /* Set DTE/DCE mode. */ - /* If DTE mode then DCD & TXC are received. */ - /* If DCE mode then DCD & TXC are driven. */ - /* Boards with MII rev=4.0 don't drive DCD. */ - if (sc->config.dte_dce == CFG_DCE) - set_gpio_bits(sc, GPIO_SSI_DCE); - else - clr_gpio_bits(sc, GPIO_SSI_DCE); - make_gpio_output(sc, GPIO_SSI_DCE); - - /* Set CRC length. */ - if (sc->config.crc_len == CFG_CRC_32) - set_mii16_bits(sc, MII16_SSI_CRC32); - else - clr_mii16_bits(sc, MII16_SSI_CRC32); - - /* Loop towards host thru cable drivers and receivers. */ - /* Asserts DCD at the far end of a null modem cable. */ - if (sc->config.loop_back == CFG_LOOP_PINS) - set_mii16_bits(sc, MII16_SSI_LOOP); - else - clr_mii16_bits(sc, MII16_SSI_LOOP); - - /* Assert pin LL in modem conn: ask modem for local loop. */ - /* Asserts TM at the far end of a null modem cable. */ - if (sc->config.loop_back == CFG_LOOP_LL) - set_mii16_bits(sc, MII16_SSI_LL); - else - clr_mii16_bits(sc, MII16_SSI_LL); - - /* Assert pin RL in modem conn: ask modem for remote loop. */ - if (sc->config.loop_back == CFG_LOOP_RL) - set_mii16_bits(sc, MII16_SSI_RL); - else - clr_mii16_bits(sc, MII16_SSI_RL); - } - -static void -ssi_ident(softc_t *sc) - { - printf(", LTC1343/44"); - } - -/* Called once a second; must not sleep. */ -static int -ssi_watchdog(softc_t *sc) - { - u_int16_t cable; - u_int16_t mii16 = read_mii(sc, 16) & MII16_SSI_MODEM; - int link_status = STATUS_UP; - - /* Software is alive. */ - led_inv(sc, MII16_SSI_LED_UL); - - /* Check the transmit clock. */ - if (sc->status.tx_speed == 0) - { - led_on(sc, MII16_SSI_LED_UR); - link_status = STATUS_DOWN; - } - else - led_off(sc, MII16_SSI_LED_UR); - - /* Check the external cable. */ - cable = read_mii(sc, 17); - cable = cable & MII17_SSI_CABLE_MASK; - cable = cable >> MII17_SSI_CABLE_SHIFT; - if (cable == 7) - { - led_off(sc, MII16_SSI_LED_LL); /* no cable */ - link_status = STATUS_DOWN; - } - else - led_on(sc, MII16_SSI_LED_LL); - - /* The unit at the other end of the cable is ready if: */ - /* DTE mode and DCD pin is asserted */ - /* DCE mode and DSR pin is asserted */ - if (((sc->config.dte_dce == CFG_DTE) && ((mii16 & MII16_SSI_DCD)==0)) || - ((sc->config.dte_dce == CFG_DCE) && ((mii16 & MII16_SSI_DSR)==0))) - { - led_off(sc, MII16_SSI_LED_LR); - link_status = STATUS_DOWN; - } - else - led_on(sc, MII16_SSI_LED_LR); - - if (DRIVER_DEBUG && (cable != sc->status.cable_type)) - printf("%s: SSI cable type changed to '%s'\n", - NAME_UNIT, ssi_cables[cable]); - sc->status.cable_type = cable; - - /* Print the modem control signals if they changed. */ - if ((DRIVER_DEBUG) && (mii16 != sc->last_mii16)) - { - char *on = "ON ", *off = "OFF"; - printf("%s: DTR=%s DSR=%s RTS=%s CTS=%s DCD=%s RI=%s LL=%s RL=%s TM=%s\n", - NAME_UNIT, - (mii16 & MII16_SSI_DTR) ? on : off, - (mii16 & MII16_SSI_DSR) ? on : off, - (mii16 & MII16_SSI_RTS) ? on : off, - (mii16 & MII16_SSI_CTS) ? on : off, - (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); - } - - /* SNMP one-second report */ - sc->status.snmp.ssi.sigs = mii16 & MII16_SSI_MODEM; - - /* Remember this state until next time. */ - sc->last_mii16 = mii16; - - /* If a loop back is in effect, link status is UP */ - if (sc->config.loop_back != CFG_LOOP_NONE) - link_status = STATUS_UP; - - return link_status; - } - -/* IOCTL SYSCALL: can sleep (but doesn't). */ -static int -ssi_ioctl(softc_t *sc, struct ioctl *ioctl) - { - int error = 0; - - if (ioctl->cmd == IOCTL_SNMP_SIGS) - { - u_int16_t mii16 = read_mii(sc, 16); - mii16 &= ~MII16_SSI_MODEM; - mii16 |= (MII16_SSI_MODEM & ioctl->data); - write_mii(sc, 16, mii16); - } - else if (ioctl->cmd == IOCTL_SET_STATUS) - { - if (ioctl->data != 0) - set_mii16_bits(sc, (MII16_SSI_DTR | MII16_SSI_RTS | MII16_SSI_DCD)); - else - clr_mii16_bits(sc, (MII16_SSI_DTR | MII16_SSI_RTS | MII16_SSI_DCD)); - } - else - error = EINVAL; - - return error; - } - -/* begin T1E1 card code */ - -/* Must not sleep. */ -static void -t1_config(softc_t *sc) - { - int i; - u_int8_t pulse, lbo, gain; - - if (sc->status.card_type == 0) - { /* defaults */ - sc->status.card_type = TLP_CSID_T1E1; - sc->config.crc_len = CFG_CRC_16; - sc->config.loop_back = CFG_LOOP_NONE; - sc->config.tx_clk_src = CFG_CLKMUX_INT; - sc->config.format = CFG_FORMAT_T1ESF; - sc->config.cable_len = 10; - sc->config.time_slots = 0x01FFFFFE; - sc->config.tx_pulse = CFG_PULSE_AUTO; - sc->config.rx_gain = CFG_GAIN_AUTO; - sc->config.tx_lbo = CFG_LBO_AUTO; - - /* Bt8370 occasionally powers up in a loopback mode. */ - /* Data sheet says zero LOOP reg and do a s/w reset. */ - write_framer(sc, Bt8370_LOOP, 0x00); /* no loopback */ - write_framer(sc, Bt8370_CR0, 0x80); /* s/w reset */ - for (i=0; i<10; i++) /* max delay 10 ms */ - if (read_framer(sc, Bt8370_CR0) & 0x80) DELAY(1000); - } - - /* Set CRC length. */ - if (sc->config.crc_len == CFG_CRC_32) - set_mii16_bits(sc, MII16_T1_CRC32); - else - clr_mii16_bits(sc, MII16_T1_CRC32); - - /* Invert HDLC payload data in SF/AMI mode. */ - /* HDLC stuff bits satisfy T1 pulse density. */ - if (FORMAT_T1SF) - set_mii16_bits(sc, MII16_T1_INVERT); - else - clr_mii16_bits(sc, MII16_T1_INVERT); - - /* Set the transmitter output impedance. */ - if (FORMAT_E1ANY) set_mii16_bits(sc, MII16_T1_Z); - - /* 001:CR0 -- Control Register 0 - T1/E1 and frame format */ - write_framer(sc, Bt8370_CR0, sc->config.format); - - /* 002:JAT_CR -- Jitter Attenuator Control Register */ - if (sc->config.tx_clk_src == CFG_CLKMUX_RT) /* loop timing */ - write_framer(sc, Bt8370_JAT_CR, 0xA3); /* JAT in RX path */ - else - { /* 64-bit elastic store; free-running JCLK and CLADO */ - write_framer(sc, Bt8370_JAT_CR, 0x4B); /* assert jcenter */ - write_framer(sc, Bt8370_JAT_CR, 0x43); /* release jcenter */ - } - - /* 00C-013:IERn -- Interrupt Enable Registers */ - for (i=Bt8370_IER7; i<=Bt8370_IER0; i++) - write_framer(sc, i, 0); /* no interrupts; polled */ - - /* 014:LOOP -- loopbacks */ - if (sc->config.loop_back == CFG_LOOP_PAYLOAD) - write_framer(sc, Bt8370_LOOP, LOOP_PAYLOAD); - else if (sc->config.loop_back == CFG_LOOP_LINE) - write_framer(sc, Bt8370_LOOP, LOOP_LINE); - else if (sc->config.loop_back == CFG_LOOP_OTHER) - write_framer(sc, Bt8370_LOOP, LOOP_ANALOG); - else if (sc->config.loop_back == CFG_LOOP_INWARD) - write_framer(sc, Bt8370_LOOP, LOOP_FRAMER); - else if (sc->config.loop_back == CFG_LOOP_DUAL) - write_framer(sc, Bt8370_LOOP, LOOP_DUAL); - else - write_framer(sc, Bt8370_LOOP, 0x00); /* no loopback */ - - /* 015:DL3_TS -- Data Link 3 */ - write_framer(sc, Bt8370_DL3_TS, 0x00); /* disabled */ - - /* 018:PIO -- Programmable I/O */ - write_framer(sc, Bt8370_PIO, 0xFF); /* all pins are outputs */ - - /* 019:POE -- Programmable Output Enable */ - write_framer(sc, Bt8370_POE, 0x00); /* all outputs are enabled */ - - /* 01A;CMUX -- Clock Input Mux */ - if (sc->config.tx_clk_src == CFG_CLKMUX_EXT) - write_framer(sc, Bt8370_CMUX, 0x0C); /* external timing */ - else - write_framer(sc, Bt8370_CMUX, 0x0F); /* internal timing */ - - /* 020:LIU_CR -- Line Interface Unit Config Register */ - write_framer(sc, Bt8370_LIU_CR, 0xC1); /* reset LIU, squelch */ - - /* 022:RLIU_CR -- RX Line Interface Unit Config Reg */ - /* Errata sheet says don't use freeze-short, but we do anyway! */ - write_framer(sc, Bt8370_RLIU_CR, 0xB1); /* AGC=2048, Long Eye */ - - /* Select Rx sensitivity based on cable length. */ - if ((gain = sc->config.rx_gain) == CFG_GAIN_AUTO) - { - if (sc->config.cable_len > 2000) - gain = CFG_GAIN_EXTEND; - else if (sc->config.cable_len > 1000) - gain = CFG_GAIN_LONG; - else if (sc->config.cable_len > 100) - gain = CFG_GAIN_MEDIUM; - else - gain = CFG_GAIN_SHORT; - } - - /* 024:VGA_MAX -- Variable Gain Amplifier Max gain */ - write_framer(sc, Bt8370_VGA_MAX, gain); - - /* 028:PRE_EQ -- Pre Equalizer */ - if (gain == CFG_GAIN_EXTEND) - write_framer(sc, Bt8370_PRE_EQ, 0xE6); /* ON; thresh 6 */ - else - write_framer(sc, Bt8370_PRE_EQ, 0xA6); /* OFF; thresh 6 */ - - /* 038-03C:GAINn -- RX Equalizer gain thresholds */ - write_framer(sc, Bt8370_GAIN0, 0x24); - write_framer(sc, Bt8370_GAIN1, 0x28); - write_framer(sc, Bt8370_GAIN2, 0x2C); - write_framer(sc, Bt8370_GAIN3, 0x30); - write_framer(sc, Bt8370_GAIN4, 0x34); - - /* 040:RCR0 -- Receiver Control Register 0 */ - if (FORMAT_T1ESF) - write_framer(sc, Bt8370_RCR0, 0x05); /* B8ZS, 2/5 FErrs */ - else if (FORMAT_T1SF) - write_framer(sc, Bt8370_RCR0, 0x84); /* AMI, 2/5 FErrs */ - else if (FORMAT_E1NONE) - write_framer(sc, Bt8370_RCR0, 0x41); /* HDB3, rabort */ - else if (FORMAT_E1CRC) - write_framer(sc, Bt8370_RCR0, 0x09); /* HDB3, 3 FErrs or 915 CErrs */ - else /* E1 no CRC */ - write_framer(sc, Bt8370_RCR0, 0x19); /* HDB3, 3 FErrs */ - - /* 041:RPATT -- Receive Test Pattern configuration */ - write_framer(sc, Bt8370_RPATT, 0x3E); /* looking for framed QRSS */ - - /* 042:RLB -- Receive Loop Back code detector config */ - write_framer(sc, Bt8370_RLB, 0x09); /* 6 bits down; 5 bits up */ - - /* 043:LBA -- Loop Back Activate code */ - write_framer(sc, Bt8370_LBA, 0x08); /* 10000 10000 10000 ... */ - - /* 044:LBD -- Loop Back Deactivate code */ - write_framer(sc, Bt8370_LBD, 0x24); /* 100100 100100 100100 ... */ - - /* 045:RALM -- Receive Alarm signal configuration */ - write_framer(sc, Bt8370_RALM, 0x0C); /* yel_intg rlof_intg */ - - /* 046:LATCH -- Alarm/Error/Counter Latch register */ - write_framer(sc, Bt8370_LATCH, 0x1F); /* stop_cnt latch_{cnt,err,alm} */ - - /* Select Pulse Shape based on cable length (T1 only). */ - if ((pulse = sc->config.tx_pulse) == CFG_PULSE_AUTO) - { - if (FORMAT_T1ANY) - { - if (sc->config.cable_len > 200) - pulse = CFG_PULSE_T1CSU; - else if (sc->config.cable_len > 160) - pulse = CFG_PULSE_T1DSX4; - else if (sc->config.cable_len > 120) - pulse = CFG_PULSE_T1DSX3; - else if (sc->config.cable_len > 80) - pulse = CFG_PULSE_T1DSX2; - else if (sc->config.cable_len > 40) - pulse = CFG_PULSE_T1DSX1; - else - pulse = CFG_PULSE_T1DSX0; - } - else - pulse = CFG_PULSE_E1TWIST; - } - - /* Select Line Build Out based on cable length (T1CSU only). */ - if ((lbo = sc->config.tx_lbo) == CFG_LBO_AUTO) - { - if (pulse == CFG_PULSE_T1CSU) - { - if (sc->config.cable_len > 1500) - lbo = CFG_LBO_0DB; - else if (sc->config.cable_len > 1000) - lbo = CFG_LBO_7DB; - else if (sc->config.cable_len > 500) - lbo = CFG_LBO_15DB; - else - lbo = CFG_LBO_22DB; - } - else - lbo = 0; - } - - /* 068:TLIU_CR -- Transmit LIU Control Register */ - write_framer(sc, Bt8370_TLIU_CR, (0x40 | (lbo & 0x30) | (pulse & 0x0E))); - - /* 070:TCR0 -- Transmit Framer Configuration */ - write_framer(sc, Bt8370_TCR0, sc->config.format>>1); - - /* 071:TCR1 -- Transmitter Configuration */ - if (FORMAT_T1SF) - write_framer(sc, Bt8370_TCR1, 0x43); /* tabort, AMI PDV enforced */ - else - write_framer(sc, Bt8370_TCR1, 0x41); /* tabort, B8ZS or HDB3 */ - - /* 072:TFRM -- Transmit Frame format MYEL YEL MF FE CRC FBIT */ - if (sc->config.format == CFG_FORMAT_T1ESF) - write_framer(sc, Bt8370_TFRM, 0x0B); /* - YEL MF - CRC FBIT */ - else if (sc->config.format == CFG_FORMAT_T1SF) - write_framer(sc, Bt8370_TFRM, 0x19); /* - YEL MF - - FBIT */ - else if (sc->config.format == CFG_FORMAT_E1FAS) - write_framer(sc, Bt8370_TFRM, 0x11); /* - YEL - - - FBIT */ - else if (sc->config.format == CFG_FORMAT_E1FASCRC) - write_framer(sc, Bt8370_TFRM, 0x1F); /* - YEL MF FE CRC FBIT */ - else if (sc->config.format == CFG_FORMAT_E1FASCAS) - write_framer(sc, Bt8370_TFRM, 0x31); /* MYEL YEL - - - FBIT */ - else if (sc->config.format == CFG_FORMAT_E1FASCRCCAS) - write_framer(sc, Bt8370_TFRM, 0x3F); /* MYEL YEL MF FE CRC FBIT */ - else if (sc->config.format == CFG_FORMAT_E1NONE) - write_framer(sc, Bt8370_TFRM, 0x00); /* NO FRAMING BITS AT ALL! */ - - /* 073:TERROR -- Transmit Error Insert */ - write_framer(sc, Bt8370_TERROR, 0x00); /* no errors, please! */ - - /* 074:TMAN -- Transmit Manual Sa-byte/FEBE configuration */ - write_framer(sc, Bt8370_TMAN, 0x00); /* none */ - - /* 075:TALM -- Transmit Alarm Signal Configuration */ - if (FORMAT_E1ANY) - write_framer(sc, Bt8370_TALM, 0x38); /* auto_myel auto_yel auto_ais */ - else if (FORMAT_T1ANY) - write_framer(sc, Bt8370_TALM, 0x18); /* auto_yel auto_ais */ - - /* 076:TPATT -- Transmit Test Pattern Configuration */ - write_framer(sc, Bt8370_TPATT, 0x00); /* disabled */ - - /* 077:TLB -- Transmit Inband Loopback Code Configuration */ - write_framer(sc, Bt8370_TLB, 0x00); /* disabled */ - - /* 090:CLAD_CR -- Clack Rate Adapter Configuration */ - if (FORMAT_T1ANY) - write_framer(sc, Bt8370_CLAD_CR, 0x06); /* loop filter gain 1/2^6 */ - else - write_framer(sc, Bt8370_CLAD_CR, 0x08); /* loop filter gain 1/2^8 */ - - /* 091:CSEL -- CLAD frequency Select */ - if (FORMAT_T1ANY) - write_framer(sc, Bt8370_CSEL, 0x55); /* 1544 kHz */ - else - write_framer(sc, Bt8370_CSEL, 0x11); /* 2048 kHz */ - - /* 092:CPHASE -- CLAD Phase detector */ - if (FORMAT_T1ANY) - write_framer(sc, Bt8370_CPHASE, 0x22); /* phase compare @ 386 kHz */ - else - write_framer(sc, Bt8370_CPHASE, 0x00); /* phase compare @ 2048 kHz */ - - if (FORMAT_T1ESF) /* BOP & PRM are enabled in T1ESF mode only. */ - { - /* 0A0:BOP -- Bit Oriented Protocol messages */ - write_framer(sc, Bt8370_BOP, RBOP_25 | TBOP_OFF); - /* 0A4:DL1_TS -- Data Link 1 Time Slot Enable */ - write_framer(sc, Bt8370_DL1_TS, 0x40); /* FDL bits in odd frames */ - /* 0A6:DL1_CTL -- Data Link 1 Control */ - write_framer(sc, Bt8370_DL1_CTL, 0x03); /* FCS mode, TX on, RX on */ - /* 0A7:RDL1_FFC -- Rx Data Link 1 Fifo Fill Control */ - write_framer(sc, Bt8370_RDL1_FFC, 0x30); /* assert "near full" at 48 */ - /* 0AA:PRM -- Performance Report Messages */ - write_framer(sc, Bt8370_PRM, 0x80); - } - - /* 0D0:SBI_CR -- System Bus Interface Configuration Register */ - if (FORMAT_T1ANY) - write_framer(sc, Bt8370_SBI_CR, 0x47); /* 1.544 with 24 TS +Fbits */ - else - write_framer(sc, Bt8370_SBI_CR, 0x46); /* 2.048 with 32 TS */ - - /* 0D1:RSB_CR -- Receive System Bus Configuration Register */ - /* Change RINDO & RFSYNC on falling edge of RSBCLKI. */ - write_framer(sc, Bt8370_RSB_CR, 0x70); - - /* 0D2,0D3:RSYNC_{TS,BIT} -- Receive frame Sync offset */ - write_framer(sc, Bt8370_RSYNC_BIT, 0x00); - write_framer(sc, Bt8370_RSYNC_TS, 0x00); - - /* 0D4:TSB_CR -- Transmit System Bus Configuration Register */ - /* Change TINDO & TFSYNC on falling edge of TSBCLKI. */ - write_framer(sc, Bt8370_TSB_CR, 0x30); - - /* 0D5,0D6:TSYNC_{TS,BIT} -- Transmit frame Sync offset */ - write_framer(sc, Bt8370_TSYNC_BIT, 0x00); - write_framer(sc, Bt8370_TSYNC_TS, 0x00); - - /* 0D7:RSIG_CR -- Receive SIGnalling Configuratin Register */ - write_framer(sc, Bt8370_RSIG_CR, 0x00); - - /* Assign and configure 64Kb TIME SLOTS. */ - /* TS24..TS1 must be assigned for T1, TS31..TS0 for E1. */ - /* Timeslots with no user data have RINDO and TINDO off. */ - for (i=0; i<32; i++) - { - /* 0E0-0FF:SBCn -- System Bus Per-Channel Control */ - if (FORMAT_T1ANY && (i==0 || i>24)) - write_framer(sc, Bt8370_SBCn +i, 0x00); /* not assigned in T1 mode */ - else if (FORMAT_E1ANY && (i==0) && !FORMAT_E1NONE) - write_framer(sc, Bt8370_SBCn +i, 0x01); /* assigned, TS0 o/h bits */ - else if (FORMAT_E1CAS && (i==16) && !FORMAT_E1NONE) - write_framer(sc, Bt8370_SBCn +i, 0x01); /* assigned, TS16 o/h bits */ - else if ((sc->config.time_slots & (1<config.time_slots & (1<>4, - read_framer(sc, Bt8370_DID)&0x0F); - } - -/* Called once a second; must not sleep. */ -static int -t1_watchdog(softc_t *sc) - { - u_int16_t LCV = 0, FERR = 0, CRC = 0, FEBE = 0; - u_int8_t alm1, alm3, loop, isr0; - int link_status = STATUS_UP; - int i; - - /* Read the alarm registers */ - alm1 = read_framer(sc, Bt8370_ALM1); - alm3 = read_framer(sc, Bt8370_ALM3); - loop = read_framer(sc, Bt8370_LOOP); - isr0 = read_framer(sc, Bt8370_ISR0); - - /* Always ignore the SIGFRZ alarm bit, */ - alm1 &= ~ALM1_SIGFRZ; - if (FORMAT_T1ANY) /* ignore RYEL in T1 modes */ - alm1 &= ~ALM1_RYEL; - else if (FORMAT_E1NONE) /* ignore all alarms except LOS */ - alm1 &= ALM1_RLOS; - - /* Software is alive. */ - led_inv(sc, MII16_T1_LED_GRN); - - /* Receiving Alarm Indication Signal (AIS). */ - if ((alm1 & ALM1_RAIS)!=0) /* receiving ais */ - led_on(sc, MII16_T1_LED_BLU); - else if ((alm1 & ALM1_RLOS)!=0) /* sending ais */ - led_inv(sc, MII16_T1_LED_BLU); - else - led_off(sc, MII16_T1_LED_BLU); - - /* Receiving Remote Alarm Indication (RAI). */ - if ((alm1 & (ALM1_RMYEL | ALM1_RYEL))!=0) /* receiving rai */ - led_on(sc, MII16_T1_LED_YEL); - else if ((alm1 & ALM1_RLOF)!=0) /* sending rai */ - led_inv(sc, MII16_T1_LED_YEL); - else - led_off(sc, MII16_T1_LED_YEL); - - /* If any alarm bits are set then the link is 'down'. */ - /* The bad bits are: rmyel ryel rais ralos rlos rlof. */ - /* Some alarm bits have been masked by this point. */ - if (alm1 != 0) link_status = STATUS_DOWN; - - /* Declare local Red Alarm if the link is down. */ - if (link_status == STATUS_DOWN) - led_on(sc, MII16_T1_LED_RED); - else if (sc->loop_timer != 0) /* loopback is active */ - led_inv(sc, MII16_T1_LED_RED); - else - led_off(sc, MII16_T1_LED_RED); - - /* Print latched error bits if they changed. */ - if ((DRIVER_DEBUG) && (alm1 != sc->last_alm1)) - { - char *on = "ON ", *off = "OFF"; - printf("%s: RLOF=%s RLOS=%s RALOS=%s RAIS=%s RYEL=%s RMYEL=%s\n", - NAME_UNIT, - (alm1 & ALM1_RLOF) ? on : off, - (alm1 & ALM1_RLOS) ? on : off, - (alm1 & ALM1_RALOS) ? on : off, - (alm1 & ALM1_RAIS) ? on : off, - (alm1 & ALM1_RYEL) ? on : off, - (alm1 & ALM1_RMYEL) ? on : off); - } - - /* Check and print error counters if non-zero. */ - LCV = read_framer(sc, Bt8370_LCV_LO) + - (read_framer(sc, Bt8370_LCV_HI)<<8); - if (!FORMAT_E1NONE) - FERR = read_framer(sc, Bt8370_FERR_LO) + - (read_framer(sc, Bt8370_FERR_HI)<<8); - if (FORMAT_E1CRC || FORMAT_T1ESF) - CRC = read_framer(sc, Bt8370_CRC_LO) + - (read_framer(sc, Bt8370_CRC_HI)<<8); - if (FORMAT_E1CRC) - FEBE = read_framer(sc, Bt8370_FEBE_LO) + - (read_framer(sc, Bt8370_FEBE_HI)<<8); - /* Only LCV is valid if Out-Of-Frame */ - if (FORMAT_E1NONE) FERR = CRC = FEBE = 0; - if ((DRIVER_DEBUG) && (LCV || FERR || CRC || FEBE)) - printf("%s: LCV=%u FERR=%u CRC=%u FEBE=%u\n", - NAME_UNIT, LCV, FERR, CRC, FEBE); - - /* Driver keeps crude link-level error counters (SNMP is better). */ - sc->status.cntrs.lcv_errs += LCV; - sc->status.cntrs.frm_errs += FERR; - sc->status.cntrs.crc_errs += CRC; - sc->status.cntrs.febe_errs += FEBE; - - /* Check for BOP messages in the ESF Facility Data Link. */ - if ((FORMAT_T1ESF) && (read_framer(sc, Bt8370_ISR1) & 0x80)) - { - u_int8_t bop_code = read_framer(sc, Bt8370_RBOP) & 0x3F; - - switch (bop_code) - { - case T1BOP_OOF: - { - if ((DRIVER_DEBUG) && ((sc->last_alm1 & ALM1_RMYEL)==0)) - printf("%s: Receiving a 'yellow alarm' BOP msg\n", NAME_UNIT); - break; - } - case T1BOP_LINE_UP: - { - if (DRIVER_DEBUG) - printf("%s: Received a 'line loopback activate' BOP msg\n", NAME_UNIT); - write_framer(sc, Bt8370_LOOP, LOOP_LINE); - sc->loop_timer = 305; - break; - } - case T1BOP_LINE_DOWN: - { - if (DRIVER_DEBUG) - printf("%s: Received a 'line loopback deactivate' BOP msg\n", NAME_UNIT); - write_framer(sc, Bt8370_LOOP, - read_framer(sc, Bt8370_LOOP) & ~LOOP_LINE); - sc->loop_timer = 0; - break; - } - case T1BOP_PAY_UP: - { - if (DRIVER_DEBUG) - printf("%s: Received a 'payload loopback activate' BOP msg\n", NAME_UNIT); - write_framer(sc, Bt8370_LOOP, LOOP_PAYLOAD); - sc->loop_timer = 305; - break; - } - case T1BOP_PAY_DOWN: - { - if (DRIVER_DEBUG) - printf("%s: Received a 'payload loopback deactivate' BOP msg\n", NAME_UNIT); - write_framer(sc, Bt8370_LOOP, - read_framer(sc, Bt8370_LOOP) & ~LOOP_PAYLOAD); - sc->loop_timer = 0; - break; - } - default: - { - if (DRIVER_DEBUG) - printf("%s: Received a type 0x%02X BOP msg\n", NAME_UNIT, bop_code); - break; - } - } - } - - /* Check for HDLC pkts in the ESF Facility Data Link. */ - if ((FORMAT_T1ESF) && (read_framer(sc, Bt8370_ISR2) & 0x70)) - { - /* while (not fifo-empty && not start-of-msg) flush fifo */ - while ((read_framer(sc, Bt8370_RDL1_STAT) & 0x0C) == 0) - read_framer(sc, Bt8370_RDL1); - /* If (not fifo-empty), then begin processing fifo contents. */ - if ((read_framer(sc, Bt8370_RDL1_STAT) & 0x0C) == 0x08) - { - u_int8_t msg[64]; - u_int8_t stat = read_framer(sc, Bt8370_RDL1); - sc->status.cntrs.fdl_pkts++; - for (i=0; i<(stat & 0x3F); i++) - msg[i] = read_framer(sc, Bt8370_RDL1); - /* Is this FDL message a T1.403 performance report? */ - if (((stat & 0x3F)==11) && - ((msg[0]==0x38) || (msg[0]==0x3A)) && - (msg[1]==1) && (msg[2]==3)) - /* Copy 4 PRs from FDL pkt to SNMP struct. */ - memcpy(sc->status.snmp.t1.prm, msg+3, 8); - } - } - - /* Check for inband loop up/down commands. */ - if (FORMAT_T1ANY) - { - u_int8_t isr6 = read_framer(sc, Bt8370_ISR6); - u_int8_t alarm2 = read_framer(sc, Bt8370_ALM2); - u_int8_t tlb = read_framer(sc, Bt8370_TLB); - - /* Inband Code == Loop Up && On Transition && Inband Tx Inactive */ - if ((isr6 & 0x40) && (alarm2 & 0x40) && ((tlb & 1)==0)) - { /* CSU loop up is 10000 10000 ... */ - if (DRIVER_DEBUG) - printf("%s: Received a 'CSU Loop Up' inband msg\n", NAME_UNIT); - write_framer(sc, Bt8370_LOOP, LOOP_LINE); /* Loop up */ - sc->loop_timer = 305; - } - /* Inband Code == Loop Down && On Transition && Inband Tx Inactive */ - if ((isr6 & 0x80) && (alarm2 & 0x80) && ((tlb & 1)==0)) - { /* CSU loop down is 100 100 100 ... */ - if (DRIVER_DEBUG) - printf("%s: Received a 'CSU Loop Down' inband msg\n", NAME_UNIT); - write_framer(sc, Bt8370_LOOP, - read_framer(sc, Bt8370_LOOP) & ~LOOP_LINE); /* loop down */ - sc->loop_timer = 0; - } - } - - /* Manually send Yellow Alarm BOP msgs. */ - if (FORMAT_T1ESF) - { - u_int8_t isr7 = read_framer(sc, Bt8370_ISR7); - - if ((isr7 & 0x02) && (alm1 & 0x02)) /* RLOF on-transition */ - { /* Start sending continuous Yellow Alarm BOP messages. */ - write_framer(sc, Bt8370_BOP, RBOP_25 | TBOP_CONT); - write_framer(sc, Bt8370_TBOP, 0x00); /* send BOP; order matters */ - } - else if ((isr7 & 0x02) && ((alm1 & 0x02)==0)) /* RLOF off-transition */ - { /* Stop sending continuous Yellow Alarm BOP messages. */ - write_framer(sc, Bt8370_BOP, RBOP_25 | TBOP_OFF); - } - } - - /* Time out loopback requests. */ - if (sc->loop_timer != 0) - if (--sc->loop_timer == 0) - if (loop != 0) - { - if (DRIVER_DEBUG) - printf("%s: Timeout: Loop Down after 300 seconds\n", NAME_UNIT); - write_framer(sc, Bt8370_LOOP, loop & ~(LOOP_PAYLOAD | LOOP_LINE)); - } - - /* RX Test Pattern status */ - if ((DRIVER_DEBUG) && (isr0 & 0x10)) - printf("%s: RX Test Pattern Sync\n", NAME_UNIT); - - /* SNMP Error Counters */ - sc->status.snmp.t1.lcv = LCV; - sc->status.snmp.t1.fe = FERR; - sc->status.snmp.t1.crc = CRC; - sc->status.snmp.t1.febe = FEBE; - - /* SNMP Line Status */ - sc->status.snmp.t1.line = 0; - if (alm1 & ALM1_RMYEL) sc->status.snmp.t1.line |= TLINE_RX_RAI; - if (alm1 & ALM1_RYEL) sc->status.snmp.t1.line |= TLINE_RX_RAI; - if (alm1 & ALM1_RLOF) sc->status.snmp.t1.line |= TLINE_TX_RAI; - if (alm1 & ALM1_RAIS) sc->status.snmp.t1.line |= TLINE_RX_AIS; - if (alm1 & ALM1_RLOS) sc->status.snmp.t1.line |= TLINE_TX_AIS; - if (alm1 & ALM1_RLOF) sc->status.snmp.t1.line |= TLINE_LOF; - if (alm1 & ALM1_RLOS) sc->status.snmp.t1.line |= TLINE_LOS; - if (alm3 & ALM3_RMAIS) sc->status.snmp.t1.line |= T1LINE_RX_TS16_AIS; - if (alm3 & ALM3_SRED) sc->status.snmp.t1.line |= T1LINE_TX_TS16_LOMF; - if (alm3 & ALM3_SEF) sc->status.snmp.t1.line |= T1LINE_SEF; - if (isr0 & 0x10) sc->status.snmp.t1.line |= T1LINE_RX_TEST; - if ((alm1 & ALM1_RMYEL) && (FORMAT_E1CAS)) - sc->status.snmp.t1.line |= T1LINE_RX_TS16_LOMF; - - /* SNMP Loopback Status */ - sc->status.snmp.t1.loop &= ~(TLOOP_FAR_LINE | TLOOP_FAR_PAYLOAD); - if (sc->config.loop_back == CFG_LOOP_TULIP) - sc->status.snmp.t1.loop |= TLOOP_NEAR_OTHER; - if (loop & LOOP_PAYLOAD) sc->status.snmp.t1.loop |= TLOOP_NEAR_PAYLOAD; - if (loop & LOOP_LINE) sc->status.snmp.t1.loop |= TLOOP_NEAR_LINE; - if (loop & LOOP_ANALOG) sc->status.snmp.t1.loop |= TLOOP_NEAR_OTHER; - if (loop & LOOP_FRAMER) sc->status.snmp.t1.loop |= TLOOP_NEAR_INWARD; - - /* Remember this state until next time. */ - sc->last_alm1 = alm1; - - /* If an INWARD loopback is in effect, link status is UP */ - if (sc->config.loop_back != CFG_LOOP_NONE) /* XXX INWARD ONLY */ - link_status = STATUS_UP; - - return link_status; - } - -/* IOCTL SYSCALL: can sleep. */ -static void -t1_send_bop(softc_t *sc, int bop_code) - { - u_int8_t bop; - int i; - - /* The BOP transmitter could be sending a continuous */ - /* BOP msg when told to send this BOP_25 message. */ - /* So save and restore the state of the BOP machine. */ - bop = read_framer(sc, Bt8370_BOP); - write_framer(sc, Bt8370_BOP, RBOP_OFF | TBOP_OFF); - for (i=0; i<40; i++) /* max delay 400 ms. */ - if (read_framer(sc, Bt8370_BOP_STAT) & 0x80) SLEEP(10000); - /* send 25 repetitions of bop_code */ - write_framer(sc, Bt8370_BOP, RBOP_OFF | TBOP_25); - write_framer(sc, Bt8370_TBOP, bop_code); /* order matters */ - /* wait for tx to stop */ - for (i=0; i<40; i++) /* max delay 400 ms. */ - if (read_framer(sc, Bt8370_BOP_STAT) & 0x80) SLEEP(10000); - /* Restore previous state of the BOP machine. */ - write_framer(sc, Bt8370_BOP, bop); - } - -/* IOCTL SYSCALL: can sleep. */ -static int -t1_ioctl(softc_t *sc, struct ioctl *ioctl) - { - int error = 0; - - switch (ioctl->cmd) - { - case IOCTL_SNMP_SEND: /* set opstatus? */ - { - switch (ioctl->data) - { - case TSEND_NORMAL: - { - write_framer(sc, Bt8370_TPATT, 0x00); /* tx pattern generator off */ - write_framer(sc, Bt8370_RPATT, 0x00); /* rx pattern detector off */ - write_framer(sc, Bt8370_TLB, 0x00); /* tx inband generator off */ - break; - } - case TSEND_LINE: - { - if (FORMAT_T1ESF) - t1_send_bop(sc, T1BOP_LINE_UP); - else if (FORMAT_T1SF) - { - write_framer(sc, Bt8370_LBP, 0x08); /* 10000 10000 ... */ - write_framer(sc, Bt8370_TLB, 0x05); /* 5 bits, framed, start */ - } - sc->status.snmp.t1.loop |= TLOOP_FAR_LINE; - break; - } - case TSEND_PAYLOAD: - { - t1_send_bop(sc, T1BOP_PAY_UP); - sc->status.snmp.t1.loop |= TLOOP_FAR_PAYLOAD; - break; - } - case TSEND_RESET: - { - if (sc->status.snmp.t1.loop == TLOOP_FAR_LINE) - { - if (FORMAT_T1ESF) - t1_send_bop(sc, T1BOP_LINE_DOWN); - else if (FORMAT_T1SF) - { - write_framer(sc, Bt8370_LBP, 0x24); /* 100100 100100 ... */ - write_framer(sc, Bt8370_TLB, 0x09); /* 6 bits, framed, start */ - } - sc->status.snmp.t1.loop &= ~TLOOP_FAR_LINE; - } - if (sc->status.snmp.t1.loop == TLOOP_FAR_PAYLOAD) - { - t1_send_bop(sc, T1BOP_PAY_DOWN); - sc->status.snmp.t1.loop &= ~TLOOP_FAR_PAYLOAD; - } - break; - } - case TSEND_QRS: - { - write_framer(sc, Bt8370_TPATT, 0x1E); /* framed QRSS */ - break; - } - default: - { - error = EINVAL; - break; - } - } - break; - } - case IOCTL_SNMP_LOOP: /* set opstatus = test? */ - { - u_int8_t new_loop = 0; - - if (ioctl->data == CFG_LOOP_NONE) - new_loop = 0; - else if (ioctl->data == CFG_LOOP_PAYLOAD) - new_loop = LOOP_PAYLOAD; - else if (ioctl->data == CFG_LOOP_LINE) - new_loop = LOOP_LINE; - else if (ioctl->data == CFG_LOOP_OTHER) - new_loop = LOOP_ANALOG; - else if (ioctl->data == CFG_LOOP_INWARD) - new_loop = LOOP_FRAMER; - else if (ioctl->data == CFG_LOOP_DUAL) - new_loop = LOOP_DUAL; - else - error = EINVAL; - if (error == 0) - { - write_framer(sc, Bt8370_LOOP, new_loop); - sc->config.loop_back = ioctl->data; - } - break; - } - default: - error = EINVAL; - break; - } - - return error; - } - -static -struct card hssi_card = - { - .config = hssi_config, - .ident = hssi_ident, - .watchdog = hssi_watchdog, - .ioctl = hssi_ioctl, - }; - -static -struct card t3_card = - { - .config = t3_config, - .ident = t3_ident, - .watchdog = t3_watchdog, - .ioctl = t3_ioctl, - }; - -static -struct card ssi_card = - { - .config = ssi_config, - .ident = ssi_ident, - .watchdog = ssi_watchdog, - .ioctl = ssi_ioctl, - }; - -static -struct card t1_card = - { - .config = t1_config, - .ident = t1_ident, - .watchdog = t1_watchdog, - .ioctl = t1_ioctl, - }; - -/* RAWIP is raw IP packets (v4 or v6) in HDLC frames with NO HEADERS. */ -/* No HDLC Address/Control fields! No line control protocol at all! */ - -/* rxintr_cleanup calls this to give a newly arrived pkt to higher levels. */ -static void -lmc_raw_input(struct ifnet *ifp, struct mbuf *mbuf) - { - softc_t *sc = IFP2SC(ifp); - - M_SETFIB(mbuf, ifp->if_fib); -# if INET - if (mbuf->m_data[0]>>4 == 4) - netisr_dispatch(NETISR_IP, mbuf); - else -# endif -# if INET6 - if (mbuf->m_data[0]>>4 == 6) - netisr_dispatch(NETISR_IPV6, mbuf); - else -# endif - { - m_freem(mbuf); - sc->status.cntrs.idiscards++; - if (DRIVER_DEBUG) - printf("%s: lmc_raw_input: rx pkt discarded: not IPv4 or IPv6\n", - NAME_UNIT); - } - } - -/* - * We are "standing on the head of a pin" in these routines. - * Tulip CSRs can be accessed, but nothing else is interrupt-safe! - * Do NOT access: MII, GPIO, SROM, BIOSROM, XILINX, SYNTH, or DAC. - */ - - -/* Singly-linked tail-queues hold mbufs with active DMA. - * For RX, single mbuf clusters; for TX, mbuf chains are queued. - * NB: mbufs are linked through their m_nextpkt field. - * Callers must hold sc->bottom_lock; not otherwise locked. - */ - -/* Put an mbuf (chain) on the tail of the descriptor ring queue. */ -static void /* BSD version */ -mbuf_enqueue(struct desc_ring *ring, struct mbuf *m) - { - m->m_nextpkt = NULL; - if (ring->tail == NULL) - ring->head = m; - else - ring->tail->m_nextpkt = m; - ring->tail = m; - } - -/* Get an mbuf (chain) from the head of the descriptor ring queue. */ -static struct mbuf* /* BSD version */ -mbuf_dequeue(struct desc_ring *ring) - { - struct mbuf *m = ring->head; - if (m != NULL) - if ((ring->head = m->m_nextpkt) == NULL) - ring->tail = NULL; - return m; - } - -static void /* *** FreeBSD ONLY *** Callout from bus_dmamap_load() */ -fbsd_dmamap_load(void *arg, bus_dma_segment_t *segs, int nsegs, int error) - { - struct desc_ring *ring = arg; - ring->nsegs = error ? 0 : nsegs; - ring->segs[0] = segs[0]; - ring->segs[1] = segs[1]; - } - -/* Initialize a DMA descriptor ring. */ -static int /* BSD version */ -create_ring(softc_t *sc, struct desc_ring *ring, int num_descs) - { - struct dma_desc *descs; - int size_descs = sizeof(struct dma_desc)*num_descs; - int i, error = 0; - - /* The DMA descriptor array must not cross a page boundary. */ - if (size_descs > PAGE_SIZE) - { - printf("%s: DMA descriptor array > PAGE_SIZE (%d)\n", NAME_UNIT, - (u_int)PAGE_SIZE); - return EINVAL; - } - - - /* Create a DMA tag for descriptors and buffers. */ - if ((error = bus_dma_tag_create(bus_get_dma_tag(sc->dev), - 4, 0, BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 2, PAGE_SIZE, BUS_DMA_ALLOCNOW, - NULL, NULL, - &ring->tag))) - { - printf("%s: bus_dma_tag_create() failed: error %d\n", NAME_UNIT, error); - return error; - } - - /* Allocate wired physical memory for DMA descriptor array */ - /* and map physical address to kernel virtual address. */ - if ((error = bus_dmamem_alloc(ring->tag, (void**)&ring->first, - BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_ZERO, &ring->map))) - { - printf("%s: bus_dmamem_alloc() failed; error %d\n", NAME_UNIT, error); - return error; - } - descs = ring->first; - - /* Map kernel virtual address to PCI address for DMA descriptor array. */ - if ((error = bus_dmamap_load(ring->tag, ring->map, descs, size_descs, - fbsd_dmamap_load, ring, 0))) - { - printf("%s: bus_dmamap_load() failed; error %d\n", NAME_UNIT, error); - return error; - } - ring->dma_addr = ring->segs[0].ds_addr; - - /* Allocate dmamaps for each DMA descriptor. */ - for (i=0; itag, 0, &descs[i].map))) - { - printf("%s: bus_dmamap_create() failed; error %d\n", NAME_UNIT, error); - return error; - } - - - ring->read = descs; - ring->write = descs; - ring->first = descs; - ring->last = descs + num_descs -1; - ring->last->control = TLP_DCTL_END_RING; - ring->num_descs = num_descs; - ring->size_descs = size_descs; - ring->head = NULL; - ring->tail = NULL; - - return 0; - } - -/* Destroy a DMA descriptor ring */ -static void /* BSD version */ -destroy_ring(softc_t *sc, struct desc_ring *ring) - { - struct dma_desc *desc; - struct mbuf *m; - - /* Free queued mbufs. */ - while ((m = mbuf_dequeue(ring)) != NULL) - m_freem(m); - - /* TX may have one pkt that is not on any queue. */ - if (sc->tx_mbuf != NULL) - { - m_freem(sc->tx_mbuf); - sc->tx_mbuf = NULL; - } - - /* Unmap active DMA descriptors. */ - while (ring->read != ring->write) - { - bus_dmamap_unload(ring->tag, ring->read->map); - if (ring->read++ == ring->last) ring->read = ring->first; - } - - - /* Free the dmamaps of all DMA descriptors. */ - for (desc=ring->first; desc!=ring->last+1; desc++) - if (desc->map != NULL) - bus_dmamap_destroy(ring->tag, desc->map); - - /* Unmap PCI address for DMA descriptor array. */ - if (ring->dma_addr != 0) - bus_dmamap_unload(ring->tag, ring->map); - /* Free kernel memory for DMA descriptor array. */ - if (ring->first != NULL) - bus_dmamem_free(ring->tag, ring->first, ring->map); - /* Free the DMA tag created for this ring. */ - if (ring->tag != NULL) - bus_dma_tag_destroy(ring->tag); - - } - -/* Clean up after a packet has been received. */ -static int /* BSD version */ -rxintr_cleanup(softc_t *sc) - { - struct desc_ring *ring = &sc->rxring; - struct dma_desc *first_desc, *last_desc; - struct mbuf *first_mbuf=NULL, *last_mbuf=NULL; - struct mbuf *new_mbuf; - int pkt_len, desc_len; - -#if defined(DEVICE_POLLING) - /* Input packet flow control (livelock prevention): */ - /* Give pkts to higher levels only if quota is > 0. */ - if (sc->quota <= 0) return 0; -#endif - - /* This looks complicated, but remember: typically packets up */ - /* to 2048 bytes long fit in one mbuf and use one descriptor. */ - - first_desc = last_desc = ring->read; - - /* ASSERTION: If there is a descriptor in the ring and the hardware has */ - /* finished with it, then that descriptor will have RX_FIRST_DESC set. */ - if ((ring->read != ring->write) && /* descriptor ring not empty */ - ((ring->read->status & TLP_DSTS_OWNER) == 0) && /* hardware done */ - ((ring->read->status & TLP_DSTS_RX_FIRST_DESC) == 0)) /* should be set */ - panic("%s: rxintr_cleanup: rx-first-descriptor not set.\n", NAME_UNIT); - - /* First decide if a complete packet has arrived. */ - /* Run down DMA descriptors looking for one marked "last". */ - /* Bail out if an active descriptor is encountered. */ - /* Accumulate most significant bits of packet length. */ - pkt_len = 0; - for (;;) - { - if (last_desc == ring->write) return 0; /* no more descs */ - if (last_desc->status & TLP_DSTS_OWNER) return 0; /* still active */ - if (last_desc->status & TLP_DSTS_RX_LAST_DESC) break; /* end of packet */ - pkt_len += last_desc->length1 + last_desc->length2; /* entire desc filled */ - if (last_desc++->control & TLP_DCTL_END_RING) last_desc = ring->first; /* ring wrap */ - } - - /* A complete packet has arrived; how long is it? */ - /* H/w ref man shows RX pkt length as a 14-bit field. */ - /* An experiment found that only the 12 LSBs work. */ - if (((last_desc->status>>16)&0xFFF) == 0) pkt_len += 4096; /* carry-bit */ - pkt_len = (pkt_len & 0xF000) + ((last_desc->status>>16) & 0x0FFF); - /* Subtract the CRC length unless doing so would underflow. */ - if (pkt_len >= sc->config.crc_len) pkt_len -= sc->config.crc_len; - - /* Run down DMA descriptors again doing the following: - * 1) put pkt info in pkthdr of first mbuf, - * 2) link mbufs, - * 3) set mbuf lengths. - */ - first_desc = ring->read; - do - { - /* Read a DMA descriptor from the ring. */ - last_desc = ring->read; - /* Advance the ring read pointer. */ - if (ring->read++ == ring->last) ring->read = ring->first; - - /* Dequeue the corresponding cluster mbuf. */ - new_mbuf = mbuf_dequeue(ring); - if (new_mbuf == NULL) - panic("%s: rxintr_cleanup: expected an mbuf\n", NAME_UNIT); - - desc_len = last_desc->length1 + last_desc->length2; - /* If bouncing, copy bounce buf to mbuf. */ - DMA_SYNC(last_desc->map, desc_len, BUS_DMASYNC_POSTREAD); - /* Unmap kernel virtual address to PCI address. */ - bus_dmamap_unload(ring->tag, last_desc->map); - - /* 1) Put pkt info in pkthdr of first mbuf. */ - if (last_desc == first_desc) - { - first_mbuf = new_mbuf; - first_mbuf->m_pkthdr.len = pkt_len; /* total pkt length */ - first_mbuf->m_pkthdr.rcvif = sc->ifp; /* how it got here */ - } - else /* 2) link mbufs. */ - { - last_mbuf->m_next = new_mbuf; - /* M_PKTHDR should be set in the first mbuf only. */ - new_mbuf->m_flags &= ~M_PKTHDR; - } - last_mbuf = new_mbuf; - - /* 3) Set mbuf lengths. */ - new_mbuf->m_len = (pkt_len >= desc_len) ? desc_len : pkt_len; - pkt_len -= new_mbuf->m_len; - } while ((last_desc->status & TLP_DSTS_RX_LAST_DESC) == 0); - - /* Decide whether to accept or to discard this packet. */ - /* RxHDLC sets MIIERR for bad CRC, abort and partial byte at pkt end. */ - if (((last_desc->status & TLP_DSTS_RX_BAD) == 0) && - (sc->status.oper_status == STATUS_UP) && - (first_mbuf->m_pkthdr.len > 0)) - { - /* Optimization: copy a small pkt into a small mbuf. */ - if (first_mbuf->m_pkthdr.len <= COPY_BREAK) - { - MGETHDR(new_mbuf, M_NOWAIT, MT_DATA); - if (new_mbuf != NULL) - { - new_mbuf->m_pkthdr.rcvif = first_mbuf->m_pkthdr.rcvif; - new_mbuf->m_pkthdr.len = first_mbuf->m_pkthdr.len; - new_mbuf->m_len = first_mbuf->m_len; - memcpy(new_mbuf->m_data, first_mbuf->m_data, - first_mbuf->m_pkthdr.len); - m_freem(first_mbuf); - first_mbuf = new_mbuf; - } - } - /* Include CRC and one flag byte in input byte count. */ - sc->status.cntrs.ibytes += first_mbuf->m_pkthdr.len + sc->config.crc_len +1; - sc->status.cntrs.ipackets++; - if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1); - LMC_BPF_MTAP(first_mbuf); -#if defined(DEVICE_POLLING) - sc->quota--; -#endif - - /* Give this good packet to the network stacks. */ -#if NETGRAPH - if (sc->ng_hook != NULL) /* is hook connected? */ - { - int error; /* ignore error */ - NG_SEND_DATA_ONLY(error, sc->ng_hook, first_mbuf); - return 1; /* did something */ - } -#endif /* NETGRAPH */ - if (sc->config.line_pkg == PKG_RAWIP) - lmc_raw_input(sc->ifp, first_mbuf); - else - { -#if NSPPP - sppp_input(sc->ifp, first_mbuf); -#elif P2P - new_mbuf = first_mbuf; - while (new_mbuf != NULL) - { - sc->p2p->p2p_hdrinput(sc->p2p, new_mbuf->m_data, new_mbuf->m_len); - new_mbuf = new_mbuf->m_next; - } - sc->p2p->p2p_input(sc->p2p, NULL); - m_freem(first_mbuf); -#else - m_freem(first_mbuf); - sc->status.cntrs.idiscards++; -#endif - } - } - else if (sc->status.oper_status != STATUS_UP) - { - /* If the link is down, this packet is probably noise. */ - m_freem(first_mbuf); - sc->status.cntrs.idiscards++; - if (DRIVER_DEBUG) - printf("%s: rxintr_cleanup: rx pkt discarded: link down\n", NAME_UNIT); - } - else /* Log and discard this bad packet. */ - { - if (DRIVER_DEBUG) - printf("%s: RX bad pkt; len=%d %s%s%s%s\n", - NAME_UNIT, first_mbuf->m_pkthdr.len, - (last_desc->status & TLP_DSTS_RX_MII_ERR) ? " miierr" : "", - (last_desc->status & TLP_DSTS_RX_DRIBBLE) ? " dribble" : "", - (last_desc->status & TLP_DSTS_RX_DESC_ERR) ? " descerr" : "", - (last_desc->status & TLP_DSTS_RX_OVERRUN) ? " overrun" : ""); - if (last_desc->status & TLP_DSTS_RX_OVERRUN) - sc->status.cntrs.fifo_over++; - else - sc->status.cntrs.ierrors++; - m_freem(first_mbuf); - } - - return 1; /* did something */ - } - -/* Setup (prepare) to receive a packet. */ -/* Try to keep the RX descriptor ring full of empty buffers. */ -static int /* BSD version */ -rxintr_setup(softc_t *sc) - { - struct desc_ring *ring = &sc->rxring; - struct dma_desc *desc; - struct mbuf *m; - int desc_len; - int error; - - /* Ring is full if (wrap(write+1)==read) */ - if (((ring->write == ring->last) ? ring->first : ring->write+1) == ring->read) - return 0; /* ring is full; nothing to do */ - - /* Allocate a small mbuf and attach an mbuf cluster. */ - MGETHDR(m, M_NOWAIT, MT_DATA); - if (m == NULL) - { - sc->status.cntrs.rxdma++; - if (DRIVER_DEBUG) - printf("%s: rxintr_setup: MGETHDR() failed\n", NAME_UNIT); - return 0; - } - if (!(MCLGET(m, M_NOWAIT))) - { - m_freem(m); - sc->status.cntrs.rxdma++; - if (DRIVER_DEBUG) - printf("%s: rxintr_setup: MCLGET() failed\n", NAME_UNIT); - return 0; - } - - /* Queue the mbuf for later processing by rxintr_cleanup. */ - mbuf_enqueue(ring, m); - - /* Write a DMA descriptor into the ring. */ - /* Hardware won't see it until the OWNER bit is set. */ - desc = ring->write; - /* Advance the ring write pointer. */ - if (ring->write++ == ring->last) ring->write = ring->first; - - desc_len = (MCLBYTES < MAX_DESC_LEN) ? MCLBYTES : MAX_DESC_LEN; - /* Map kernel virtual address to PCI address. */ - if ((error = DMA_LOAD(desc->map, m->m_data, desc_len))) - printf("%s: bus_dmamap_load(rx) failed; error %d\n", NAME_UNIT, error); - /* Invalidate the cache for this mbuf. */ - DMA_SYNC(desc->map, desc_len, BUS_DMASYNC_PREREAD); - - /* Set up the DMA descriptor. */ - desc->address1 = ring->segs[0].ds_addr; - desc->length1 = desc_len>>1; - desc->address2 = desc->address1 + desc->length1; - desc->length2 = desc_len>>1; - - /* Before setting the OWNER bit, flush the cache (memory barrier). */ - DMA_SYNC(ring->map, ring->size_descs, BUS_DMASYNC_PREWRITE); - - /* Commit the DMA descriptor to the hardware. */ - desc->status = TLP_DSTS_OWNER; - - /* Notify the receiver that there is another buffer available. */ - WRITE_CSR(TLP_RX_POLL, 1); - - return 1; /* did something */ - } - -/* Clean up after a packet has been transmitted. */ -/* Free the mbuf chain and update the DMA descriptor ring. */ -static int /* BSD version */ -txintr_cleanup(softc_t *sc) - { - struct desc_ring *ring = &sc->txring; - struct dma_desc *desc; - - while ((ring->read != ring->write) && /* while ring is not empty */ - ((ring->read->status & TLP_DSTS_OWNER) == 0)) - { - /* Read a DMA descriptor from the ring. */ - desc = ring->read; - /* Advance the ring read pointer. */ - if (ring->read++ == ring->last) ring->read = ring->first; - - /* This is a no-op on most architectures. */ - DMA_SYNC(desc->map, desc->length1 + desc->length2, BUS_DMASYNC_POSTWRITE); - /* Unmap kernel virtual address to PCI address. */ - bus_dmamap_unload(ring->tag, desc->map); - - /* If this descriptor is the last segment of a packet, */ - /* then dequeue and free the corresponding mbuf chain. */ - if ((desc->control & TLP_DCTL_TX_LAST_SEG) != 0) - { - struct mbuf *m; - if ((m = mbuf_dequeue(ring)) == NULL) - panic("%s: txintr_cleanup: expected an mbuf\n", NAME_UNIT); - - /* Include CRC and one flag byte in output byte count. */ - sc->status.cntrs.obytes += m->m_pkthdr.len + sc->config.crc_len +1; - sc->status.cntrs.opackets++; - if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1); - LMC_BPF_MTAP(m); - /* The only bad TX status is fifo underrun. */ - if ((desc->status & TLP_DSTS_TX_UNDERRUN) != 0) - sc->status.cntrs.fifo_under++; - - m_freem(m); - return 1; /* did something */ - } - } - - return 0; - } - -/* Build DMA descriptors for a transmit packet mbuf chain. */ -static int /* 0=success; 1=error */ /* BSD version */ -txintr_setup_mbuf(softc_t *sc, struct mbuf *m) - { - struct desc_ring *ring = &sc->txring; - struct dma_desc *desc; - unsigned int desc_len; - - /* build DMA descriptors for a chain of mbufs. */ - while (m != NULL) - { - char *data = m->m_data; - int length = m->m_len; /* zero length mbufs happen! */ - - /* Build DMA descriptors for one mbuf. */ - while (length > 0) - { - int error; - - /* Ring is full if (wrap(write+1)==read) */ - if (((ring->temp==ring->last) ? ring->first : ring->temp+1) == ring->read) - { /* Not enough DMA descriptors; try later. */ - for (; ring->temp!=ring->write; - ring->temp = (ring->temp==ring->first)? ring->last : ring->temp-1) - bus_dmamap_unload(ring->tag, ring->temp->map); - sc->status.cntrs.txdma++; - return 1; - } - - /* Provisionally, write a descriptor into the ring. */ - /* But don't change the REAL ring write pointer. */ - /* Hardware won't see it until the OWNER bit is set. */ - desc = ring->temp; - /* Advance the temporary ring write pointer. */ - if (ring->temp++ == ring->last) ring->temp = ring->first; - - /* Clear all control bits except the END_RING bit. */ - desc->control &= TLP_DCTL_END_RING; - /* Don't pad short packets up to 64 bytes. */ - desc->control |= TLP_DCTL_TX_NO_PAD; - /* Use Tulip's CRC-32 generator, if appropriate. */ - if (sc->config.crc_len != CFG_CRC_32) - desc->control |= TLP_DCTL_TX_NO_CRC; - /* Set the OWNER bit, except in the first descriptor. */ - if (desc != ring->write) - desc->status = TLP_DSTS_OWNER; - - desc_len = (length > MAX_CHUNK_LEN) ? MAX_CHUNK_LEN : length; - /* Map kernel virtual address to PCI address. */ - if ((error = DMA_LOAD(desc->map, data, desc_len))) - printf("%s: bus_dmamap_load(tx) failed; error %d\n", NAME_UNIT, error); - /* Flush the cache and if bouncing, copy mbuf to bounce buf. */ - DMA_SYNC(desc->map, desc_len, BUS_DMASYNC_PREWRITE); - - /* Prevent wild fetches if mapping fails (nsegs==0). */ - desc->length1 = desc->length2 = 0; - desc->address1 = desc->address2 = 0; - { - bus_dma_segment_t *segs = ring->segs; - int nsegs = ring->nsegs; - if (nsegs >= 1) - { - desc->address1 = segs[0].ds_addr; - desc->length1 = segs[0].ds_len; - } - if (nsegs == 2) - { - desc->address2 = segs[1].ds_addr; - desc->length2 = segs[1].ds_len; - } - } - - data += desc_len; - length -= desc_len; - } /* while (length > 0) */ - - m = m->m_next; - } /* while (m != NULL) */ - - return 0; /* success */ - } - -/* Setup (prepare) to transmit a packet. */ -/* Select a packet, build DMA descriptors and give packet to hardware. */ -/* If DMA descriptors run out, abandon the attempt and return 0. */ -static int /* BSD version */ -txintr_setup(softc_t *sc) - { - struct desc_ring *ring = &sc->txring; - struct dma_desc *first_desc, *last_desc; - - /* Protect against half-up links: Don't transmit */ - /* if the receiver can't hear the far end. */ - if (sc->status.oper_status != STATUS_UP) return 0; - - /* Pick a packet to transmit. */ -#if NETGRAPH - if ((sc->ng_hook != NULL) && (sc->tx_mbuf == NULL)) - { - if (!IFQ_IS_EMPTY(&sc->ng_fastq)) - IFQ_DEQUEUE(&sc->ng_fastq, sc->tx_mbuf); - else - IFQ_DEQUEUE(&sc->ng_sndq, sc->tx_mbuf); - } - else -#endif - if (sc->tx_mbuf == NULL) - { - if (sc->config.line_pkg == PKG_RAWIP) - IFQ_DEQUEUE(&sc->ifp->if_snd, sc->tx_mbuf); - else - { -#if NSPPP - sc->tx_mbuf = sppp_dequeue(sc->ifp); -#elif P2P - if (!IFQ_IS_EMPTY(&sc->p2p->p2p_isnd)) - IFQ_DEQUEUE(&sc->p2p->p2p_isnd, sc->tx_mbuf); - else - IFQ_DEQUEUE(&sc->ifp->if_snd, sc->tx_mbuf); -#endif - } - } - if (sc->tx_mbuf == NULL) return 0; /* no pkt to transmit */ - - /* Build DMA descriptors for an outgoing mbuf chain. */ - ring->temp = ring->write; /* temporary ring write pointer */ - if (txintr_setup_mbuf(sc, sc->tx_mbuf) != 0) return 0; - - /* Enqueue the mbuf; txintr_cleanup will free it. */ - mbuf_enqueue(ring, sc->tx_mbuf); - - /* The transmitter has room for another packet. */ - sc->tx_mbuf = NULL; - - /* Set first & last segment bits. */ - /* last_desc is the desc BEFORE the one pointed to by ring->temp. */ - first_desc = ring->write; - first_desc->control |= TLP_DCTL_TX_FIRST_SEG; - last_desc = (ring->temp==ring->first)? ring->last : ring->temp-1; - last_desc->control |= TLP_DCTL_TX_LAST_SEG; - /* Interrupt at end-of-transmission? Why bother the poor computer! */ -/* last_desc->control |= TLP_DCTL_TX_INTERRUPT; */ - - /* Make sure the OWNER bit is not set in the next descriptor. */ - /* The OWNER bit may have been set if a previous call aborted. */ - ring->temp->status = 0; - - /* Commit the DMA descriptors to the software. */ - ring->write = ring->temp; - - /* Before setting the OWNER bit, flush the cache (memory barrier). */ - DMA_SYNC(ring->map, ring->size_descs, BUS_DMASYNC_PREWRITE); - - /* Commit the DMA descriptors to the hardware. */ - first_desc->status = TLP_DSTS_OWNER; - - /* Notify the transmitter that there is another packet to send. */ - WRITE_CSR(TLP_TX_POLL, 1); - - return 1; /* did something */ - } - - - -static void -check_intr_status(softc_t *sc) - { - u_int32_t status, cfcs, op_mode; - u_int32_t missed, overruns; - - /* Check for four unusual events: - * 1) fatal PCI bus errors - some are recoverable - * 2) transmitter FIFO underruns - increase fifo threshold - * 3) receiver FIFO overruns - clear potential hangup - * 4) no receive descs or bufs - count missed packets - */ - - /* 1) A fatal bus error causes a Tulip to stop initiating bus cycles. */ - /* Module unload/load or boot are the only fixes for Parity Errors. */ - /* Master and Target Aborts can be cleared and life may continue. */ - status = READ_CSR(TLP_STATUS); - if ((status & TLP_STAT_FATAL_ERROR) != 0) - { - u_int32_t fatal = (status & TLP_STAT_FATAL_BITS)>>TLP_STAT_FATAL_SHIFT; - printf("%s: FATAL PCI BUS ERROR: %s%s%s%s\n", NAME_UNIT, - (fatal == 0) ? "PARITY ERROR" : "", - (fatal == 1) ? "MASTER ABORT" : "", - (fatal == 2) ? "TARGET ABORT" : "", - (fatal >= 3) ? "RESERVED (?)" : ""); - cfcs = READ_PCI_CFG(sc, TLP_CFCS); /* try to clear it */ - cfcs &= ~(TLP_CFCS_MSTR_ABORT | TLP_CFCS_TARG_ABORT); - WRITE_PCI_CFG(sc, TLP_CFCS, cfcs); - } - - /* 2) If the transmitter fifo underruns, increase the transmit fifo */ - /* threshold: the number of bytes required to be in the fifo */ - /* before starting the transmitter (cost: increased tx delay). */ - /* The TX_FSM must be stopped to change this parameter. */ - if ((status & TLP_STAT_TX_UNDERRUN) != 0) - { - op_mode = READ_CSR(TLP_OP_MODE); - /* enable store-and-forward mode if tx_threshold tops out? */ - if ((op_mode & TLP_OP_TX_THRESH) < TLP_OP_TX_THRESH) - { - op_mode += 0x4000; /* increment TX_THRESH field; can't overflow */ - WRITE_CSR(TLP_OP_MODE, op_mode & ~TLP_OP_TX_RUN); - /* Wait for the TX FSM to stop; it might be processing a pkt. */ - while (READ_CSR(TLP_STATUS) & TLP_STAT_TX_FSM); /* XXX HANG */ - WRITE_CSR(TLP_OP_MODE, op_mode); /* restart tx */ - if (DRIVER_DEBUG) - printf("%s: tx underrun; tx fifo threshold now %d bytes\n", - NAME_UNIT, 128<<((op_mode>>TLP_OP_TR_SHIFT)&3)); - } - } - - /* 3) Errata memo from Digital Equipment Corp warns that 21140A */ - /* receivers through rev 2.2 can hang if the fifo overruns. */ - /* Recommended fix: stop and start the RX FSM after an overrun. */ - missed = READ_CSR(TLP_MISSED); - if ((overruns = ((missed & TLP_MISS_OVERRUN)>>TLP_OVERRUN_SHIFT)) != 0) - { - if (DRIVER_DEBUG) - printf("%s: rx overrun cntr=%d\n", NAME_UNIT, overruns); - sc->status.cntrs.overruns += overruns; - if ((READ_PCI_CFG(sc, TLP_CFRV) & 0xFF) <= 0x22) - { - op_mode = READ_CSR(TLP_OP_MODE); - WRITE_CSR(TLP_OP_MODE, op_mode & ~TLP_OP_RX_RUN); - /* Wait for the RX FSM to stop; it might be processing a pkt. */ - while (READ_CSR(TLP_STATUS) & TLP_STAT_RX_FSM); /* XXX HANG */ - WRITE_CSR(TLP_OP_MODE, op_mode); /* restart rx */ - } - } - - /* 4) When the receiver is enabled and a packet arrives, but no DMA */ - /* descriptor is available, the packet is counted as 'missed'. */ - /* The receiver should never miss packets; warn if it happens. */ - if ((missed = (missed & TLP_MISS_MISSED)) != 0) - { - if (DRIVER_DEBUG) - printf("%s: rx missed %d pkts\n", NAME_UNIT, missed); - sc->status.cntrs.missed += missed; - } - } - -static void /* This is where the work gets done. */ -core_interrupt(void *arg, int check_status) - { - softc_t *sc = arg; - int activity; - - /* If any CPU is inside this critical section, then */ - /* other CPUs should go away without doing anything. */ - if (BOTTOM_TRYLOCK == 0) - { - sc->status.cntrs.lck_intr++; - return; - } - - /* Clear pending card interrupts. */ - WRITE_CSR(TLP_STATUS, READ_CSR(TLP_STATUS)); - - /* In Linux, pci_alloc_consistent() means DMA descriptors */ - /* don't need explicit syncing. */ - { - struct desc_ring *ring = &sc->txring; - DMA_SYNC(sc->txring.map, sc->txring.size_descs, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - ring = &sc->rxring; - DMA_SYNC(sc->rxring.map, sc->rxring.size_descs, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - } - - do /* This is the main loop for interrupt processing. */ - { - activity = txintr_cleanup(sc); - activity += txintr_setup(sc); - activity += rxintr_cleanup(sc); - activity += rxintr_setup(sc); - } while (activity); - - { - struct desc_ring *ring = &sc->txring; - DMA_SYNC(sc->txring.map, sc->txring.size_descs, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - ring = &sc->rxring; - DMA_SYNC(sc->rxring.map, sc->rxring.size_descs, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - } - - /* As the interrupt is dismissed, check for four unusual events. */ - if (check_status) check_intr_status(sc); - - BOTTOM_UNLOCK; - } - -/* user_interrupt() may be called from a syscall or a softirq */ -static void -user_interrupt(softc_t *sc, int check_status) - { - DISABLE_INTR; /* noop on FreeBSD-5 and Linux */ - core_interrupt(sc, check_status); - ENABLE_INTR; /* noop on FreeBSD-5 and Linux */ - } - - -# if defined(DEVICE_POLLING) - -/* Service the card from the kernel idle loop without interrupts. */ -static int -fbsd_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) - { - softc_t *sc = IFP2SC(ifp); - - - sc->quota = count; - core_interrupt(sc, (cmd==POLL_AND_CHECK_STATUS)); - return 0; - } - -# endif /* DEVICE_POLLING */ - -/* BSD kernels call this procedure when an interrupt happens. */ -static intr_return_t -bsd_interrupt(void *arg) - { - softc_t *sc = arg; - - /* Cut losses early if this is not our interrupt. */ - if ((READ_CSR(TLP_STATUS) & TLP_INT_TXRX) == 0) - return IRQ_NONE; - -# if defined(DEVICE_POLLING) - if (sc->ifp->if_capenable & IFCAP_POLLING) - return IRQ_NONE; - - if ((sc->ifp->if_capabilities & IFCAP_POLLING) && - (ether_poll_register(fbsd_poll, sc->ifp))) - { - WRITE_CSR(TLP_INT_ENBL, TLP_INT_DISABLE); - return IRQ_NONE; - } - else - sc->quota = sc->rxring.num_descs; /* input flow control */ -# endif /* DEVICE_POLLING */ - - /* Disable card interrupts. */ - WRITE_CSR(TLP_INT_ENBL, TLP_INT_DISABLE); - - core_interrupt(sc, 0); - - /* Enable card interrupts. */ - WRITE_CSR(TLP_INT_ENBL, TLP_INT_TXRX); - - return IRQ_HANDLED; - } - - -/* Administrative status of the driver (UP or DOWN) has changed. */ -/* A card-specific action may be required: T1 and T3 cards: no-op. */ -/* HSSI and SSI cards change the state of modem ready signals. */ -static void -set_status(softc_t *sc, int status) - { - struct ioctl ioctl; - - ioctl.cmd = IOCTL_SET_STATUS; - ioctl.data = status; - - sc->card->ioctl(sc, &ioctl); - } - -#if P2P - -/* Callout from P2P: */ -/* Get the state of DCD (Data Carrier Detect). */ -static int -p2p_getmdm(struct p2pcom *p2p, caddr_t result) - { - softc_t *sc = IFP2SC(&p2p->p2p_if); - - /* Non-zero isn't good enough; TIOCM_CAR is 0x40. */ - *(int *)result = (sc->status.oper_status==STATUS_UP) ? TIOCM_CAR : 0; - - return 0; - } - -/* Callout from P2P: */ -/* Set the state of DTR (Data Terminal Ready). */ -static int -p2p_mdmctl(struct p2pcom *p2p, int flag) - { - softc_t *sc = IFP2SC(&p2p->p2p_if); - - set_status(sc, flag); - - return 0; - } - -#endif /* P2P */ - -#if NSPPP - -# ifndef PP_FR -# define PP_FR 0 -# endif - -/* Callout from SPPP: */ -static void -sppp_tls(struct sppp *sppp) - { - if (!(sppp->pp_mode & IFF_LINK2) && - !(sppp->pp_flags & PP_FR)) - sppp->pp_up(sppp); - } - -/* Callout from SPPP: */ -static void -sppp_tlf(struct sppp *sppp) - { - if (!(sppp->pp_mode & IFF_LINK2) && - !(sppp->pp_flags & PP_FR)) - sppp->pp_down(sppp); - } - -#endif /* NSPPP */ - -/* Configure line protocol stuff. - * Called by attach_card() during module init. - * Called by core_ioctl() when lmcconfig writes sc->config. - * Called by detach_card() during module shutdown. - */ -static void -config_proto(softc_t *sc, struct config *config) - { - /* Use line protocol stack instead of RAWIP mode. */ - if ((sc->config.line_pkg == PKG_RAWIP) && - (config->line_pkg != PKG_RAWIP)) - { -#if NSPPP - LMC_BPF_DETACH; - sppp_attach(sc->ifp); - LMC_BPF_ATTACH(DLT_PPP, 4); - sc->sppp->pp_tls = sppp_tls; - sc->sppp->pp_tlf = sppp_tlf; - /* Force reconfiguration of SPPP params. */ - sc->config.line_prot = 0; - sc->config.keep_alive = config->keep_alive ? 0:1; -#elif P2P - int error = 0; - sc->p2p->p2p_proto = 0; /* force p2p_attach */ - if ((error = p2p_attach(sc->p2p))) /* calls bpfattach() */ - { - printf("%s: p2p_attach() failed; error %d\n", NAME_UNIT, error); - config->line_pkg = PKG_RAWIP; /* still in RAWIP mode */ - } - else - { - sc->p2p->p2p_mdmctl = p2p_mdmctl; /* set DTR */ - sc->p2p->p2p_getmdm = p2p_getmdm; /* get DCD */ - } -#elif GEN_HDLC - int error = 0; - sc->net_dev->mtu = HDLC_MAX_MTU; - if ((error = hdlc_open(sc->net_dev))) - { - printf("%s: hdlc_open() failed; error %d\n", NAME_UNIT, error); - printf("%s: Try 'sethdlc %s ppp'\n", NAME_UNIT, NAME_UNIT); - config->line_pkg = PKG_RAWIP; /* still in RAWIP mode */ - } -#else /* no line protocol stack was configured */ - config->line_pkg = PKG_RAWIP; /* still in RAWIP mode */ -#endif - } - - /* Bypass line protocol stack and return to RAWIP mode. */ - if ((sc->config.line_pkg != PKG_RAWIP) && - (config->line_pkg == PKG_RAWIP)) - { -#if NSPPP - LMC_BPF_DETACH; - sppp_flush(sc->ifp); - sppp_detach(sc->ifp); - setup_ifnet(sc->ifp); - LMC_BPF_ATTACH(DLT_RAW, 0); -#elif P2P - int error = 0; - if_qflush(&sc->p2p->p2p_isnd); - if ((error = p2p_detach(sc->p2p))) - { - printf("%s: p2p_detach() failed; error %d\n", NAME_UNIT, error); - printf("%s: Try 'ifconfig %s down -remove'\n", NAME_UNIT, NAME_UNIT); - config->line_pkg = PKG_P2P; /* not in RAWIP mode; still attached to P2P */ - } - else - { - setup_ifnet(sc->ifp); - LMC_BPF_ATTACH(DLT_RAW, 0); - } -#elif GEN_HDLC - hdlc_proto_detach(sc->hdlc_dev); - hdlc_close(sc->net_dev); - setup_netdev(sc->net_dev); -#endif - } - -#if NSPPP - - if (config->line_pkg != PKG_RAWIP) - { - /* Check for change to PPP protocol. */ - if ((sc->config.line_prot != PROT_PPP) && - (config->line_prot == PROT_PPP)) - { - LMC_BPF_DETACH; - sc->ifp->if_flags &= ~IFF_LINK2; - sc->sppp->pp_flags &= ~PP_FR; - LMC_BPF_ATTACH(DLT_PPP, 4); - sppp_ioctl(sc->ifp, SIOCSIFFLAGS, NULL); - } - -# ifndef DLT_C_HDLC -# define DLT_C_HDLC DLT_PPP -# endif - - /* Check for change to C_HDLC protocol. */ - if ((sc->config.line_prot != PROT_C_HDLC) && - (config->line_prot == PROT_C_HDLC)) - { - LMC_BPF_DETACH; - sc->ifp->if_flags |= IFF_LINK2; - sc->sppp->pp_flags &= ~PP_FR; - LMC_BPF_ATTACH(DLT_C_HDLC, 4); - sppp_ioctl(sc->ifp, SIOCSIFFLAGS, NULL); - } - - /* Check for change to Frame Relay protocol. */ - if ((sc->config.line_prot != PROT_FRM_RLY) && - (config->line_prot == PROT_FRM_RLY)) - { - LMC_BPF_DETACH; - sc->ifp->if_flags &= ~IFF_LINK2; - sc->sppp->pp_flags |= PP_FR; - LMC_BPF_ATTACH(DLT_FRELAY, 4); - sppp_ioctl(sc->ifp, SIOCSIFFLAGS, NULL); - } - - /* Check for disabling keep-alives. */ - if ((sc->config.keep_alive != 0) && - (config->keep_alive == 0)) - sc->sppp->pp_flags &= ~PP_KEEPALIVE; - - /* Check for enabling keep-alives. */ - if ((sc->config.keep_alive == 0) && - (config->keep_alive != 0)) - sc->sppp->pp_flags |= PP_KEEPALIVE; - } - -#endif /* NSPPP */ - - /* Loop back through the TULIP Ethernet chip; (no CRC). */ - /* Data sheet says stop DMA before changing OPMODE register. */ - /* But that's not as simple as it sounds; works anyway. */ - /* Check for enabling loopback thru Tulip chip. */ - if ((sc->config.loop_back != CFG_LOOP_TULIP) && - (config->loop_back == CFG_LOOP_TULIP)) - { - u_int32_t op_mode = READ_CSR(TLP_OP_MODE); - op_mode |= TLP_OP_INT_LOOP; - WRITE_CSR(TLP_OP_MODE, op_mode); - config->crc_len = CFG_CRC_0; - } - - /* Check for disabling loopback thru Tulip chip. */ - if ((sc->config.loop_back == CFG_LOOP_TULIP) && - (config->loop_back != CFG_LOOP_TULIP)) - { - u_int32_t op_mode = READ_CSR(TLP_OP_MODE); - op_mode &= ~TLP_OP_LOOP_MODE; - WRITE_CSR(TLP_OP_MODE, op_mode); - config->crc_len = CFG_CRC_16; - } - } - -/* This is the core ioctl procedure. */ -/* It handles IOCTLs from lmcconfig(8). */ -/* It must not run when card watchdogs run. */ -/* Called from a syscall (user context; no spinlocks). */ -/* This procedure can SLEEP. */ -static int -core_ioctl(softc_t *sc, u_long cmd, caddr_t data) - { - struct iohdr *iohdr = (struct iohdr *) data; - struct ioctl *ioctl = (struct ioctl *) data; - struct status *status = (struct status *) data; - struct config *config = (struct config *) data; - int error = 0; - - /* All structs start with a string and a cookie. */ - if (((struct iohdr *)data)->cookie != NGM_LMC_COOKIE) - return EINVAL; - - while (TOP_TRYLOCK == 0) - { - sc->status.cntrs.lck_ioctl++; - SLEEP(10000); /* yield? */ - } - switch (cmd) - { - case LMCIOCGSTAT: - { - *status = sc->status; - iohdr->cookie = NGM_LMC_COOKIE; - break; - } - case LMCIOCGCFG: - { - *config = sc->config; - iohdr->cookie = NGM_LMC_COOKIE; - break; - } - case LMCIOCSCFG: - { - if ((error = CHECK_CAP)) break; - config_proto(sc, config); - sc->config = *config; - sc->card->config(sc); - break; - } - case LMCIOCREAD: - { - if (ioctl->cmd == IOCTL_RW_PCI) - { - if (ioctl->address > 252) { error = EFAULT; break; } - ioctl->data = READ_PCI_CFG(sc, ioctl->address); - } - else if (ioctl->cmd == IOCTL_RW_CSR) - { - if (ioctl->address > 15) { error = EFAULT; break; } - ioctl->data = READ_CSR(ioctl->address*TLP_CSR_STRIDE); - } - else if (ioctl->cmd == IOCTL_RW_SROM) - { - if (ioctl->address > 63) { error = EFAULT; break; } - ioctl->data = read_srom(sc, ioctl->address); - } - else if (ioctl->cmd == IOCTL_RW_BIOS) - ioctl->data = read_bios(sc, ioctl->address); - else if (ioctl->cmd == IOCTL_RW_MII) - ioctl->data = read_mii(sc, ioctl->address); - else if (ioctl->cmd == IOCTL_RW_FRAME) - ioctl->data = read_framer(sc, ioctl->address); - else - error = EINVAL; - break; - } - case LMCIOCWRITE: - { - if ((error = CHECK_CAP)) break; - if (ioctl->cmd == IOCTL_RW_PCI) - { - if (ioctl->address > 252) { error = EFAULT; break; } - WRITE_PCI_CFG(sc, ioctl->address, ioctl->data); - } - else if (ioctl->cmd == IOCTL_RW_CSR) - { - if (ioctl->address > 15) { error = EFAULT; break; } - WRITE_CSR(ioctl->address*TLP_CSR_STRIDE, ioctl->data); - } - else if (ioctl->cmd == IOCTL_RW_SROM) - { - if (ioctl->address > 63) { error = EFAULT; break; } - write_srom(sc, ioctl->address, ioctl->data); /* can sleep */ - } - else if (ioctl->cmd == IOCTL_RW_BIOS) - { - if (ioctl->address == 0) erase_bios(sc); - write_bios(sc, ioctl->address, ioctl->data); /* can sleep */ - } - else if (ioctl->cmd == IOCTL_RW_MII) - write_mii(sc, ioctl->address, ioctl->data); - else if (ioctl->cmd == IOCTL_RW_FRAME) - write_framer(sc, ioctl->address, ioctl->data); - else if (ioctl->cmd == IOCTL_WO_SYNTH) - write_synth(sc, (struct synth *)&ioctl->data); - else if (ioctl->cmd == IOCTL_WO_DAC) - { - write_dac(sc, 0x9002); /* set Vref = 2.048 volts */ - write_dac(sc, ioctl->data & 0xFFF); - } - else - error = EINVAL; - break; - } - case LMCIOCTL: - { - if ((error = CHECK_CAP)) break; - if (ioctl->cmd == IOCTL_XILINX_RESET) - { - reset_xilinx(sc); - sc->card->config(sc); - } - else if (ioctl->cmd == IOCTL_XILINX_ROM) - { - load_xilinx_from_rom(sc); /* can sleep */ - sc->card->config(sc); - } - else if (ioctl->cmd == IOCTL_XILINX_FILE) - { - /* load_xilinx_from_file() can sleep. */ - error = load_xilinx_from_file(sc, ioctl->ucode, ioctl->data); - if (error != 0) load_xilinx_from_rom(sc); /* try the rom */ - sc->card->config(sc); - set_status(sc, (error==0)); /* XXX */ - } - else if (ioctl->cmd == IOCTL_RESET_CNTRS) - { - memset(&sc->status.cntrs, 0, sizeof(struct event_cntrs)); - microtime(&sc->status.cntrs.reset_time); - } - else - error = sc->card->ioctl(sc, ioctl); /* can sleep */ - break; - } - default: - error = EINVAL; - break; - } - TOP_UNLOCK; - - return error; - } - -/* This is the core watchdog procedure. */ -/* It calculates link speed, and calls the card-specific watchdog code. */ -/* Calls interrupt() in case one got lost; also kick-starts the device. */ -/* ioctl syscalls and card watchdog routines must be interlocked. */ -/* This procedure must not sleep. */ -static void -core_watchdog(softc_t *sc) - { - /* Read and restart the Tulip timer. */ - u_int32_t tx_speed = READ_CSR(TLP_TIMER); - WRITE_CSR(TLP_TIMER, 0xFFFF); - - /* Measure MII clock using a timer in the Tulip chip. - * This timer counts transmitter bits divided by 4096. - * Since this is called once a second the math is easy. - * This is only correct when the link is NOT sending pkts. - * On a fully-loaded link, answer will be HALF actual rate. - * Clock rate during pkt is HALF clk rate between pkts. - * Measuring clock rate really measures link utilization! - */ - sc->status.tx_speed = (0xFFFF - (tx_speed & 0xFFFF)) << 12; - - /* The first status reset time is when the calendar clock is set. */ - if (sc->status.cntrs.reset_time.tv_sec < 1000) - microtime(&sc->status.cntrs.reset_time); - - /* Update hardware (operational) status. */ - /* Call the card-specific watchdog routines. */ - if (TOP_TRYLOCK != 0) - { - sc->status.oper_status = sc->card->watchdog(sc); - - /* Increment a counter which tells user-land */ - /* observers that SNMP state has been updated. */ - sc->status.ticks++; - - TOP_UNLOCK; - } - else - sc->status.cntrs.lck_watch++; - - /* In case an interrupt gets lost... */ - user_interrupt(sc, 1); - } - - -/* Called from a syscall (user context; no spinlocks). */ -static int -lmc_raw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) - { - struct ifreq *ifr = (struct ifreq *) data; - int error = 0; - - switch (cmd) - { - case SIOCAIFADDR: - case SIOCSIFFLAGS: - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; /* a Unix tradition */ - break; - case SIOCSIFMTU: - ifp->if_mtu = ifr->ifr_mtu; - break; - default: - error = EINVAL; - break; - } - return error; - } - -/* Called from a syscall (user context; no spinlocks). */ -static int -lmc_ifnet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) - { - softc_t *sc = IFP2SC(ifp); - int error = 0; - - switch (cmd) - { - /* Catch the IOCTLs used by lmcconfig. */ - case LMCIOCGSTAT: - case LMCIOCGCFG: - case LMCIOCSCFG: - case LMCIOCREAD: - case LMCIOCWRITE: - case LMCIOCTL: - error = core_ioctl(sc, cmd, data); - break; - /* Pass the rest to the line protocol. */ - default: - if (sc->config.line_pkg == PKG_RAWIP) - error = lmc_raw_ioctl(ifp, cmd, data); - else -# if NSPPP - error = sppp_ioctl(ifp, cmd, data); -# elif P2P - error = p2p_ioctl(ifp, cmd, data); -# else - error = EINVAL; -# endif - break; - } - - if (DRIVER_DEBUG && (error!=0)) - printf("%s: lmc_ifnet_ioctl; cmd=0x%08lx error=%d\n", - NAME_UNIT, cmd, error); - - return error; - } - -/* Called from a syscall (user context; no spinlocks). */ -static void -lmc_ifnet_start(struct ifnet *ifp) - { - softc_t *sc = IFP2SC(ifp); - - /* Start the transmitter; incoming pkts are NOT processed. */ - user_interrupt(sc, 0); - } - -/* sppp and p2p replace this with their own proc. */ -/* RAWIP mode is the only time this is used. */ -/* Called from a syscall (user context; no spinlocks). */ -static int -lmc_raw_output(struct ifnet *ifp, struct mbuf *m, - const struct sockaddr *dst, struct route *ro) - { - softc_t *sc = IFP2SC(ifp); - int error = 0; - - /* Fail if the link is down. */ - if (sc->status.oper_status != STATUS_UP) - { - m_freem(m); - sc->status.cntrs.odiscards++; - if (DRIVER_DEBUG) - printf("%s: lmc_raw_output: tx pkt discarded: link down\n", NAME_UNIT); - return ENETDOWN; - } - -# if NETGRAPH - /* Netgraph has priority over the ifnet kernel interface. */ - if (sc->ng_hook != NULL) - { - m_freem(m); - sc->status.cntrs.odiscards++; - if (DRIVER_DEBUG) - printf("%s: lmc_raw_output: tx pkt discarded: netgraph active\n", - NAME_UNIT); - return EBUSY; - } -# endif - - /* lmc_raw_output() ENQUEUEs in a syscall or softirq. */ - /* txintr_setup() DEQUEUEs in a hard interrupt. */ - /* Some BSD QUEUE routines are not interrupt-safe. */ - { - DISABLE_INTR; - IFQ_ENQUEUE(&ifp->if_snd, m, error); - ENABLE_INTR; - } - - if (error==0) - user_interrupt(sc, 0); /* start the transmitter */ - else - { - m_freem(m); - sc->status.cntrs.odiscards++; - if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1); - if (DRIVER_DEBUG) - printf("%s: lmc_raw_output: IFQ_ENQUEUE() failed; error %d\n", - NAME_UNIT, error); - } - - return error; - } - -/* Called from a softirq once a second. */ -static void -lmc_watchdog(void *arg) -{ - struct ifnet *ifp = arg; - softc_t *sc = IFP2SC(ifp); - u_int8_t old_oper_status = sc->status.oper_status; - - core_watchdog(sc); /* updates oper_status */ - -#if NETGRAPH - if (sc->ng_hook != NULL) - { - sc->status.line_pkg = PKG_NG; - sc->status.line_prot = 0; - } - else -#endif - if (sc->config.line_pkg == PKG_RAWIP) - { - sc->status.line_pkg = PKG_RAWIP; - sc->status.line_prot = PROT_IP_HDLC; - } - else - { -# if P2P - /* Notice change in link status. */ - if ((old_oper_status != sc->status.oper_status) && (sc->p2p->p2p_modem)) - (*sc->p2p->p2p_modem)(sc->p2p, sc->status.oper_status==STATUS_UP); - - /* Notice change in line protocol. */ - sc->status.line_pkg = PKG_P2P; - switch (sc->ifp->if_type) - { - case IFT_PPP: - sc->status.line_prot = PROT_PPP; - break; - case IFT_PTPSERIAL: - sc->status.line_prot = PROT_C_HDLC; - break; - case IFT_FRELAY: - sc->status.line_prot = PROT_FRM_RLY; - break; - default: - sc->status.line_prot = 0; - break; - } - -# elif NSPPP - /* Notice change in link status. */ - if ((old_oper_status != STATUS_UP) && - (sc->status.oper_status == STATUS_UP)) /* link came up */ - sppp_tls(sc->sppp); - if ((old_oper_status == STATUS_UP) && - (sc->status.oper_status != STATUS_UP)) /* link went down */ - sppp_tlf(sc->sppp); - - /* Notice change in line protocol. */ - sc->status.line_pkg = PKG_SPPP; - if (sc->sppp->pp_flags & PP_FR) - sc->status.line_prot = PROT_FRM_RLY; - else if (sc->ifp->if_flags & IFF_LINK2) - sc->status.line_prot = PROT_C_HDLC; - else - sc->status.line_prot = PROT_PPP; - -# else - /* Suppress compiler warning. */ - if (old_oper_status == STATUS_UP); -# endif - } - - ifp->if_baudrate = sc->status.tx_speed; - if (sc->status.oper_status == STATUS_UP) - ifp->if_link_state = LINK_STATE_UP; - else - ifp->if_link_state = LINK_STATE_DOWN; - - /* Call this procedure again after one second. */ - callout_reset(&sc->callout, hz, lmc_watchdog, ifp); -} - -static uint64_t -lmc_get_counter(struct ifnet *ifp, ift_counter cnt) -{ - softc_t *sc; - struct event_cntrs *cntrs; - - sc = if_getsoftc(ifp); - cntrs = &sc->status.cntrs; - - switch (cnt) { - case IFCOUNTER_IPACKETS: - return (cntrs->ipackets); - case IFCOUNTER_OPACKETS: - return (cntrs->opackets); - case IFCOUNTER_IBYTES: - return (cntrs->ibytes); - case IFCOUNTER_OBYTES: - return (cntrs->obytes); - case IFCOUNTER_IERRORS: - return (cntrs->ierrors); - case IFCOUNTER_OERRORS: - return (cntrs->oerrors); - case IFCOUNTER_IQDROPS: - return (cntrs->idiscards); - default: - return (if_get_counter_default(ifp, cnt)); - } -} - -static void -setup_ifnet(struct ifnet *ifp) - { - softc_t *sc = ifp->if_softc; - - /* Initialize the generic network interface. */ - ifp->if_flags = IFF_POINTOPOINT; - ifp->if_flags |= IFF_RUNNING; - ifp->if_ioctl = lmc_ifnet_ioctl; - ifp->if_start = lmc_ifnet_start; /* sppp changes this */ - ifp->if_output = lmc_raw_output; /* sppp & p2p change this */ - ifp->if_input = lmc_raw_input; - ifp->if_get_counter = lmc_get_counter; - ifp->if_mtu = MAX_DESC_LEN; /* sppp & p2p change this */ - ifp->if_type = IFT_PTPSERIAL; /* p2p changes this */ - -# if defined(DEVICE_POLLING) - ifp->if_capabilities |= IFCAP_POLLING; -# endif - - if_initname(ifp, device_get_name(sc->dev), device_get_unit(sc->dev)); - } - -static int -lmc_ifnet_attach(softc_t *sc) - { - sc->ifp = if_alloc(NSPPP ? IFT_PPP : IFT_OTHER); - if (sc->ifp == NULL) return ENOMEM; -# if NSPPP - sc->sppp = sc->ifp->if_l2com; -# elif P2P - sc->ifp = &sc->p2pcom.p2p_if; - sc->p2p = &sc->p2pcom; -# endif - - /* Initialize the network interface struct. */ - sc->ifp->if_softc = sc; - setup_ifnet(sc->ifp); - - /* ALTQ output queue initialization. */ - IFQ_SET_MAXLEN(&sc->ifp->if_snd, SNDQ_MAXLEN); - IFQ_SET_READY(&sc->ifp->if_snd); - - /* Attach to the ifnet kernel interface. */ - if_attach(sc->ifp); - - /* Attach Berkeley Packet Filter. */ - LMC_BPF_ATTACH(DLT_RAW, 0); - - callout_reset(&sc->callout, hz, lmc_watchdog, sc); - - return 0; - } - -static void -lmc_ifnet_detach(softc_t *sc) - { - -# if defined(DEVICE_POLLING) - if (sc->ifp->if_capenable & IFCAP_POLLING) - ether_poll_deregister(sc->ifp); -# endif - - /* Detach Berkeley Packet Filter. */ - LMC_BPF_DETACH; - - /* Detach from the ifnet kernel interface. */ - if_detach(sc->ifp); - - if_free(sc->ifp); - } - - -#if NETGRAPH - -/* These next two macros should be added to netgraph */ -# define NG_TYPE_REF(type) atomic_add_int(&(type)->refs, 1) -# define NG_TYPE_UNREF(type) \ -do { \ - if ((type)->refs == 1) \ - ng_rmtype(type); \ - else \ - atomic_subtract_int(&(type)->refs, 1); \ - } while (0) - -/* It is an error to construct new copies of this Netgraph node. */ -/* All instances are constructed by ng_attach and are persistent. */ -static int ng_constructor(node_p node) { return EINVAL; } - -/* Incoming Netgraph control message. */ -static int -ng_rcvmsg(node_p node, item_p item, hook_p lasthook) - { - struct ng_mesg *msg; - struct ng_mesg *resp = NULL; - softc_t *sc = NG_NODE_PRIVATE(node); - int error = 0; - - NGI_GET_MSG(item, msg); - if (msg->header.typecookie == NGM_LMC_COOKIE) - { - switch (msg->header.cmd) - { - case LMCIOCGSTAT: - case LMCIOCGCFG: - case LMCIOCSCFG: - case LMCIOCREAD: - case LMCIOCWRITE: - case LMCIOCTL: - { - /* Call the core ioctl procedure. */ - error = core_ioctl(sc, msg->header.cmd, msg->data); - if ((msg->header.cmd & IOC_OUT) != 0) - { /* synchronous response */ - NG_MKRESPONSE(resp, msg, sizeof(struct ng_mesg) + - IOCPARM_LEN(msg->header.cmd), M_NOWAIT); - if (resp == NULL) - error = ENOMEM; - else - memcpy(resp->data, msg->data, IOCPARM_LEN(msg->header.cmd)); - } - break; - } - default: - error = EINVAL; - break; - } - } - else if ((msg->header.typecookie == NGM_GENERIC_COOKIE) && - (msg->header.cmd == NGM_TEXT_STATUS)) - { /* synchronous response */ - NG_MKRESPONSE(resp, msg, sizeof(struct ng_mesg) + - NG_TEXTRESPONSE, M_NOWAIT); - if (resp == NULL) - error = ENOMEM; - else - { - char *s = resp->data; - sprintf(s, "Card type = <%s>\n" - "This driver considers the link to be %s.\n" - "Use lmcconfig to configure this interface.\n", - sc->dev_desc, (sc->status.oper_status==STATUS_UP) ? "UP" : "DOWN"); - resp->header.arglen = strlen(s) +1; - } - } - else -/* Netgraph should be able to read and write these - * parameters with text-format control messages: - * SSI HSSI T1E1 T3 - * crc crc crc crc - * loop loop loop loop - * clksrc clksrc - * dte dte format format - * synth synth cablen cablen - * cable timeslot scram - * gain - * pulse - * lbo - * Someday I'll implement this... - */ - error = EINVAL; - - /* Handle synchronous response. */ - NG_RESPOND_MSG(error, node, item, resp); - NG_FREE_MSG(msg); - - return error; - } - -/* This is a persistent netgraph node. */ -static int -ng_shutdown(node_p node) - { - /* unless told to really die, bounce back to life */ - if ((node->nd_flags & NG_REALLY_DIE)==0) - node->nd_flags &= ~NG_INVALID; /* bounce back to life */ - - return 0; - } - -/* ng_disconnect is the opposite of this procedure. */ -static int -ng_newhook(node_p node, hook_p hook, const char *name) - { - softc_t *sc = NG_NODE_PRIVATE(node); - - /* Hook name must be 'rawdata'. */ - if (strncmp(name, "rawdata", 7) != 0) return EINVAL; - - /* Is our hook connected? */ - if (sc->ng_hook != NULL) return EBUSY; - - /* Accept the hook. */ - sc->ng_hook = hook; - - return 0; - } - -/* Both ends have accepted their hooks and the links have been made. */ -/* This is the last chance to reject the connection request. */ -static int -ng_connect(hook_p hook) - { - /* Probably not at splnet, force outward queueing. (huh?) */ - NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); - return 0; /* always accept */ - } - -/* Receive data in mbufs from another Netgraph node. */ -/* Transmit an mbuf-chain on the communication link. */ -/* This procedure is very similar to lmc_raw_output(). */ -/* Called from a syscall (user context; no spinlocks). */ -static int -ng_rcvdata(hook_p hook, item_p item) - { - softc_t *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - int error = 0; - struct mbuf *m; - meta_p meta = NULL; - - NGI_GET_M(item, m); - NGI_GET_META(item, meta); - NG_FREE_ITEM(item); - - /* This macro must not store into meta! */ - NG_FREE_META(meta); - - /* Fail if the link is down. */ - if (sc->status.oper_status != STATUS_UP) - { - m_freem(m); - sc->status.cntrs.odiscards++; - if (DRIVER_DEBUG) - printf("%s: ng_rcvdata: tx pkt discarded: link down\n", NAME_UNIT); - return ENETDOWN; - } - - /* ng_rcvdata() ENQUEUEs in a syscall or softirq. */ - /* txintr_setup() DEQUEUEs in a hard interrupt. */ - /* Some BSD QUEUE routines are not interrupt-safe. */ - { - DISABLE_INTR; - if (meta==NULL) - IFQ_ENQUEUE(&sc->ng_sndq, m, error); - else - IFQ_ENQUEUE(&sc->ng_fastq, m, error); - ENABLE_INTR; - } - - if (error==0) - user_interrupt(sc, 0); /* start the transmitter */ - else - { - m_freem(m); - sc->status.cntrs.odiscards++; - if (DRIVER_DEBUG) - printf("%s: ng_rcvdata: IFQ_ENQUEUE() failed; error %d\n", - NAME_UNIT, error); - } - - return error; - } - -/* ng_newhook is the opposite of this procedure, not */ -/* ng_connect, as you might expect from the names. */ -static int -ng_disconnect(hook_p hook) - { - softc_t *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - - /* Disconnect the hook. */ - sc->ng_hook = NULL; - - return 0; - } - -static -struct ng_type ng_type = - { - .version = NG_ABI_VERSION, - .name = NG_LMC_NODE_TYPE, - .mod_event = NULL, - .constructor = ng_constructor, - .rcvmsg = ng_rcvmsg, - .close = NULL, - .shutdown = ng_shutdown, - .newhook = ng_newhook, - .findhook = NULL, - .connect = ng_connect, - .rcvdata = ng_rcvdata, - .disconnect = ng_disconnect, - }; - - -/* Attach to the Netgraph kernel interface (/sys/netgraph). - * It is called once for each physical card during device attach. - * This is effectively ng_constructor. - */ -static int -ng_attach(softc_t *sc) - { - int error; - - /* If this node type is not known to Netgraph then register it. */ - if (ng_type.refs == 0) /* or: if (ng_findtype(&ng_type) == NULL) */ - { - if ((error = ng_newtype(&ng_type))) - { - printf("%s: ng_newtype() failed; error %d\n", NAME_UNIT, error); - return error; - } - } - else - NG_TYPE_REF(&ng_type); - - /* Call the superclass node constructor. */ - if ((error = ng_make_node_common(&ng_type, &sc->ng_node))) - { - NG_TYPE_UNREF(&ng_type); - printf("%s: ng_make_node_common() failed; error %d\n", NAME_UNIT, error); - return error; - } - - /* Associate a name with this netgraph node. */ - if ((error = ng_name_node(sc->ng_node, NAME_UNIT))) - { - NG_NODE_UNREF(sc->ng_node); - NG_TYPE_UNREF(&ng_type); - printf("%s: ng_name_node() failed; error %d\n", NAME_UNIT, error); - return error; - } - - /* Initialize the send queue mutexes. */ - mtx_init(&sc->ng_sndq.ifq_mtx, NAME_UNIT, "sndq", MTX_DEF); - mtx_init(&sc->ng_fastq.ifq_mtx, NAME_UNIT, "fastq", MTX_DEF); - - /* Put a backpointer to the softc in the netgraph node. */ - NG_NODE_SET_PRIVATE(sc->ng_node, sc); - - /* ALTQ output queue initialization. */ - IFQ_SET_MAXLEN(&sc->ng_fastq, SNDQ_MAXLEN); - IFQ_SET_READY(&sc->ng_fastq); - IFQ_SET_MAXLEN(&sc->ng_sndq, SNDQ_MAXLEN); - IFQ_SET_READY(&sc->ng_sndq); - - - return 0; - } - -static void -ng_detach(softc_t *sc) - { - callout_drain(&sc->callout); - mtx_destroy(&sc->ng_sndq.ifq_mtx); - mtx_destroy(&sc->ng_fastq.ifq_mtx); - ng_rmnode_self(sc->ng_node); /* free hook */ - NG_NODE_UNREF(sc->ng_node); /* free node */ - NG_TYPE_UNREF(&ng_type); - } - -#endif /* NETGRAPH */ - -/* The next few procedures initialize the card. */ - -/* Returns 0 on success; error code on failure. */ -static int -startup_card(softc_t *sc) - { - int num_rx_descs, error = 0; - u_int32_t tlp_bus_pbl, tlp_bus_cal, tlp_op_tr; - u_int32_t tlp_cfdd, tlp_cfcs; - u_int32_t tlp_cflt, tlp_csid, tlp_cfit; - - /* Make sure the COMMAND bits are reasonable. */ - tlp_cfcs = READ_PCI_CFG(sc, TLP_CFCS); - tlp_cfcs &= ~TLP_CFCS_MWI_ENABLE; - tlp_cfcs |= TLP_CFCS_BUS_MASTER; - tlp_cfcs |= TLP_CFCS_MEM_ENABLE; - tlp_cfcs |= TLP_CFCS_IO_ENABLE; - tlp_cfcs |= TLP_CFCS_PAR_ERROR; - tlp_cfcs |= TLP_CFCS_SYS_ERROR; - WRITE_PCI_CFG(sc, TLP_CFCS, tlp_cfcs); - - /* Set the LATENCY TIMER to the recommended value, */ - /* and make sure the CACHE LINE SIZE is reasonable. */ - tlp_cfit = READ_PCI_CFG(sc, TLP_CFIT); - tlp_cflt = READ_PCI_CFG(sc, TLP_CFLT); - tlp_cflt &= ~TLP_CFLT_LATENCY; - tlp_cflt |= (tlp_cfit & TLP_CFIT_MAX_LAT)>>16; - /* "prgmbl burst length" and "cache alignment" used below. */ - switch(tlp_cflt & TLP_CFLT_CACHE) - { - case 8: /* 8 bytes per cache line */ - { tlp_bus_pbl = 32; tlp_bus_cal = 1; break; } - case 16: - { tlp_bus_pbl = 32; tlp_bus_cal = 2; break; } - case 32: - { tlp_bus_pbl = 32; tlp_bus_cal = 3; break; } - default: - { - tlp_bus_pbl = 32; tlp_bus_cal = 1; - tlp_cflt &= ~TLP_CFLT_CACHE; - tlp_cflt |= 8; - break; - } - } - WRITE_PCI_CFG(sc, TLP_CFLT, tlp_cflt); - - /* Make sure SNOOZE and SLEEP modes are disabled. */ - tlp_cfdd = READ_PCI_CFG(sc, TLP_CFDD); - tlp_cfdd &= ~TLP_CFDD_SLEEP; - tlp_cfdd &= ~TLP_CFDD_SNOOZE; - WRITE_PCI_CFG(sc, TLP_CFDD, tlp_cfdd); - DELAY(11*1000); /* Tulip wakes up in 10 ms max */ - - /* Software Reset the Tulip chip; stops DMA and Interrupts. */ - /* This does not change the PCI config regs just set above. */ - WRITE_CSR(TLP_BUS_MODE, TLP_BUS_RESET); /* self-clearing */ - DELAY(5); /* Tulip is dead for 50 PCI cycles after reset. */ - - /* Reset the Xilinx Field Programmable Gate Array. */ - reset_xilinx(sc); /* side effect: turns on all four LEDs */ - - /* Configure card-specific stuff (framers, line interfaces, etc.). */ - sc->card->config(sc); - - /* Initializing cards can glitch clocks and upset fifos. */ - /* Reset the FIFOs between the Tulip and Xilinx chips. */ - set_mii16_bits(sc, MII16_FIFO); - clr_mii16_bits(sc, MII16_FIFO); - - /* Initialize the PCI busmode register. */ - /* The PCI bus cycle type "Memory Write and Invalidate" does NOT */ - /* work cleanly in any version of the 21140A, so don't enable it! */ - WRITE_CSR(TLP_BUS_MODE, - (tlp_bus_cal ? TLP_BUS_READ_LINE : 0) | - (tlp_bus_cal ? TLP_BUS_READ_MULT : 0) | - (tlp_bus_pbl<txring, NUM_TX_DESCS))) return error; - WRITE_CSR(TLP_TX_LIST, sc->txring.dma_addr); - if ((error = create_ring(sc, &sc->rxring, num_rx_descs))) return error; - WRITE_CSR(TLP_RX_LIST, sc->rxring.dma_addr); - - /* Initialize the operating mode register. */ - WRITE_CSR(TLP_OP_MODE, TLP_OP_INIT | (tlp_op_tr<txring); - destroy_ring(sc, &sc->rxring); - } - -/* Start the card and attach a kernel interface and line protocol. */ -static int -attach_card(softc_t *sc, const char *intrstr) - { - struct config config; - u_int32_t tlp_cfrv; - u_int16_t mii3; - u_int8_t *ieee; - int i, error = 0; - - /* Start the card. */ - if ((error = startup_card(sc))) return error; - - callout_init(&sc->callout, 0); - - /* Attach a kernel interface. */ -#if NETGRAPH - if ((error = ng_attach(sc))) return error; - sc->flags |= FLAG_NETGRAPH; -#endif - if ((error = lmc_ifnet_attach(sc))) return error; - sc->flags |= FLAG_IFNET; - - /* Attach a line protocol stack. */ - sc->config.line_pkg = PKG_RAWIP; - config = sc->config; /* get current config */ - config.line_pkg = 0; /* select external stack */ - config.line_prot = PROT_C_HDLC; - config.keep_alive = 1; - config_proto(sc, &config); /* reconfigure */ - sc->config = config; /* save new configuration */ - - /* Print interesting hardware-related things. */ - mii3 = read_mii(sc, 3); - tlp_cfrv = READ_PCI_CFG(sc, TLP_CFRV); - printf("%s: PCI rev %d.%d, MII rev %d.%d", NAME_UNIT, - (tlp_cfrv>>4) & 0xF, tlp_cfrv & 0xF, (mii3>>4) & 0xF, mii3 & 0xF); - ieee = (u_int8_t *)sc->status.ieee; - for (i=0; i<3; i++) sc->status.ieee[i] = read_srom(sc, 10+i); - printf(", IEEE addr %02x:%02x:%02x:%02x:%02x:%02x", - ieee[0], ieee[1], ieee[2], ieee[3], ieee[4], ieee[5]); - sc->card->ident(sc); - printf(" %s\n", intrstr); - - /* Print interesting software-related things. */ - printf("%s: Driver rev %d.%d.%d", NAME_UNIT, - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_SUB_VERSION); - printf(", Options %s%s%s%s%s%s%s%s%s\n", - NETGRAPH ? "NETGRAPH " : "", GEN_HDLC ? "GEN_HDLC " : "", - NSPPP ? "SPPP " : "", P2P ? "P2P " : "", - ALTQ_PRESENT ? "ALTQ " : "", NBPFILTER ? "BPF " : "", - DEV_POLL ? "POLL " : "", IOREF_CSR ? "IO_CSR " : "MEM_CSR ", - (BYTE_ORDER == BIG_ENDIAN) ? "BIG_END " : "LITTLE_END "); - - /* Make the local hardware ready. */ - set_status(sc, 1); - - return 0; - } - -/* Detach from the kernel in all ways. */ -static void -detach_card(softc_t *sc) - { - struct config config; - - /* Make the local hardware NOT ready. */ - set_status(sc, 0); - - /* Detach external line protocol stack. */ - if (sc->config.line_pkg != PKG_RAWIP) - { - config = sc->config; - config.line_pkg = PKG_RAWIP; - config_proto(sc, &config); - sc->config = config; - } - - /* Detach kernel interfaces. */ -#if NETGRAPH - if (sc->flags & FLAG_NETGRAPH) - { - IFQ_PURGE(&sc->ng_fastq); - IFQ_PURGE(&sc->ng_sndq); - ng_detach(sc); - sc->flags &= ~FLAG_NETGRAPH; - } -#endif - if (sc->flags & FLAG_IFNET) - { - IFQ_PURGE(&sc->ifp->if_snd); - lmc_ifnet_detach(sc); - sc->flags &= ~FLAG_IFNET; - } - - /* Reset the Tulip chip; stops DMA and Interrupts. */ - shutdown_card(sc); - } - -/* This is the I/O configuration interface for FreeBSD */ - - -static int -fbsd_probe(device_t dev) - { - u_int32_t cfid = pci_read_config(dev, TLP_CFID, 4); - u_int32_t csid = pci_read_config(dev, TLP_CSID, 4); - - /* Looking for a DEC 21140A chip on any Lan Media Corp card. */ - if (cfid != TLP_CFID_TULIP) return ENXIO; - switch (csid) - { - case TLP_CSID_HSSI: - case TLP_CSID_HSSIc: - device_set_desc(dev, HSSI_DESC); - break; - case TLP_CSID_T3: - device_set_desc(dev, T3_DESC); - break; - case TLP_CSID_SSI: - device_set_desc(dev, SSI_DESC); - break; - case TLP_CSID_T1E1: - device_set_desc(dev, T1E1_DESC); - break; - default: - return ENXIO; - } - return 0; - } - -static int -fbsd_detach(device_t dev) - { - softc_t *sc = device_get_softc(dev); - - /* Stop the card and detach from the kernel. */ - detach_card(sc); - - /* Release resources. */ - if (sc->irq_cookie != NULL) - { - bus_teardown_intr(dev, sc->irq_res, sc->irq_cookie); - sc->irq_cookie = NULL; - } - if (sc->irq_res != NULL) - { - bus_release_resource(dev, SYS_RES_IRQ, sc->irq_res_id, sc->irq_res); - sc->irq_res = NULL; - } - if (sc->csr_res != NULL) - { - bus_release_resource(dev, sc->csr_res_type, sc->csr_res_id, sc->csr_res); - sc->csr_res = NULL; - } - - mtx_destroy(&sc->top_mtx); - mtx_destroy(&sc->bottom_mtx); - return 0; /* no error */ - } - -static int -fbsd_shutdown(device_t dev) - { - shutdown_card(device_get_softc(dev)); - return 0; - } - -static int -fbsd_attach(device_t dev) - { - softc_t *sc = device_get_softc(dev); - int error; - - /* READ/WRITE_PCI_CFG need this. */ - sc->dev = dev; - - /* What kind of card are we driving? */ - switch (READ_PCI_CFG(sc, TLP_CSID)) - { - case TLP_CSID_HSSI: - case TLP_CSID_HSSIc: - sc->card = &hssi_card; - break; - case TLP_CSID_T3: - sc->card = &t3_card; - break; - case TLP_CSID_SSI: - sc->card = &ssi_card; - break; - case TLP_CSID_T1E1: - sc->card = &t1_card; - break; - default: - return ENXIO; - } - sc->dev_desc = device_get_desc(dev); - - /* Allocate PCI memory or IO resources to access the Tulip chip CSRs. */ -# if IOREF_CSR - sc->csr_res_id = TLP_CBIO; - sc->csr_res_type = SYS_RES_IOPORT; -# else - sc->csr_res_id = TLP_CBMA; - sc->csr_res_type = SYS_RES_MEMORY; -# endif - sc->csr_res = bus_alloc_resource_any(dev, sc->csr_res_type, &sc->csr_res_id, - RF_ACTIVE); - if (sc->csr_res == NULL) - { - printf("%s: bus_alloc_resource(csr) failed.\n", NAME_UNIT); - return ENXIO; - } - sc->csr_tag = rman_get_bustag(sc->csr_res); - sc->csr_handle = rman_get_bushandle(sc->csr_res); - - /* Allocate PCI interrupt resources for the card. */ - sc->irq_res_id = 0; - sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_res_id, - RF_ACTIVE | RF_SHAREABLE); - if (sc->irq_res == NULL) - { - printf("%s: bus_alloc_resource(irq) failed.\n", NAME_UNIT); - fbsd_detach(dev); - return ENXIO; - } - if ((error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, - NULL, bsd_interrupt, sc, &sc->irq_cookie))) - { - printf("%s: bus_setup_intr() failed; error %d\n", NAME_UNIT, error); - fbsd_detach(dev); - return error; - } - - /* Initialize the top-half and bottom-half locks. */ - mtx_init(&sc->top_mtx, NAME_UNIT, "top half lock", MTX_DEF); - mtx_init(&sc->bottom_mtx, NAME_UNIT, "bottom half lock", MTX_DEF); - - /* Start the card and attach a kernel interface and line protocol. */ - if ((error = attach_card(sc, ""))) detach_card(sc); - gone_in_dev(dev, 12, "lmc(4) driver"); - return error; - } - -static device_method_t methods[] = - { - DEVMETHOD(device_probe, fbsd_probe), - DEVMETHOD(device_attach, fbsd_attach), - DEVMETHOD(device_detach, fbsd_detach), - DEVMETHOD(device_shutdown, fbsd_shutdown), - /* This driver does not suspend and resume. */ - { 0, 0 } - }; - -static driver_t driver = - { - .name = DEVICE_NAME, - .methods = methods, - .size = sizeof(softc_t), - }; - -static devclass_t devclass; - -DRIVER_MODULE(lmc, pci, driver, devclass, 0, 0); -MODULE_VERSION(lmc, 2); -MODULE_DEPEND(lmc, pci, 1, 1, 1); -# if NETGRAPH -MODULE_DEPEND(lmc, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); -# endif -# if NSPPP -MODULE_DEPEND(lmc, sppp, 1, 1, 1); -# endif - - -/* This is the I/O configuration interface for NetBSD. */ - - -/* This is the I/O configuration interface for OpenBSD. */ - - -/* This is the I/O configuration interface for BSD/OS. */ - - Index: sys/modules/Makefile =================================================================== --- sys/modules/Makefile +++ sys/modules/Makefile @@ -221,7 +221,6 @@ libmchain \ linuxkpi \ ${_lio} \ - lmc \ lpt \ mac_biba \ mac_bsdextended \ Index: sys/modules/lmc/Makefile =================================================================== --- sys/modules/lmc/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# $FreeBSD$ - -KMOD = if_lmc -.PATH: ${SRCTOP}/sys/dev/lmc - -SRCS = if_lmc.c if_lmc.h -SRCS += device_if.h bus_if.h pci_if.h -SRCS += opt_inet.h opt_inet6.h -SRCS += opt_netgraph.h -SRCS += opt_bpf.h - -opt_netgraph.h: - echo "#define NETGRAPH 1" > ${.TARGET} - -.include Index: tools/kerneldoc/subsys/Doxyfile-dev_lmc =================================================================== --- tools/kerneldoc/subsys/Doxyfile-dev_lmc +++ /dev/null @@ -1,21 +0,0 @@ -# Doxyfile 1.5.2 - -# $FreeBSD$ - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = "FreeBSD kernel LMC device code" -OUTPUT_DIRECTORY = $(DOXYGEN_DEST_PATH)/dev_lmc/ -EXTRACT_ALL = YES # for undocumented src, no warnings enabled -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = $(DOXYGEN_SRC_PATH)/dev/lmc/ \ - $(NOTREVIEWED) - -GENERATE_TAGFILE = dev_lmc/dev_lmc.tag - -@INCLUDE_PATH = $(DOXYGEN_INCLUDE_PATH) -@INCLUDE = common-Doxyfile - Index: usr.sbin/Makefile =================================================================== --- usr.sbin/Makefile +++ usr.sbin/Makefile @@ -161,7 +161,6 @@ SUBDIR.${MK_NAND}+= nandsim SUBDIR.${MK_NAND}+= nandtool SUBDIR.${MK_NETGRAPH}+= flowctl -SUBDIR.${MK_NETGRAPH}+= lmcconfig SUBDIR.${MK_NETGRAPH}+= ngctl SUBDIR.${MK_NETGRAPH}+= nghook SUBDIR.${MK_NIS}+= rpc.yppasswdd Index: usr.sbin/lmcconfig/Makefile =================================================================== --- usr.sbin/lmcconfig/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD$ - -PROG= lmcconfig -MAN= lmcconfig.8 - -LIBADD= netgraph - -WARNS?= 3 - -.include Index: usr.sbin/lmcconfig/Makefile.depend =================================================================== --- usr.sbin/lmcconfig/Makefile.depend +++ /dev/null @@ -1,18 +0,0 @@ -# $FreeBSD$ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - gnu/lib/csu \ - include \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - lib/libcompiler_rt \ - lib/libnetgraph \ - - -.include - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif Index: usr.sbin/lmcconfig/lmcconfig.8 =================================================================== --- usr.sbin/lmcconfig/lmcconfig.8 +++ /dev/null @@ -1,723 +0,0 @@ -.\" 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. -.\" -.\" $FreeBSD$ -.\" -.Dd October 3, 2005 -.Dt LMCCONFIG 8 -.Os -.Sh NAME -.Nm lmcconfig -.Nd configuration program for -.Tn SBE -(formerly -.Tn LMC ) -wide-area network interface cards -.Sh SYNOPSIS -.Nm -.Ar interface -.Op Fl abBcCdDeEfhLmMpPrsStTuwxXyYzZ? -.Nm -.Ar interface -.Fl 1 -.Op Fl aABceEfFgiIlLpPstTuUxX -.Nm -.Ar interface -.Fl 3 -.Op Fl aABcefFlLsSv -.Sh DESCRIPTION -The -.Nm -utility -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 -The -.Nm -utility -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 -.Dq Li 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 -.Dq Li 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 -.Ss Commands for all cards -The following parameters apply to more than one card type. -.Bl -tag -width indent -.It Fl a Ar number -Set Transmitter clock source to -.Ar number . -.Pp -.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). -.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 -.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 -.Fx 5.4 -and later. -.It Fl h -Print help (usage message). -.It Fl i -Set interface name (e.g.\& -.Dq Li lmc0 ) . -.It Fl L Ar number -Set loopback mode to -.Ar number . -.Pp -.Bl -column "99" "payload" "inward thru drvrs/rcvrsxxx" "HSSI, SSI" -offset 1m -compact -.It "1" Ta "none" Ta "default" Ta \& -.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 . -.Pp -.Bl -column "9" -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 -.Pp -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 -.Nm -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 -.Ar 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 \[em] see the -.Sx 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 \[em] bypass line protocol code. -.It Fl X -Select line protocol code rather than RAWIP mode. -.It Fl y -Disable SPPP keep-alive packets. -.It Fl Y -Enable SPPP keep-alive packets. -.It Fl z -Set SPPP line protocol to Cisco-HDLC. -.It Fl Z -Set SPPP line protocol to PPP. -.It Fl ?\& -Print help (usage message). -.El -.Ss Commands for T1E1 cards -The following parameters apply to the T1E1 card type: -.Bl -tag -width indent -.It Fl a Sm Cm y | a | b Sm -Stop sending alarm signal. -.Pp -.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 -.Pp -Red alarm, also known as AIS (Alarm Indication Signal), -and Blue alarm are identical in T1. -.It Fl A Sm Cm y | a | b Sm -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 \[em] see the -.Sx EXAMPLES -section. -.It Fl e Ar number -Set the framing format to -.Ar number : -.Pp -.Bl -column "99" -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. -The -.Ar number -argument -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 : -.Pp -.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 -.Pp -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 \[em] see the -.Sx EXAMPLES -section. -.It Fl t -Stop sending test pattern. -.It Fl T Ar number -Start sending test pattern -.Ar number : -.Pp -.Bl -column "99" -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 : -.Pp -.Bl -column "99" -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 : -.Pp -.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)" Ta \& -.El -.Pp -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 -.Ss Commands for T3 cards -The following parameters apply to the T3 card type: -.Bl -tag -width indent -.It Fl a Sm Cm y | a | b | i Sm -Stop sending alarm signal. -.Pp -.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 Sm Cm y | a | b | i Sm -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 \[em] see the -.Sx EXAMPLES -section. -.It Fl e Ar number -Set the framing format to -.Ar number : -.Pp -.Bl -column "100" -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 \[em] see the -.Sx EXAMPLES -section. -.It Fl S Ar number -Set payload scrambler polynomial to -.Ar number : -.Pp -.Bl -column "9" -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. -A -.Ar number -is written to a Digital-Analog Converter (DAC) which connects -to a Voltage Controlled Crystal Oscillator (VCXO). -.El -.Ss Event Counters -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 ".Va underruns" -.It Va ibytes -Bytes received in packets with good ending status. -.It Va obytes -Bytes transmitted. -.It Va ipackets -Packets received with good ending status. -.It Va opackets -Packets transmitted. -.It Va ierrors -Packets received with bad ending status. -.It Va oerrors -Packets transmitted with bad ending status. -.It Va idiscards -Packets received but discarded because -the input queue was full or the interface was down. -.It Va odiscards -Packets presented for transmission but discarded because -the output queue was full or the interface was down. -.It Va 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 Va 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 Va 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 Va missed -Packets that are missed because the receiver is stopped. -.It Va overruns -Packets that are missed because the receiver -had no DMA descriptors available. -.It Va fdl_pkts -Packets received on the T1 Facility Data Link. -.It Va crc-errs -Cyclic Redundancy Checksum errors detected by the CRC-6 in -T1 Extended SuperFrames (ESF) or the CRC-4 in E1 frames. -.It Va 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 Va frm-errs -T1 or T3 bit errors in the frame alignment signal. -.It Va febe-errs -Far End Block Errors: -T1 or T3 bit errors detected by the device at the far end of the link. -.It Va par-errs -T3 bit errors detected by the hop-by-hop parity mechanism. -.It Va cpar-errs -T3 bit errors detected by the end-to-end parity mechanism. -.It Va mfrm-errs -T3 bit errors in the multi-frame alignment signal. -.El -.Ss Transmit Speed -The hardware counts transmit clocks divided by 2048. -The software computes -.Dq "Tx speed" -from this (see -.Sx 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 -.Dq "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 -.Dq "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 is 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. -.Sh EXAMPLES -When -.Dq Li lmc0 -is a T1E1 card, -.Dq Li lmcconfig lmc0 -generates the following output: -.Bd -literal -offset 2m -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 -.Pp -When -.Dq Li lmc0 -is a T1E1 card, -.Dq Li "lmcconfig lmc0 -1 -d" -generates the following output: -.Bd -literal -offset 2m -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 -.Sh DIAGNOSTICS -Messages indicating the specified interface does not exist, or -the user is not privileged and tried to alter an interface's configuration. -.Sh SEE ALSO -.Xr ioctl 2 , -.Xr lmc 4 , -.Xr netgraph 4 , -.Xr ifconfig 8 , -.Xr ifnet 9 -.Pp -.Pa http://www.sbei.com/ -.Sh HISTORY -This is a total rewrite of the program -.Nm lmcctl -by -.An Andrew Stanley-Jones . -.Sh AUTHORS -.An David Boggs Aq Mt boggs@boggs.palo-alto.ca.us Index: usr.sbin/lmcconfig/lmcconfig.c =================================================================== --- usr.sbin/lmcconfig/lmcconfig.c +++ /dev/null @@ -1,2553 +0,0 @@ -/* - * First author: Michael Graff. - * Copyright (c) 1997-2000 Lan Media Corp. (www.lanmedia.com). - * All rights reserved. - * - * Second author: Andrew Stanley-Jones. - * Copyright (c) 2000-2002 SBE Corp. (www.sbei.com). - * All rights reserved. - * - * Third author: David Boggs. - * Copyright (c) 2002-2004 David Boggs. (boggs@boggs.palo-alto.ca.us). - * All rights reserved. - * - * BSD License: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * GNU General Public License: - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Description: - * - * This program configures the Unix/Linux device driver for SBE Corp's - * wanADAPT and wanPMC series of Wide Area Network Interface Cards. - * There is a man page for this program; go find it. - * - * If Netgraph is present (FreeBSD only): - * cc -o lmcconfig -l netgraph -D NETGRAPH lmcconfig.c - * If Netgraph is NOT present: - * cc -o lmcconfig lmcconfig.c - * Install the executable program in /usr/local/sbin/lmcconfig. - * - * $FreeBSD$ - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(NETGRAPH) -# include -#endif -#include - -#include - -/* program global variables */ -char * progname; /* name of this program */ -char * ifname; /* interface name */ -int fdcs; /* ifnet File Desc or ng Ctl Socket */ -struct status status; /* card status (read only) */ -struct config config; /* card configuration (read/write) */ -int netgraph = 0; /* non-zero if netgraph present */ -int summary = 0; /* print summary at end */ -int update = 0; /* update driver config */ -int verbose = 0; /* verbose output */ -u_int8_t checksum; /* gate array ucode file checksum */ - -/* Functions currently unused. Keep compiler happy and provide prototypes. */ -void ioctl_snmp_loop(u_int32_t); -void init_srom(int); - -static void -usage(void) -{ - fprintf(stderr, "Usage: %s interface [-abBcCdDeEfhiLmMpPsStTuUvVwWxXyYzZ?]\n", progname); - fprintf(stderr, "or\n"); - fprintf(stderr, "Usage: %s interface -1 [-aABcdeEfFgiIlLpPstTuUvxX]\n", progname); - fprintf(stderr, "or\n"); - fprintf(stderr, "Usage: %s interface -3 [-aABcdefFlLsSvV]\n\n", progname); - fprintf(stderr, "\tInterface is the interface name, e.g. '%s'\n", ifname); -#if defined(NETGRAPH) - fprintf(stderr, "\tIf interface name ends with ':' then use netgraph\n"); -#endif - fprintf(stderr, "\t-1 following parameters apply to T1E1 cards\n"); - fprintf(stderr, "\t-3 following parameters apply to T3 cards\n"); - fprintf(stderr, "\t-a Set Tx clock source, where:\n"); - fprintf(stderr, "\t 1:modem Tx clk 2:int src 3:modem Rx Clk 4:ext conn\n"); - fprintf(stderr, "\t-b Read and print bios rom addrs 0-255\n"); - fprintf(stderr, "\t-B Write bios rom with address pattern\n"); - fprintf(stderr, "\t-c Set 16-bit CRC (default)\n"); - fprintf(stderr, "\t-C Set 32-bit CRC\n"); - fprintf(stderr, "\t-d Clear driver DEBUG flag\n"); - fprintf(stderr, "\t-D Set driver DEBUG flag (more log msgs)\n"); - fprintf(stderr, "\t-e Set DTE mode (default)\n"); - fprintf(stderr, "\t-E Set DCE mode\n"); - fprintf(stderr, "\t-f Set synth osc freq in bits/sec\n"); - fprintf(stderr, "\t-F Set SPPP line protocol to Frame-Relay\n"); - fprintf(stderr, "\t-h Help: this usage message\n"); - fprintf(stderr, "\t-i Interface name (eg, lmc0)\n"); - fprintf(stderr, "\t-L Set loopback: 1:none 2:payload 3:line 4:other\n"); - fprintf(stderr, "\t 5:inward 6:dual 16:Tulip 17:pins 18:LA/LL 19:LB/RL\n"); - fprintf(stderr, "\t-m Read and print MII regs\n"); - fprintf(stderr, "\t-M Write MII reg\n"); - fprintf(stderr, "\t-p Read and print PCI config regs\n"); - fprintf(stderr, "\t-P Write PCI config reg\n"); - fprintf(stderr, "\t-s Read and print Tulip SROM\n"); - fprintf(stderr, "\t-S Initialize Tulip SROM\n"); - fprintf(stderr, "\t-t Read and print Tulip Control/Status regs\n"); - fprintf(stderr, "\t-T Write Tulip Control/status reg\n"); - fprintf(stderr, "\t-u Reset event counters\n"); - fprintf(stderr, "\t-U Reset gate array\n"); - fprintf(stderr, "\t-v Set verbose printout mode\n"); - fprintf(stderr, "\t-V Print card configuration\n"); - fprintf(stderr, "\t-w Load gate array from ROM\n"); - fprintf(stderr, "\t-W Load gate array from file\n"); - fprintf(stderr, "\t-x select RAWIP mode and bypass line protocols\n"); - fprintf(stderr, "\t-X Select line protocols: SPPP, P2P or HDLC\n"); - fprintf(stderr, "\t-y disable SPPP keep-alive packets\n"); - fprintf(stderr, "\t-Y enable SPPP keep-alive packets\n"); - fprintf(stderr, "\t-z Set SPPP line protocol to Cisco-HDLC\n"); - fprintf(stderr, "\t-Z Set SPPP line protocol to PPP\n"); - - fprintf(stderr, "The -1 switch precedes T1/E1 commands.\n"); - fprintf(stderr, "\t-a Stop sending Yellow|Blue|AIS signal\n"); - fprintf(stderr, "\t-A Start sending Yellow|Blue|AIS signal\n"); - fprintf(stderr, "\t-B Send BOP msg 25 times\n"); - fprintf(stderr, "\t-c Set cable length in meters\n"); - fprintf(stderr, "\t-d Print status of T1 DSU/CSU\n"); - fprintf(stderr, "\t-e Set framing format, where:\n"); - fprintf(stderr, "\t 27:T1-ESF 9:T1-SF 0:E1-FAS 8:E1-FAS+CRC\n"); - fprintf(stderr, "\t 16:E1-FAS+CAS 24:E1-FAS+CRC+CAS 32:E1-NO-FRAMING\n"); - fprintf(stderr, "\t-E <32-bit hex number> 1 activates a channel and 0 deactivates it.\n"); - fprintf(stderr, "\t Use this to config a link in fractional T1/E1 mode\n"); - fprintf(stderr, "\t-f Read and print Framer/LIU registers\n"); - fprintf(stderr, "\t-F Write Framer/LIU register\n"); - fprintf(stderr, "\t-g Set receiver gain, where:\n"); - fprintf(stderr, "\t 0:short range 1:medium range\n"); - fprintf(stderr, "\t 2:long range 3:extended range\n"); - fprintf(stderr, "\t 4:auto-set based on cable length\n"); - fprintf(stderr, "\t-i Send 'CSU Loop Down' inband msg\n"); - fprintf(stderr, "\t-I Send 'CSU Loop Up' inband msg\n"); - fprintf(stderr, "\t-l Send 'Line Loop Down' BOP msg\n"); - fprintf(stderr, "\t-L Send 'Line Loop Up' BOP msg\n"); - fprintf(stderr, "\t-p Send 'Payload Loop Down' BOP msg\n"); - fprintf(stderr, "\t-P Send 'Payload Loop Up' BOP msg\n"); - fprintf(stderr, "\t-s Print status of T1 DSU/CSU\n"); - fprintf(stderr, "\t-t Stop sending test pattern\n"); - fprintf(stderr, "\t-T Start sending test pattern, where:\n"); - fprintf(stderr, "\t 0:unframed 2^11 1:unframed 2^15\n"); - fprintf(stderr, "\t 2:unframed 2^20 3:unframed 2^23\n"); - fprintf(stderr, "\t 4:unframed 2^11 w/ZS 5:unframed 2^15 w/ZS\n"); - fprintf(stderr, "\t 6:unframed QRSS 7:unframed 2^23 w/ZS\n"); - fprintf(stderr, "\t 8: framed 2^11 9: framed 2^15\n"); - fprintf(stderr, "\t 10: framed 2^20 11: framed 2^23\n"); - fprintf(stderr, "\t 12: framed 2^11 w/ZS 13: framed 2^15 w/ZS\n"); - fprintf(stderr, "\t 14: framed QRSS 15: framed 2^23 w/ZS\n"); - fprintf(stderr, "\t-u Set transmitter pulse shape, where:\n"); - fprintf(stderr, "\t 0:T1-DSX 0-40m 1:T1-DSX 40-80m\n"); - fprintf(stderr, "\t 2:T1-DSX 80-120m 3:T1-DSX 120-160m\n"); - fprintf(stderr, "\t 4:T1-DSX 160-200m 5:E1-G.703 75ohm coax\n"); - fprintf(stderr, "\t 6:E1-G.703 120ohm TP 7:T1-CSU Long range\n"); - fprintf(stderr, "\t 8:auto-set based on cable length (T1 only)\n"); - fprintf(stderr, "\t-U Set line build out where:\n"); - fprintf(stderr, "\t 0:0dB 1:7.5dB 2:15dB 3:22.5dB\n"); - fprintf(stderr, "\t 4:auto-set based on cable length\n"); - fprintf(stderr, "\t-v Set verbose printout mode\n"); - fprintf(stderr, "\t-x disable Transmitter outputs\n"); - fprintf(stderr, "\t-X enable Transmitter outputs\n"); - - fprintf(stderr, "The -3 switch precedes T3 commands.\n"); - fprintf(stderr, "\t-a Stop sending Yellow|Blue|AIS|Idle signal\n"); - fprintf(stderr, "\t-A Start sending Yellow|Blue|AIS|Idle signal\n"); - fprintf(stderr, "\t-B Send BOP msg 10 times\n"); - fprintf(stderr, "\t-c Set cable length in meters\n"); - fprintf(stderr, "\t-d Print status of T3 DSU/CSU\n"); - fprintf(stderr, "\t-e Set T3 frame format, where:\n"); - fprintf(stderr, "\t 100:C-Bit Parity 101:M13\n"); - fprintf(stderr, "\t-f Read and print Framer registers\n"); - fprintf(stderr, "\t-F Write Framer register\n"); - fprintf(stderr, "\t-l Send 'Line Loop Down' BOP msg\n"); - fprintf(stderr, "\t-L Send 'Line Loop Up' BOP msg\n"); - fprintf(stderr, "\t-s Print status of T3 DSU/CSU\n"); - fprintf(stderr, "\t-S Set DS3 scrambler mode, where:\n"); - fprintf(stderr, "\t 1:OFF 2:DigitalLink|Kentrox 3:Larse\n"); - fprintf(stderr, "\t-v Set verbose printout mode\n"); - fprintf(stderr, "\t-V Write to T3 VCXO freq control DAC\n"); -} - -static void -call_driver(unsigned long cmd, struct iohdr *iohdr) -{ - int error = 0; - - strlcpy(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); - } -} - -static 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; -} - -static 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); -} - -static 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; -} - -static 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); -} - -static 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; -} - -static 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); -} - -static 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; -} - -static 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); -} - -static 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; -} - -static 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); -} - -static 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; -} - -static 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); -} - -static 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); -} - -static 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); -} - -static void -reset_xilinx(void) -{ - struct ioctl ioctl; - - ioctl.iohdr.direction = DIR_IOWR; - ioctl.iohdr.length = sizeof(struct ioctl); - ioctl.cmd = IOCTL_XILINX_RESET; - - call_driver(LMCIOCTL, &ioctl.iohdr); -} - -static void -load_xilinx_from_rom(void) -{ - struct ioctl ioctl; - - ioctl.iohdr.direction = DIR_IOWR; - ioctl.iohdr.length = sizeof(struct ioctl); - ioctl.cmd = IOCTL_XILINX_ROM; - - call_driver(LMCIOCTL, &ioctl.iohdr); -} - -static 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); -} - -static 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); -} - -static void -ioctl_reset_cntrs(void) -{ - struct ioctl ioctl; - - ioctl.iohdr.direction = DIR_IOWR; - ioctl.iohdr.length = sizeof(struct ioctl); - ioctl.cmd = IOCTL_RESET_CNTRS; - - call_driver(LMCIOCTL, &ioctl.iohdr); -} - -static void -ioctl_read_config(void) -{ - config.iohdr.direction = DIR_IOWR; - config.iohdr.length = sizeof(struct config); - - call_driver(LMCIOCGCFG, &config.iohdr); -} - -static void -ioctl_write_config(void) -{ - config.iohdr.direction = DIR_IOW; - config.iohdr.length = sizeof(struct config); - - call_driver(LMCIOCSCFG, &config.iohdr); -} - -static void -ioctl_read_status(void) -{ - status.iohdr.direction = DIR_IOWR; - status.iohdr.length = sizeof(struct status); - - call_driver(LMCIOCGSTAT, &status.iohdr); -} - -static void -print_card_name(void) -{ - printf("Card name:\t\t%s\n", ifname); -} - -static void -print_card_type(void) -{ - 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; - } -} - -static void -print_status(void) -{ - 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); -} - -static void -print_tx_speed(void) -{ - printf("Tx Speed:\t\t%u\n", status.tx_speed); -} - -static void -print_debug(void) -{ - if (config.debug != 0) - printf("Debug:\t\t\t%s\n", "On"); -} - -static void -print_line_prot(void) -{ - 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); -} - -static void -print_crc_len(void) -{ - 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); -} - -static void -print_loop_back(void) -{ - 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; - } -} - -static void -print_tx_clk_src(void) -{ - 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; - } -} - -static void -print_format(void) -{ - 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; - } -} - -static void -print_dte_dce(void) -{ - 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; - } -} - -static void -print_synth_freq(void) -{ - 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); -} - -static void -synth_freq(unsigned long target) -{ - unsigned int n, m, v, x, r; - double Fout, Fvco, Ftarg; - double newdiff, olddiff; - double bestF=0.0, bestV=0.0; - unsigned prescale = (target < 50000) ? 9:4; - - Ftarg = target< SYNTH_FMAX) continue; - Fout = Fvco / (1<<(x+r)); - if (Fout >= Ftarg) - newdiff = Fout - Ftarg; - else - newdiff = Ftarg - Fout; - if (bestF >= Ftarg) - olddiff = bestF - Ftarg; - else - olddiff = Ftarg - bestF; - if ((newdiff < olddiff) || - ((newdiff == olddiff) && (Fvco < bestV))) - { - config.synth.n = n; - config.synth.m = m; - config.synth.v = v; - config.synth.x = x; - config.synth.r = r; - config.synth.prescale = prescale; - bestF = Fout; - bestV = Fvco; - } - } -#if 0 - printf("Fbest=%.0f, Ftarg=%u, Fout=%.0f\n", bestF>>prescale, target, bestF); - printf("N=%u, M=%u, V=%u, X=%u, R=%u\n", config.synth.n, - config.synth.m, config.synth.v, config.synth.x, config.synth.r); -#endif -} - -static void -print_cable_len(void) -{ - printf("Cable length:\t\t%d meters\n", config.cable_len); -} - -static void -print_cable_type(void) -{ - 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]); -} - -static void -print_time_slots(void) -{ - printf("TimeSlot [31-0]:\t0x%08X\n", config.time_slots); -} - -static void -print_scrambler(void) -{ - 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); -} - -static 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); - return 64.0; -} - -static void -print_rx_gain(void) -{ - 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)); -} - -static void -print_tx_lbo(void) -{ - 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; -} - -static void -print_tx_pulse(void) -{ - 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; -} - -static void -print_ssi_sigs(void) -{ - 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); -} - -static void -print_hssi_sigs(void) -{ - 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); -} - -static void -print_events(void) -{ - const char *reset_time; - time_t now; - - now = time(NULL); - printf("Current time:\t\t%s", ctime(&now)); - if (status.cntrs.reset_time.tv_sec < 1000) - reset_time = "Never\n"; - else - reset_time = ctime(&status.cntrs.reset_time.tv_sec); - printf("Cntrs reset:\t\t%s", reset_time); - - if (status.cntrs.ibytes) printf("Rx bytes:\t\t%ju\n", (uintmax_t)status.cntrs.ibytes); - if (status.cntrs.obytes) printf("Tx bytes:\t\t%ju\n", (uintmax_t)status.cntrs.obytes); - if (status.cntrs.ipackets) printf("Rx packets:\t\t%ju\n", (uintmax_t)status.cntrs.ipackets); - if (status.cntrs.opackets) printf("Tx packets:\t\t%ju\n", (uintmax_t)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); - } -} - -static void -print_summary(void) -{ - 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; - } - } -} - -static 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"; - } -} - -static void -print_t3_snmp(void) -{ - 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"); -} - -static void -print_t3_dsu(void) -{ - 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(); -} - -static 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 */ - -static 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; - } -} - -static 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"; - } -} - -static 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"); -} - -static void -print_t1_snmp(void) -{ - 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); - } -} - -static void -print_t1_dsu(void) -{ - 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(); -} - -static 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 */ -static 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; - int c; - - if (verbose) printf("Load firmware from file %s...\n", name); - if ((f = fopen(name, "r")) == NULL) - { - perror("Failed to open file"); - exit(1); - } - - ucode = (char *)malloc(8192); bzero(ucode, 8192); - - c = fgetc(f); - if (c == 'X') - { /* Xilinx raw bits file (foo.rbt) */ - /* skip seven lines of boiler plate */ - for (i=0; i<7;) if ((c=fgetc(f))=='\n') i++; - /* build a dense bit array */ - i = length = 0; - while ((c=fgetc(f))!=EOF) - { /* LSB first */ - if (c=='1') ucode[length] |= 1<>= 1) - crc = (crc >> 1) ^ (((crc ^ data) & 1) ? poly : 0); - - return crc; -} - -/* 8-bit CRC calculated left-to-right over 16-bit words */ -static 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); -}