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