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