1/*-
2 * $NetBSD: lmcconfig.c,v 1.10 2006/05/25 00:16:48 christos Exp $
3 *
4 * First author: Michael Graff.
5 * Copyright (c) 1997-2000 Lan Media Corp.
6 * All rights reserved.
7 *
8 * Second author: Andrew Stanley-Jones.
9 * Copyright (c) 2000-2002 SBE Corp.
10 * All rights reserved.
11 *
12 * Third author: David Boggs.
13 * Copyright (c) 2002-2006 David Boggs.
14 * All rights reserved.
15 *
16 * BSD License:
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * GNU General Public License:
40 *
41 * This program is free software; you can redistribute it and/or modify it
42 * under the terms of the GNU General Public License as published by the Free
43 * Software Foundation; either version 2 of the License, or (at your option)
44 * any later version.
45 *
46 * This program is distributed in the hope that it will be useful, but WITHOUT
47 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
48 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
49 * more details.
50 *
51 * You should have received a copy of the GNU General Public License along with
52 * this program; if not, write to the Free Software Foundation, Inc., 59
53 * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
54 *
55 * Description:
56 *
57 * This program configures the Unix/Linux device driver
58 *  for LMC wide area network interface cards.
59 * A complete man page for this program exists.
60 * This is a total rewrite of the program 'lmcctl' by
61 *  Michael Graff, Rob Braun and Andrew Stanley-Jones.
62 *
63 * If Netgraph is present (FreeBSD only):
64 *    cc -o lmcconfig -l netgraph -D NETGRAPH lmcconfig.c
65 * If Netgraph is NOT present:
66 *    cc -o lmcconfig lmcconfig.c
67 */
68
69#include <errno.h>
70#include <stdio.h>
71#include <stdlib.h>
72#include <string.h>
73#include <time.h>
74#include <unistd.h>
75#if defined(NETGRAPH)
76# include <netgraph.h>
77#endif
78#include <sys/cdefs.h>
79#include <sys/ioctl.h>
80#include <sys/param.h>
81#include <sys/socket.h>
82#include <sys/types.h>
83#include <sys/time.h>
84#include <net/if.h>
85/* and finally... */
86# include "if_lmc.h"
87
88/* procedure prototypes */
89
90void usage(void);
91
92void call_driver(unsigned long, struct iohdr *);
93
94u_int32_t read_pci_config(u_int8_t);
95void     write_pci_config(u_int8_t, u_int32_t);
96u_int32_t read_csr(u_int8_t);
97void     write_csr(u_int8_t, u_int32_t);
98u_int16_t read_srom(u_int8_t);
99void     write_srom(u_int8_t, u_int16_t);
100u_int8_t  read_bios_rom(u_int32_t);
101void     write_bios_rom(u_int32_t, u_int8_t);
102u_int16_t read_mii(u_int8_t);
103void     write_mii(u_int8_t, u_int16_t);
104u_int8_t  read_framer(u_int16_t);
105void     write_framer(u_int16_t, u_int8_t);
106
107void write_synth(struct synth);
108void write_dac(u_int16_t);
109
110void reset_xilinx(void);
111void load_xilinx_from_rom(void);
112void load_xilinx_from_file(char *, int);
113
114void ioctl_snmp_send(u_int32_t);
115void ioctl_snmp_loop(u_int32_t);
116void ioctl_reset_cntrs(void);
117void ioctl_read_config(void);
118void ioctl_write_config(void);
119void ioctl_read_status(void);
120
121void print_card_name(void);
122void print_card_type(void);
123void print_status(void);
124void print_tx_speed(void);
125void print_debug(void);
126void print_line_prot(void);
127void print_crc_len(void);
128void print_loop_back(int);
129void print_tx_clk_src(void);
130void print_format(void);
131void print_dte_dce(void);
132void print_synth_freq(void);
133void synth_freq(unsigned long);
134void print_cable_len(void);
135void print_cable_type(void);
136void print_time_slots(void);
137void print_scrambler(void);
138double vga_dbs(u_int8_t);
139void print_rx_gain_max(void);
140void print_tx_lbo(void);
141void print_tx_pulse(int);
142void print_ssi_sigs(void);
143void print_hssi_sigs(void);
144void print_events(void);
145void print_summary(void);
146
147const char *print_t3_bop(int);
148void print_t3_snmp(void);
149void print_t3_dsu(void);
150void t3_cmd(int, char **);
151
152const char *print_t1_bop(int);
153void print_t1_test_pattern(int);
154void print_t1_far_report(int);
155void print_t1_snmp(void);
156void print_t1_dsu(void);
157void t1_cmd(int, char **);
158
159unsigned char read_hex(FILE *);
160void load_xilinx(char *);
161
162u_int32_t crc32(u_int8_t *, int);
163u_int8_t  crc8(u_int16_t *, int);
164
165void main_cmd(int, char **);
166/* int main(int, char **); */
167
168/* program global variables */
169
170char *		progname;	/* name of this program */
171const char *	ifname;		/* interface name */
172int		fdcs;		/* ifnet File Desc or ng Ctl Socket */
173struct status	status;		/* card status (read only) */
174struct config	config;		/* card configuration (read/write) */
175int		netgraph = 0;	/* non-zero if netgraph present */
176int		summary  = 0;	/* print summary at end */
177int		update   = 0;	/* update driver config */
178int		verbose  = 0;	/* verbose output */
179unsigned int	waittime = 0;	/* time in seconds between status prints */
180u_int8_t	checksum;	/* gate array ucode file checksum */
181
182void usage()
183  {
184  fprintf(stderr, "Usage: %s interface [-abBcCdDeEfgGhiLmMpPsStTuUvVwxXyY?]\n", progname);
185  fprintf(stderr, "or\n");
186  fprintf(stderr, "Usage: %s interface -1 [-aABcdeEfFgiIlLpPstTuUvxX]\n", progname);
187  fprintf(stderr, "or\n");
188  fprintf(stderr, "Usage: %s interface -3 [-aABcdefFlLsSvV]\n\n", progname);
189  fprintf(stderr, "\tInterface is the interface name, e.g. '%s'\n", ifname);
190#if defined(NETGRAPH)
191  fprintf(stderr, "\tIf interface name ends with ':' then use netgraph\n");
192#endif
193  fprintf(stderr, "\t-1 following parameters apply to T1E1 cards\n");
194  fprintf(stderr, "\t-3 following parameters apply to T3 cards\n");
195  fprintf(stderr, "\t-a <number> Set Tx clock source, where:\n");
196  fprintf(stderr, "\t   1:modem Tx clk 2:xtal osc 3:modem Rx Clk 4:ext conn\n");
197  fprintf(stderr, "\t-b Read and print bios rom addrs 0-255\n");
198  fprintf(stderr, "\t-B Write bios rom with address pattern\n");
199  fprintf(stderr, "\t-c Set 16-bit CRC (default)\n");
200  fprintf(stderr, "\t-C Set 32-bit CRC\n");
201  fprintf(stderr, "\t-d Clear driver DEBUG flag\n");
202  fprintf(stderr, "\t-D Set driver DEBUG flag (more log msgs)\n");
203  fprintf(stderr, "\t-e Set DTE mode (default)\n");
204  fprintf(stderr, "\t-E Set DCE mode\n");
205  fprintf(stderr, "\t-f <number> Set synth osc freq in bits/sec\n");
206  fprintf(stderr, "\t-g Load gate array from ROM\n");
207  fprintf(stderr, "\t-G <filename> Load gate array from file\n");
208  fprintf(stderr, "\t-h Help: this usage message\n");
209  fprintf(stderr, "\t-i Interface name (eg, lmc0)\n");
210  fprintf(stderr, "\t-L <number> Set loopback, where:\n");
211  fprintf(stderr, "\t   1:none 2:payload 3:line 4:other 5: inward\n");
212  fprintf(stderr, "\t   6:dual 16:Tulip 17:pins 18:LA/LL 19:LB/RL\n");
213  fprintf(stderr, "\t-m Read and print MII regs\n");
214  fprintf(stderr, "\t-M <addr> <data> Write MII reg\n");
215  fprintf(stderr, "\t-p Read and print PCI config regs\n");
216  fprintf(stderr, "\t-P <addr> <data> Write PCI config reg\n");
217  fprintf(stderr, "\t-s Read and print Tulip SROM\n");
218  fprintf(stderr, "\t-S <number> Initialize Tulip SROM\n");
219  fprintf(stderr, "\t-t Read and print Tulip Control/Status regs\n");
220  fprintf(stderr, "\t-T <addr> <data> Write Tulip Control/status reg\n");
221  fprintf(stderr, "\t-u Reset event counters\n");
222  fprintf(stderr, "\t-U Reset gate array\n");
223  fprintf(stderr, "\t-v Set verbose printout mode\n");
224  fprintf(stderr, "\t-V Print card configuration\n");
225  fprintf(stderr, "\t-w <number> Seconds between status prints\n");
226  fprintf(stderr, "\t-x <number> Set line protocol where:\n");
227  fprintf(stderr, "\t   1:RAW-IP 2:PPP 3:C-HDLC 4:FRM-RLY 5:RAW-ETH\n");
228  fprintf(stderr, "\t-X <number> Set line package where:\n");
229  fprintf(stderr, "\t   1:RAW-IP 2:SPPP 3:P2P 4:GEN-HDLC 5:SYNC-PPP\n");
230  fprintf(stderr, "\t-y Disable SPPP keep-alive packets\n");
231  fprintf(stderr, "\t-Y  Enable SPPP keep-alive packets\n");
232
233  fprintf(stderr, "The -1 switch precedes T1/E1 commands.\n");
234  fprintf(stderr, "\t-a <y|b|a> Stop  sending Yellow|Blue|AIS signal\n");
235  fprintf(stderr, "\t-A <y|b|a> Start sending Yellow|Blue}AIS signal\n");
236  fprintf(stderr, "\t-B <number> Send BOP msg 25 times\n");
237  fprintf(stderr, "\t-c <number> Set cable length in meters\n");
238  fprintf(stderr, "\t-d Print status of T1 DSU/CSU\n");
239  fprintf(stderr, "\t-e <number> Set framing format, where:\n");
240  fprintf(stderr, "\t   27:T1-ESF 9:T1-SF 0:E1-FAS 8:E1-FAS+CRC\n");
241  fprintf(stderr, "\t   16:E1-FAS+CAS 24:E1-FAS+CRC+CAS 32:E1-NO-FRAMING\n");
242  fprintf(stderr, "\t-E <32-bit hex number> 1 activates a channel and 0 deactivates it.\n");
243  fprintf(stderr, "\t   Use this to config a link in fractional T1/E1 mode\n");
244  fprintf(stderr, "\t-f Read and print Framer/LIU registers\n");
245  fprintf(stderr, "\t-F <addr> <data> Write Framer/LIU register\n");
246  fprintf(stderr, "\t-g <number> Set receiver gain, where:\n");
247  fprintf(stderr, "\t   0:short range  1:medium range\n");
248  fprintf(stderr, "\t   2:long range   3:extended range\n");
249  fprintf(stderr, "\t   4:auto-set based on cable length\n");
250  fprintf(stderr, "\t-i Send 'CSU Loop Down' inband msg\n");
251  fprintf(stderr, "\t-I Send 'CSU Loop Up' inband msg\n");
252  fprintf(stderr, "\t-l Send 'Line Loop Down' BOP msg\n");
253  fprintf(stderr, "\t-L Send 'Line Loop Up' BOP msg\n");
254  fprintf(stderr, "\t-p Send 'Payload Loop Down' BOP msg\n");
255  fprintf(stderr, "\t-P Send 'Payload Loop Up' BOP msg\n");
256  fprintf(stderr, "\t-s Print status of T1 DSU/CSU\n");
257  fprintf(stderr, "\t-t Stop sending test pattern\n");
258  fprintf(stderr, "\t-T <number> Start sending test pattern, where:\n");
259  fprintf(stderr, "\t    0:unframed 2^11       1:unframed 2^15\n");
260  fprintf(stderr, "\t    2:unframed 2^20       3:unframed 2^23\n");
261  fprintf(stderr, "\t    4:unframed 2^11 w/ZS  5:unframed 2^15 w/ZS\n");
262  fprintf(stderr, "\t    6:unframed QRSS       7:unframed 2^23 w/ZS\n");
263  fprintf(stderr, "\t    8:  framed 2^11       9:  framed 2^15\n");
264  fprintf(stderr, "\t   10:  framed 2^20      11:  framed 2^23\n");
265  fprintf(stderr, "\t   12:  framed 2^11 w/ZS 13:  framed 2^15 w/ZS\n");
266  fprintf(stderr, "\t   14:  framed QRSS      15:  framed 2^23 w/ZS\n");
267  fprintf(stderr, "\t-u <number> Set transmitter pulse shape, where:\n");
268  fprintf(stderr, "\t   0:T1-DSX   0-40m       1:T1-DSX  40-80m\n");
269  fprintf(stderr, "\t   2:T1-DSX  80-120m      3:T1-DSX 120-160m\n");
270  fprintf(stderr, "\t   4:T1-DSX 160-200m      5:E1-G.703 75ohm coax\n");
271  fprintf(stderr, "\t   6:E1-G.703 120ohm TP   7:T1-CSU Long range\n");
272  fprintf(stderr, "\t   8:auto-set based on cable length (T1 only)\n");
273  fprintf(stderr, "\t-U <number> Set line build out where:\n");
274  fprintf(stderr, "\t   0:0dB 1:7.5dB 2:15dB 3:22.5dB\n");
275  fprintf(stderr, "\t   4:auto-set based on cable length\n");
276  fprintf(stderr, "\t-x Disable Transmitter outputs\n");
277  fprintf(stderr, "\t-X  Enable Transmitter outputs\n");
278
279  fprintf(stderr, "The -3 switch precedes T3 commands.\n");
280  fprintf(stderr, "\t-a <y|b|a|i> Stop  sending Yellow|Blue|AIS|Idle signal\n");
281  fprintf(stderr, "\t-A <y|b|a|i> Start sending Yellow|Blue|AIS|Idle signal\n");
282  fprintf(stderr, "\t-B <bopcode> Send BOP msg 10 times\n");
283  fprintf(stderr, "\t-c <number> Set cable length in meters\n");
284  fprintf(stderr, "\t-d Print status of T3 DSU/CSU\n");
285  fprintf(stderr, "\t-e <number> Set T3 frame format, where:\n");
286  fprintf(stderr, "\t   100:C-Bit Parity  101:M13\n");
287  fprintf(stderr, "\t-f Read and print Framer registers\n");
288  fprintf(stderr, "\t-F <addr> <data> Write Framer register\n");
289  fprintf(stderr, "\t-l Send 'Line Loop Down' BOP msg\n");
290  fprintf(stderr, "\t-L Send 'Line Loop Up' BOP msg\n");
291  fprintf(stderr, "\t-s Print status of T3 DSU/CSU\n");
292  fprintf(stderr, "\t-S <number> Set DS3 scrambler mode, where:\n");
293  fprintf(stderr, "\t   1:OFF 2:DigitalLink|Kentrox 3:Larse\n");
294  fprintf(stderr, "\t-V <number> Write to T3 VCXO freq control DAC\n");
295  }
296
297void call_driver(unsigned long cmd, struct iohdr *iohdr)
298  {
299  strncpy(iohdr->ifname, ifname, sizeof(iohdr->ifname));
300  iohdr->cookie = NGM_LMC_COOKIE;
301  iohdr->iohdr = iohdr;
302
303  /* Exchange data with a running device driver. */
304#if defined(NETGRAPH)
305  if (netgraph)
306    {
307    NgSendMsg(fdcs, ifname, NGM_LMC_COOKIE, cmd, iohdr, IOCPARM_LEN(cmd));
308    if (cmd & IOC_OUT)
309      {
310      int replen = sizeof(struct ng_mesg) + IOCPARM_LEN(cmd);
311      char rep[replen];  /* storage for the reply */
312      struct ng_mesg *reply = (struct ng_mesg *)rep;
313      int rl = NgRecvMsg(fdcs, reply, replen, NULL);
314      if (rl == replen)
315        bcopy(&reply->data, iohdr, IOCPARM_LEN(cmd));
316      else
317        {
318        fprintf(stderr, "%s: NgRecvMsg returned %d bytes, expected %d\n",
319          progname, rl, replen);
320        exit(1);
321	}
322      }
323    }
324  else
325#endif
326    {
327    if (ioctl(fdcs, cmd, (caddr_t)iohdr) < 0)
328      {
329      fprintf(stderr, "%s: ioctl() returned error code %d: %s\n",
330       progname, errno, strerror(errno));
331      exit(1);
332      }
333    }
334
335  if (iohdr->cookie != NGM_LMC_COOKIE)
336    {
337    fprintf(stderr, "%s: cookie is 0x%08X; expected 0x%08X\n",
338     progname, iohdr->cookie, NGM_LMC_COOKIE);
339    fprintf(stderr, "%s: recompile this program!\n", progname);
340    exit(1);
341    }
342  }
343
344u_int32_t read_pci_config(u_int8_t addr)
345  {
346  struct ioctl ioc;
347
348  ioc.iohdr.direction = DIR_IOWR;
349  ioc.iohdr.length = sizeof(struct ioctl);
350  ioc.cmd = IOCTL_RW_PCI;
351  ioc.address = addr;
352
353  call_driver(LMCIOCREAD, &ioc.iohdr);
354
355  return ioc.data;
356  }
357
358void write_pci_config(u_int8_t addr, u_int32_t data)
359  {
360  struct ioctl ioc;
361
362  ioc.iohdr.direction = DIR_IOW;
363  ioc.iohdr.length = sizeof(struct ioctl);
364  ioc.cmd = IOCTL_RW_PCI;
365  ioc.address = addr;
366  ioc.data = data;
367
368  call_driver(LMCIOCWRITE, &ioc.iohdr);
369  }
370
371u_int32_t read_csr(u_int8_t addr)
372  {
373  struct ioctl ioc;
374
375  ioc.iohdr.direction = DIR_IOWR;
376  ioc.iohdr.length = sizeof(struct ioctl);
377  ioc.cmd = IOCTL_RW_CSR;
378  ioc.address = addr;
379
380  call_driver(LMCIOCREAD, &ioc.iohdr);
381
382  return ioc.data;
383  }
384
385void write_csr(u_int8_t addr, u_int32_t data)
386  {
387  struct ioctl ioc;
388
389  ioc.iohdr.direction = DIR_IOW;
390  ioc.iohdr.length = sizeof(struct ioctl);
391  ioc.cmd = IOCTL_RW_CSR;
392  ioc.address = addr;
393  ioc.data = data;
394
395  call_driver(LMCIOCWRITE, &ioc.iohdr);
396  }
397
398u_int16_t read_srom(u_int8_t addr)
399  {
400  struct ioctl ioc;
401
402  ioc.iohdr.direction = DIR_IOWR;
403  ioc.iohdr.length = sizeof(struct ioctl);
404  ioc.cmd = IOCTL_RW_SROM;
405  ioc.address = addr;
406
407  call_driver(LMCIOCREAD, &ioc.iohdr);
408
409  return ioc.data;
410  }
411
412void write_srom(u_int8_t addr, u_int16_t data)
413  {
414  struct ioctl ioc;
415
416  ioc.iohdr.direction = DIR_IOW;
417  ioc.iohdr.length = sizeof(struct ioctl);
418  ioc.cmd = IOCTL_RW_SROM;
419  ioc.address = addr;
420  ioc.data = data;
421
422  call_driver(LMCIOCWRITE, &ioc.iohdr);
423  }
424
425u_int8_t read_bios_rom(u_int32_t addr)
426  {
427  struct ioctl ioc;
428
429  ioc.iohdr.direction = DIR_IOWR;
430  ioc.iohdr.length = sizeof(struct ioctl);
431  ioc.cmd = IOCTL_RW_BIOS;
432  ioc.address = addr;
433
434  call_driver(LMCIOCREAD, &ioc.iohdr);
435
436  return ioc.data;
437  }
438
439void write_bios_rom(u_int32_t addr, u_int8_t data)
440  {
441  struct ioctl ioc;
442
443  ioc.iohdr.direction = DIR_IOW;
444  ioc.iohdr.length = sizeof(struct ioctl);
445  ioc.cmd = IOCTL_RW_BIOS;
446  ioc.address = addr;
447  ioc.data = data;
448
449  call_driver(LMCIOCWRITE, &ioc.iohdr);
450  }
451
452u_int16_t read_mii(u_int8_t addr)
453  {
454  struct ioctl ioc;
455
456  ioc.iohdr.direction = DIR_IOWR;
457  ioc.iohdr.length = sizeof(struct ioctl);
458  ioc.cmd = IOCTL_RW_MII;
459  ioc.address = addr;
460
461  call_driver(LMCIOCREAD, &ioc.iohdr);
462
463  return ioc.data;
464  }
465
466void write_mii(u_int8_t addr, u_int16_t data)
467  {
468  struct ioctl ioc;
469
470  ioc.iohdr.direction = DIR_IOW;
471  ioc.iohdr.length = sizeof(struct ioctl);
472  ioc.cmd = IOCTL_RW_MII;
473  ioc.address = addr;
474  ioc.data = data;
475
476  call_driver(LMCIOCWRITE, &ioc.iohdr);
477  }
478
479u_int8_t read_framer(u_int16_t addr)
480  {
481  struct ioctl ioc;
482
483  ioc.iohdr.direction = DIR_IOWR;
484  ioc.iohdr.length = sizeof(struct ioctl);
485  ioc.cmd = IOCTL_RW_FRAME;
486  ioc.address = addr;
487
488  call_driver(LMCIOCREAD, &ioc.iohdr);
489
490  return ioc.data;
491  }
492
493void write_framer(u_int16_t addr, u_int8_t data)
494  {
495  struct ioctl ioc;
496
497  ioc.iohdr.direction = DIR_IOW;
498  ioc.iohdr.length = sizeof(struct ioctl);
499  ioc.cmd = IOCTL_RW_FRAME;
500  ioc.address = addr;
501  ioc.data = data;
502
503  call_driver(LMCIOCWRITE, &ioc.iohdr);
504  }
505
506void write_synth(struct synth synth)
507  {
508  struct ioctl ioc;
509
510  ioc.iohdr.direction = DIR_IOW;
511  ioc.iohdr.length = sizeof(struct ioctl);
512  ioc.cmd = IOCTL_WO_SYNTH;
513  bcopy(&synth, &ioc.data, sizeof(synth));
514
515  call_driver(LMCIOCWRITE, &ioc.iohdr);
516  }
517
518void write_dac(u_int16_t data)
519  {
520  struct ioctl ioc;
521
522  ioc.iohdr.direction = DIR_IOW;
523  ioc.iohdr.length = sizeof(struct ioctl);
524  ioc.cmd = IOCTL_WO_DAC;
525  ioc.data = data;
526
527  call_driver(LMCIOCWRITE, &ioc.iohdr);
528  }
529
530void reset_xilinx()
531  {
532  struct ioctl ioc;
533
534  ioc.iohdr.direction = DIR_IOWR;
535  ioc.iohdr.length = sizeof(struct ioctl);
536  ioc.cmd = IOCTL_XILINX_RESET;
537
538  call_driver(LMCIOCTL, &ioc.iohdr);
539  }
540
541void load_xilinx_from_rom()
542  {
543  struct ioctl ioc;
544
545  ioc.iohdr.direction = DIR_IOWR;
546  ioc.iohdr.length = sizeof(struct ioctl);
547  ioc.cmd = IOCTL_XILINX_ROM;
548
549  call_driver(LMCIOCTL, &ioc.iohdr);
550  }
551
552void load_xilinx_from_file(char *ucode, int len)
553  {
554  struct ioctl ioc;
555
556  ioc.iohdr.direction = DIR_IOWR;
557  ioc.iohdr.length = sizeof(struct ioctl);
558  ioc.cmd = IOCTL_XILINX_FILE;
559  ioc.data = len;
560  ioc.ucode = ucode;
561
562  call_driver(LMCIOCTL, &ioc.iohdr);
563  }
564
565void ioctl_snmp_send(u_int32_t sendval)
566  {
567  struct ioctl ioc;
568
569  ioc.iohdr.direction = DIR_IOWR;
570  ioc.iohdr.length = sizeof(struct ioctl);
571  ioc.cmd = IOCTL_SNMP_SEND;
572  ioc.data = sendval;
573
574  call_driver(LMCIOCTL, &ioc.iohdr);
575  }
576
577void ioctl_snmp_loop(u_int32_t loop)
578  {
579  struct ioctl ioc;
580
581  ioc.iohdr.direction = DIR_IOWR;
582  ioc.iohdr.length = sizeof(struct ioctl);
583  ioc.cmd = IOCTL_SNMP_LOOP;
584  ioc.data = loop;
585
586  call_driver(LMCIOCTL, &ioc.iohdr);
587  }
588
589void ioctl_reset_cntrs()
590  {
591  struct ioctl ioc;
592
593  ioc.iohdr.direction = DIR_IOWR;
594  ioc.iohdr.length = sizeof(struct ioctl);
595  ioc.cmd = IOCTL_RESET_CNTRS;
596
597  call_driver(LMCIOCTL, &ioc.iohdr);
598  }
599
600void ioctl_read_config()
601  {
602  config.iohdr.direction = DIR_IOWR;
603  config.iohdr.length = sizeof(struct config);
604
605  call_driver(LMCIOCGCFG, &config.iohdr);
606  }
607
608void ioctl_write_config()
609  {
610  config.iohdr.direction = DIR_IOW;
611  config.iohdr.length = sizeof(struct config);
612
613  call_driver(LMCIOCSCFG, &config.iohdr);
614  }
615
616void ioctl_read_status()
617  {
618  status.iohdr.direction = DIR_IOWR;
619  status.iohdr.length = sizeof(struct status);
620
621  call_driver(LMCIOCGSTAT, &status.iohdr);
622  }
623
624void print_card_name()
625  {
626  printf("Card name:\t\t%s\n", ifname);
627  }
628
629void print_card_type()
630  {
631  printf("Card type:\t\t");
632  switch(status.card_type)
633    {
634    case CSID_LMC_HSSI:
635      printf("HSSI (lmc5200)\n");
636      break;
637    case CSID_LMC_T3:
638      printf("T3 (lmc5245)\n");
639      break;
640    case CSID_LMC_SSI:
641      printf("SSI (lmc1000)\n");
642      break;
643    case CSID_LMC_T1E1:
644      printf("T1E1 (lmc1200)\n");
645      break;
646    case CSID_LMC_HSSIc:
647      printf("HSSI (lmc5200C)\n");
648      break;
649    default:
650      printf("Unknown card_type: %d\n", status.card_type);
651      break;
652    }
653  }
654
655void print_status()
656  {
657  const char *status_string;
658
659  if      (status.link_state == STATE_UP)
660    status_string = "Up";
661  else if (status.link_state == STATE_DOWN)
662    status_string = "Down";
663  else if (status.link_state == STATE_TEST)
664    status_string = "Test";
665  else
666    status_string = "Unknown";
667  printf("Link status:\t\t%s\n", status_string);
668  }
669
670void print_tx_speed()
671  {
672  printf("Tx Speed:\t\t%u\n", status.tx_speed);
673  }
674
675void print_debug()
676  {
677  if (config.debug != 0)
678    printf("Debug:\t\t\t%s\n", "On");
679  }
680
681void print_line_prot()
682  {
683  const char *on = "On", *off = "Off";
684
685  printf("Line Prot/Pkg:\t\t");
686  switch (status.proto)
687    {
688    case 0:
689      printf("NotSet/");
690      break;
691    case PROTO_IP_HDLC:
692      printf("IP-in-HDLC/");
693      break;
694    case PROTO_PPP:
695      printf("PPP/");
696      break;
697    case PROTO_C_HDLC:
698      printf("Cisco-HDLC/");
699      break;
700    case PROTO_FRM_RLY:
701      printf("Frame-Relay/");
702      break;
703    case PROTO_ETH_HDLC:
704      printf("Ether-in-HDLC/");
705      break;
706    case PROTO_X25:
707      printf("X25+LAPB/");
708      break;
709    default:
710      printf("Unknown proto: %d/", status.proto);
711      break;
712    }
713
714  switch (status.stack)
715    {
716    case 0:
717      printf("NotSet\n");
718      break;
719    case STACK_RAWIP:
720      printf("Driver\n");
721      break;
722    case STACK_SPPP:
723      printf("SPPP\n");
724      break;
725    case STACK_P2P:
726      printf("P2P\n");
727      break;
728    case STACK_GEN_HDLC:
729      printf("GenHDLC\n");
730      break;
731    case STACK_SYNC_PPP:
732      printf("SyncPPP\n");
733      break;
734    case STACK_NETGRAPH:
735      printf("Netgraph\n");
736      break;
737    default:
738      printf("Unknown stack: %d\n", status.stack);
739      break;
740    }
741
742  if ((status.stack == STACK_SPPP) ||
743      (status.stack == STACK_SYNC_PPP) ||
744     ((status.stack == STACK_GEN_HDLC) && (status.proto == PROTO_PPP)))
745    printf("Keep-alive pkts:\t%s\n", status.keep_alive ? on : off);
746  }
747
748void print_crc_len()
749  {
750  printf("CRC length:\t\t");
751  if      (config.crc_len == CFG_CRC_0)
752    printf("no CRC\n");
753  else if (config.crc_len == CFG_CRC_16)
754    printf("16 bits\n");
755  else if (config.crc_len == CFG_CRC_32)
756    printf("32 bits\n");
757  else
758    printf("bad crc_len: %d\n", config.crc_len);
759  }
760
761void print_loop_back(int skip_none)
762  {
763  if ((config.loop_back == CFG_LOOP_NONE) && skip_none)
764    return;
765
766  printf("Loopback:\t\t");
767  switch (config.loop_back)
768    {
769    case CFG_LOOP_NONE:
770      printf("None\n");
771      break;
772    case CFG_LOOP_PAYLOAD:
773      printf("Outward thru framer (payload loop)\n");
774      break;
775    case CFG_LOOP_LINE:
776      printf("Outward thru line interface (line loop)\n");
777      break;
778    case CFG_LOOP_OTHER:
779      printf("Inward thru line interface\n");
780      break;
781    case CFG_LOOP_INWARD:
782      printf("Inward thru framer\n");
783      break;
784    case CFG_LOOP_DUAL:
785      printf("Inward & outward (dual loop)\n");
786      break;
787    case CFG_LOOP_TULIP:
788      printf("Inward thru Tulip chip\n");
789      break;
790    case CFG_LOOP_PINS:
791      printf("Inward thru drvrs/rcvrs\n");
792      break;
793    case CFG_LOOP_LL:
794      printf("LA/LL asserted\n");
795      break;
796    case CFG_LOOP_RL:
797      printf("LB/RL asserted\n");
798      break;
799    default:
800      printf("Unknown loop_back: %d\n", config.loop_back);
801      break;
802    }
803  }
804
805void print_tx_clk_src()
806  {
807  printf("Tx Clk src:\t\t");
808  switch (config.tx_clk_src)
809    {
810    case CFG_CLKMUX_ST:
811      printf("Modem Tx Clk\n");
812      break;
813    case CFG_CLKMUX_INT:
814      printf("Crystal osc\n");
815      break;
816    case CFG_CLKMUX_RT:
817      printf("Modem Rx Clk (loop timed)\n");
818      break;
819    case CFG_CLKMUX_EXT:
820      printf("External connector\n");
821      break;
822    default:
823      printf("Unknown tx_clk_src: %d\n", config.tx_clk_src);
824      break;
825    }
826  }
827
828void print_format()
829  {
830  printf("Format-Frame/Code:\t");
831  switch (config.format)
832    {
833    case CFG_FORMAT_T1SF:
834      printf("T1-SF/AMI\n");
835      break;
836    case CFG_FORMAT_T1ESF:
837      printf("T1-ESF/B8ZS\n");
838      break;
839    case CFG_FORMAT_E1FAS:
840      printf("E1-FAS/HDB3\n");
841      break;
842    case CFG_FORMAT_E1FASCRC:
843      printf("E1-FAS+CRC/HDB3\n");
844      break;
845    case CFG_FORMAT_E1FASCAS:
846      printf("E1-FAS+CAS/HDB3\n");
847      break;
848    case CFG_FORMAT_E1FASCRCCAS:
849      printf("E1-FAS+CRC+CAS/HDB3\n");
850      break;
851    case CFG_FORMAT_E1NONE:
852      printf("E1-NOFRAMING/HDB3\n");
853      break;
854    case CFG_FORMAT_T3CPAR:
855      printf("T3-CParity/B3ZS\n");
856      break;
857    case CFG_FORMAT_T3M13:
858      printf("T3-M13/B3ZS\n");
859      break;
860    default:
861      printf("Unknown format: %d\n", config.format);
862      break;
863    }
864  }
865
866void print_dte_dce()
867  {
868  printf("DTE or DCE:\t\t");
869  switch(config.dte_dce)
870    {
871    case CFG_DTE:
872      printf("DTE (receiving TxClk)\n");
873      break;
874    case CFG_DCE:
875      printf("DCE (driving TxClk)\n");
876      break;
877    default:
878      printf("Unknown dte_dce: %d\n", config.dte_dce);
879      break;
880    }
881  }
882
883void print_synth_freq()
884  {
885  double Fref = 20e6;
886  double Fout, Fvco;
887
888  /* decode the synthesizer params */
889  Fvco = (Fref * (config.synth.n<<(3*config.synth.v)))/config.synth.m;
890  Fout =  Fvco / (1<<(config.synth.x+config.synth.r+config.synth.prescale));
891
892  printf("Synth freq:\t\t%.0f\n", Fout);
893  }
894
895void synth_freq(unsigned long target)
896  {
897  unsigned int n, m, v, x, r;
898  double Fout, Fvco, Ftarg;
899  double newdiff, olddiff;
900  double bestF=0.0, bestV=0.0;
901  unsigned prescale = (target < 50000) ? 9:4;
902
903  Ftarg = target<<prescale;
904  for (n=3; n<=127; n++)
905    for (m=3; m<=127; m++)
906      for (v=0;  v<=1;  v++)
907        for (x=0;  x<=3;  x++)
908          for (r=0;  r<=3;  r++)
909            {
910            Fvco = (SYNTH_FREF * (n<<(3*v)))/m;
911            if (Fvco < SYNTH_FMIN || Fvco > SYNTH_FMAX) continue;
912            Fout =  Fvco / (1<<(x+r));
913            if (Fout >= Ftarg)
914              newdiff = Fout - Ftarg;
915            else
916              newdiff = Ftarg - Fout;
917            if (bestF >= Ftarg)
918              olddiff = bestF - Ftarg;
919            else
920              olddiff = Ftarg - bestF;
921            if ((newdiff < olddiff) ||
922               ((newdiff == olddiff) && (Fvco < bestV)))
923              {
924              config.synth.n = n;
925              config.synth.m = m;
926              config.synth.v = v;
927              config.synth.x = x;
928              config.synth.r = r;
929              config.synth.prescale = prescale;
930              bestF = Fout;
931              bestV = Fvco;
932	      }
933            }
934#if 0
935  printf("Fbest=%.0f, Ftarg=%u, Fout=%.0f\n", bestF>>prescale, target, bestF);
936  printf("N=%u, M=%u, V=%u, X=%u, R=%u\n", config.synth.n,
937   config.synth.m, config.synth.v, config.synth.x, config.synth.r);
938#endif
939  }
940
941void print_cable_len()
942  {
943  printf("Cable length:\t\t%d meters\n", config.cable_len);
944  }
945
946void print_cable_type()
947  {
948  printf("Cable type:\t\t");
949  if (status.cable_type > 7)
950    printf("Unknown cable_type: %d\n", status.cable_type);
951  else
952    printf("%s\n", ssi_cables[status.cable_type]);
953  }
954
955void print_time_slots()
956  {
957  printf("TimeSlot [31-0]:\t0x%08X\n", status.time_slots);
958  }
959
960void print_scrambler()
961  {
962  printf("Scrambler:\t\t");
963  if      (config.scrambler == CFG_SCRAM_OFF)
964    printf("off\n");
965  else if (config.scrambler == CFG_SCRAM_DL_KEN)
966    printf("DigLink/Kentrox: X^43+1\n");
967  else if (config.scrambler == CFG_SCRAM_LARS)
968    printf("Larse: X^20+X^17+1 w/28ZS\n");
969  else
970    printf("Unknown scrambler: %d\n", config.scrambler);
971  }
972
973double vga_dbs(u_int8_t vga)
974  {
975  if  (vga <  0x0F)                   	   return  0.0;
976  else if ((vga >= 0x0F) && (vga <= 0x1B)) return  0.0 + 0.77 * (vga - 0x0F);
977  else if ((vga >= 0x1C) && (vga <= 0x33)) return 10.0 + 1.25 * (vga - 0x1C);
978  else if ((vga >= 0x34) && (vga <= 0x39)) return 40.0 + 1.67 * (vga - 0x34);
979  else if ((vga >= 0x3A) && (vga <= 0x3F)) return 50.0 + 2.80 * (vga - 0x3A);
980  else /* if  (vga >  0x3F) */             return 64.0;
981  }
982
983void print_rx_gain_max()
984  {
985  if (config.rx_gain_max != CFG_GAIN_AUTO)
986    {
987    printf("Rx gain max:\t\t");
988    printf("up to %02.1f dB\n", vga_dbs(config.rx_gain_max));
989    }
990  }
991
992void print_tx_lbo()
993  {
994  u_int8_t saved_lbo = config.tx_lbo;
995
996  printf("LBO = ");
997  if (config.tx_lbo == CFG_LBO_AUTO)
998    {
999    config.tx_lbo = read_framer(Bt8370_TLIU_CR) & 0x30;
1000    printf("auto-set to ");
1001    }
1002
1003  switch (config.tx_lbo)
1004    {
1005    case CFG_LBO_0DB:
1006      printf("0 dB\n");
1007      break;
1008    case CFG_LBO_7DB:
1009      printf("7.5 dB\n");
1010      break;
1011    case CFG_LBO_15DB:
1012      printf("15 dB\n");
1013      break;
1014    case CFG_LBO_22DB:
1015      printf("22.5 dB\n");
1016      break;
1017    default:
1018      printf("Unknown tx_lbo: %d\n", config.tx_lbo);
1019      break;
1020    }
1021
1022  if (saved_lbo == CFG_LBO_AUTO)
1023    config.tx_lbo = saved_lbo;
1024  }
1025
1026void print_tx_pulse(int skip_auto)
1027  {
1028  u_int8_t saved_pulse = config.tx_pulse;
1029
1030  if ((config.tx_pulse == CFG_PULSE_AUTO) && skip_auto)
1031    return;
1032
1033  printf("Tx pulse shape:\t\t");
1034  if (config.tx_pulse == CFG_PULSE_AUTO)
1035    {
1036    config.tx_pulse = read_framer(Bt8370_TLIU_CR) & 0x0E;
1037    printf("auto-set to ");
1038    }
1039
1040  switch (config.tx_pulse)
1041    {
1042    case CFG_PULSE_T1DSX0:
1043      printf("T1-DSX: 0 to 40 meters\n");
1044      break;
1045    case CFG_PULSE_T1DSX1:
1046      printf("T1-DSX: 40 to 80 meters\n");
1047      break;
1048    case CFG_PULSE_T1DSX2:
1049      printf("T1-DSX: 80 to 120 meters\n");
1050      break;
1051    case CFG_PULSE_T1DSX3:
1052      printf("T1-DSX: 120 to 160 meters\n");
1053      break;
1054    case CFG_PULSE_T1DSX4:
1055      printf("T1-DSX: 160 to 200 meters\n");
1056      break;
1057    case CFG_PULSE_E1COAX:
1058      printf("E1: Twin Coax\n");
1059      break;
1060    case CFG_PULSE_E1TWIST:
1061      printf("E1: Twisted Pairs\n");
1062      break;
1063    case CFG_PULSE_T1CSU:
1064      printf("T1-CSU; ");
1065      print_tx_lbo();
1066      break;
1067    default:
1068      printf("Unknown tx_pulse: %d\n", config.tx_pulse);
1069      break;
1070    }
1071
1072  if (saved_pulse == CFG_PULSE_AUTO)
1073    config.tx_pulse = saved_pulse;
1074  }
1075
1076void print_ssi_sigs()
1077  {
1078  u_int32_t mii16 = status.snmp.ssi.sigs;
1079  const char *on = "On", *off = "Off";
1080
1081  printf("Modem signals:\t\tDTR=%s DSR=%s RTS=%s CTS=%s\n",
1082   (mii16 & MII16_SSI_DTR) ? on : off,
1083   (mii16 & MII16_SSI_DSR) ? on : off,
1084   (mii16 & MII16_SSI_RTS) ? on : off,
1085   (mii16 & MII16_SSI_CTS) ? on : off);
1086  printf("Modem signals:\t\tDCD=%s RI=%s LL=%s RL=%s TM=%s\n",
1087   (mii16 & MII16_SSI_DCD) ? on : off,
1088   (mii16 & MII16_SSI_RI)  ? on : off,
1089   (mii16 & MII16_SSI_LL)  ? on : off,
1090   (mii16 & MII16_SSI_RL)  ? on : off,
1091   (mii16 & MII16_SSI_TM)  ? on : off);
1092  }
1093
1094void print_hssi_sigs()
1095  {
1096  u_int32_t mii16 = status.snmp.hssi.sigs;
1097  const char *on = "On", *off = "Off";
1098
1099  printf("Modem signals:\t\tTA=%s CA=%s\n",
1100   (mii16 & MII16_HSSI_TA) ? on : off,
1101   (mii16 & MII16_HSSI_CA) ? on : off);
1102  printf("Modem signals:\t\tLA=%s LB=%s LC=%s TM=%s\n",
1103   (mii16 & MII16_HSSI_LA) ? on : off,
1104   (mii16 & MII16_HSSI_LB) ? on : off,
1105   (mii16 & MII16_HSSI_LC) ? on : off,
1106   (mii16 & MII16_HSSI_TM) ? on : off);
1107  }
1108
1109void print_events()
1110  {
1111  const char *timestr;
1112  struct timeval tv;
1113  time_t tv_sec;
1114
1115  (void)gettimeofday(&tv, NULL);
1116  tv_sec = tv.tv_sec;
1117  timestr = ctime(&tv_sec);
1118  printf("Current time:\t\t%s", timestr);
1119
1120  if (status.cntrs.reset_time.tv_sec < 1000)
1121    timestr = "Never\n";
1122  else
1123    {
1124    tv_sec = status.cntrs.reset_time.tv_sec;
1125    timestr = ctime(&tv_sec);
1126    }
1127  printf("Cntrs reset:\t\t%s", timestr);
1128
1129  if (status.cntrs.ibytes)     printf("Rx bytes:\t\t%llu\n",   (unsigned long long)status.cntrs.ibytes);
1130  if (status.cntrs.obytes)     printf("Tx bytes:\t\t%llu\n",   (unsigned long long)status.cntrs.obytes);
1131  if (status.cntrs.ipackets)   printf("Rx packets:\t\t%llu\n", (unsigned long long)status.cntrs.ipackets);
1132  if (status.cntrs.opackets)   printf("Tx packets:\t\t%llu\n", (unsigned long long)status.cntrs.opackets);
1133  if (status.cntrs.ierrors)    printf("Rx errors:\t\t%u\n",    status.cntrs.ierrors);
1134  if (status.cntrs.oerrors)    printf("Tx errors:\t\t%u\n",    status.cntrs.oerrors);
1135  if (status.cntrs.idrops)     printf("Rx drops:\t\t%u\n",     status.cntrs.idrops);
1136  if (status.cntrs.missed)     printf("Rx missed:\t\t%u\n",    status.cntrs.missed);
1137  if (status.cntrs.odrops)     printf("Tx drops:\t\t%u\n",     status.cntrs.odrops);
1138  if (status.cntrs.fifo_over)  printf("Rx fifo overruns:\t%u\n", status.cntrs.fifo_over);
1139  if (status.cntrs.overruns)   printf("Rx overruns:\t\t%u\n",  status.cntrs.overruns);
1140  if (status.cntrs.fifo_under) printf("Tx fifo underruns:\t%u\n", status.cntrs.fifo_under);
1141  if (status.cntrs.underruns)  printf("Rx underruns:\t\t%u\n", status.cntrs.underruns);
1142  if (status.cntrs.fdl_pkts)   printf("Rx FDL pkts:\t\t%u\n",  status.cntrs.fdl_pkts);
1143  if (status.cntrs.crc_errs)   printf("Rx CRC:\t\t\t%u\n",     status.cntrs.crc_errs);
1144  if (status.cntrs.lcv_errs)   printf("Rx line code:\t\t%u\n", status.cntrs.lcv_errs);
1145  if (status.cntrs.frm_errs)   printf("Rx F-bits:\t\t%u\n",    status.cntrs.frm_errs);
1146  if (status.cntrs.febe_errs)  printf("Rx FEBE:\t\t%u\n",      status.cntrs.febe_errs);
1147  if (status.cntrs.par_errs)   printf("Rx P-parity:\t\t%u\n",  status.cntrs.par_errs);
1148  if (status.cntrs.cpar_errs)  printf("Rx C-parity:\t\t%u\n",  status.cntrs.cpar_errs);
1149  if (status.cntrs.mfrm_errs)  printf("Rx M-bits:\t\t%u\n",    status.cntrs.mfrm_errs);
1150  if (config.debug)
1151    { /* These events are hard to explain and may worry users, */
1152    if (status.cntrs.rxbuf)     printf("Rx no buffs:\t\t%u\n", status.cntrs.rxbuf);
1153    if (status.cntrs.txdma)     printf("Tx no descs:\t\t%u\n", status.cntrs.txdma);
1154    if (status.cntrs.lck_watch) printf("Lock watch:\t\t%u\n",  status.cntrs.lck_watch);
1155    if (status.cntrs.lck_intr)  printf("Lock intr:\t\t%u\n",   status.cntrs.lck_intr);
1156    if (status.cntrs.spare1)    printf("Spare1:\t\t\t%u\n",    status.cntrs.spare1);
1157    if (status.cntrs.spare2)    printf("Spare2:\t\t\t%u\n",    status.cntrs.spare2);
1158    if (status.cntrs.spare3)    printf("Spare3:\t\t\t%u\n",    status.cntrs.spare3);
1159    if (status.cntrs.spare4)    printf("Spare4:\t\t\t%u\n",    status.cntrs.spare4);
1160    }
1161  }
1162
1163void print_summary()
1164  {
1165  switch(status.card_type)
1166    {
1167    case CSID_LMC_HSSI:
1168      {
1169      print_card_name();
1170      print_card_type();
1171      print_debug();
1172      print_status();
1173      print_tx_speed();
1174      print_line_prot();
1175      print_crc_len();
1176      print_loop_back(1);
1177      print_tx_clk_src();
1178      print_hssi_sigs();
1179      print_events();
1180      break;
1181      }
1182    case CSID_LMC_T3:
1183      {
1184      print_card_name();
1185      print_card_type();
1186      print_debug();
1187      print_status();
1188      print_tx_speed();
1189      print_line_prot();
1190      print_crc_len();
1191      print_loop_back(1);
1192      print_format();
1193      print_cable_len();
1194      print_scrambler();
1195      print_events();
1196      break;
1197      }
1198    case CSID_LMC_SSI:
1199      {
1200      print_card_name();
1201      print_card_type();
1202      print_debug();
1203      print_status();
1204      print_tx_speed();
1205      print_line_prot();
1206      print_crc_len();
1207      print_loop_back(1);
1208      print_dte_dce();
1209      print_synth_freq();
1210      print_cable_type();
1211      print_ssi_sigs();
1212      print_events();
1213      break;
1214      }
1215    case CSID_LMC_T1E1:
1216      {
1217      print_card_name();
1218      print_card_type();
1219      print_debug();
1220      print_status();
1221      print_tx_speed();
1222      print_line_prot();
1223      print_crc_len();
1224      print_loop_back(1);
1225      print_tx_clk_src();
1226      print_format();
1227      print_time_slots();
1228      print_cable_len();
1229      print_tx_pulse(1);
1230      print_rx_gain_max();
1231      print_events();
1232      break;
1233      }
1234    case CSID_LMC_HSSIc:
1235      {
1236      print_card_name();
1237      print_card_type();
1238      print_debug();
1239      print_status();
1240      print_line_prot();
1241      print_tx_speed();
1242      print_crc_len();
1243      print_loop_back(1);
1244      print_tx_clk_src();
1245      print_dte_dce();
1246      print_synth_freq();
1247      print_hssi_sigs();
1248      print_events();
1249      break;
1250      }
1251    default:
1252      {
1253      printf("%s: Unknown card type: %d\n", ifname, status.card_type);
1254      break;
1255      }
1256    }
1257  }
1258
1259const char *print_t3_bop(int bop_code)
1260  {
1261  switch(bop_code)
1262    {
1263    case 0x00:
1264      return "far end LOF";
1265    case 0x0E:
1266      return "far end LOS";
1267    case 0x16:
1268      return "far end AIS";
1269    case 0x1A:
1270      return "far end IDL";
1271    case 0x07:
1272      return "Line Loopback activate";
1273    case 0x1C:
1274      return "Line Loopback deactivate";
1275    case 0x1B:
1276      return "Entire DS3 line";
1277    default:
1278      return "Unknown BOP code";
1279    }
1280  }
1281
1282void print_t3_snmp()
1283  {
1284  printf("SNMP performance data:\n");
1285  printf(" LCV=%d",  status.snmp.t3.lcv);
1286  printf(" LOS=%d", (status.snmp.t3.line & TLINE_LOS)    ? 1 : 0);
1287  printf(" PCV=%d",  status.snmp.t3.pcv);
1288  printf(" CCV=%d",  status.snmp.t3.ccv);
1289  printf(" AIS=%d", (status.snmp.t3.line & TLINE_RX_AIS) ? 1 : 0);
1290  printf(" SEF=%d", (status.snmp.t3.line & T1LINE_SEF)   ? 1 : 0);
1291  printf(" OOF=%d", (status.snmp.t3.line & TLINE_LOF)    ? 1 : 0);
1292  printf(" FEBE=%d", status.snmp.t3.febe);
1293  printf(" RAI=%d", (status.snmp.t3.line & TLINE_RX_RAI) ? 1 : 0);
1294  printf("\n");
1295  }
1296
1297void print_t3_dsu()
1298  {
1299  const char *no = "No", *yes = "Yes";
1300  u_int16_t mii16 = read_mii(16);
1301  u_int8_t ctl1   = read_framer(T3CSR_CTL1);
1302  u_int8_t ctl8   = read_framer(T3CSR_CTL8);
1303  u_int8_t stat9  = read_framer(T3CSR_STAT9);
1304  u_int8_t ctl12  = read_framer(T3CSR_CTL12);
1305  u_int8_t stat16 = read_framer(T3CSR_STAT16);
1306
1307  printf("Framing:       \t\t%s\n", ctl1   & CTL1_M13MODE    ? "M13" : "CPAR");
1308  print_tx_speed();
1309  if ((mii16 & MII16_DS3_SCRAM)==0)
1310    printf("Scrambler:     \t\toff\n");
1311  else if (mii16 & MII16_DS3_POLY)
1312    printf("Scrambler:     \t\tX^20+X^17+1\n");
1313  else
1314    printf("Scrambler:     \t\tX^43+1\n");
1315  printf("Cable length   \t\t%s\n", mii16  & MII16_DS3_ZERO  ? "Short" : "Long");
1316  printf("Line    loop:  \t\t%s\n", mii16  & MII16_DS3_LNLBK ? yes : no);
1317  printf("Payload loop:  \t\t%s\n", ctl12  & CTL12_RTPLOOP   ? yes : no);
1318  printf("Frame   loop:  \t\t%s\n", ctl1   & CTL1_3LOOP      ? yes : no);
1319  printf("Host    loop:  \t\t%s\n", mii16  & MII16_DS3_TRLBK ? yes : no);
1320  printf("Transmit RAI:  \t\t%s\n", ctl1   & CTL1_XTX        ? no  : yes);
1321  printf("Receive  RAI:  \t\t%s\n", stat16 & STAT16_XERR     ? yes : no);
1322  printf("Transmit AIS:  \t\t%s\n", ctl1   & CTL1_TXAIS      ? yes : no);
1323  printf("Receive  AIS:  \t\t%s\n", stat16 & STAT16_RAIS     ? yes : no);
1324  printf("Transmit IDLE: \t\t%s\n", ctl1   & CTL1_TXIDL      ? yes : no);
1325  printf("Receive  IDLE: \t\t%s\n", stat16 & STAT16_RIDL     ? yes : no);
1326  printf("Transmit BLUE: \t\t%s\n", ctl8   & CTL8_TBLU       ? yes : no);
1327  printf("Receive  BLUE: \t\t%s\n", stat9  & STAT9_RBLU      ? yes : no);
1328  printf("Loss of Signal:\t\t%s\n", stat16 & STAT16_RLOS     ? yes : no);
1329  printf("Loss of Frame: \t\t%s\n", stat16 & STAT16_ROOF     ? yes : no);
1330  printf("Sev Err Frms:  \t\t%s\n", stat16 & STAT16_SEF      ? yes : no);
1331  printf("Code  errors:  \t\t%d\n", read_framer(T3CSR_CVLO) + (read_framer(T3CSR_CVHI)<<8));
1332  printf("C-Par errors:  \t\t%d\n", read_framer(T3CSR_CERR));
1333  printf("P-Par errors:  \t\t%d\n", read_framer(T3CSR_PERR));
1334  printf("F-Bit errors:  \t\t%d\n", read_framer(T3CSR_FERR));
1335  printf("M-Bit errors:  \t\t%d\n", read_framer(T3CSR_MERR));
1336  printf("FarEndBitErrs: \t\t%d\n", read_framer(T3CSR_FEBE));
1337  printf("Last Tx  FEAC msg:\t0x%02X (%s)\n",
1338   read_framer(T3CSR_TX_FEAC)  & 0x3F,
1339   print_t3_bop(read_framer(T3CSR_TX_FEAC) & 0x3F));
1340  printf("Last dbl FEAC msg:\t0x%02X (%s)\n",
1341   read_framer(T3CSR_DBL_FEAC) & 0x3F,
1342   print_t3_bop(read_framer(T3CSR_DBL_FEAC) & 0x3F));
1343  printf("Last Rx  FEAC msg:\t0x%02X (%s)\n",
1344   read_framer(T3CSR_RX_FEAC)  & 0x3F,
1345   print_t3_bop(read_framer(T3CSR_RX_FEAC) & 0x3F));
1346  print_t3_snmp();
1347  }
1348
1349void t3_cmd(int argc, char **argv)
1350  {
1351  int ch;
1352  const char *optstring = "a:A:B:c:de:fF:lLsS:V:";
1353
1354  while ((ch = getopt(argc, argv, optstring)) != -1)
1355    {
1356    switch (ch)
1357      {
1358      case 'a': /* stop alarms */
1359        {
1360        switch (optarg[0])
1361          {
1362          case 'a': /* Stop sending AIS Signal */
1363            {
1364            write_mii(16,
1365             read_mii(16) & ~MII16_DS3_FRAME);
1366            write_framer(T3CSR_CTL1,
1367             read_framer(T3CSR_CTL1) & ~CTL1_TXAIS);
1368            if (verbose) printf("Stop sending Alarm Indication Signal (AIS)\n");
1369            break;
1370            }
1371          case 'b': /* Stop sending Blue signal */
1372            {
1373            write_mii(16,
1374             read_mii(16) & ~MII16_DS3_FRAME);
1375            write_framer(T3CSR_CTL8,
1376             read_framer(T3CSR_CTL8) & ~CTL8_TBLU);
1377            if (verbose) printf("Stop sending Blue signal\n");
1378            break;
1379            }
1380          case 'i': /* Stop sending IDLE signal */
1381            {
1382            write_framer(T3CSR_CTL1,
1383             read_framer(T3CSR_CTL1) & ~CTL1_TXIDL);
1384            if (verbose) printf("Stop sending IDLE signal\n");
1385            break;
1386            }
1387          case 'y': /* Stop sending Yellow alarm */
1388            {
1389            write_framer(T3CSR_CTL1,
1390             read_framer(T3CSR_CTL1) | CTL1_XTX);
1391            if (verbose) printf("Stop sending Yellow alarm\n");
1392            break;
1393            }
1394          default:
1395            printf("Unknown alarm: %c\n", optarg[0]);
1396            break;
1397          }
1398        break;
1399        }
1400      case 'A': /* start alarms */
1401        {
1402        switch (optarg[0])
1403          {
1404          case 'a': /* Start sending AIS Signal */
1405            {
1406            write_mii(16,
1407             read_mii(16) | MII16_DS3_FRAME);
1408            write_framer(T3CSR_CTL1,
1409             read_framer(T3CSR_CTL1) | CTL1_TXAIS);
1410            if (verbose) printf("Sending AIS signal (framed 1010..)\n");
1411            break;
1412            }
1413          case 'b': /* Start sending Blue signal */
1414            {
1415            write_mii(16,
1416             read_mii(16) | MII16_DS3_FRAME);
1417            write_framer(T3CSR_CTL8,
1418             read_framer(T3CSR_CTL8) | CTL8_TBLU);
1419            if (verbose) printf("Sending Blue signal (unframed all 1s)\n");
1420            break;
1421            }
1422          case 'i': /* Start sending IDLE signal */
1423            {
1424            write_framer(T3CSR_CTL1,
1425             read_framer(T3CSR_CTL1) | CTL1_TXIDL);
1426            if (verbose) printf("Sending IDLE signal (framed 1100..)\n");
1427            break;
1428            }
1429          case 'y': /* Start sending Yellow alarm */
1430            {
1431            write_framer(T3CSR_CTL1,
1432             read_framer(T3CSR_CTL1) & ~CTL1_XTX);
1433            if (verbose) printf("Sending Yellow alarm (X-bits=0)\n");
1434            break;
1435            }
1436          default:
1437            printf("Unknown alarm: %c\n", optarg[0]);
1438            break;
1439          }
1440        break;
1441        }
1442      case 'B': /* send BOP msg */
1443        {
1444        u_int8_t bop = (u_int8_t)strtoul(optarg, NULL, 0);
1445        write_framer(T3CSR_TX_FEAC,  0xC0 + bop);
1446        if (verbose) printf("Sent '0x%02X' BOP msg 10 times\n", bop);
1447        break;
1448	}
1449      case 'c': /* set cable length */
1450        {
1451        config.cable_len = strtoul(optarg, NULL, 0);
1452        if (verbose) print_cable_len();
1453        update = 1;
1454        break;
1455        }
1456      case 'd': /* DSU status */
1457      case 's': /* deprecated */
1458        {
1459        print_t3_dsu();
1460        break;
1461        }
1462      case 'e': /* set framimg format */
1463        {
1464        config.format = strtoul(optarg, NULL, 0);
1465        if (verbose) print_format();
1466        update = 1;
1467        break;
1468        }
1469      case 'f': /* read and print framer regs */
1470        {
1471        int i;
1472        printf("TXC03401 regs:\n");
1473        printf("     0  1  2  3  4  5  6  7");
1474        for (i=0; i<21; i++)
1475          {
1476          if (i%8 == 0) printf("\n%02X: ", i);
1477          printf("%02X ", read_framer(i));
1478          }
1479        printf("\n\n");
1480        break;
1481        }
1482      case 'F': /* write framer reg */
1483        {
1484        u_int32_t addr = strtoul(optarg, NULL, 0);
1485        u_int32_t data = strtoul(argv[optind++], NULL, 0);
1486        write_framer(addr, data);
1487        if (verbose)
1488          {
1489          data = read_framer(addr);
1490          printf("Write framer register: addr = 0x%02X data = 0x%02X\n", addr, data);
1491	  }
1492        break;
1493        }
1494      case 'l': /* send DS3 line loopback deactivate BOP cmd */
1495        {
1496        ioctl_snmp_send(TSEND_RESET);
1497        if (verbose) printf("Sent 'DS3 Line Loopback deactivate' BOP cmd\n");
1498        break;
1499        }
1500      case 'L': /* send DS3 line loopback activate BOP cmd */
1501        {
1502        ioctl_snmp_send(TSEND_LINE);
1503        if (verbose) printf("Sent 'DS3 Line Loopback activate' BOP cmd\n");
1504        break;
1505        }
1506      case 'S': /* set scrambler */
1507        {
1508        config.scrambler = strtoul(optarg, NULL, 0);
1509        if (verbose) print_scrambler();
1510        update = 1;
1511        break;
1512        }
1513      case 'V': /* set T3 freq control DAC */
1514        {
1515        u_int32_t dac = strtoul(optarg, NULL, 0);
1516        write_dac(dac);
1517        if (verbose) printf("VCXO DAC value is %d\n", dac);
1518        break;
1519        }
1520      default:
1521        {
1522        printf("Unknown command char: %c\n", ch);
1523        exit(1);
1524        } /* case */
1525      } /* switch */
1526    } /* while */
1527  } /* proc */
1528
1529const char *print_t1_bop(int bop_code)
1530  {
1531  switch(bop_code)
1532    {
1533    case 0x00:
1534      return "Yellow Alarm (far end LOF)";
1535    case 0x07:
1536      return "Line Loop up";
1537    case 0x1C:
1538      return "Line Loop down";
1539    case 0x0A:
1540      return "Payload Loop up";
1541    case 0x19:
1542      return "Payload Loop down";
1543    case 0x09:
1544      return "Network Loop up";
1545    case 0x12:
1546      return "Network Loop down";
1547    default:
1548      return "Unknown BOP code";
1549    }
1550  }
1551
1552void print_t1_test_pattern(int patt)
1553  {
1554  printf("Test Pattern:\t\t");
1555  switch (patt)
1556    {
1557    case 0:
1558      printf("unframed X^11+X^9+1\n");
1559      break;
1560    case 1:
1561      printf("unframed X^15+X^14+1\n");
1562      break;
1563    case 2:
1564      printf("unframed X^20+X^17+1\n");
1565      break;
1566    case 3:
1567      printf("unframed X^23+X^18+1\n");
1568      break;
1569    case 4:
1570      printf("unframed X^11+X^9+1 w/7ZS\n");
1571      break;
1572    case 5:
1573      printf("unframed X^15+X^14+1 w/7ZS\n");
1574      break;
1575    case 6:
1576      printf("unframed X^20+X^17+1 w/14ZS (QRSS)\n");
1577      break;
1578    case 7:
1579      printf("unframed X^23+X^18+1 w/14ZS\n");
1580      break;
1581    case 8:
1582      printf("framed X^11+X^9+1\n");
1583      break;
1584    case 9:
1585      printf("framed X^15+X^14+1\n");
1586      break;
1587    case 10:
1588      printf("framed X^20+X^17+1\n");
1589      break;
1590    case 11:
1591      printf("framed X^23+X^18+1\n");
1592      break;
1593    case 12:;
1594      printf("framed X^11+X^9+1 w/7ZS\n");
1595      break;
1596    case 13:
1597      printf("framed X^15+X^14+1 w/7ZS\n");
1598      break;
1599    case 14:
1600      printf("framed X^20+X^17+1 w/14ZS (QRSS)\n");
1601      break;
1602    case 15:
1603      printf("framed X^23+X^18+1 w/14ZS\n");
1604      break;
1605    }
1606  }
1607
1608void print_t1_far_report(int idx)
1609  {
1610  u_int16_t far = status.snmp.t1.prm[idx];
1611
1612  printf(" SEQ=%d ", (far & T1PRM_SEQ)>>8);
1613  if      (far & T1PRM_G1) printf("CRC=1");
1614  else if (far & T1PRM_G2) printf("CRC=1 to 5");
1615  else if (far & T1PRM_G3) printf("CRC=5 to 10");
1616  else if (far & T1PRM_G4) printf("CRC=10 to 100");
1617  else if (far & T1PRM_G5) printf("CRC=100 to 319");
1618  else if (far & T1PRM_G6) printf("CRC>=320");
1619  else                     printf("CRC=0");
1620  printf(" SE=%d", (far & T1PRM_SE) ? 1 : 0);
1621  printf(" FE=%d", (far & T1PRM_FE) ? 1 : 0);
1622  printf(" LV=%d", (far & T1PRM_LV) ? 1 : 0);
1623  printf(" SL=%d", (far & T1PRM_SL) ? 1 : 0);
1624  printf(" LB=%d", (far & T1PRM_LB) ? 1 : 0);
1625  printf("\n");
1626  }
1627
1628void print_t1_snmp()
1629  {
1630  printf("SNMP Near-end performance data:\n");
1631  printf(" LCV=%d",  status.snmp.t1.lcv);
1632  printf(" LOS=%d", (status.snmp.t1.line & TLINE_LOS)    ? 1 : 0);
1633  printf(" FE=%d",   status.snmp.t1.fe);
1634  printf(" CRC=%d",  status.snmp.t1.crc);
1635  printf(" AIS=%d", (status.snmp.t1.line & TLINE_RX_AIS) ? 1 : 0);
1636  printf(" SEF=%d", (status.snmp.t1.line & T1LINE_SEF)   ? 1 : 0);
1637  printf(" OOF=%d", (status.snmp.t1.line & TLINE_LOF)    ? 1 : 0);
1638  printf("  RAI=%d",(status.snmp.t1.line & TLINE_RX_RAI) ? 1 : 0);
1639  printf("\n");
1640  if (config.format == CFG_FORMAT_T1ESF)
1641    {
1642    printf("ANSI Far-end performance reports:\n");
1643    print_t1_far_report(0);
1644    print_t1_far_report(1);
1645    print_t1_far_report(2);
1646    print_t1_far_report(3);
1647    }
1648  }
1649
1650void print_t1_dsu()
1651  {
1652  const char *no = "No", *yes = "Yes";
1653  u_int16_t mii16  = read_mii(16);
1654  u_int8_t isr0    = read_framer(Bt8370_ISR0);
1655  u_int8_t loop    = read_framer(Bt8370_LOOP);
1656  u_int8_t vga_max = read_framer(Bt8370_VGA_MAX) & 0x3F;
1657  u_int8_t alm1    = read_framer(Bt8370_ALM1);
1658  u_int8_t alm3    = read_framer(Bt8370_ALM3);
1659  u_int8_t talm    = read_framer(Bt8370_TALM);
1660  u_int8_t tpatt   = read_framer(Bt8370_TPATT);
1661  u_int8_t tpulse  = read_framer(Bt8370_TLIU_CR);
1662  u_int8_t vga;
1663  u_int8_t bop;
1664  u_int8_t saved_pulse, saved_lbo;
1665
1666  /* d/c write required before read */
1667  write_framer(Bt8370_VGA, 0);
1668  vga = read_framer(Bt8370_VGA) & 0x3F;
1669
1670  print_format();
1671  print_time_slots();
1672  print_tx_clk_src();
1673  print_tx_speed();
1674
1675  saved_pulse     = config.tx_pulse;
1676  config.tx_pulse = tpulse & 0x0E;
1677  saved_lbo       = config.tx_lbo;
1678  config.tx_lbo   = tpulse & 0x30;
1679  print_tx_pulse(0);
1680  config.tx_pulse = saved_pulse;
1681  config.tx_lbo   = saved_lbo;
1682
1683  printf("Tx outputs:    \t\t%sabled\n", (mii16 & MII16_T1_XOE) ? "En" : "Dis");
1684  printf("Line impedance:\t\t%s ohms\n", (mii16 & MII16_T1_Z) ? "120" : "100");
1685  printf("Max line loss: \t\t%4.1f dB\n", vga_dbs(vga_max));
1686  printf("Cur line loss: \t\t%4.1f dB\n", vga_dbs(vga));
1687  printf("Invert data:   \t\t%s\n", (mii16 & MII16_T1_INVERT) ? yes : no);
1688  printf("Line    loop:  \t\t%s\n", (loop & LOOP_LINE)    ? yes : no);
1689  printf("Payload loop:  \t\t%s\n", (loop & LOOP_PAYLOAD) ? yes : no);
1690  printf("Framer  loop:  \t\t%s\n", (loop & LOOP_FRAMER)  ? yes : no);
1691  printf("Analog  loop:  \t\t%s\n", (loop & LOOP_ANALOG)  ? yes : no);
1692  printf("Tx AIS:        \t\t%s\n", ((talm & TALM_TAIS) ||
1693   ((talm & TALM_AUTO_AIS) && (alm1 & ALM1_RLOS))) ? yes : no);
1694  printf("Rx AIS:        \t\t%s\n", (alm1 & ALM1_RAIS)  ? yes : no);
1695  if (((config.format & 1)==0) && (config.format != CFG_FORMAT_E1NONE))
1696    {
1697    printf("Tx RAI:        \t\t%s\n", ((talm & TALM_TYEL) ||
1698     ((talm & TALM_AUTO_YEL) && (alm3 & ALM3_FRED))) ? yes : no);
1699    printf("Rx RAI:        \t\t%s\n", (alm1 & ALM1_RYEL)  ? yes : no);
1700    }
1701  if (config.format == CFG_FORMAT_T1ESF)
1702    {
1703    printf("Tx BOP RAI:    \t\t%s\n", (alm1 & ALM1_RLOF)  ? yes : no);
1704    printf("Rx BOP RAI:    \t\t%s\n", (alm1 & ALM1_RMYEL) ? yes : no);
1705    }
1706  if ((config.format & 0x11) == 0x10) /* E1CAS */
1707    {
1708    printf("Rx TS16 AIS:   \t\t%s\n", (alm3 & ALM3_RMAIS) ? yes : no);
1709    printf("Tx TS16 RAI;   \t\t%s\n",
1710     ((talm & TALM_AUTO_MYEL) && (alm3 & ALM3_SRED)) ? yes : no);
1711    }
1712  printf("Rx LOS analog: \t\t%s\n", (alm1 & ALM1_RALOS) ? yes : no);
1713  printf("Rx LOS digital:\t\t%s\n", (alm1 & ALM1_RLOS)  ? yes : no);
1714  printf("Rx LOF:        \t\t%s\n", (alm1 & ALM1_RLOF)  ? yes : no);
1715  printf("Tx QRS:        \t\t%s\n", (tpatt & 0x10)      ? yes : no);
1716  printf("Rx QRS:        \t\t%s\n", (isr0 & 0x10)       ? yes : no);
1717  printf("LCV errors:    \t\t%d\n",
1718   read_framer(Bt8370_LCV_LO)  + (read_framer(Bt8370_LCV_HI)<<8));
1719  if (config.format != CFG_FORMAT_E1NONE)
1720    {
1721    if ((config.format & 1)==0) printf("Far End Block Errors:\t%d\n",
1722     read_framer(Bt8370_FEBE_LO) + (read_framer(Bt8370_FEBE_HI)<<8));
1723    printf("CRC errors:    \t\t%d\n",
1724     read_framer(Bt8370_CRC_LO)  + (read_framer(Bt8370_CRC_HI)<<8));
1725    printf("Frame errors:  \t\t%d\n",
1726     read_framer(Bt8370_FERR_LO) + (read_framer(Bt8370_FERR_HI)<<8));
1727    printf("Sev Err Frms:  \t\t%d\n", read_framer(Bt8370_AERR) & 0x03);
1728    printf("Change of Frm align:\t%d\n",  (read_framer(Bt8370_AERR) & 0x0C)>>2);
1729    printf("Loss of Frame events:\t%d\n", (read_framer(Bt8370_AERR) & 0xF0)>>4);
1730    }
1731  if (config.format == CFG_FORMAT_T1ESF)
1732    {
1733    if ((bop = read_framer(Bt8370_TBOP)))
1734      printf("Last Tx BOP msg:\t0x%02X (%s)\n", bop, print_t1_bop(bop));
1735    if ((bop = read_framer(Bt8370_RBOP)))
1736      printf("Last Rx BOP msg:\t0x%02X (%s)\n", bop, print_t1_bop(bop&0x3F));
1737    }
1738  print_t1_snmp();
1739  }
1740
1741void t1_cmd(int argc, char **argv)
1742  {
1743  int ch;
1744  const char *optstring = "a:A:B:c:de:E:fF:g:iIlLpPstT:u:U:xX";
1745
1746  while ((ch = getopt(argc, argv, optstring)) != -1)
1747    {
1748    switch (ch)
1749      {
1750      case 'a': /* stop alarms */
1751        {
1752        switch (optarg[0])
1753          {
1754          case 'y': /* Stop sending Yellow Alarm */
1755            {
1756            if ((config.format == CFG_FORMAT_T1SF) ||
1757                (config.format == CFG_FORMAT_E1NONE))
1758              printf("No Yellow alarm for this frame format\n");
1759            else if (config.format == CFG_FORMAT_T1ESF)
1760              write_framer(Bt8370_BOP,  0xE0); /* rbop 25, tbop off */
1761            else
1762              {
1763              u_int8_t talm = read_framer(Bt8370_TALM);
1764              write_framer(Bt8370_TALM, talm & ~TALM_TYEL);
1765	      }
1766            if (verbose) printf("Stop sending Yellow alarm\n");
1767            break;
1768            }
1769          case 'a': /* Stop sending AIS */
1770          case 'b': /* Stop sending Blue Alarm */
1771            {
1772            u_int8_t talm = read_framer(Bt8370_TALM);
1773            write_framer(Bt8370_TALM, talm & ~TALM_TAIS);
1774            if (verbose) printf("Stop sending AIS/Blue signal\n");
1775            break;
1776            }
1777          default:
1778            printf("Unknown alarm: %c\n", optarg[0]);
1779          }
1780        break;
1781        }
1782      case 'A': /* start alarms */
1783        {
1784        switch (optarg[0])
1785          {
1786          case 'y': /* Start sending Yellow Alarm */
1787            {
1788            if ((config.format == CFG_FORMAT_T1SF) ||
1789                (config.format == CFG_FORMAT_E1NONE))
1790              printf("No Yellow alarm for this frame format\n");
1791            else if (config.format == CFG_FORMAT_T1ESF)
1792              {
1793              write_framer(Bt8370_BOP,  0x0F); /* rbop off, tbop cont */
1794              write_framer(Bt8370_TBOP, T1BOP_OOF);
1795	      }
1796            else
1797              {
1798              u_int8_t talm = read_framer(Bt8370_TALM);
1799              write_framer(Bt8370_TALM, talm | TALM_TYEL);
1800	      }
1801            if (verbose) printf("Sending Yellow alarm\n");
1802            break;
1803            }
1804          case 'a': /* Start sending AIS */
1805          case 'b': /* Start sending Blue Alarm */
1806            {
1807            u_int8_t talm = read_framer(Bt8370_TALM);
1808            write_framer(Bt8370_TALM, talm | TALM_TAIS);
1809            if (verbose) printf("Sending AIS/Blue signal\n");
1810            break;
1811            }
1812          default:
1813            printf("Unknown alarm: %c\n", optarg[0]);
1814          }
1815        break;
1816        }
1817      case 'B': /* send BOP msg */
1818        {
1819        u_int8_t bop = (u_int8_t)strtoul(optarg, NULL, 0);
1820        if (config.format == CFG_FORMAT_T1ESF)
1821          {
1822          write_framer(Bt8370_BOP, 0x0B); /* rbop off, tbop 25 */
1823          write_framer(Bt8370_TBOP, bop); /* start sending BOP msg */
1824          sleep(1);  /* sending 25 BOP msgs takes about 100 ms. */
1825          write_framer(Bt8370_BOP, 0xE0); /* rbop 25, tbop off */
1826          if (verbose) printf("Sent '0x%02X' BOP msg 25 times\n", bop);
1827	  }
1828        else
1829          printf("BOP msgs only work in T1-ESF format\n");
1830        break;
1831	}
1832      case 'c': /* set cable length */
1833        {
1834        config.cable_len = strtoul(optarg, NULL, 0);
1835        if (verbose) print_cable_len();
1836        update = 1;
1837        break;
1838        }
1839      case 'd': /* DSU status */
1840      case 's': /* deprecated */
1841        {
1842        print_t1_dsu();
1843        break;
1844        }
1845      case 'e': /* set framimg format */
1846        {
1847        config.format = strtoul(optarg, NULL, 0);
1848        if (verbose) print_format();
1849        update = 1;
1850        break;
1851        }
1852      case 'E': /* set time slots */
1853        {
1854        config.time_slots = strtoul(optarg, NULL, 16);
1855        if (verbose) print_time_slots();
1856        update = 1;
1857        break;
1858        }
1859      case 'f': /* read and print framer regs */
1860        {
1861        int i;
1862        printf("Bt8370 regs:\n");
1863        printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
1864        for (i=0; i<512; i++)
1865          {
1866          if (i%16 == 0) printf("\n%03X: ", i);
1867          printf("%02X ", read_framer(i));
1868	  }
1869        printf("\n\n");
1870        break;
1871	}
1872      case 'F': /* write framer reg */
1873        {
1874        u_int32_t addr = strtoul(optarg, NULL, 0);
1875        u_int32_t data = strtoul(argv[optind++], NULL, 0);
1876        write_framer(addr, data);
1877        if (verbose)
1878          {
1879          data = read_framer(addr);
1880          printf("Write framer register: addr = 0x%02X data = 0x%02X\n", addr, data);
1881	  }
1882        break;
1883	}
1884      case 'g': /* set receiver gain */
1885        {
1886        config.rx_gain_max = strtoul(optarg, NULL, 0);
1887        if (verbose) print_rx_gain_max();
1888        update = 1;
1889        break;
1890        }
1891      case 'i': /* send CSU loopback deactivate inband cmd */
1892        {
1893        if (config.format == CFG_FORMAT_T1SF)
1894          {
1895          if (verbose) printf("Sending 'CSU loop down' inband cmd for 10 secs...");
1896          ioctl_snmp_send(TSEND_RESET);
1897          sleep(10);
1898          ioctl_snmp_send(TSEND_NORMAL);
1899          if (verbose) printf("done\n");
1900	  }
1901        else
1902          printf("Inband loopback cmds only work in T1-SF format");
1903        break;
1904        }
1905      case 'I': /* send CSU loopback activate inband cmd */
1906        {
1907        if (config.format == CFG_FORMAT_T1SF)
1908          {
1909          if (verbose) printf("Sending 'CSU loop up' inband cmd for 10 secs...");
1910          ioctl_snmp_send(TSEND_LINE);
1911          sleep(10);
1912          ioctl_snmp_send(TSEND_NORMAL);
1913          if (verbose) printf("done\n");
1914	  }
1915        else
1916          printf("Inband loopback cmds only work in T1-SF format");
1917        break;
1918        }
1919      case 'l': /* send line loopback deactivate BOP msg */
1920        {
1921        if (config.format == CFG_FORMAT_T1ESF)
1922          {
1923          ioctl_snmp_send(TSEND_RESET);
1924          if (verbose) printf("Sent 'Line Loop Down' BOP cmd\n");
1925	  }
1926        else
1927          printf("BOP msgs only work in T1-ESF format\n");
1928        break;
1929        }
1930      case 'L': /* send line loopback activate BOP msg */
1931        {
1932        if (config.format == CFG_FORMAT_T1ESF)
1933          {
1934          ioctl_snmp_send(TSEND_LINE);
1935          if (verbose) printf("Sent 'Line Loop Up' BOP cmd\n");
1936	  }
1937        else
1938          printf("BOP msgs only work in T1-ESF format\n");
1939        break;
1940        }
1941      case 'p': /* send payload loopback deactivate BOP msg */
1942        {
1943        if (config.format == CFG_FORMAT_T1ESF)
1944          {
1945          ioctl_snmp_send(TSEND_RESET);
1946          if (verbose) printf("Sent 'Payload Loop Down' BOP cmd\n");
1947	  }
1948        else
1949          printf("BOP msgs only work in T1-ESF format\n");
1950        break;
1951        }
1952      case 'P': /* send payload loopback activate BOP msg */
1953        {
1954        if (config.format == CFG_FORMAT_T1ESF)
1955          {
1956          ioctl_snmp_send(TSEND_PAYLOAD);
1957          if (verbose) printf("Sent 'Payload Loop Up' BOP cmd\n");
1958	  }
1959        else
1960          printf("BOP msgs only work in T1-ESF format\n");
1961        break;
1962        }
1963      case 't': /* stop sending test pattern */
1964        {
1965        ioctl_snmp_send(TSEND_NORMAL);
1966        if (verbose) printf("Stop sending test pattern\n");
1967        break;
1968        }
1969      case 'T': /* start sending test pattern */
1970        {
1971        u_int8_t patt = (u_int8_t)strtoul(optarg, NULL, 0);
1972        write_framer(Bt8370_TPATT, 0x10 + patt);
1973        write_framer(Bt8370_RPATT, 0x30 + patt);
1974        if (verbose) print_t1_test_pattern(patt);
1975        break;
1976        }
1977      case 'u': /* set transmit pulse shape */
1978        {
1979        config.tx_pulse = strtoul(optarg, NULL, 0);
1980        if (verbose) print_tx_pulse(0);
1981        update = 1;
1982        break;
1983        }
1984      case 'U': /* set tx line build-out */
1985        {
1986        if (config.tx_pulse == CFG_PULSE_T1CSU)
1987          {
1988          config.tx_lbo = strtoul(optarg, NULL, 0);
1989          if (verbose) print_tx_pulse(0);
1990          update = 1;
1991	  }
1992        else
1993          printf("LBO only meaningful if Tx Pulse is T1CSU\n");
1994        break;
1995        }
1996      case 'x': /* disable transmitter outputs */
1997        {
1998        write_mii(16, read_mii(16) & ~MII16_T1_XOE);
1999        if (verbose) printf("Transmitter outputs disabled\n");
2000        break;
2001	}
2002      case 'X': /* enable transmitter outputs */
2003        {
2004        write_mii(16, read_mii(16) |  MII16_T1_XOE);
2005        if (verbose) printf("Transmitter outputs enabled\n");
2006        break;
2007        }
2008      default:
2009        {
2010        printf("Unknown command char: %c\n", ch);
2011        exit(1);
2012        } /* case */
2013      } /* switch */
2014    } /* while */
2015  } /* proc */
2016
2017/* used when reading Motorola S-Record format ROM files */
2018unsigned char read_hex(FILE *f)
2019  {
2020  unsigned char a, b, c;
2021  for (a=0, b=0; a<2; a++)
2022    {
2023    c = fgetc(f);
2024    c -= 48;
2025    if (c > 9) c -= 7;
2026    b = (b<<4) | (c & 0xF);
2027    }
2028  checksum += b;
2029  return b;
2030  }
2031
2032void load_xilinx(char *name)
2033  {
2034  FILE *f;
2035  char *ucode;
2036  int c, i, length;
2037
2038  if (verbose) printf("Load firmware from file %s...\n", name);
2039  if ((f = fopen(name, "r")) == 0)
2040    {
2041    perror("Failed to open file");
2042    exit(1);
2043    }
2044
2045  ucode = (char *)malloc(8192); bzero(ucode, 8192);
2046
2047  c = fgetc(f);
2048  if (c == 'X')
2049    { /* Xilinx raw bits file (foo.rbt) */
2050    /* skip seven lines of boiler plate */
2051    for (i=0; i<7;) if ((c=fgetc(f))=='\n') i++;
2052    /* build a dense bit array */
2053    i = length = 0;
2054    while ((c=fgetc(f))!=EOF)
2055      {  /* LSB first */
2056      if (c=='1') ucode[length] |= 1<<i++;
2057      if (c=='0') i++;
2058      if (i==8) { i=0; length++; }
2059      }
2060    }
2061  else if (c == 'S')
2062    { /* Motarola S records (foo.exo) */
2063    int blklen;
2064    length = 0;
2065    ungetc(c, f);
2066    while ((c = fgetc(f)) != EOF)
2067      {
2068      if (c != 'S')
2069        {
2070        printf("I'm confused; I expected an 'S'\n");
2071        exit(1);
2072        }
2073      c = fgetc(f);
2074      if (c == '9') break;
2075      else if (c == '1')
2076        {
2077        checksum = 0;
2078        blklen = read_hex(f) -3;
2079        read_hex(f); /* hi blkaddr */
2080        read_hex(f); /* lo blkaddr */
2081        for (i=0; i<blklen; i++)
2082          ucode[length++] = read_hex(f);
2083        read_hex(f); /* process but ignore checksum */
2084        if (checksum != 0xFF)
2085          {
2086          printf("File checksum error\n");
2087          exit(1);
2088          }
2089        c = fgetc(f); /* throw away eol */
2090        c = fgetc(f); /* throw away eol */
2091        }
2092      else
2093        {
2094        printf("I'm confused; I expected a '1' or a '9'\n");
2095        exit(1);
2096        }
2097      } /* while */
2098    } /* Motorola S-Record */
2099  else
2100    {
2101    printf("Unknown file type giving up\n");
2102    exit(1);
2103    }
2104
2105  load_xilinx_from_file(ucode, length);
2106  }
2107
2108/* 32-bit CRC calculated right-to-left over 8-bit bytes */
2109u_int32_t crc32(u_int8_t *bufp, int len)
2110  {
2111  int bit, i;
2112  u_int32_t data;
2113  u_int32_t crc  = 0xFFFFFFFFL;
2114  u_int32_t poly = 0xEDB88320L;
2115
2116  for (i = 0; i < len; i++)
2117    for (data = *bufp++, bit = 0; bit < 8; bit++, data >>= 1)
2118      crc = (crc >> 1) ^ (((crc ^ data) & 1) ? poly : 0);
2119
2120  return crc;
2121  }
2122
2123/* 8-bit CRC calculated left-to-right over 16-bit words */
2124u_int8_t crc8(u_int16_t *bufp, int len)
2125  {
2126  int bit, i;
2127  u_int16_t data;
2128  u_int8_t crc  = 0xFF;
2129  u_int8_t poly = 0x07;
2130
2131  for (i = 0; i < len; i++)
2132    for (data = *bufp++, bit = 15; bit >= 0; bit--)
2133      {
2134      if ((i==8) && (bit==7)) break;
2135      crc = (crc << 1) ^ ((((crc >> 7) ^ (data >> bit)) & 1) ? poly : 0);
2136      }
2137  return crc;
2138  }
2139
2140void main_cmd(int argc, char **argv)
2141  {
2142  int ch;
2143  const char *optstring = "13a:bBcCdDeEf:gG:hi:L:mM:pP:sS:tT:uUvVw:x:X:yY?";
2144
2145  while ((ch = getopt(argc, argv, optstring)) != -1)
2146    {
2147    switch (ch)
2148      {
2149      case '1': /* T1 commands */
2150        {
2151        if (verbose) printf("Doing T1 settings\n");
2152        if (status.card_type != CSID_LMC_T1E1)
2153          {
2154          printf("T1 settings only apply to T1E1 cards\n");
2155          exit(1);
2156          }
2157        t1_cmd(argc, argv);
2158        break;
2159        }
2160      case '3': /* T3 commands */
2161        {
2162        if (verbose) printf("Doing T3 settings\n");
2163        if (status.card_type != CSID_LMC_T3)
2164          {
2165          printf("T3 settings only apply to T3 cards\n");
2166          exit(1);
2167          }
2168        t3_cmd(argc, argv);
2169        break;
2170        }
2171      case 'a': /* clock source */
2172        {
2173        if ((status.card_type != CSID_LMC_T1E1) ||
2174            (status.card_type != CSID_LMC_HSSI) ||
2175            (status.card_type != CSID_LMC_HSSIc))
2176          {
2177          if (verbose) print_tx_clk_src();
2178          config.tx_clk_src = strtoul(optarg, NULL, 0);
2179          update = 1;
2180	  }
2181        else
2182          printf("txclksrc only applies to T1E1 and HSSI card types\n");
2183        break;
2184        }
2185      case 'b': /* read bios rom */
2186        {
2187        unsigned int i;
2188        printf("Bios ROM:\n");
2189        printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
2190        for (i=0; i<256; i++)
2191          {
2192          if (i%16 == 0) printf("\n%02X: ", i);
2193          printf("%02X ", read_bios_rom(i));
2194	  }
2195        printf("\n\n");
2196        break;
2197	}
2198      case 'B': /* write bios rom */
2199        {
2200        unsigned int i;
2201        for (i=0; i<256; i++) write_bios_rom(i, 255-i);
2202        if (verbose) printf("wrote (0..255) to bios rom addrs (0..255)\n");
2203        break;
2204	}
2205      case 'c': /* set crc_len = 16 */
2206        {
2207        config.crc_len = CFG_CRC_16;
2208        if (verbose) print_crc_len();
2209        update = 1;
2210        break;
2211        }
2212      case 'C': /* set crc_len = 32 */
2213        {
2214        config.crc_len = CFG_CRC_32;
2215        if (verbose) print_crc_len();
2216        update = 1;
2217        break;
2218        }
2219      case 'd': /* clear DEBUG flag */
2220        {
2221        config.debug = 0;
2222        if (verbose) printf("DEBUG flag cleared\n");
2223        update = 1;
2224        break;
2225	}
2226      case 'D': /* set DEBUG flag */
2227        {
2228        config.debug = 1;
2229        if (verbose) printf("DEBUG flag set\n");
2230        update = 1;
2231        break;
2232	}
2233      case 'e': /* set DTE (default) */
2234        {
2235        if ((status.card_type == CSID_LMC_SSI) ||
2236            (status.card_type == CSID_LMC_HSSIc))
2237          {
2238          config.dte_dce = CFG_DTE;
2239          if (verbose) print_dte_dce();
2240          update = 1;
2241	  }
2242        else
2243          printf("DTE cmd only applies to SSI & HSSIc cards\n");
2244        break;
2245	}
2246      case 'E': /* set DCE */
2247        {
2248        if ((status.card_type == CSID_LMC_SSI) ||
2249            (status.card_type == CSID_LMC_HSSIc))
2250          {
2251          config.dte_dce = CFG_DCE;
2252          if (verbose) print_dte_dce();
2253          update = 1;
2254	  }
2255        else
2256          printf("DCE cmd only applies to SSI & HSSIc cards\n");
2257        break;
2258	}
2259      case 'f': /* set synth osc freq */
2260        {
2261        if ((status.card_type == CSID_LMC_SSI) ||
2262            (status.card_type == CSID_LMC_HSSIc))
2263          {
2264          synth_freq(strtoul(optarg, NULL, 0));
2265          write_synth(config.synth);
2266          if (verbose) print_synth_freq();
2267	  }
2268        else
2269          printf("synth osc freq only applies to SSI & HSSIc cards\n");
2270        break;
2271        }
2272      case 'g': /* load gate array microcode from ROM */
2273        {
2274        load_xilinx_from_rom();
2275        if (verbose) printf("gate array configured from on-board ROM\n");
2276        break;
2277        }
2278      case 'G': /* load gate array microcode from file */
2279        {
2280        load_xilinx(optarg);
2281        if (verbose) printf("gate array configured from file %s\n", optarg);
2282        break;
2283        }
2284      case 'h': /* help */
2285      case '?':
2286        {
2287        usage();
2288        exit(0);
2289        /*NOTREACHED*/
2290        }
2291      case 'i': /* interface name */
2292        {
2293        /* already scanned this */
2294        break;
2295        }
2296      case 'L': /* set loopback modes */
2297        {
2298        config.loop_back = strtoul(optarg, NULL, 0);
2299        if (verbose) print_loop_back(0);
2300        update = 1;
2301        break;
2302	}
2303      case 'm': /* read and print MII regs */
2304        {
2305        int i;
2306        printf("MII regs:\n");
2307        printf("      0    1    2    3    4    5    6    7");
2308        for (i=0; i<32; i++)
2309          {
2310          u_int16_t mii = read_mii(i);
2311          if (i%8 == 0) printf("\n%02X: ", i);
2312          printf("%04X ", mii);
2313	  }
2314        printf("\n\n");
2315        break;
2316        }
2317      case 'M': /* write MII reg */
2318        {
2319        u_int32_t addr = strtoul(optarg, NULL, 0);
2320        u_int32_t data = strtoul(argv[optind++], NULL, 0);
2321        write_mii(addr, data);
2322        if (verbose)
2323          {
2324          data = read_mii(addr);
2325          printf("Write mii register: addr = 0x%02X data = 0x%04X\n", addr, data);
2326	  }
2327        break;
2328        }
2329      case 'p': /* read and print PCI config regs */
2330        {
2331        int i;
2332        printf("21140A PCI Config regs:\n");
2333        printf("       0        1        2        3");
2334        for (i=0; i<16; i++)
2335          {
2336          if (i%4 == 0) printf("\n%X: ", i);
2337          printf("%08X ", read_pci_config(i<<2));
2338	  }
2339        printf("\n\n");
2340        break;
2341	}
2342      case 'P': /* write PCI config reg */
2343        {
2344        u_int32_t addr = strtoul(optarg, NULL, 0);
2345        u_int32_t data = strtoul(argv[optind++], NULL, 0);
2346        write_pci_config(addr, data);
2347        if (verbose)
2348          {
2349          data = read_pci_config(addr);
2350          printf("Write PCI config reg: addr = 0x%02X data = 0x%08X\n", addr, data);
2351	  }
2352        break;
2353	}
2354      case 's': /* read and print Tulip SROM */
2355        {
2356        int i;
2357        printf("21140A SROM:\n");
2358        printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
2359        for (i=0; i<64; i++)
2360          {
2361          u_int16_t srom = read_srom(i);
2362          if (i%8 == 0) printf("\n%02X: ", i<<1);
2363          printf("%02X %02X ", srom & 0xFF, srom>>8);
2364	  }
2365        printf("\n\n");
2366        break;
2367	}
2368      case 'S': /* write Tulip SROM loc */
2369        {
2370        int i;
2371        u_int16_t srom[64];
2372        u_int32_t board = strtoul(optarg, NULL, 0);
2373        /* board: HSSI=3, DS3=4, SSI=5, T1E1=6, HSSIc=7 */
2374
2375        for (i=0; i<64; i++) srom[i] = 0;
2376        srom[0]  = 0x1376; /* subsys vendor id */
2377        srom[1]  = board ? (u_int16_t)board : (read_mii(3)>>4 & 0xF) +1;
2378        /* Tulip hardware checks this checksum */
2379        srom[8]  = crc8(srom, 9);
2380        srom[10] = 0x6000; /* ethernet address */
2381        srom[11] = 0x0099; /* ethernet address */
2382        srom[12] = read_srom(12); /* 0x0000; */
2383        /* srom checksum is low 16 bits of Ethernet CRC-32 */
2384        srom[63] = (u_int16_t)~crc32((u_int8_t *)srom, 126);
2385
2386#if 0 /* really write it */
2387        for (i=0; i<64; i++) write_srom(i, srom[i]);
2388#else /* print what would be written */
2389        printf("Caution! Recompile %s to enable this.\n", progname);
2390        printf("This is what would have been written:\n");
2391        printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
2392        for (i=0; i<64; i++)
2393          {
2394          if (i%8 == 0) printf("\n%02X: ", i<<1);
2395          printf("%02X %02X ", srom[i] & 0xFF, srom[i]>>8);
2396          }
2397        printf("\n\n");
2398#endif
2399        break;
2400	}
2401      case 't': /* read and print Tulip CSRs */
2402        {
2403        int i;
2404        printf("21140A CSRs:\n");
2405        printf("       0        1        2        3");
2406        for (i=0; i<16; i++)
2407          {
2408          if (i%4 == 0) printf("\n%X: ", i);
2409          printf("%08X ", read_csr(i));
2410	  }
2411        printf("\n\n");
2412        break;
2413	}
2414      case 'T': /* write Tulip CSR */
2415        {
2416        u_int32_t addr = strtoul(optarg, NULL, 0);
2417        u_int32_t data = strtoul(argv[optind++], NULL, 0);
2418        write_csr(addr, data);
2419        if (verbose)
2420          {
2421          data = read_csr(addr);
2422          printf("Write 21140A CSR: addr = 0x%02X data = 0x%08X\n", addr, data);
2423	  }
2424        break;
2425	}
2426      case 'u': /* reset event counters */
2427        {
2428        ioctl_reset_cntrs();
2429        if (verbose) printf("Event counters reset\n");
2430        break;
2431	}
2432      case 'U': /* reset gate array */
2433        {
2434        reset_xilinx();
2435        if (verbose) printf("gate array reset\n");
2436        break;
2437        }
2438      case 'v': /* set verbose mode */
2439        {
2440        verbose = 1;
2441        break;
2442        }
2443      case 'V': /* print card configuration */
2444        {
2445        summary = 1;
2446        break;
2447	}
2448      case 'w':
2449        {
2450        waittime = strtoul(optarg, NULL, 0);
2451        break;
2452	}
2453      case 'x': /* <number> set line protocol */
2454        {
2455        config.keep_alive = 1; /* required for LMI operation */
2456        config.proto = strtoul(optarg, NULL, 0);
2457        if (verbose) printf("line protocol set to %d\n", config.proto);
2458        update = 1;
2459        break;
2460	}
2461      case 'X': /* <number> set line package */
2462        {
2463        config.keep_alive = 1; /* required for LMI operation */
2464        config.stack = strtoul(optarg, NULL, 0);
2465        if (verbose) printf("line package set to %d\n", config.stack);
2466        update = 1;
2467        break;
2468	}
2469      case 'y': /* disable SPPP keep-alive packets */
2470        {
2471        if ((config.stack == STACK_SPPP) &&
2472            (config.proto == PROTO_FRM_RLY))
2473          printf("keep-alives must be ON for Frame-Relay/SPPP\n");
2474        else
2475          {
2476          config.keep_alive = 0;
2477          if (verbose) printf("SPPP keep-alive packets disabled\n");
2478          update = 1;
2479	  }
2480        break;
2481	}
2482      case 'Y': /* enable SPPP keep-alive packets */
2483        {
2484        config.keep_alive = 1;
2485        if (verbose) printf("SPPP keep-alive packets enabled\n");
2486        update = 1;
2487        break;
2488	}
2489      default:
2490        {
2491        printf("Unknown command char: %c\n", ch);
2492        exit(1);
2493	} /* case */
2494      } /* switch */
2495    } /* while */
2496  } /* proc */
2497
2498int main(int argc, char **argv)
2499  {
2500  int i, error;
2501
2502  progname = (char *)argv[0];
2503
2504  /* 1) Read the interface name from the command line. */
2505#if __linux__
2506  ifname = (argc==1) ? "hdlc0" : (char *)argv[1];
2507#else
2508  ifname = (argc==1) ? DEVICE_NAME"0" : (char *)argv[1];
2509#endif
2510
2511  /* 2) Open the device; decide if netgraph is being used, */
2512  /* use netgraph if ifname ends with ":" */
2513  for (i=0; ifname[i] != 0; i++) continue;
2514
2515  /* Get a socket type file descriptor. */
2516#if defined(NETGRAPH)
2517  if ((netgraph = (ifname[i-1] == ':')))
2518    error = NgMkSockNode(NULL, &fdcs, NULL);
2519  else
2520#endif
2521    error = fdcs = socket(AF_INET, SOCK_DGRAM, 0);
2522  if (error < 0)
2523    {
2524    fprintf(stderr, "%s: %s() failed: %s\n", progname,
2525     netgraph? "NgMkSockNode" : "socket", strerror(errno));
2526    exit(1);
2527    }
2528
2529  /* 3) Read the current interface configuration from the driver. */
2530  ioctl_read_config();
2531  ioctl_read_status();
2532
2533  summary = (argc <= 2);  /* print summary at end */
2534  update  = 0;	/* write to card at end */
2535
2536  /* 4) Read the command line args and carry out their actions. */
2537  optind = 2;
2538  if (argc > 2) main_cmd(argc, argv);
2539
2540  if (summary) print_summary();
2541
2542  /* 5) Write the modified interface configuration to the driver. */
2543  if (update) ioctl_write_config();
2544
2545  while (waittime)
2546    {
2547    struct status old;
2548
2549    ioctl_read_status();
2550    old = status;
2551    sleep(waittime);
2552    ioctl_read_status();
2553
2554    status.cntrs.ibytes    -= old.cntrs.ibytes;
2555    status.cntrs.obytes    -= old.cntrs.obytes;
2556    status.cntrs.ipackets  -= old.cntrs.ipackets;
2557    status.cntrs.opackets  -= old.cntrs.opackets;
2558    status.cntrs.ierrors   -= old.cntrs.ierrors;
2559    status.cntrs.oerrors   -= old.cntrs.oerrors;
2560    status.cntrs.idrops    -= old.cntrs.idrops;
2561    status.cntrs.missed    -= old.cntrs.missed;
2562    status.cntrs.odrops    -= old.cntrs.odrops;
2563    status.cntrs.fifo_over -= old.cntrs.fifo_over;
2564    status.cntrs.overruns  -= old.cntrs.overruns;
2565    status.cntrs.fifo_under-= old.cntrs.fifo_under;
2566    status.cntrs.underruns -= old.cntrs.underruns;
2567    status.cntrs.crc_errs  -= old.cntrs.crc_errs;
2568    status.cntrs.lcv_errs  -= old.cntrs.lcv_errs;
2569    status.cntrs.frm_errs  -= old.cntrs.frm_errs;
2570    status.cntrs.febe_errs -= old.cntrs.febe_errs;
2571    status.cntrs.par_errs  -= old.cntrs.par_errs;
2572    status.cntrs.cpar_errs -= old.cntrs.cpar_errs;
2573    status.cntrs.mfrm_errs -= old.cntrs.mfrm_errs;
2574    status.cntrs.rxbuf     -= old.cntrs.rxbuf;
2575    status.cntrs.txdma     -= old.cntrs.txdma;
2576    status.cntrs.lck_watch -= old.cntrs.lck_watch;
2577    status.cntrs.lck_intr  -= old.cntrs.lck_intr;
2578    status.cntrs.spare1    -= old.cntrs.spare1;
2579    status.cntrs.spare2    -= old.cntrs.spare2;
2580    status.cntrs.spare3    -= old.cntrs.spare3;
2581    status.cntrs.spare4    -= old.cntrs.spare4;
2582
2583    putchar('\n');
2584
2585    print_summary();
2586    }
2587
2588  exit(0);
2589  /* NOTREACHED */
2590  }
2591