FreeBSD/Linux Kernel Cross Reference
sys/dev/cp/if_cp.c
1 /*-
2 * Cronyx-Tau-PCI adapter driver for FreeBSD.
3 * Supports PPP/HDLC, Cisco/HDLC and FrameRelay protocol in synchronous mode,
4 * and asyncronous channels with full modem control.
5 * Keepalive protocol implemented in both Cisco and PPP modes.
6 *
7 * Copyright (C) 1999-2004 Cronyx Engineering.
8 * Author: Kurakin Roman, <rik@cronyx.ru>
9 *
10 * Copyright (C) 1999-2002 Cronyx Engineering.
11 * Author: Serge Vakulenko, <vak@cronyx.ru>
12 *
13 * This software is distributed with NO WARRANTIES, not even the implied
14 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * Authors grant any other persons or organisations a permission to use,
17 * modify and redistribute this software in source and binary forms,
18 * as long as this message is kept with the software, all derivative
19 * works or modified versions.
20 *
21 * Cronyx Id: if_cp.c,v 1.1.2.41 2004/06/23 17:09:13 rik Exp $
22 */
23
24 #include <sys/cdefs.h>
25 __FBSDID("$FreeBSD: releng/5.4/sys/dev/cp/if_cp.c 141479 2005-02-07 21:33:40Z rik $");
26
27 #include <sys/param.h>
28 #include <sys/ucred.h>
29 #include <sys/proc.h>
30 #include <sys/systm.h>
31 #include <sys/mbuf.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/conf.h>
35 #include <sys/malloc.h>
36 #include <sys/socket.h>
37 #include <sys/sockio.h>
38 #include <sys/sysctl.h>
39 #include <sys/tty.h>
40 #include <sys/bus.h>
41 #include <vm/vm.h>
42 #include <vm/pmap.h>
43 #include <net/if.h>
44 #include <dev/pci/pcivar.h>
45 #include <dev/pci/pcireg.h>
46 #include <machine/bus.h>
47 #include <sys/rman.h>
48 #include "opt_ng_cronyx.h"
49 #ifdef NETGRAPH_CRONYX
50 # include "opt_netgraph.h"
51 # ifndef NETGRAPH
52 # error #option NETGRAPH missed from configuration
53 # endif
54 # include <netgraph/ng_message.h>
55 # include <netgraph/netgraph.h>
56 # include <dev/cp/ng_cp.h>
57 #else
58 # include <net/if_sppp.h>
59 # define PP_CISCO IFF_LINK2
60 # include <net/bpf.h>
61 #endif
62 #include <dev/cx/machdep.h>
63 #include <dev/cp/cpddk.h>
64 #include <machine/cserial.h>
65 #include <machine/resource.h>
66 #include <machine/pmap.h>
67
68 /* If we don't have Cronyx's sppp version, we don't have fr support via sppp */
69 #ifndef PP_FR
70 #define PP_FR 0
71 #endif
72
73 #define CP_DEBUG(d,s) ({if (d->chan->debug) {\
74 printf ("%s: ", d->name); printf s;}})
75 #define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\
76 printf ("%s: ", d->name); printf s;}})
77 #define CP_LOCK_NAME "cpX"
78
79 static int cp_mpsafenet = 1;
80 TUNABLE_INT("debug.cp.mpsafenet", &cp_mpsafenet);
81 SYSCTL_NODE(_debug, OID_AUTO, cp, CTLFLAG_RD, 0, "Cronyx Tau-PCI Adapters");
82 SYSCTL_INT(_debug_cp, OID_AUTO, mpsafenet, CTLFLAG_RD, &cp_mpsafenet, 0,
83 "Enable/disable MPSAFE network support for Cronyx Tau-PCI Adapters");
84
85 #define CP_LOCK(_bd) do { \
86 if (cp_mpsafenet) \
87 mtx_lock (&(_bd)->cp_mtx); \
88 } while (0)
89 #define CP_UNLOCK(_bd) do { \
90 if (cp_mpsafenet) \
91 mtx_unlock (&(_bd)->cp_mtx); \
92 } while (0)
93
94 #define CP_LOCK_ASSERT(_bd) do { \
95 if (cp_mpsafenet) \
96 mtx_assert (&(_bd)->cp_mtx, MA_OWNED); \
97 } while (0)
98
99 #define CDEV_MAJOR 134
100
101 static int cp_probe __P((device_t));
102 static int cp_attach __P((device_t));
103 static int cp_detach __P((device_t));
104
105 static device_method_t cp_methods[] = {
106 /* Device interface */
107 DEVMETHOD(device_probe, cp_probe),
108 DEVMETHOD(device_attach, cp_attach),
109 DEVMETHOD(device_detach, cp_detach),
110
111 {0, 0}
112 };
113
114 typedef struct _cp_dma_mem_t {
115 unsigned long phys;
116 void *virt;
117 size_t size;
118 bus_dma_tag_t dmat;
119 bus_dmamap_t mapp;
120 } cp_dma_mem_t;
121
122 typedef struct _drv_t {
123 char name [8];
124 int running;
125 cp_chan_t *chan;
126 cp_board_t *board;
127 cp_dma_mem_t dmamem;
128 #ifdef NETGRAPH
129 char nodename [NG_NODELEN+1];
130 hook_p hook;
131 hook_p debug_hook;
132 node_p node;
133 struct ifqueue queue;
134 struct ifqueue hi_queue;
135 short timeout;
136 struct callout timeout_handle;
137 #else
138 struct ifqueue queue;
139 struct sppp pp;
140 #endif
141 struct cdev *devt;
142 } drv_t;
143
144 typedef struct _bdrv_t {
145 cp_board_t *board;
146 struct resource *cp_res;
147 struct resource *cp_irq;
148 void *cp_intrhand;
149 cp_dma_mem_t dmamem;
150 drv_t channel [NCHAN];
151 struct mtx cp_mtx;
152 } bdrv_t;
153
154 static driver_t cp_driver = {
155 "cp",
156 cp_methods,
157 sizeof(bdrv_t),
158 };
159
160 static devclass_t cp_devclass;
161
162 static void cp_receive (cp_chan_t *c, unsigned char *data, int len);
163 static void cp_transmit (cp_chan_t *c, void *attachment, int len);
164 static void cp_error (cp_chan_t *c, int data);
165 static void cp_up (drv_t *d);
166 static void cp_start (drv_t *d);
167 static void cp_down (drv_t *d);
168 static void cp_watchdog (drv_t *d);
169 #ifdef NETGRAPH
170 extern struct ng_type typestruct;
171 #else
172 static void cp_ifstart (struct ifnet *ifp);
173 static void cp_tlf (struct sppp *sp);
174 static void cp_tls (struct sppp *sp);
175 static void cp_ifwatchdog (struct ifnet *ifp);
176 static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data);
177 static void cp_initialize (void *softc);
178 #endif
179
180 static cp_board_t *adapter [NBRD];
181 static drv_t *channel [NBRD*NCHAN];
182 static struct callout led_timo [NBRD];
183 static struct callout timeout_handle;
184
185 static int cp_destroy = 0;
186
187 /*
188 * Print the mbuf chain, for debug purposes only.
189 */
190 static void printmbuf (struct mbuf *m)
191 {
192 printf ("mbuf:");
193 for (; m; m=m->m_next) {
194 if (m->m_flags & M_PKTHDR)
195 printf (" HDR %d:", m->m_pkthdr.len);
196 if (m->m_flags & M_EXT)
197 printf (" EXT:");
198 printf (" %d", m->m_len);
199 }
200 printf ("\n");
201 }
202
203 /*
204 * Make an mbuf from data.
205 */
206 static struct mbuf *makembuf (void *buf, unsigned len)
207 {
208 struct mbuf *m;
209
210 MGETHDR (m, M_DONTWAIT, MT_DATA);
211 if (! m)
212 return 0;
213 MCLGET (m, M_DONTWAIT);
214 if (! (m->m_flags & M_EXT)) {
215 m_freem (m);
216 return 0;
217 }
218 m->m_pkthdr.len = m->m_len = len;
219 bcopy (buf, mtod (m, caddr_t), len);
220 return m;
221 }
222
223 static int cp_probe (device_t dev)
224 {
225 if ((pci_get_vendor (dev) == cp_vendor_id) &&
226 (pci_get_device (dev) == cp_device_id)) {
227 device_set_desc (dev, "Cronyx-Tau-PCI serial adapter");
228 return 0;
229 }
230 return ENXIO;
231 }
232
233 static void cp_timeout (void *arg)
234 {
235 drv_t *d;
236 int s, i, k;
237
238 for (i = 0; i < NBRD; ++i) {
239 if (adapter[i] == NULL)
240 continue;
241 for (k = 0; k < NCHAN; ++k) {
242 s = splimp ();
243 if (cp_destroy) {
244 splx (s);
245 return;
246 }
247 d = channel[i * NCHAN + k];
248 if (!d) {
249 splx (s);
250 continue;
251 }
252 CP_LOCK ((bdrv_t *)d->board->sys);
253 switch (d->chan->type) {
254 case T_G703:
255 cp_g703_timer (d->chan);
256 break;
257 case T_E1:
258 cp_e1_timer (d->chan);
259 break;
260 case T_E3:
261 case T_T3:
262 case T_STS1:
263 cp_e3_timer (d->chan);
264 break;
265 default:
266 break;
267 }
268 CP_UNLOCK ((bdrv_t *)d->board->sys);
269 splx (s);
270 }
271 }
272 s = splimp ();
273 if (!cp_destroy)
274 callout_reset (&timeout_handle, hz, cp_timeout, 0);
275 splx (s);
276 }
277
278 static void cp_led_off (void *arg)
279 {
280 cp_board_t *b = arg;
281 bdrv_t *bd = (bdrv_t *) b->sys;
282 int s;
283 s = splimp ();
284 if (cp_destroy) {
285 splx (s);
286 return;
287 }
288 CP_LOCK (bd);
289 cp_led (b, 0);
290 CP_UNLOCK (bd);
291 splx (s);
292 }
293
294 static void cp_intr (void *arg)
295 {
296 bdrv_t *bd = arg;
297 cp_board_t *b = bd->board;
298 #ifndef NETGRAPH
299 int i;
300 #endif
301 int s = splimp ();
302 if (cp_destroy) {
303 splx (s);
304 return;
305 }
306 CP_LOCK (bd);
307 /* Check if we are ready */
308 if (b->sys == NULL) {
309 /* Not we are not, just cleanup. */
310 cp_interrupt_poll (b, 1);
311 CP_UNLOCK (bd);
312 return;
313 }
314 /* Turn LED on. */
315 cp_led (b, 1);
316
317 cp_interrupt (b);
318
319 /* Turn LED off 50 msec later. */
320 callout_reset (&led_timo[b->num], hz/20, cp_led_off, b);
321 CP_UNLOCK (bd);
322 splx (s);
323
324 #ifndef NETGRAPH
325 /* Pass packets in a lock-free state */
326 for (i = 0; i < NCHAN && b->chan[i].type; i++) {
327 drv_t *d = b->chan[i].sys;
328 struct mbuf *m;
329 while (_IF_QLEN(&d->queue)) {
330 IF_DEQUEUE (&d->queue,m);
331 if (!m)
332 continue;
333 sppp_input (&d->pp.pp_if, m);
334 }
335 }
336 #endif
337 }
338
339 extern struct cdevsw cp_cdevsw;
340
341 static void
342 cp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error)
343 {
344 unsigned long *addr;
345
346 if (error)
347 return;
348
349 KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg));
350 addr = arg;
351 *addr = segs->ds_addr;
352 }
353
354 static int
355 cp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem)
356 {
357 int error;
358
359 error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT,
360 BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1,
361 dmem->size, 0, NULL, NULL, &dmem->dmat);
362 if (error) {
363 if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum);
364 else printf ("cp%d: ", bnum);
365 printf ("couldn't allocate tag for dma memory\n");
366 return 0;
367 }
368 error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt,
369 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp);
370 if (error) {
371 if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum);
372 else printf ("cp%d: ", bnum);
373 printf ("couldn't allocate mem for dma memory\n");
374 bus_dma_tag_destroy (dmem->dmat);
375 return 0;
376 }
377 error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt,
378 dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0);
379 if (error) {
380 if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum);
381 else printf ("cp%d: ", bnum);
382 printf ("couldn't load mem map for dma memory\n");
383 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp);
384 bus_dma_tag_destroy (dmem->dmat);
385 return 0;
386 }
387 return 1;
388 }
389
390 static void
391 cp_bus_dma_mem_free (cp_dma_mem_t *dmem)
392 {
393 bus_dmamap_unload (dmem->dmat, dmem->mapp);
394 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp);
395 bus_dma_tag_destroy (dmem->dmat);
396 }
397
398 /*
399 * Called if the probe succeeded.
400 */
401 static int cp_attach (device_t dev)
402 {
403 bdrv_t *bd = device_get_softc (dev);
404 int unit = device_get_unit (dev);
405 char *cp_ln = CP_LOCK_NAME;
406 unsigned short res;
407 vm_offset_t vbase;
408 int rid, error;
409 cp_board_t *b;
410 cp_chan_t *c;
411 drv_t *d;
412 int s = splimp ();
413
414 b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK);
415 if (!b) {
416 printf ("cp%d: couldn't allocate memory\n", unit);
417 splx (s);
418 return (ENXIO);
419 }
420 bzero (b, sizeof(cp_board_t));
421
422 bd->board = b;
423 rid = PCIR_BAR(0);
424 bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid,
425 0, ~0, 1, RF_ACTIVE);
426 if (! bd->cp_res) {
427 printf ("cp%d: cannot map memory\n", unit);
428 free (b, M_DEVBUF);
429 splx (s);
430 return (ENXIO);
431 }
432 vbase = (vm_offset_t) rman_get_virtual (bd->cp_res);
433
434 cp_ln[2] = '' + unit;
435 mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE);
436 res = cp_init (b, unit, (u_char*) vbase);
437 if (res) {
438 printf ("cp%d: can't init, error code:%x\n", unit, res);
439 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
440 free (b, M_DEVBUF);
441 splx (s);
442 return (ENXIO);
443 }
444
445 bd->dmamem.size = sizeof(cp_qbuf_t);
446 if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) {
447 free (b, M_DEVBUF);
448 splx (s);
449 return (ENXIO);
450 }
451 CP_LOCK (bd);
452 cp_reset (b, bd->dmamem.virt, bd->dmamem.phys);
453 CP_UNLOCK (bd);
454
455 rid = 0;
456 bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
457 RF_SHAREABLE | RF_ACTIVE);
458 if (! bd->cp_irq) {
459 cp_destroy = 1;
460 printf ("cp%d: cannot map interrupt\n", unit);
461 bus_release_resource (dev, SYS_RES_MEMORY,
462 PCIR_BAR(0), bd->cp_res);
463 mtx_destroy (&bd->cp_mtx);
464 free (b, M_DEVBUF);
465 splx (s);
466 return (ENXIO);
467 }
468 callout_init (&led_timo[unit], cp_mpsafenet ? CALLOUT_MPSAFE : 0);
469 error = bus_setup_intr (dev, bd->cp_irq,
470 INTR_TYPE_NET|(cp_mpsafenet?INTR_MPSAFE:0),
471 cp_intr, bd, &bd->cp_intrhand);
472 if (error) {
473 cp_destroy = 1;
474 printf ("cp%d: cannot set up irq\n", unit);
475 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
476 bus_release_resource (dev, SYS_RES_MEMORY,
477 PCIR_BAR(0), bd->cp_res);
478 mtx_destroy (&bd->cp_mtx);
479 free (b, M_DEVBUF);
480 splx (s);
481 return (ENXIO);
482 }
483 printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000);
484
485 for (c = b->chan; c < b->chan + NCHAN; ++c) {
486 if (! c->type)
487 continue;
488 d = &bd->channel[c->num];
489 d->dmamem.size = sizeof(cp_buf_t);
490 if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem))
491 continue;
492 channel [b->num*NCHAN + c->num] = d;
493 sprintf (d->name, "cp%d.%d", b->num, c->num);
494 d->board = b;
495 d->chan = c;
496 c->sys = d;
497 #ifdef NETGRAPH
498 if (ng_make_node_common (&typestruct, &d->node) != 0) {
499 printf ("%s: cannot make common node\n", d->name);
500 d->node = NULL;
501 continue;
502 }
503 NG_NODE_SET_PRIVATE (d->node, d);
504 sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE,
505 c->board->num*NCHAN + c->num);
506 if (ng_name_node (d->node, d->nodename)) {
507 printf ("%s: cannot name node\n", d->nodename);
508 NG_NODE_UNREF (d->node);
509 continue;
510 }
511 d->queue.ifq_maxlen = IFQ_MAXLEN;
512 d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
513 mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF);
514 mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF);
515 callout_init (&d->timeout_handle,
516 cp_mpsafenet ? CALLOUT_MPSAFE : 0);
517 #else /*NETGRAPH*/
518 d->pp.pp_if.if_softc = d;
519 if_initname (&d->pp.pp_if, "cp", b->num * NCHAN + c->num);
520 d->pp.pp_if.if_mtu = PP_MTU;
521 d->pp.pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
522 if (!cp_mpsafenet)
523 d->pp.pp_if.if_flags |= IFF_NEEDSGIANT;
524 d->pp.pp_if.if_ioctl = cp_sioctl;
525 d->pp.pp_if.if_start = cp_ifstart;
526 d->pp.pp_if.if_watchdog = cp_ifwatchdog;
527 d->pp.pp_if.if_init = cp_initialize;
528 d->queue.ifq_maxlen = NRBUF;
529 mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF);
530 sppp_attach (&d->pp.pp_if);
531 if_attach (&d->pp.pp_if);
532 d->pp.pp_tlf = cp_tlf;
533 d->pp.pp_tls = cp_tls;
534 /* If BPF is in the kernel, call the attach for it.
535 * The header size of PPP or Cisco/HDLC is 4 bytes. */
536 bpfattach (&d->pp.pp_if, DLT_PPP, 4);
537 #endif /*NETGRAPH*/
538 cp_start_e1 (c);
539 cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys);
540
541 /* Register callback functions. */
542 cp_register_transmit (c, &cp_transmit);
543 cp_register_receive (c, &cp_receive);
544 cp_register_error (c, &cp_error);
545 d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT,
546 GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num);
547 }
548 CP_LOCK (bd);
549 b->sys = bd;
550 adapter[unit] = b;
551 CP_UNLOCK (bd);
552 splx (s);
553 return 0;
554 }
555
556 static int cp_detach (device_t dev)
557 {
558 bdrv_t *bd = device_get_softc (dev);
559 cp_board_t *b = bd->board;
560 cp_chan_t *c;
561 int s;
562
563 KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized"));
564 s = splimp ();
565 CP_LOCK (bd);
566 /* Check if the device is busy (open). */
567 for (c = b->chan; c < b->chan + NCHAN; ++c) {
568 drv_t *d = (drv_t*) c->sys;
569
570 if (! d || ! d->chan->type)
571 continue;
572 if (d->running) {
573 CP_UNLOCK (bd);
574 splx (s);
575 return EBUSY;
576 }
577 }
578
579 /* Ok, we can unload driver */
580 /* At first we should stop all channels */
581 for (c = b->chan; c < b->chan + NCHAN; ++c) {
582 drv_t *d = (drv_t*) c->sys;
583
584 if (! d || ! d->chan->type)
585 continue;
586
587 cp_stop_chan (c);
588 cp_stop_e1 (c);
589 cp_set_dtr (d->chan, 0);
590 cp_set_rts (d->chan, 0);
591 }
592
593 /* Reset the adapter. */
594 cp_destroy = 1;
595 cp_interrupt_poll (b, 1);
596 cp_led_off (b);
597 cp_reset (b, 0 ,0);
598 callout_stop (&led_timo[b->num]);
599
600 for (c=b->chan; c<b->chan+NCHAN; ++c) {
601 drv_t *d = (drv_t*) c->sys;
602
603 if (! d || ! d->chan->type)
604 continue;
605 #ifndef NETGRAPH
606 /* Detach from the packet filter list of interfaces. */
607 bpfdetach (&d->pp.pp_if);
608
609 /* Detach from the sync PPP list. */
610 sppp_detach (&d->pp.pp_if);
611
612 /* Detach from the system list of interfaces. */
613 if_detach (&d->pp.pp_if);
614 IF_DRAIN (&d->queue);
615 mtx_destroy (&d->queue.ifq_mtx);
616 #else
617 if (d->node) {
618 ng_rmnode_self (d->node);
619 NG_NODE_UNREF (d->node);
620 d->node = NULL;
621 }
622 mtx_destroy (&d->queue.ifq_mtx);
623 mtx_destroy (&d->hi_queue.ifq_mtx);
624 #endif
625 destroy_dev (d->devt);
626 }
627
628 b->sys = NULL;
629 CP_UNLOCK (bd);
630
631 /* Disable the interrupt request. */
632 bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand);
633 bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
634 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
635 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
636
637 CP_LOCK (bd);
638 cp_led_off (b);
639 CP_UNLOCK (bd);
640 callout_drain (&led_timo[b->num]);
641 splx (s);
642
643 s = splimp ();
644 for (c = b->chan; c < b->chan + NCHAN; ++c) {
645 drv_t *d = (drv_t*) c->sys;
646
647 if (! d || ! d->chan->type)
648 continue;
649 channel [b->num*NCHAN + c->num] = 0;
650 /* Deallocate buffers. */
651 cp_bus_dma_mem_free (&d->dmamem);
652 }
653 adapter [b->num] = 0;
654 cp_bus_dma_mem_free (&bd->dmamem);
655 free (b, M_DEVBUF);
656 splx (s);
657 mtx_destroy (&bd->cp_mtx);
658 return 0;
659 }
660
661 #ifndef NETGRAPH
662 static void cp_ifstart (struct ifnet *ifp)
663 {
664 drv_t *d = ifp->if_softc;
665 bdrv_t *bd = d->board->sys;
666
667 CP_LOCK (bd);
668 cp_start (d);
669 CP_UNLOCK (bd);
670 }
671
672 static void cp_ifwatchdog (struct ifnet *ifp)
673 {
674 drv_t *d = ifp->if_softc;
675
676 cp_watchdog (d);
677 }
678
679 static void cp_tlf (struct sppp *sp)
680 {
681 drv_t *d = sp->pp_if.if_softc;
682
683 CP_DEBUG2 (d, ("cp_tlf\n"));
684 /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */
685 /* cp_set_dtr (d->chan, 0);*/
686 /* cp_set_rts (d->chan, 0);*/
687 if (!(d->pp.pp_flags & PP_FR) && !(d->pp.pp_if.if_flags & PP_CISCO))
688 sp->pp_down (sp);
689 }
690
691 static void cp_tls (struct sppp *sp)
692 {
693 drv_t *d = sp->pp_if.if_softc;
694
695 CP_DEBUG2 (d, ("cp_tls\n"));
696 if (!(d->pp.pp_flags & PP_FR) && !(d->pp.pp_if.if_flags & PP_CISCO))
697 sp->pp_up (sp);
698 }
699
700 /*
701 * Process an ioctl request.
702 */
703 static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
704 {
705 drv_t *d = ifp->if_softc;
706 bdrv_t *bd = d->board->sys;
707 int error, s, was_up, should_be_up;
708
709 was_up = (ifp->if_flags & IFF_RUNNING) != 0;
710 error = sppp_ioctl (ifp, cmd, data);
711
712 if (error)
713 return error;
714
715 if (! (ifp->if_flags & IFF_DEBUG))
716 d->chan->debug = 0;
717 else if (! d->chan->debug)
718 d->chan->debug = 1;
719
720 switch (cmd) {
721 default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0;
722 case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0;
723 case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0;
724 case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break;
725 case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break;
726 }
727
728 /* We get here only in case of SIFFLAGS or SIFADDR. */
729 s = splimp ();
730 CP_LOCK (bd);
731 should_be_up = (ifp->if_flags & IFF_RUNNING) != 0;
732 if (! was_up && should_be_up) {
733 /* Interface goes up -- start it. */
734 cp_up (d);
735 cp_start (d);
736 } else if (was_up && ! should_be_up) {
737 /* Interface is going down -- stop it. */
738 /* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/
739 cp_down (d);
740 }
741 CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd));
742 CP_UNLOCK (bd);
743 splx (s);
744 return 0;
745 }
746
747 /*
748 * Initialization of interface.
749 * It seems to be never called by upper level?
750 */
751 static void cp_initialize (void *softc)
752 {
753 drv_t *d = softc;
754
755 CP_DEBUG (d, ("cp_initialize\n"));
756 }
757 #endif /*NETGRAPH*/
758
759 /*
760 * Stop the interface. Called on splimp().
761 */
762 static void cp_down (drv_t *d)
763 {
764 CP_DEBUG (d, ("cp_down\n"));
765 /* Interface is going down -- stop it. */
766 cp_set_dtr (d->chan, 0);
767 cp_set_rts (d->chan, 0);
768
769 d->running = 0;
770 }
771
772 /*
773 * Start the interface. Called on splimp().
774 */
775 static void cp_up (drv_t *d)
776 {
777 CP_DEBUG (d, ("cp_up\n"));
778 cp_set_dtr (d->chan, 1);
779 cp_set_rts (d->chan, 1);
780 d->running = 1;
781 }
782
783 /*
784 * Start output on the interface. Get another datagram to send
785 * off of the interface queue, and copy it to the interface
786 * before starting the output.
787 */
788 static void cp_send (drv_t *d)
789 {
790 struct mbuf *m;
791 u_short len;
792
793 CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te));
794
795 /* No output if the interface is down. */
796 if (! d->running)
797 return;
798
799 /* No output if the modem is off. */
800 if (! (d->chan->lloop || d->chan->type != T_SERIAL ||
801 cp_get_dsr (d->chan)))
802 return;
803
804 while (cp_transmit_space (d->chan)) {
805 /* Get the packet to send. */
806 #ifdef NETGRAPH
807 IF_DEQUEUE (&d->hi_queue, m);
808 if (! m)
809 IF_DEQUEUE (&d->queue, m);
810 #else
811 m = sppp_dequeue (&d->pp.pp_if);
812 #endif
813 if (! m)
814 return;
815 #ifndef NETGRAPH
816 if (d->pp.pp_if.if_bpf)
817 BPF_MTAP (&d->pp.pp_if, m);
818 #endif
819 len = m->m_pkthdr.len;
820 if (len >= BUFSZ)
821 printf ("%s: too long packet: %d bytes: ",
822 d->name, len);
823 else if (! m->m_next)
824 cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0);
825 else {
826 u_char *buf = d->chan->tbuf[d->chan->te];
827 m_copydata (m, 0, len, buf);
828 cp_send_packet (d->chan, buf, len, 0);
829 }
830 m_freem (m);
831 /* Set up transmit timeout, if the transmit ring is not empty.*/
832 #ifdef NETGRAPH
833 d->timeout = 10;
834 #else
835 d->pp.pp_if.if_timer = 10;
836 #endif
837 }
838 #ifndef NETGRAPH
839 d->pp.pp_if.if_flags |= IFF_OACTIVE;
840 #endif
841 }
842
843 /*
844 * Start output on the interface.
845 * Always called on splimp().
846 */
847 static void cp_start (drv_t *d)
848 {
849 if (d->running) {
850 if (! d->chan->dtr)
851 cp_set_dtr (d->chan, 1);
852 if (! d->chan->rts)
853 cp_set_rts (d->chan, 1);
854 cp_send (d);
855 }
856 }
857
858 /*
859 * Handle transmit timeouts.
860 * Recover after lost transmit interrupts.
861 * Always called on splimp().
862 */
863 static void cp_watchdog (drv_t *d)
864 {
865 bdrv_t *bd = d->board->sys;
866 CP_DEBUG (d, ("device timeout\n"));
867 if (d->running) {
868 int s = splimp ();
869
870 CP_LOCK (bd);
871 cp_stop_chan (d->chan);
872 cp_stop_e1 (d->chan);
873 cp_start_e1 (d->chan);
874 cp_start_chan (d->chan, 1, 1, 0, 0);
875 cp_set_dtr (d->chan, 1);
876 cp_set_rts (d->chan, 1);
877 cp_start (d);
878 CP_UNLOCK (bd);
879 splx (s);
880 }
881 }
882
883 static void cp_transmit (cp_chan_t *c, void *attachment, int len)
884 {
885 drv_t *d = c->sys;
886
887 #ifdef NETGRAPH
888 d->timeout = 0;
889 #else
890 ++d->pp.pp_if.if_opackets;
891 d->pp.pp_if.if_flags &= ~IFF_OACTIVE;
892 d->pp.pp_if.if_timer = 0;
893 #endif
894 cp_start (d);
895 }
896
897 static void cp_receive (cp_chan_t *c, unsigned char *data, int len)
898 {
899 drv_t *d = c->sys;
900 struct mbuf *m;
901 #ifdef NETGRAPH
902 int error;
903 #endif
904
905 if (! d->running)
906 return;
907
908 m = makembuf (data, len);
909 if (! m) {
910 CP_DEBUG (d, ("no memory for packet\n"));
911 #ifndef NETGRAPH
912 ++d->pp.pp_if.if_iqdrops;
913 #endif
914 return;
915 }
916 if (c->debug > 1)
917 printmbuf (m);
918 #ifdef NETGRAPH
919 m->m_pkthdr.rcvif = 0;
920 NG_SEND_DATA_ONLY (error, d->hook, m);
921 #else
922 ++d->pp.pp_if.if_ipackets;
923 m->m_pkthdr.rcvif = &d->pp.pp_if;
924 /* Check if there's a BPF listener on this interface.
925 * If so, hand off the raw packet to bpf. */
926 if (d->pp.pp_if.if_bpf)
927 BPF_TAP (&d->pp.pp_if, data, len);
928 IF_ENQUEUE (&d->queue, m);
929 #endif
930 }
931
932 static void cp_error (cp_chan_t *c, int data)
933 {
934 drv_t *d = c->sys;
935
936 switch (data) {
937 case CP_FRAME:
938 CP_DEBUG (d, ("frame error\n"));
939 #ifndef NETGRAPH
940 ++d->pp.pp_if.if_ierrors;
941 #endif
942 break;
943 case CP_CRC:
944 CP_DEBUG (d, ("crc error\n"));
945 #ifndef NETGRAPH
946 ++d->pp.pp_if.if_ierrors;
947 #endif
948 break;
949 case CP_OVERRUN:
950 CP_DEBUG (d, ("overrun error\n"));
951 #ifndef NETGRAPH
952 ++d->pp.pp_if.if_collisions;
953 ++d->pp.pp_if.if_ierrors;
954 #endif
955 break;
956 case CP_OVERFLOW:
957 CP_DEBUG (d, ("overflow error\n"));
958 #ifndef NETGRAPH
959 ++d->pp.pp_if.if_ierrors;
960 #endif
961 break;
962 case CP_UNDERRUN:
963 CP_DEBUG (d, ("underrun error\n"));
964 #ifdef NETGRAPH
965 d->timeout = 0;
966 #else
967 ++d->pp.pp_if.if_oerrors;
968 d->pp.pp_if.if_flags &= ~IFF_OACTIVE;
969 d->pp.pp_if.if_timer = 0;
970 #endif
971 cp_start (d);
972 break;
973 default:
974 CP_DEBUG (d, ("error #%d\n", data));
975 break;
976 }
977 }
978
979 /*
980 * You also need read, write, open, close routines.
981 * This should get you started
982 */
983 static int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td)
984 {
985 int unit = minor (dev);
986 drv_t *d;
987
988 if (unit >= NBRD*NCHAN || ! (d = channel[unit]))
989 return ENXIO;
990 CP_DEBUG2 (d, ("cp_open\n"));
991 return 0;
992 }
993
994 /*
995 * Only called on the LAST close.
996 */
997 static int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td)
998 {
999 drv_t *d = channel [minor (dev)];
1000
1001 CP_DEBUG2 (d, ("cp_close\n"));
1002 return 0;
1003 }
1004
1005 static int cp_modem_status (cp_chan_t *c)
1006 {
1007 drv_t *d = c->sys;
1008 bdrv_t *bd = d->board->sys;
1009 int status, s;
1010
1011 status = d->running ? TIOCM_LE : 0;
1012 s = splimp ();
1013 CP_LOCK (bd);
1014 if (cp_get_cd (c)) status |= TIOCM_CD;
1015 if (cp_get_cts (c)) status |= TIOCM_CTS;
1016 if (cp_get_dsr (c)) status |= TIOCM_DSR;
1017 if (c->dtr) status |= TIOCM_DTR;
1018 if (c->rts) status |= TIOCM_RTS;
1019 CP_UNLOCK (bd);
1020 splx (s);
1021 return status;
1022 }
1023
1024 static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
1025 {
1026 drv_t *d = channel [minor (dev)];
1027 bdrv_t *bd = d->board->sys;
1028 cp_chan_t *c = d->chan;
1029 struct serial_statistics *st;
1030 struct e1_statistics *opte1;
1031 struct e3_statistics *opte3;
1032 int error, s;
1033 char mask[16];
1034
1035 switch (cmd) {
1036 case SERIAL_GETREGISTERED:
1037 CP_DEBUG2 (d, ("ioctl: getregistered\n"));
1038 bzero (mask, sizeof(mask));
1039 for (s=0; s<NBRD*NCHAN; ++s)
1040 if (channel [s])
1041 mask [s/8] |= 1 << (s & 7);
1042 bcopy (mask, data, sizeof (mask));
1043 return 0;
1044
1045 #ifndef NETGRAPH
1046 case SERIAL_GETPROTO:
1047 CP_DEBUG2 (d, ("ioctl: getproto\n"));
1048 strcpy ((char*)data, (d->pp.pp_flags & PP_FR) ? "fr" :
1049 (d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp");
1050 return 0;
1051
1052 case SERIAL_SETPROTO:
1053 CP_DEBUG2 (d, ("ioctl: setproto\n"));
1054 /* Only for superuser! */
1055 error = suser (td);
1056 if (error)
1057 return error;
1058 if (d->pp.pp_if.if_flags & IFF_RUNNING)
1059 return EBUSY;
1060 if (! strcmp ("cisco", (char*)data)) {
1061 d->pp.pp_flags &= ~(PP_FR);
1062 d->pp.pp_flags |= PP_KEEPALIVE;
1063 d->pp.pp_if.if_flags |= PP_CISCO;
1064 } else if (! strcmp ("fr", (char*)data) && PP_FR) {
1065 d->pp.pp_if.if_flags &= ~(PP_CISCO);
1066 d->pp.pp_flags |= PP_FR | PP_KEEPALIVE;
1067 } else if (! strcmp ("ppp", (char*)data)) {
1068 d->pp.pp_flags &= ~PP_FR;
1069 d->pp.pp_flags &= ~PP_KEEPALIVE;
1070 d->pp.pp_if.if_flags &= ~(PP_CISCO);
1071 } else
1072 return EINVAL;
1073 return 0;
1074
1075 case SERIAL_GETKEEPALIVE:
1076 CP_DEBUG2 (d, ("ioctl: getkeepalive\n"));
1077 if ((d->pp.pp_flags & PP_FR) ||
1078 (d->pp.pp_if.if_flags & PP_CISCO))
1079 return EINVAL;
1080 *(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0;
1081 return 0;
1082
1083 case SERIAL_SETKEEPALIVE:
1084 CP_DEBUG2 (d, ("ioctl: setkeepalive\n"));
1085 /* Only for superuser! */
1086 error = suser (td);
1087 if (error)
1088 return error;
1089 if ((d->pp.pp_flags & PP_FR) ||
1090 (d->pp.pp_if.if_flags & PP_CISCO))
1091 return EINVAL;
1092 s = splimp ();
1093 CP_LOCK (bd);
1094 if (*(int*)data)
1095 d->pp.pp_flags |= PP_KEEPALIVE;
1096 else
1097 d->pp.pp_flags &= ~PP_KEEPALIVE;
1098 CP_UNLOCK (bd);
1099 splx (s);
1100 return 0;
1101 #endif /*NETGRAPH*/
1102
1103 case SERIAL_GETMODE:
1104 CP_DEBUG2 (d, ("ioctl: getmode\n"));
1105 *(int*)data = SERIAL_HDLC;
1106 return 0;
1107
1108 case SERIAL_SETMODE:
1109 /* Only for superuser! */
1110 error = suser (td);
1111 if (error)
1112 return error;
1113 if (*(int*)data != SERIAL_HDLC)
1114 return EINVAL;
1115 return 0;
1116
1117 case SERIAL_GETCFG:
1118 CP_DEBUG2 (d, ("ioctl: getcfg\n"));
1119 if (c->type != T_E1 || c->unfram)
1120 return EINVAL;
1121 *(char*)data = c->board->mux ? 'c' : 'a';
1122 return 0;
1123
1124 case SERIAL_SETCFG:
1125 CP_DEBUG2 (d, ("ioctl: setcfg\n"));
1126 error = suser (td);
1127 if (error)
1128 return error;
1129 if (c->type != T_E1)
1130 return EINVAL;
1131 s = splimp ();
1132 CP_LOCK (bd);
1133 cp_set_mux (c->board, *((char*)data) == 'c');
1134 CP_UNLOCK (bd);
1135 splx (s);
1136 return 0;
1137
1138 case SERIAL_GETSTAT:
1139 CP_DEBUG2 (d, ("ioctl: getstat\n"));
1140 st = (struct serial_statistics*) data;
1141 st->rintr = c->rintr;
1142 st->tintr = c->tintr;
1143 st->mintr = 0;
1144 st->ibytes = c->ibytes;
1145 st->ipkts = c->ipkts;
1146 st->obytes = c->obytes;
1147 st->opkts = c->opkts;
1148 st->ierrs = c->overrun + c->frame + c->crc;
1149 st->oerrs = c->underrun;
1150 return 0;
1151
1152 case SERIAL_GETESTAT:
1153 CP_DEBUG2 (d, ("ioctl: getestat\n"));
1154 if (c->type != T_E1 && c->type != T_G703)
1155 return EINVAL;
1156 opte1 = (struct e1_statistics*) data;
1157 opte1->status = c->status;
1158 opte1->cursec = c->cursec;
1159 opte1->totsec = c->totsec + c->cursec;
1160
1161 opte1->currnt.bpv = c->currnt.bpv;
1162 opte1->currnt.fse = c->currnt.fse;
1163 opte1->currnt.crce = c->currnt.crce;
1164 opte1->currnt.rcrce = c->currnt.rcrce;
1165 opte1->currnt.uas = c->currnt.uas;
1166 opte1->currnt.les = c->currnt.les;
1167 opte1->currnt.es = c->currnt.es;
1168 opte1->currnt.bes = c->currnt.bes;
1169 opte1->currnt.ses = c->currnt.ses;
1170 opte1->currnt.oofs = c->currnt.oofs;
1171 opte1->currnt.css = c->currnt.css;
1172 opte1->currnt.dm = c->currnt.dm;
1173
1174 opte1->total.bpv = c->total.bpv + c->currnt.bpv;
1175 opte1->total.fse = c->total.fse + c->currnt.fse;
1176 opte1->total.crce = c->total.crce + c->currnt.crce;
1177 opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce;
1178 opte1->total.uas = c->total.uas + c->currnt.uas;
1179 opte1->total.les = c->total.les + c->currnt.les;
1180 opte1->total.es = c->total.es + c->currnt.es;
1181 opte1->total.bes = c->total.bes + c->currnt.bes;
1182 opte1->total.ses = c->total.ses + c->currnt.ses;
1183 opte1->total.oofs = c->total.oofs + c->currnt.oofs;
1184 opte1->total.css = c->total.css + c->currnt.css;
1185 opte1->total.dm = c->total.dm + c->currnt.dm;
1186 for (s=0; s<48; ++s) {
1187 opte1->interval[s].bpv = c->interval[s].bpv;
1188 opte1->interval[s].fse = c->interval[s].fse;
1189 opte1->interval[s].crce = c->interval[s].crce;
1190 opte1->interval[s].rcrce = c->interval[s].rcrce;
1191 opte1->interval[s].uas = c->interval[s].uas;
1192 opte1->interval[s].les = c->interval[s].les;
1193 opte1->interval[s].es = c->interval[s].es;
1194 opte1->interval[s].bes = c->interval[s].bes;
1195 opte1->interval[s].ses = c->interval[s].ses;
1196 opte1->interval[s].oofs = c->interval[s].oofs;
1197 opte1->interval[s].css = c->interval[s].css;
1198 opte1->interval[s].dm = c->interval[s].dm;
1199 }
1200 return 0;
1201
1202 case SERIAL_GETE3STAT:
1203 CP_DEBUG2 (d, ("ioctl: gete3stat\n"));
1204 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1)
1205 return EINVAL;
1206 opte3 = (struct e3_statistics*) data;
1207
1208 opte3->status = c->e3status;
1209 opte3->cursec = (c->e3csec_5 * 2 + 1) / 10;
1210 opte3->totsec = c->e3tsec + opte3->cursec;
1211
1212 opte3->ccv = c->e3ccv;
1213 opte3->tcv = c->e3tcv + opte3->ccv;
1214
1215 for (s = 0; s < 48; ++s) {
1216 opte3->icv[s] = c->e3icv[s];
1217 }
1218 return 0;
1219
1220 case SERIAL_CLRSTAT:
1221 CP_DEBUG2 (d, ("ioctl: clrstat\n"));
1222 /* Only for superuser! */
1223 error = suser (td);
1224 if (error)
1225 return error;
1226 c->rintr = 0;
1227 c->tintr = 0;
1228 c->ibytes = 0;
1229 c->obytes = 0;
1230 c->ipkts = 0;
1231 c->opkts = 0;
1232 c->overrun = 0;
1233 c->frame = 0;
1234 c->crc = 0;
1235 c->underrun = 0;
1236 bzero (&c->currnt, sizeof (c->currnt));
1237 bzero (&c->total, sizeof (c->total));
1238 bzero (c->interval, sizeof (c->interval));
1239 c->e3ccv = 0;
1240 c->e3tcv = 0;
1241 bzero (c->e3icv, sizeof (c->e3icv));
1242 return 0;
1243
1244 case SERIAL_GETBAUD:
1245 CP_DEBUG2 (d, ("ioctl: getbaud\n"));
1246 *(long*)data = c->baud;
1247 return 0;
1248
1249 case SERIAL_SETBAUD:
1250 CP_DEBUG2 (d, ("ioctl: setbaud\n"));
1251 /* Only for superuser! */
1252 error = suser (td);
1253 if (error)
1254 return error;
1255 s = splimp ();
1256 CP_LOCK (bd);
1257 cp_set_baud (c, *(long*)data);
1258 CP_UNLOCK (bd);
1259 splx (s);
1260 return 0;
1261
1262 case SERIAL_GETLOOP:
1263 CP_DEBUG2 (d, ("ioctl: getloop\n"));
1264 *(int*)data = c->lloop;
1265 return 0;
1266
1267 case SERIAL_SETLOOP:
1268 CP_DEBUG2 (d, ("ioctl: setloop\n"));
1269 /* Only for superuser! */
1270 error = suser (td);
1271 if (error)
1272 return error;
1273 s = splimp ();
1274 CP_LOCK (bd);
1275 cp_set_lloop (c, *(int*)data);
1276 CP_UNLOCK (bd);
1277 splx (s);
1278 return 0;
1279
1280 case SERIAL_GETDPLL:
1281 CP_DEBUG2 (d, ("ioctl: getdpll\n"));
1282 if (c->type != T_SERIAL)
1283 return EINVAL;
1284 *(int*)data = c->dpll;
1285 return 0;
1286
1287 case SERIAL_SETDPLL:
1288 CP_DEBUG2 (d, ("ioctl: setdpll\n"));
1289 /* Only for superuser! */
1290 error = suser (td);
1291 if (error)
1292 return error;
1293 if (c->type != T_SERIAL)
1294 return EINVAL;
1295 s = splimp ();
1296 CP_LOCK (bd);
1297 cp_set_dpll (c, *(int*)data);
1298 CP_UNLOCK (bd);
1299 splx (s);
1300 return 0;
1301
1302 case SERIAL_GETNRZI:
1303 CP_DEBUG2 (d, ("ioctl: getnrzi\n"));
1304 if (c->type != T_SERIAL)
1305 return EINVAL;
1306 *(int*)data = c->nrzi;
1307 return 0;
1308
1309 case SERIAL_SETNRZI:
1310 CP_DEBUG2 (d, ("ioctl: setnrzi\n"));
1311 /* Only for superuser! */
1312 error = suser (td);
1313 if (error)
1314 return error;
1315 if (c->type != T_SERIAL)
1316 return EINVAL;
1317 s = splimp ();
1318 CP_LOCK (bd);
1319 cp_set_nrzi (c, *(int*)data);
1320 CP_UNLOCK (bd);
1321 splx (s);
1322 return 0;
1323
1324 case SERIAL_GETDEBUG:
1325 CP_DEBUG2 (d, ("ioctl: getdebug\n"));
1326 *(int*)data = d->chan->debug;
1327 return 0;
1328
1329 case SERIAL_SETDEBUG:
1330 CP_DEBUG2 (d, ("ioctl: setdebug\n"));
1331 /* Only for superuser! */
1332 error = suser (td);
1333 if (error)
1334 return error;
1335 d->chan->debug = *(int*)data;
1336 #ifndef NETGRAPH
1337 if (d->chan->debug)
1338 d->pp.pp_if.if_flags |= IFF_DEBUG;
1339 else
1340 d->pp.pp_if.if_flags &= ~IFF_DEBUG;
1341 #endif
1342 return 0;
1343
1344 case SERIAL_GETHIGAIN:
1345 CP_DEBUG2 (d, ("ioctl: gethigain\n"));
1346 if (c->type != T_E1)
1347 return EINVAL;
1348 *(int*)data = c->higain;
1349 return 0;
1350
1351 case SERIAL_SETHIGAIN:
1352 CP_DEBUG2 (d, ("ioctl: sethigain\n"));
1353 /* Only for superuser! */
1354 error = suser (td);
1355 if (error)
1356 return error;
1357 if (c->type != T_E1)
1358 return EINVAL;
1359 s = splimp ();
1360 CP_LOCK (bd);
1361 cp_set_higain (c, *(int*)data);
1362 CP_UNLOCK (bd);
1363 splx (s);
1364 return 0;
1365
1366 case SERIAL_GETPHONY:
1367 CP_DEBUG2 (d, ("ioctl: getphony\n"));
1368 if (c->type != T_E1)
1369 return EINVAL;
1370 *(int*)data = c->phony;
1371 return 0;
1372
1373 case SERIAL_SETPHONY:
1374 CP_DEBUG2 (d, ("ioctl: setphony\n"));
1375 /* Only for superuser! */
1376 error = suser (td);
1377 if (error)
1378 return error;
1379 if (c->type != T_E1)
1380 return EINVAL;
1381 s = splimp ();
1382 CP_LOCK (bd);
1383 cp_set_phony (c, *(int*)data);
1384 CP_UNLOCK (bd);
1385 splx (s);
1386 return 0;
1387
1388 case SERIAL_GETUNFRAM:
1389 CP_DEBUG2 (d, ("ioctl: getunfram\n"));
1390 if (c->type != T_E1)
1391 return EINVAL;
1392 *(int*)data = c->unfram;
1393 return 0;
1394
1395 case SERIAL_SETUNFRAM:
1396 CP_DEBUG2 (d, ("ioctl: setunfram\n"));
1397 /* Only for superuser! */
1398 error = suser (td);
1399 if (error)
1400 return error;
1401 if (c->type != T_E1)
1402 return EINVAL;
1403 s = splimp ();
1404 CP_LOCK (bd);
1405 cp_set_unfram (c, *(int*)data);
1406 CP_UNLOCK (bd);
1407 splx (s);
1408 return 0;
1409
1410 case SERIAL_GETSCRAMBLER:
1411 CP_DEBUG2 (d, ("ioctl: getscrambler\n"));
1412 if (c->type != T_G703 && !c->unfram)
1413 return EINVAL;
1414 *(int*)data = c->scrambler;
1415 return 0;
1416
1417 case SERIAL_SETSCRAMBLER:
1418 CP_DEBUG2 (d, ("ioctl: setscrambler\n"));
1419 /* Only for superuser! */
1420 error = suser (td);
1421 if (error)
1422 return error;
1423 if (c->type != T_G703 && !c->unfram)
1424 return EINVAL;
1425 s = splimp ();
1426 CP_LOCK (bd);
1427 cp_set_scrambler (c, *(int*)data);
1428 CP_UNLOCK (bd);
1429 splx (s);
1430 return 0;
1431
1432 case SERIAL_GETMONITOR:
1433 CP_DEBUG2 (d, ("ioctl: getmonitor\n"));
1434 if (c->type != T_E1 &&
1435 c->type != T_E3 &&
1436 c->type != T_T3 &&
1437 c->type != T_STS1)
1438 return EINVAL;
1439 *(int*)data = c->monitor;
1440 return 0;
1441
1442 case SERIAL_SETMONITOR:
1443 CP_DEBUG2 (d, ("ioctl: setmonitor\n"));
1444 /* Only for superuser! */
1445 error = suser (td);
1446 if (error)
1447 return error;
1448 if (c->type != T_E1)
1449 return EINVAL;
1450 s = splimp ();
1451 CP_LOCK (bd);
1452 cp_set_monitor (c, *(int*)data);
1453 CP_UNLOCK (bd);
1454 splx (s);
1455 return 0;
1456
1457 case SERIAL_GETUSE16:
1458 CP_DEBUG2 (d, ("ioctl: getuse16\n"));
1459 if (c->type != T_E1 || c->unfram)
1460 return EINVAL;
1461 *(int*)data = c->use16;
1462 return 0;
1463
1464 case SERIAL_SETUSE16:
1465 CP_DEBUG2 (d, ("ioctl: setuse16\n"));
1466 /* Only for superuser! */
1467 error = suser (td);
1468 if (error)
1469 return error;
1470 if (c->type != T_E1)
1471 return EINVAL;
1472 s = splimp ();
1473 CP_LOCK (bd);
1474 cp_set_use16 (c, *(int*)data);
1475 CP_UNLOCK (bd);
1476 splx (s);
1477 return 0;
1478
1479 case SERIAL_GETCRC4:
1480 CP_DEBUG2 (d, ("ioctl: getcrc4\n"));
1481 if (c->type != T_E1 || c->unfram)
1482 return EINVAL;
1483 *(int*)data = c->crc4;
1484 return 0;
1485
1486 case SERIAL_SETCRC4:
1487 CP_DEBUG2 (d, ("ioctl: setcrc4\n"));
1488 /* Only for superuser! */
1489 error = suser (td);
1490 if (error)
1491 return error;
1492 if (c->type != T_E1)
1493 return EINVAL;
1494 s = splimp ();
1495 CP_LOCK (bd);
1496 cp_set_crc4 (c, *(int*)data);
1497 CP_UNLOCK (bd);
1498 splx (s);
1499 return 0;
1500
1501 case SERIAL_GETCLK:
1502 CP_DEBUG2 (d, ("ioctl: getclk\n"));
1503 if (c->type != T_E1 &&
1504 c->type != T_G703 &&
1505 c->type != T_E3 &&
1506 c->type != T_T3 &&
1507 c->type != T_STS1)
1508 return EINVAL;
1509 switch (c->gsyn) {
1510 default: *(int*)data = E1CLK_INTERNAL; break;
1511 case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break;
1512 case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break;
1513 case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break;
1514 case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break;
1515 case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break;
1516 }
1517 return 0;
1518
1519 case SERIAL_SETCLK:
1520 CP_DEBUG2 (d, ("ioctl: setclk\n"));
1521 /* Only for superuser! */
1522 error = suser (td);
1523 if (error)
1524 return error;
1525 if (c->type != T_E1 &&
1526 c->type != T_G703 &&
1527 c->type != T_E3 &&
1528 c->type != T_T3 &&
1529 c->type != T_STS1)
1530 return EINVAL;
1531 s = splimp ();
1532 CP_LOCK (bd);
1533 switch (*(int*)data) {
1534 default: cp_set_gsyn (c, GSYN_INT); break;
1535 case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break;
1536 case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break;
1537 case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break;
1538 case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break;
1539 case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break;
1540 }
1541 CP_UNLOCK (bd);
1542 splx (s);
1543 return 0;
1544
1545 case SERIAL_GETTIMESLOTS:
1546 CP_DEBUG2 (d, ("ioctl: gettimeslots\n"));
1547 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA)
1548 return EINVAL;
1549 *(u_long*)data = c->ts;
1550 return 0;
1551
1552 case SERIAL_SETTIMESLOTS:
1553 CP_DEBUG2 (d, ("ioctl: settimeslots\n"));
1554 /* Only for superuser! */
1555 error = suser (td);
1556 if (error)
1557 return error;
1558 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA)
1559 return EINVAL;
1560 s = splimp ();
1561 CP_LOCK (bd);
1562 cp_set_ts (c, *(u_long*)data);
1563 CP_UNLOCK (bd);
1564 splx (s);
1565 return 0;
1566
1567 case SERIAL_GETINVCLK:
1568 CP_DEBUG2 (d, ("ioctl: getinvclk\n"));
1569 #if 1
1570 return EINVAL;
1571 #else
1572 if (c->type != T_SERIAL)
1573 return EINVAL;
1574 *(int*)data = c->invtxc;
1575 return 0;
1576 #endif
1577
1578 case SERIAL_SETINVCLK:
1579 CP_DEBUG2 (d, ("ioctl: setinvclk\n"));
1580 /* Only for superuser! */
1581 error = suser (td);
1582 if (error)
1583 return error;
1584 if (c->type != T_SERIAL)
1585 return EINVAL;
1586 s = splimp ();
1587 CP_LOCK (bd);
1588 cp_set_invtxc (c, *(int*)data);
1589 cp_set_invrxc (c, *(int*)data);
1590 CP_UNLOCK (bd);
1591 splx (s);
1592 return 0;
1593
1594 case SERIAL_GETINVTCLK:
1595 CP_DEBUG2 (d, ("ioctl: getinvtclk\n"));
1596 if (c->type != T_SERIAL)
1597 return EINVAL;
1598 *(int*)data = c->invtxc;
1599 return 0;
1600
1601 case SERIAL_SETINVTCLK:
1602 CP_DEBUG2 (d, ("ioctl: setinvtclk\n"));
1603 /* Only for superuser! */
1604 error = suser (td);
1605 if (error)
1606 return error;
1607 if (c->type != T_SERIAL)
1608 return EINVAL;
1609 s = splimp ();
1610 CP_LOCK (bd);
1611 cp_set_invtxc (c, *(int*)data);
1612 CP_UNLOCK (bd);
1613 splx (s);
1614 return 0;
1615
1616 case SERIAL_GETINVRCLK:
1617 CP_DEBUG2 (d, ("ioctl: getinvrclk\n"));
1618 if (c->type != T_SERIAL)
1619 return EINVAL;
1620 *(int*)data = c->invrxc;
1621 return 0;
1622
1623 case SERIAL_SETINVRCLK:
1624 CP_DEBUG2 (d, ("ioctl: setinvrclk\n"));
1625 /* Only for superuser! */
1626 error = suser (td);
1627 if (error)
1628 return error;
1629 if (c->type != T_SERIAL)
1630 return EINVAL;
1631 s = splimp ();
1632 CP_LOCK (bd);
1633 cp_set_invrxc (c, *(int*)data);
1634 CP_UNLOCK (bd);
1635 splx (s);
1636 return 0;
1637
1638 case SERIAL_GETLEVEL:
1639 CP_DEBUG2 (d, ("ioctl: getlevel\n"));
1640 if (c->type != T_G703)
1641 return EINVAL;
1642 s = splimp ();
1643 CP_LOCK (bd);
1644 *(int*)data = cp_get_lq (c);
1645 CP_UNLOCK (bd);
1646 splx (s);
1647 return 0;
1648
1649 #if 0
1650 case SERIAL_RESET:
1651 CP_DEBUG2 (d, ("ioctl: reset\n"));
1652 /* Only for superuser! */
1653 error = suser (td);
1654 if (error)
1655 return error;
1656 s = splimp ();
1657 CP_LOCK (bd);
1658 cp_reset (c->board, 0, 0);
1659 CP_UNLOCK (bd);
1660 splx (s);
1661 return 0;
1662
1663 case SERIAL_HARDRESET:
1664 CP_DEBUG2 (d, ("ioctl: hardreset\n"));
1665 /* Only for superuser! */
1666 error = suser (td);
1667 if (error)
1668 return error;
1669 s = splimp ();
1670 CP_LOCK (bd);
1671 /* hard_reset (c->board); */
1672 CP_UNLOCK (bd);
1673 splx (s);
1674 return 0;
1675 #endif
1676
1677 case SERIAL_GETCABLE:
1678 CP_DEBUG2 (d, ("ioctl: getcable\n"));
1679 if (c->type != T_SERIAL)
1680 return EINVAL;
1681 s = splimp ();
1682 CP_LOCK (bd);
1683 *(int*)data = cp_get_cable (c);
1684 CP_UNLOCK (bd);
1685 splx (s);
1686 return 0;
1687
1688 case SERIAL_GETDIR:
1689 CP_DEBUG2 (d, ("ioctl: getdir\n"));
1690 if (c->type != T_E1 && c->type != T_DATA)
1691 return EINVAL;
1692 *(int*)data = c->dir;
1693 return 0;
1694
1695 case SERIAL_SETDIR:
1696 CP_DEBUG2 (d, ("ioctl: setdir\n"));
1697 /* Only for superuser! */
1698 error = suser (td);
1699 if (error)
1700 return error;
1701 s = splimp ();
1702 CP_LOCK (bd);
1703 cp_set_dir (c, *(int*)data);
1704 CP_UNLOCK (bd);
1705 splx (s);
1706 return 0;
1707
1708 case SERIAL_GETRLOOP:
1709 CP_DEBUG2 (d, ("ioctl: getrloop\n"));
1710 if (c->type != T_G703 &&
1711 c->type != T_E3 &&
1712 c->type != T_T3 &&
1713 c->type != T_STS1)
1714 return EINVAL;
1715 *(int*)data = cp_get_rloop (c);
1716 return 0;
1717
1718 case SERIAL_SETRLOOP:
1719 CP_DEBUG2 (d, ("ioctl: setloop\n"));
1720 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1)
1721 return EINVAL;
1722 /* Only for superuser! */
1723 error = suser (td);
1724 if (error)
1725 return error;
1726 s = splimp ();
1727 CP_LOCK (bd);
1728 cp_set_rloop (c, *(int*)data);
1729 CP_UNLOCK (bd);
1730 splx (s);
1731 return 0;
1732
1733 case SERIAL_GETCABLEN:
1734 CP_DEBUG2 (d, ("ioctl: getcablen\n"));
1735 if (c->type != T_T3 && c->type != T_STS1)
1736 return EINVAL;
1737 *(int*)data = c->cablen;
1738 return 0;
1739
1740 case SERIAL_SETCABLEN:
1741 CP_DEBUG2 (d, ("ioctl: setloop\n"));
1742 if (c->type != T_T3 && c->type != T_STS1)
1743 return EINVAL;
1744 /* Only for superuser! */
1745 error = suser (td);
1746 if (error)
1747 return error;
1748 s = splimp ();
1749 CP_LOCK (bd);
1750 cp_set_cablen (c, *(int*)data);
1751 CP_UNLOCK (bd);
1752 splx (s);
1753 return 0;
1754
1755 case TIOCSDTR: /* Set DTR */
1756 s = splimp ();
1757 CP_LOCK (bd);
1758 cp_set_dtr (c, 1);
1759 CP_UNLOCK (bd);
1760 splx (s);
1761 return 0;
1762
1763 case TIOCCDTR: /* Clear DTR */
1764 s = splimp ();
1765 CP_LOCK (bd);
1766 cp_set_dtr (c, 0);
1767 CP_UNLOCK (bd);
1768 splx (s);
1769 return 0;
1770
1771 case TIOCMSET: /* Set DTR/RTS */
1772 s = splimp ();
1773 CP_LOCK (bd);
1774 cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0);
1775 cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0);
1776 CP_UNLOCK (bd);
1777 splx (s);
1778 return 0;
1779
1780 case TIOCMBIS: /* Add DTR/RTS */
1781 s = splimp ();
1782 CP_LOCK (bd);
1783 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1);
1784 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1);
1785 CP_UNLOCK (bd);
1786 splx (s);
1787 return 0;
1788
1789 case TIOCMBIC: /* Clear DTR/RTS */
1790 s = splimp ();
1791 CP_LOCK (bd);
1792 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0);
1793 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0);
1794 CP_UNLOCK (bd);
1795 splx (s);
1796 return 0;
1797
1798 case TIOCMGET: /* Get modem status */
1799 *(int*)data = cp_modem_status (c);
1800 return 0;
1801 }
1802 return ENOTTY;
1803 }
1804
1805 static struct cdevsw cp_cdevsw = {
1806 .d_version = D_VERSION,
1807 .d_open = cp_open,
1808 .d_close = cp_close,
1809 .d_ioctl = cp_ioctl,
1810 .d_name = "cp",
1811 .d_maj = CDEV_MAJOR,
1812 .d_flags = D_NEEDGIANT,
1813 };
1814
1815 #ifdef NETGRAPH
1816 static int ng_cp_constructor (node_p node)
1817 {
1818 drv_t *d = NG_NODE_PRIVATE (node);
1819 CP_DEBUG (d, ("Constructor\n"));
1820 return EINVAL;
1821 }
1822
1823 static int ng_cp_newhook (node_p node, hook_p hook, const char *name)
1824 {
1825 int s;
1826 drv_t *d = NG_NODE_PRIVATE (node);
1827 bdrv_t *bd = d->board->sys;
1828
1829 CP_DEBUG (d, ("Newhook\n"));
1830 /* Attach debug hook */
1831 if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) {
1832 NG_HOOK_SET_PRIVATE (hook, NULL);
1833 d->debug_hook = hook;
1834 return 0;
1835 }
1836
1837 /* Check for raw hook */
1838 if (strcmp (name, NG_CP_HOOK_RAW) != 0)
1839 return EINVAL;
1840
1841 NG_HOOK_SET_PRIVATE (hook, d);
1842 d->hook = hook;
1843 s = splimp ();
1844 CP_LOCK (bd);
1845 cp_up (d);
1846 CP_UNLOCK (bd);
1847 splx (s);
1848 return 0;
1849 }
1850
1851 static char *format_timeslots (u_long s)
1852 {
1853 static char buf [100];
1854 char *p = buf;
1855 int i;
1856
1857 for (i=1; i<32; ++i)
1858 if ((s >> i) & 1) {
1859 int prev = (i > 1) & (s >> (i-1));
1860 int next = (i < 31) & (s >> (i+1));
1861
1862 if (prev) {
1863 if (next)
1864 continue;
1865 *p++ = '-';
1866 } else if (p > buf)
1867 *p++ = ',';
1868
1869 if (i >= 10)
1870 *p++ = '' + i / 10;
1871 *p++ = '' + i % 10;
1872 }
1873 *p = 0;
1874 return buf;
1875 }
1876
1877 static int print_modems (char *s, cp_chan_t *c, int need_header)
1878 {
1879 int status = cp_modem_status (c);
1880 int length = 0;
1881
1882 if (need_header)
1883 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n");
1884 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n",
1885 status & TIOCM_LE ? "On" : "-",
1886 status & TIOCM_DTR ? "On" : "-",
1887 status & TIOCM_DSR ? "On" : "-",
1888 status & TIOCM_RTS ? "On" : "-",
1889 status & TIOCM_CTS ? "On" : "-",
1890 status & TIOCM_CD ? "On" : "-");
1891 return length;
1892 }
1893
1894 static int print_stats (char *s, cp_chan_t *c, int need_header)
1895 {
1896 int length = 0;
1897
1898 if (need_header)
1899 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n");
1900 length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n",
1901 c->rintr, c->tintr, 0l, (unsigned long) c->ibytes,
1902 c->ipkts, c->overrun + c->frame + c->crc,
1903 (unsigned long) c->obytes, c->opkts, c->underrun);
1904 return length;
1905 }
1906
1907 static char *format_e1_status (u_char status)
1908 {
1909 static char buf [80];
1910
1911 if (status & E1_NOALARM)
1912 return "Ok";
1913 buf[0] = 0;
1914 if (status & E1_LOS) strcat (buf, ",LOS");
1915 if (status & E1_AIS) strcat (buf, ",AIS");
1916 if (status & E1_LOF) strcat (buf, ",LOF");
1917 if (status & E1_LOMF) strcat (buf, ",LOMF");
1918 if (status & E1_FARLOF) strcat (buf, ",FARLOF");
1919 if (status & E1_AIS16) strcat (buf, ",AIS16");
1920 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF");
1921 if (status & E1_TSTREQ) strcat (buf, ",TSTREQ");
1922 if (status & E1_TSTERR) strcat (buf, ",TSTERR");
1923 if (buf[0] == ',')
1924 return buf+1;
1925 return "Unknown";
1926 }
1927
1928 static int print_frac (char *s, int leftalign, u_long numerator, u_long divider)
1929 {
1930 int n, length = 0;
1931
1932 if (numerator < 1 || divider < 1) {
1933 length += sprintf (s+length, leftalign ? "/- " : " -");
1934 return length;
1935 }
1936 n = (int) (0.5 + 1000.0 * numerator / divider);
1937 if (n < 1000) {
1938 length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n);
1939 return length;
1940 }
1941 *(s + length) = leftalign ? '/' : ' ';
1942 length ++;
1943
1944 if (n >= 1000000) n = (n+500) / 1000 * 1000;
1945 else if (n >= 100000) n = (n+50) / 100 * 100;
1946 else if (n >= 10000) n = (n+5) / 10 * 10;
1947
1948 switch (n) {
1949 case 1000: length += printf (s+length, ".999"); return length;
1950 case 10000: n = 9990; break;
1951 case 100000: n = 99900; break;
1952 case 1000000: n = 999000; break;
1953 }
1954 if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100);
1955 else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10);
1956 else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000);
1957 else length += sprintf (s+length, "%d", n/1000);
1958
1959 return length;
1960 }
1961
1962 static int print_e1_stats (char *s, cp_chan_t *c)
1963 {
1964 struct e1_counters total;
1965 u_long totsec;
1966 int length = 0;
1967
1968 totsec = c->totsec + c->cursec;
1969 total.bpv = c->total.bpv + c->currnt.bpv;
1970 total.fse = c->total.fse + c->currnt.fse;
1971 total.crce = c->total.crce + c->currnt.crce;
1972 total.rcrce = c->total.rcrce + c->currnt.rcrce;
1973 total.uas = c->total.uas + c->currnt.uas;
1974 total.les = c->total.les + c->currnt.les;
1975 total.es = c->total.es + c->currnt.es;
1976 total.bes = c->total.bes + c->currnt.bes;
1977 total.ses = c->total.ses + c->currnt.ses;
1978 total.oofs = c->total.oofs + c->currnt.oofs;
1979 total.css = c->total.css + c->currnt.css;
1980 total.dm = c->total.dm + c->currnt.dm;
1981
1982 length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n");
1983
1984 /* Unavailable seconds, degraded minutes */
1985 length += print_frac (s + length, 0, c->currnt.uas, c->cursec);
1986 length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec);
1987
1988 /* Bipolar violations, frame sync errors */
1989 length += print_frac (s + length, 0, c->currnt.bpv, c->cursec);
1990 length += print_frac (s + length, 1, c->currnt.fse, c->cursec);
1991
1992 /* CRC errors, remote CRC errors (E-bit) */
1993 length += print_frac (s + length, 0, c->currnt.crce, c->cursec);
1994 length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec);
1995
1996 /* Errored seconds, line errored seconds */
1997 length += print_frac (s + length, 0, c->currnt.es, c->cursec);
1998 length += print_frac (s + length, 1, c->currnt.les, c->cursec);
1999
2000 /* Severely errored seconds, burst errored seconds */
2001 length += print_frac (s + length, 0, c->currnt.ses, c->cursec);
2002 length += print_frac (s + length, 1, c->currnt.bes, c->cursec);
2003
2004 /* Out of frame seconds, controlled slip seconds */
2005 length += print_frac (s + length, 0, c->currnt.oofs, c->cursec);
2006 length += print_frac (s + length, 1, c->currnt.css, c->cursec);
2007
2008 length += sprintf (s + length, " %s\n", format_e1_status (c->status));
2009
2010 /* Print total statistics. */
2011 length += print_frac (s + length, 0, total.uas, totsec);
2012 length += print_frac (s + length, 1, 60 * total.dm, totsec);
2013
2014 length += print_frac (s + length, 0, total.bpv, totsec);
2015 length += print_frac (s + length, 1, total.fse, totsec);
2016
2017 length += print_frac (s + length, 0, total.crce, totsec);
2018 length += print_frac (s + length, 1, total.rcrce, totsec);
2019
2020 length += print_frac (s + length, 0, total.es, totsec);
2021 length += print_frac (s + length, 1, total.les, totsec);
2022
2023 length += print_frac (s + length, 0, total.ses, totsec);
2024 length += print_frac (s + length, 1, total.bes, totsec);
2025
2026 length += print_frac (s + length, 0, total.oofs, totsec);
2027 length += print_frac (s + length, 1, total.css, totsec);
2028
2029 length += sprintf (s + length, " -- Total\n");
2030 return length;
2031 }
2032
2033 static int print_chan (char *s, cp_chan_t *c)
2034 {
2035 drv_t *d = c->sys;
2036 bdrv_t *bd = d->board->sys;
2037 int length = 0;
2038
2039 length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num);
2040 if (d->chan->debug)
2041 length += sprintf (s + length, " debug=%d", d->chan->debug);
2042
2043 if (c->board->mux) {
2044 length += sprintf (s + length, " cfg=C");
2045 } else {
2046 length += sprintf (s + length, " cfg=A");
2047 }
2048
2049 if (c->baud)
2050 length += sprintf (s + length, " %ld", c->baud);
2051 else
2052 length += sprintf (s + length, " extclock");
2053
2054 if (c->type == T_E1 || c->type == T_G703)
2055 switch (c->gsyn) {
2056 case GSYN_INT : length += sprintf (s + length, " syn=int"); break;
2057 case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break;
2058 case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break;
2059 case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break;
2060 case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break;
2061 case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break;
2062 }
2063 if (c->type == T_SERIAL) {
2064 length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off");
2065 length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off");
2066 length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off");
2067 }
2068 if (c->type == T_E1)
2069 length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off");
2070
2071 length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off");
2072
2073 if (c->type == T_E1)
2074 length += sprintf (s + length, " ts=%s", format_timeslots (c->ts));
2075 if (c->type == T_G703) {
2076 int lq, x;
2077
2078 x = splimp ();
2079 CP_LOCK (bd);
2080 lq = cp_get_lq (c);
2081 CP_UNLOCK (bd);
2082 splx (x);
2083 length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0);
2084 }
2085 length += sprintf (s + length, "\n");
2086 return length;
2087 }
2088
2089 static int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook)
2090 {
2091 drv_t *d = NG_NODE_PRIVATE (node);
2092 struct ng_mesg *msg;
2093 struct ng_mesg *resp = NULL;
2094 int error = 0;
2095
2096 CP_DEBUG (d, ("Rcvmsg\n"));
2097 NGI_GET_MSG (item, msg);
2098 switch (msg->header.typecookie) {
2099 default:
2100 error = EINVAL;
2101 break;
2102
2103 case NGM_CP_COOKIE:
2104 printf ("Not implemented yet\n");
2105 error = EINVAL;
2106 break;
2107
2108 case NGM_GENERIC_COOKIE:
2109 switch (msg->header.cmd) {
2110 default:
2111 error = EINVAL;
2112 break;
2113
2114 case NGM_TEXT_STATUS: {
2115 char *s;
2116 int l = 0;
2117 int dl = sizeof (struct ng_mesg) + 730;
2118
2119 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT);
2120 if (! resp) {
2121 error = ENOMEM;
2122 break;
2123 }
2124 s = (resp)->data;
2125 if (d) {
2126 l += print_chan (s + l, d->chan);
2127 l += print_stats (s + l, d->chan, 1);
2128 l += print_modems (s + l, d->chan, 1);
2129 l += print_e1_stats (s + l, d->chan);
2130 } else
2131 l += sprintf (s + l, "Error: node not connect to channel");
2132 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN);
2133 }
2134 break;
2135 }
2136 break;
2137 }
2138 NG_RESPOND_MSG (error, node, item, resp);
2139 NG_FREE_MSG (msg);
2140 return error;
2141 }
2142
2143 static int ng_cp_rcvdata (hook_p hook, item_p item)
2144 {
2145 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook));
2146 struct mbuf *m;
2147 struct ng_tag_prio *ptag;
2148 bdrv_t *bd = d->board->sys;
2149 struct ifqueue *q;
2150 int s;
2151
2152 CP_DEBUG2 (d, ("Rcvdata\n"));
2153 NGI_GET_M (item, m);
2154 NG_FREE_ITEM (item);
2155 if (! NG_HOOK_PRIVATE (hook) || ! d) {
2156 NG_FREE_M (m);
2157 return ENETDOWN;
2158 }
2159
2160 /* Check for high priority data */
2161 if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE,
2162 NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) )
2163 q = &d->hi_queue;
2164 else
2165 q = &d->queue;
2166
2167 s = splimp ();
2168 CP_LOCK (bd);
2169 IF_LOCK (q);
2170 if (_IF_QFULL (q)) {
2171 _IF_DROP (q);
2172 IF_UNLOCK (q);
2173 CP_UNLOCK (bd);
2174 splx (s);
2175 NG_FREE_M (m);
2176 return ENOBUFS;
2177 }
2178 _IF_ENQUEUE (q, m);
2179 IF_UNLOCK (q);
2180 cp_start (d);
2181 CP_UNLOCK (bd);
2182 splx (s);
2183 return 0;
2184 }
2185
2186 static int ng_cp_rmnode (node_p node)
2187 {
2188 drv_t *d = NG_NODE_PRIVATE (node);
2189
2190 CP_DEBUG (d, ("Rmnode\n"));
2191 if (d && d->running) {
2192 bdrv_t *bd = d->board->sys;
2193 int s = splimp ();
2194 CP_LOCK (bd);
2195 cp_down (d);
2196 CP_UNLOCK (bd);
2197 splx (s);
2198 }
2199 #ifdef KLD_MODULE
2200 if (node->nd_flags & NGF_REALLY_DIE) {
2201 NG_NODE_SET_PRIVATE (node, NULL);
2202 NG_NODE_UNREF (node);
2203 }
2204 NG_NODE_REVIVE(node); /* Persistant node */
2205 #endif
2206 return 0;
2207 }
2208
2209 static void ng_cp_watchdog (void *arg)
2210 {
2211 drv_t *d = arg;
2212
2213 if (d) {
2214 if (d->timeout == 1)
2215 cp_watchdog (d);
2216 if (d->timeout)
2217 d->timeout--;
2218 callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d);
2219 }
2220 }
2221
2222 static int ng_cp_connect (hook_p hook)
2223 {
2224 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook));
2225
2226 if (d) {
2227 CP_DEBUG (d, ("Connect\n"));
2228 callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d);
2229 }
2230
2231 return 0;
2232 }
2233
2234 static int ng_cp_disconnect (hook_p hook)
2235 {
2236 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook));
2237
2238 if (d) {
2239 CP_DEBUG (d, ("Disconnect\n"));
2240 if (NG_HOOK_PRIVATE (hook))
2241 {
2242 bdrv_t *bd = d->board->sys;
2243 int s = splimp ();
2244 CP_LOCK (bd);
2245 cp_down (d);
2246 CP_UNLOCK (bd);
2247 splx (s);
2248 }
2249 /* If we were wait it than it reasserted now, just stop it. */
2250 if (!callout_drain (&d->timeout_handle))
2251 callout_stop (&d->timeout_handle);
2252 }
2253 return 0;
2254 }
2255 #endif
2256
2257 static int cp_modevent (module_t mod, int type, void *unused)
2258 {
2259 static int load_count = 0;
2260
2261 if (!debug_mpsafenet && cp_mpsafenet) {
2262 printf ("WORNING! Network stack is not MPSAFE. "
2263 "Turning off debug.cp.mpsafenet.\n");
2264 cp_mpsafenet = 0;
2265 }
2266 if (cp_mpsafenet)
2267 cp_cdevsw.d_flags &= ~D_NEEDGIANT;
2268
2269 switch (type) {
2270 case MOD_LOAD:
2271 #ifdef NETGRAPH
2272 if (ng_newtype (&typestruct))
2273 printf ("Failed to register ng_cp\n");
2274 #endif
2275 ++load_count;
2276 callout_init (&timeout_handle, cp_mpsafenet?CALLOUT_MPSAFE:0);
2277 callout_reset (&timeout_handle, hz*5, cp_timeout, 0);
2278 break;
2279 case MOD_UNLOAD:
2280 if (load_count == 1) {
2281 printf ("Removing device entry for Tau-PCI\n");
2282 #ifdef NETGRAPH
2283 ng_rmtype (&typestruct);
2284 #endif
2285 }
2286 /* If we were wait it than it reasserted now, just stop it.
2287 * Actually we shouldn't get this condition. But code could be
2288 * changed in the future, so just be a litle paranoid.
2289 */
2290 if (!callout_drain (&timeout_handle))
2291 callout_stop (&timeout_handle);
2292 --load_count;
2293 break;
2294 case MOD_SHUTDOWN:
2295 break;
2296 }
2297 return 0;
2298 }
2299
2300 #ifdef NETGRAPH
2301 static struct ng_type typestruct = {
2302 .version = NG_ABI_VERSION,
2303 .name = NG_CP_NODE_TYPE,
2304 .constructor = ng_cp_constructor,
2305 .rcvmsg = ng_cp_rcvmsg,
2306 .shutdown = ng_cp_rmnode,
2307 .newhook = ng_cp_newhook,
2308 .connect = ng_cp_connect,
2309 .rcvdata = ng_cp_rcvdata,
2310 .disconnect = ng_cp_disconnect,
2311 };
2312 #endif /*NETGRAPH*/
2313
2314 #ifdef NETGRAPH
2315 MODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
2316 #else
2317 MODULE_DEPEND (cp, sppp, 1, 1, 1);
2318 #endif
2319 DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL);
2320 MODULE_VERSION (cp, 1);
Cache object: 8767dc36b016e40a96588503a40ffcd1
|