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