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