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