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