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