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