if_cx.c revision 136480
1/*
2 * Cronyx-Sigma adapter driver for FreeBSD.
3 * Supports PPP/HDLC and Cisco/HDLC protocol in synchronous mode,
4 * and asyncronous channels with full modem control.
5 * Keepalive protocol implemented in both Cisco and PPP modes.
6 *
7 * Copyright (C) 1994-2002 Cronyx Engineering.
8 * Author: Serge Vakulenko, <vak@cronyx.ru>
9 *
10 * Copyright (C) 1999-2004 Cronyx Engineering.
11 * Rewritten on DDK, ported to NETGRAPH, rewritten for FreeBSD 3.x-5.x by
12 * Kurakin Roman, <rik@cronyx.ru>
13 *
14 * This software is distributed with NO WARRANTIES, not even the implied
15 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * Authors grant any other persons or organisations a permission to use,
18 * modify and redistribute this software in source and binary forms,
19 * as long as this message is kept with the software, all derivative
20 * works or modified versions.
21 *
22 * Cronyx Id: if_cx.c,v 1.1.2.34 2004/06/23 17:09:13 rik Exp $
23 */
24
25#include <sys/cdefs.h>
26__FBSDID("$FreeBSD: head/sys/dev/cx/if_cx.c 136480 2004-10-13 09:27:18Z phk $");
27
28#include <sys/param.h>
29
30#include <sys/systm.h>
31#include <sys/kernel.h>
32#include <sys/module.h>
33#include <sys/proc.h>
34#include <sys/mbuf.h>
35#include <sys/sockio.h>
36#include <sys/malloc.h>
37#include <sys/socket.h>
38#include <sys/conf.h>
39#include <sys/errno.h>
40#include <sys/serial.h>
41#include <sys/tty.h>
42#include <sys/bus.h>
43#include <machine/bus.h>
44#include <sys/rman.h>
45#include <isa/isavar.h>
46#include <sys/fcntl.h>
47#include <sys/interrupt.h>
48#include <vm/vm.h>
49#include <vm/pmap.h>
50#include <net/if.h>
51#include <machine/cpufunc.h>
52#include <machine/cserial.h>
53#include <machine/clock.h>
54#include <machine/resource.h>
55#include <dev/cx/machdep.h>
56#include <dev/cx/cxddk.h>
57#include <dev/cx/cronyxfw.h>
58#include "opt_ng_cronyx.h"
59#ifdef NETGRAPH_CRONYX
60#   include "opt_netgraph.h"
61#   include <netgraph/ng_message.h>
62#   include <netgraph/netgraph.h>
63#   include <dev/cx/ng_cx.h>
64#else
65#   include <net/if_types.h>
66#   include <net/if_sppp.h>
67#   define PP_CISCO IFF_LINK2
68#   include <net/bpf.h>
69#endif
70
71#define NCX	1
72
73/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */
74#ifndef PP_FR
75#define PP_FR 0
76#endif
77
78#define CX_DEBUG(d,s)	({if (d->chan->debug) {\
79				printf ("%s: ", d->name); printf s;}})
80#define CX_DEBUG2(d,s)	({if (d->chan->debug>1) {\
81				printf ("%s: ", d->name); printf s;}})
82
83typedef struct _async_q {
84	int beg;
85	int end;
86	#define BF_SZ 14400
87	int buf[BF_SZ+1];
88} async_q;
89
90#define AQ_GSZ(q)	((BF_SZ + (q)->end - (q)->beg)%BF_SZ)
91#define AQ_PUSH(q,c)	{*((q)->buf + (q)->end) = c;\
92			(q)->end = ((q)->end + 1)%BF_SZ;}
93#define AQ_POP(q,c)	{c = *((q)->buf + (q)->beg);\
94			(q)->beg = ((q)->beg + 1)%BF_SZ;}
95
96static void cx_identify		__P((driver_t *, device_t));
97static int cx_probe		__P((device_t));
98static int cx_attach		__P((device_t));
99static int cx_detach		__P((device_t));
100static t_open_t			cx_topen;
101static t_modem_t		cx_tmodem;
102static t_close_t		cx_tclose;
103
104static device_method_t cx_isa_methods [] = {
105	DEVMETHOD(device_identify,	cx_identify),
106	DEVMETHOD(device_probe,		cx_probe),
107	DEVMETHOD(device_attach,	cx_attach),
108	DEVMETHOD(device_detach,	cx_detach),
109	{0, 0}
110};
111
112typedef struct _cx_dma_mem_t {
113	unsigned long	phys;
114	void		*virt;
115	size_t		size;
116	bus_dma_tag_t	dmat;
117	bus_dmamap_t	mapp;
118} cx_dma_mem_t;
119
120typedef struct _drv_t {
121	char name [8];
122	cx_chan_t *chan;
123	cx_board_t *board;
124	cx_dma_mem_t dmamem;
125	struct tty *tty;
126	struct callout_handle dcd_timeout_handle;
127	unsigned callout;
128	unsigned lock;
129	int open_dev;
130	int cd;
131	int running;
132#ifdef NETGRAPH
133	char	nodename [NG_NODELEN+1];
134	hook_p	hook;
135	hook_p	debug_hook;
136	node_p	node;
137	struct	ifqueue lo_queue;
138	struct	ifqueue hi_queue;
139	short	timeout;
140	struct	callout_handle timeout_handle;
141#else
142	struct sppp pp;
143#endif
144	struct cdev *devt;
145	async_q aqueue;
146#define CX_READ 1
147#define CX_WRITE 2
148	int intr_action;
149	short atimeout;
150} drv_t;
151
152typedef struct _bdrv_t {
153	cx_board_t	*board;
154	struct resource	*base_res;
155	struct resource	*drq_res;
156	struct resource	*irq_res;
157	int		base_rid;
158	int		drq_rid;
159	int		irq_rid;
160	void		*intrhand;
161	drv_t		channel [NCHAN];
162} bdrv_t;
163
164static driver_t cx_isa_driver = {
165	"cx",
166	cx_isa_methods,
167	sizeof (bdrv_t),
168};
169
170static devclass_t cx_devclass;
171
172extern long csigma_fw_len;
173extern const char *csigma_fw_version;
174extern const char *csigma_fw_date;
175extern const char *csigma_fw_copyright;
176extern const cr_dat_tst_t csigma_fw_tvec[];
177extern const u_char csigma_fw_data[];
178static void cx_oproc (struct tty *tp);
179static int cx_param (struct tty *tp, struct termios *t);
180static void cx_stop (struct tty *tp, int flag);
181static void cx_receive (cx_chan_t *c, char *data, int len);
182static void cx_transmit (cx_chan_t *c, void *attachment, int len);
183static void cx_error (cx_chan_t *c, int data);
184static void cx_modem (cx_chan_t *c);
185static void cx_up (drv_t *d);
186static void cx_start (drv_t *d);
187static void cx_softintr (void *);
188static void *cx_fast_ih;
189static void cx_down (drv_t *d);
190static void cx_watchdog (drv_t *d);
191static void cx_carrier (void *arg);
192
193#ifdef NETGRAPH
194extern struct ng_type typestruct;
195#else
196static void cx_ifstart (struct ifnet *ifp);
197static void cx_tlf (struct sppp *sp);
198static void cx_tls (struct sppp *sp);
199static void cx_ifwatchdog (struct ifnet *ifp);
200static int cx_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data);
201static void cx_initialize (void *softc);
202#endif
203
204static cx_board_t *adapter [NCX];
205static drv_t *channel [NCX*NCHAN];
206static struct callout_handle led_timo [NCX];
207static struct callout_handle timeout_handle;
208extern struct cdevsw cx_cdevsw;
209
210static int MY_SOFT_INTR;
211
212/*
213 * Print the mbuf chain, for debug purposes only.
214 */
215static void printmbuf (struct mbuf *m)
216{
217	printf ("mbuf:");
218	for (; m; m=m->m_next) {
219		if (m->m_flags & M_PKTHDR)
220			printf (" HDR %d:", m->m_pkthdr.len);
221		if (m->m_flags & M_EXT)
222			printf (" EXT:");
223		printf (" %d", m->m_len);
224	}
225	printf ("\n");
226}
227
228/*
229 * Make an mbuf from data.
230 */
231static struct mbuf *makembuf (void *buf, u_int len)
232{
233	struct mbuf *m, *o, *p;
234
235	MGETHDR (m, M_DONTWAIT, MT_DATA);
236
237	if (! m)
238		return 0;
239
240	if (len >= MINCLSIZE)
241		MCLGET (m, M_DONTWAIT);
242
243	m->m_pkthdr.len = len;
244	m->m_len = 0;
245
246	p = m;
247	while (len) {
248		u_int n = M_TRAILINGSPACE (p);
249		if (n > len)
250			n = len;
251		if (! n) {
252			/* Allocate new mbuf. */
253			o = p;
254			MGET (p, M_DONTWAIT, MT_DATA);
255			if (! p) {
256				m_freem (m);
257				return 0;
258			}
259			if (len >= MINCLSIZE)
260				MCLGET (p, M_DONTWAIT);
261			p->m_len = 0;
262			o->m_next = p;
263
264			n = M_TRAILINGSPACE (p);
265			if (n > len)
266				n = len;
267		}
268		bcopy (buf, mtod (p, caddr_t) + p->m_len, n);
269
270		p->m_len += n;
271		buf = n + (char*) buf;
272		len -= n;
273	}
274	return m;
275}
276
277/*
278 * Recover after lost transmit interrupts.
279 */
280static void cx_timeout (void *arg)
281{
282	drv_t *d;
283	int s, i;
284
285	for (i=0; i<NCX*NCHAN; ++i) {
286		d = channel[i];
287		if (! d)
288			continue;
289		s = splhigh ();
290		if (d->atimeout == 1 && d->tty && d->tty->t_state & TS_BUSY) {
291			d->tty->t_state &= ~TS_BUSY;
292			if (d->tty->t_dev) {
293				d->intr_action |= CX_WRITE;
294				MY_SOFT_INTR = 1;
295				swi_sched (cx_fast_ih, 0);
296			}
297			CX_DEBUG (d, ("cx_timeout\n"));
298		}
299		if (d->atimeout)
300			d->atimeout--;
301		splx (s);
302	}
303	timeout_handle = timeout (cx_timeout, 0, hz*5);
304}
305
306static void cx_led_off (void *arg)
307{
308	cx_board_t *b = arg;
309	int s = splhigh ();
310
311	cx_led (b, 0);
312	led_timo[b->num].callout = 0;
313	splx (s);
314}
315
316/*
317 * Activate interupt handler from DDK.
318 */
319static void cx_intr (void *arg)
320{
321	bdrv_t *bd = arg;
322	cx_board_t *b = bd->board;
323	int s = splhigh ();
324
325	/* Turn LED on. */
326	cx_led (b, 1);
327
328	cx_int_handler (b);
329
330	/* Turn LED off 50 msec later. */
331	if (! led_timo[b->num].callout)
332		led_timo[b->num] = timeout (cx_led_off, b, hz/20);
333	splx (s);
334}
335
336static int probe_irq (cx_board_t *b, int irq)
337{
338	int mask, busy, cnt;
339
340	/* Clear pending irq, if any. */
341	cx_probe_irq (b, -irq);
342	DELAY (100);
343	for (cnt=0; cnt<5; ++cnt) {
344		/* Get the mask of pending irqs, assuming they are busy.
345		 * Activate the adapter on given irq. */
346		busy = cx_probe_irq (b, irq);
347		DELAY (100);
348
349		/* Get the mask of active irqs.
350		 * Deactivate our irq. */
351		mask = cx_probe_irq (b, -irq);
352		DELAY (100);
353		if ((mask & ~busy) == 1 << irq) {
354			cx_probe_irq (b, 0);
355			/* printf ("cx%d: irq %d ok, mask=0x%04x, busy=0x%04x\n",
356				b->num, irq, mask, busy); */
357			return 1;
358		}
359	}
360	/* printf ("cx%d: irq %d not functional, mask=0x%04x, busy=0x%04x\n",
361		b->num, irq, mask, busy); */
362	cx_probe_irq (b, 0);
363	return 0;
364}
365
366static short porttab [] = {
367	0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0,
368	0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0
369};
370static char dmatab [] = { 7, 6, 5, 0 };
371static char irqtab [] = { 5, 10, 11, 7, 3, 15, 12, 0 };
372
373static int cx_is_free_res (device_t dev, int rid, int type, u_long start,
374	u_long end, u_long count)
375{
376	struct resource *res;
377
378	if (!(res = bus_alloc_resource (dev, type, &rid, start, end, count,
379	    RF_ALLOCATED)))
380		return 0;
381
382	bus_release_resource (dev, type, rid, res);
383
384	return 1;
385}
386
387static void cx_identify (driver_t *driver, device_t dev)
388{
389	u_long iobase, rescount;
390	int devcount;
391	device_t *devices;
392	device_t child;
393	devclass_t my_devclass;
394	int i, k;
395
396	if ((my_devclass = devclass_find ("cx")) == NULL)
397		return;
398
399	devclass_get_devices (my_devclass, &devices, &devcount);
400
401	if (devcount == 0) {
402		/* We should find all devices by our self. We could alter other
403		 * devices, but we don't have a choise
404		 */
405		for (i = 0; (iobase = porttab [i]) != 0; i++) {
406			if (!cx_is_free_res (dev, 0, SYS_RES_IOPORT,
407			    iobase, iobase + NPORT, NPORT))
408				continue;
409			if (cx_probe_board (iobase, -1, -1) == 0)
410				continue;
411
412			devcount++;
413
414			child = BUS_ADD_CHILD (dev, ISA_ORDER_SPECULATIVE, "cx",
415			    -1);
416
417			if (child == NULL)
418				return;
419
420			device_set_desc_copy (child, "Cronyx Sigma");
421			device_set_driver (child, driver);
422			bus_set_resource (child, SYS_RES_IOPORT, 0,
423			    iobase, NPORT);
424
425			if (devcount >= NCX)
426				break;
427		}
428	} else {
429		static short porttab [] = {
430			0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0,
431			0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0
432		};
433		/* Lets check user choise.
434		 */
435		for (k = 0; k < devcount; k++) {
436			if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0,
437			    &iobase, &rescount) != 0)
438				continue;
439
440			for (i = 0; porttab [i] != 0; i++) {
441				if (porttab [i] != iobase)
442					continue;
443				if (!cx_is_free_res (devices[k], 0, SYS_RES_IOPORT,
444				    iobase, iobase + NPORT, NPORT))
445					continue;
446				if (cx_probe_board (iobase, -1, -1) == 0)
447					continue;
448				porttab [i] = -1;
449				device_set_desc_copy (devices[k], "Cronyx Sigma");
450				break;
451			}
452
453			if (porttab [i] == 0) {
454				device_delete_child (
455				    device_get_parent (devices[k]),
456				    devices [k]);
457				devices[k] = 0;
458				continue;
459			}
460		}
461		for (k = 0; k < devcount; k++) {
462			if (devices[k] == 0)
463				continue;
464			if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0,
465			    &iobase, &rescount) == 0)
466				continue;
467			for (i = 0; (iobase = porttab [i]) != 0; i++) {
468				if (porttab [i] == -1) {
469					continue;
470				}
471				if (!cx_is_free_res (devices[k], 0, SYS_RES_IOPORT,
472				    iobase, iobase + NPORT, NPORT))
473					continue;
474				if (cx_probe_board (iobase, -1, -1) == 0)
475					continue;
476
477				bus_set_resource (devices[k], SYS_RES_IOPORT, 0,
478				    iobase, NPORT);
479				porttab [i] = -1;
480				device_set_desc_copy (devices[k], "Cronyx Sigma");
481				break;
482			}
483			if (porttab [i] == 0) {
484				device_delete_child (
485				    device_get_parent (devices[k]),
486				    devices [k]);
487			}
488		}
489		free (devices, M_TEMP);
490	}
491
492	return;
493}
494
495static int cx_probe (device_t dev)
496{
497	int unit = device_get_unit (dev);
498	int i;
499	u_long iobase, rescount;
500
501	if (!device_get_desc (dev) ||
502	    strcmp (device_get_desc (dev), "Cronyx Sigma"))
503		return ENXIO;
504
505	if (bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount) != 0) {
506		printf ("cx%d: Couldn't get IOPORT\n", unit);
507		return ENXIO;
508	}
509
510	if (!cx_is_free_res (dev, 0, SYS_RES_IOPORT,
511	    iobase, iobase + NPORT, NPORT)) {
512		printf ("cx%d: Resource IOPORT isn't free %lx\n", unit, iobase);
513		return ENXIO;
514	}
515
516	for (i = 0; porttab [i] != 0; i++) {
517		if (porttab [i] == iobase) {
518			porttab [i] = -1;
519			break;
520		}
521	}
522
523	if (porttab [i] == 0) {
524		return ENXIO;
525	}
526
527	if (!cx_probe_board (iobase, -1, -1)) {
528		printf ("cx%d: probing for Sigma at %lx faild\n", unit, iobase);
529		return ENXIO;
530	}
531
532	return 0;
533}
534
535static void
536cx_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error)
537{
538	unsigned long *addr;
539
540	if (error)
541		return;
542
543	KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg));
544	addr = arg;
545	*addr = segs->ds_addr;
546}
547
548static int
549cx_bus_dma_mem_alloc (int bnum, int cnum, cx_dma_mem_t *dmem)
550{
551	int error;
552
553	error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_24BIT,
554		BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1,
555		dmem->size, 0, NULL, NULL, &dmem->dmat);
556	if (error) {
557		if (cnum >= 0)	printf ("cx%d-%d: ", bnum, cnum);
558		else		printf ("cx%d: ", bnum);
559		printf ("couldn't allocate tag for dma memory\n");
560 		return 0;
561	}
562	error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt,
563		BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp);
564	if (error) {
565		if (cnum >= 0)	printf ("cx%d-%d: ", bnum, cnum);
566		else		printf ("cx%d: ", bnum);
567		printf ("couldn't allocate mem for dma memory\n");
568		bus_dma_tag_destroy (dmem->dmat);
569 		return 0;
570	}
571	error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt,
572		dmem->size, cx_bus_dmamap_addr, &dmem->phys, 0);
573	if (error) {
574		if (cnum >= 0)	printf ("cx%d-%d: ", bnum, cnum);
575		else		printf ("cx%d: ", bnum);
576		printf ("couldn't load mem map for dma memory\n");
577		bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp);
578		bus_dma_tag_destroy (dmem->dmat);
579 		return 0;
580	}
581	return 1;
582}
583
584static void
585cx_bus_dma_mem_free (cx_dma_mem_t *dmem)
586{
587	bus_dmamap_unload (dmem->dmat, dmem->mapp);
588	bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp);
589	bus_dma_tag_destroy (dmem->dmat);
590}
591
592/*
593 * The adapter is present, initialize the driver structures.
594 */
595static int cx_attach (device_t dev)
596{
597	bdrv_t *bd = device_get_softc (dev);
598	u_long iobase, drq, irq, rescount;
599	int unit = device_get_unit (dev);
600	cx_board_t *b;
601	cx_chan_t *c;
602	drv_t *d;
603	int i;
604	int s;
605
606	KASSERT ((bd != NULL), ("cx%d: NULL device softc\n", unit));
607
608	bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount);
609	bd->base_rid = 0;
610	bd->base_res = bus_alloc_resource (dev, SYS_RES_IOPORT, &bd->base_rid,
611		iobase, iobase + NPORT, NPORT, RF_ACTIVE);
612	if (! bd->base_res) {
613		printf ("cx%d: cannot allocate base address\n", unit);
614		return ENXIO;
615	}
616
617	if (bus_get_resource (dev, SYS_RES_DRQ, 0, &drq, &rescount) != 0) {
618		for (i = 0; (drq = dmatab [i]) != 0; i++) {
619			if (!cx_is_free_res (dev, 0, SYS_RES_DRQ,
620			    drq, drq + 1, 1))
621				continue;
622			bus_set_resource (dev, SYS_RES_DRQ, 0, drq, 1);
623			break;
624		}
625
626		if (dmatab[i] == 0) {
627			bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid,
628				bd->base_res);
629			printf ("cx%d: Couldn't get DRQ\n", unit);
630			return ENXIO;
631		}
632	}
633
634	bd->drq_rid = 0;
635	bd->drq_res = bus_alloc_resource (dev, SYS_RES_DRQ, &bd->drq_rid,
636		drq, drq + 1, 1, RF_ACTIVE);
637	if (! bd->drq_res) {
638		printf ("cx%d: cannot allocate drq\n", unit);
639		bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid,
640			bd->base_res);
641		return ENXIO;
642	}
643
644	if (bus_get_resource (dev, SYS_RES_IRQ, 0, &irq, &rescount) != 0) {
645		for (i = 0; (irq = irqtab [i]) != 0; i++) {
646			if (!cx_is_free_res (dev, 0, SYS_RES_IRQ,
647			    irq, irq + 1, 1))
648				continue;
649			bus_set_resource (dev, SYS_RES_IRQ, 0, irq, 1);
650			break;
651		}
652
653		if (irqtab[i] == 0) {
654			bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid,
655				bd->drq_res);
656			bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid,
657				bd->base_res);
658			printf ("cx%d: Couldn't get IRQ\n", unit);
659			return ENXIO;
660		}
661	}
662
663	bd->irq_rid = 0;
664	bd->irq_res = bus_alloc_resource (dev, SYS_RES_IRQ, &bd->irq_rid,
665		irq, irq + 1, 1, RF_ACTIVE);
666	if (! bd->irq_res) {
667		printf ("cx%d: Couldn't allocate irq\n", unit);
668		bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid,
669			bd->drq_res);
670		bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid,
671			bd->base_res);
672		return ENXIO;
673	}
674
675	b = malloc (sizeof (cx_board_t), M_DEVBUF, M_WAITOK);
676	if (!b) {
677		printf ("cx:%d: Couldn't allocate memory\n", unit);
678		return (ENXIO);
679	}
680	adapter[unit] = b;
681	bzero (b, sizeof(cx_board_t));
682
683	if (! cx_open_board (b, unit, iobase, irq, drq)) {
684		printf ("cx%d: error loading firmware\n", unit);
685		free (b, M_DEVBUF);
686		bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid,
687			bd->irq_res);
688		bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid,
689			bd->drq_res);
690		bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid,
691			bd->base_res);
692 		return ENXIO;
693	}
694
695	bd->board = b;
696
697	if (! probe_irq (b, irq)) {
698		printf ("cx%d: irq %ld not functional\n", unit, irq);
699		bd->board = 0;
700		adapter [unit] = 0;
701		free (b, M_DEVBUF);
702		bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid,
703			bd->irq_res);
704		bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid,
705			bd->drq_res);
706		bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid,
707			bd->base_res);
708 		return ENXIO;
709	}
710
711	s = splhigh ();
712	if (bus_setup_intr (dev, bd->irq_res, INTR_TYPE_NET, cx_intr, bd,
713	    &bd->intrhand)) {
714		printf ("cx%d: Can't setup irq %ld\n", unit, irq);
715		bd->board = 0;
716		adapter [unit] = 0;
717		free (b, M_DEVBUF);
718		bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid,
719			bd->irq_res);
720		bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid,
721			bd->drq_res);
722		bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid,
723			bd->base_res);
724		splx (s);
725 		return ENXIO;
726	}
727
728	cx_init (b, b->num, b->port, irq, drq);
729	cx_setup_board (b, 0, 0, 0);
730
731	printf ("cx%d: <Cronyx-Sigma-%s>\n", b->num, b->name);
732
733	for (c=b->chan; c<b->chan+NCHAN; ++c) {
734		if (c->type == T_NONE)
735			continue;
736		d = &bd->channel[c->num];
737		d->dmamem.size = sizeof(cx_buf_t);
738		if (! cx_bus_dma_mem_alloc (unit, c->num, &d->dmamem))
739			continue;
740		channel [b->num*NCHAN + c->num] = d;
741		sprintf (d->name, "cx%d.%d", b->num, c->num);
742		d->board = b;
743		d->chan = c;
744		d->open_dev = 0;
745		c->sys = d;
746
747		switch (c->type) {
748		case T_SYNC_RS232:
749		case T_SYNC_V35:
750		case T_SYNC_RS449:
751		case T_UNIV:
752		case T_UNIV_RS232:
753		case T_UNIV_RS449:
754		case T_UNIV_V35:
755#ifdef NETGRAPH
756		if (ng_make_node_common (&typestruct, &d->node) != 0) {
757			printf ("%s: cannot make common node\n", d->name);
758			channel [b->num*NCHAN + c->num] = 0;
759			c->sys = 0;
760			cx_bus_dma_mem_free (&d->dmamem);
761			continue;
762		}
763		NG_NODE_SET_PRIVATE (d->node, d);
764		sprintf (d->nodename, "%s%d", NG_CX_NODE_TYPE,
765			 c->board->num*NCHAN + c->num);
766		if (ng_name_node (d->node, d->nodename)) {
767			printf ("%s: cannot name node\n", d->nodename);
768			NG_NODE_UNREF (d->node);
769			channel [b->num*NCHAN + c->num] = 0;
770			c->sys = 0;
771			cx_bus_dma_mem_free (&d->dmamem);
772			continue;
773		}
774		d->lo_queue.ifq_maxlen = IFQ_MAXLEN;
775		d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
776		mtx_init (&d->lo_queue.ifq_mtx, "cx_queue_lo", NULL, MTX_DEF);
777		mtx_init (&d->hi_queue.ifq_mtx, "cx_queue_hi", NULL, MTX_DEF);
778#else /*NETGRAPH*/
779		d->pp.pp_if.if_softc    = d;
780		if_initname (&d->pp.pp_if, "cx", b->num * NCHAN + c->num);
781		d->pp.pp_if.if_mtu	= PP_MTU;
782		d->pp.pp_if.if_flags	= IFF_POINTOPOINT | IFF_MULTICAST |
783					  IFF_NEEDSGIANT;
784		d->pp.pp_if.if_ioctl	= cx_sioctl;
785		d->pp.pp_if.if_start	= cx_ifstart;
786		d->pp.pp_if.if_watchdog	= cx_ifwatchdog;
787		d->pp.pp_if.if_init	= cx_initialize;
788		sppp_attach (&d->pp.pp_if);
789		if_attach (&d->pp.pp_if);
790		d->pp.pp_tlf		= cx_tlf;
791		d->pp.pp_tls		= cx_tls;
792		/* If BPF is in the kernel, call the attach for it.
793		 * Size of PPP header is 4 bytes. */
794		bpfattach (&d->pp.pp_if, DLT_PPP, 4);
795#endif /*NETGRAPH*/
796		}
797		d->tty = ttyalloc ();
798		d->tty->t_open = cx_topen;
799		d->tty->t_close = cx_tclose;
800		d->tty->t_param = cx_param;
801		d->tty->t_stop  = cx_stop;
802		d->tty->t_modem  = cx_tmodem;
803		d->tty->t_sc = d;
804		cx_start_chan (c, d->dmamem.virt, d->dmamem.phys);
805		cx_register_receive (c, &cx_receive);
806		cx_register_transmit (c, &cx_transmit);
807		cx_register_error (c, &cx_error);
808		cx_register_modem (c, &cx_modem);
809
810		ttycreate(d->tty, NULL, 0, MINOR_CALLOUT,
811		    "x%r%r", b->num, c->num);
812		d->devt = make_dev (&cx_cdevsw, b->num*NCHAN + c->num + 64, UID_ROOT, GID_WHEEL, 0600, "cx%d", b->num*NCHAN + c->num);
813		d->devt->si_drv1 = d;
814	}
815	splx (s);
816
817	return 0;
818}
819
820static int cx_detach (device_t dev)
821{
822	bdrv_t *bd = device_get_softc (dev);
823	cx_board_t *b = bd->board;
824	cx_chan_t *c;
825	int s = splhigh ();
826
827	/* Check if the device is busy (open). */
828	for (c = b->chan; c < b->chan + NCHAN; ++c) {
829		drv_t *d = (drv_t*) c->sys;
830
831		if (!d || d->chan->type == T_NONE)
832			continue;
833		if (d->lock) {
834			splx (s);
835			return EBUSY;
836		}
837		if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) &&
838		    (d->open_dev|0x2)) {
839			splx (s);
840			return EBUSY;
841		}
842		if (d->running) {
843			splx (s);
844			return EBUSY;
845		}
846	}
847
848	/* Deactivate the timeout routine. And soft interrupt*/
849	if (led_timo[b->num].callout)
850		untimeout (cx_led_off, b, led_timo[b->num]);
851
852	for (c = b->chan; c < b->chan + NCHAN; ++c) {
853		drv_t *d = c->sys;
854
855		if (!d || d->chan->type == T_NONE)
856			continue;
857
858		if (d->dcd_timeout_handle.callout)
859			untimeout (cx_carrier, c, d->dcd_timeout_handle);
860	}
861	bus_teardown_intr (dev, bd->irq_res, bd->intrhand);
862	bus_deactivate_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res);
863	bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res);
864
865	bus_deactivate_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res);
866	bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res);
867
868	bus_deactivate_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->irq_res);
869	bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->base_res);
870
871	cx_close_board (b);
872
873	/* Detach the interfaces, free buffer memory. */
874	for (c = b->chan; c < b->chan + NCHAN; ++c) {
875		drv_t *d = (drv_t*) c->sys;
876
877		if (!d || d->chan->type == T_NONE)
878			continue;
879
880		if (d->tty) {
881			ttyfree (d->tty);
882			d->tty = NULL;
883		}
884
885#ifdef NETGRAPH
886		if (d->node) {
887			ng_rmnode_self (d->node);
888			NG_NODE_UNREF (d->node);
889			d->node = NULL;
890		}
891		mtx_destroy (&d->lo_queue.ifq_mtx);
892		mtx_destroy (&d->hi_queue.ifq_mtx);
893#else
894		/* Detach from the packet filter list of interfaces. */
895		bpfdetach (&d->pp.pp_if);
896		/* Detach from the sync PPP list. */
897		sppp_detach (&d->pp.pp_if);
898
899		if_detach (&d->pp.pp_if);
900#endif
901		destroy_dev (d->devt);
902	}
903
904	cx_led_off (b);
905	if (led_timo[b->num].callout)
906		untimeout (cx_led_off, b, led_timo[b->num]);
907	splx (s);
908
909	s = splhigh ();
910	for (c = b->chan; c < b->chan + NCHAN; ++c) {
911		drv_t *d = (drv_t*) c->sys;
912
913		if (!d || d->chan->type == T_NONE)
914			continue;
915
916		/* Deallocate buffers. */
917		cx_bus_dma_mem_free (&d->dmamem);
918	}
919	bd->board = 0;
920	adapter [b->num] = 0;
921	free (b, M_DEVBUF);
922	splx (s);
923
924	return 0;
925}
926
927#ifndef NETGRAPH
928static void cx_ifstart (struct ifnet *ifp)
929{
930	drv_t *d = ifp->if_softc;
931
932	cx_start (d);
933}
934
935static void cx_ifwatchdog (struct ifnet *ifp)
936{
937	drv_t *d = ifp->if_softc;
938
939	cx_watchdog (d);
940}
941
942static void cx_tlf (struct sppp *sp)
943{
944	drv_t *d = sp->pp_if.if_softc;
945
946	CX_DEBUG (d, ("cx_tlf\n"));
947/*	cx_set_dtr (d->chan, 0);*/
948/*	cx_set_rts (d->chan, 0);*/
949	sp->pp_down (sp);
950}
951
952static void cx_tls (struct sppp *sp)
953{
954	drv_t *d = sp->pp_if.if_softc;
955
956	CX_DEBUG (d, ("cx_tls\n"));
957	sp->pp_up (sp);
958}
959
960/*
961 * Initialization of interface.
962 * It seems to be never called by upper level.
963 */
964static void cx_initialize (void *softc)
965{
966	drv_t *d = softc;
967
968	CX_DEBUG (d, ("cx_initialize\n"));
969}
970
971/*
972 * Process an ioctl request.
973 */
974static int cx_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
975{
976	drv_t *d = ifp->if_softc;
977	int error, s, was_up, should_be_up;
978
979	/* No socket ioctls while the channel is in async mode. */
980	if (d->chan->type == T_NONE || d->chan->mode == M_ASYNC)
981		return EBUSY;
982
983	/* Socket ioctls on slave subchannels are not allowed. */
984	was_up = (ifp->if_flags & IFF_RUNNING) != 0;
985	error = sppp_ioctl (ifp, cmd, data);
986	if (error)
987		return error;
988
989	if (! (ifp->if_flags & IFF_DEBUG))
990		d->chan->debug = 0;
991	else if (! d->chan->debug)
992		d->chan->debug = 1;
993
994	switch (cmd) {
995	default:	   CX_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0;
996	case SIOCADDMULTI: CX_DEBUG2 (d, ("SIOCADDMULTI\n"));     return 0;
997	case SIOCDELMULTI: CX_DEBUG2 (d, ("SIOCDELMULTI\n"));     return 0;
998	case SIOCSIFFLAGS: CX_DEBUG2 (d, ("SIOCSIFFLAGS\n"));     break;
999	case SIOCSIFADDR:  CX_DEBUG2 (d, ("SIOCSIFADDR\n"));      break;
1000	}
1001
1002	/* We get here only in case of SIFFLAGS or SIFADDR. */
1003	s = splhigh ();
1004	should_be_up = (ifp->if_flags & IFF_RUNNING) != 0;
1005	if (!was_up && should_be_up) {
1006		/* Interface goes up -- start it. */
1007		cx_up (d);
1008		cx_start (d);
1009	} else if (was_up && !should_be_up) {
1010		/* Interface is going down -- stop it. */
1011		/* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/
1012		cx_down (d);
1013	}
1014	splx (s);
1015	return 0;
1016}
1017#endif /*NETGRAPH*/
1018
1019/*
1020 * Stop the interface.  Called on splimp().
1021 */
1022static void cx_down (drv_t *d)
1023{
1024	int s = splhigh ();
1025	CX_DEBUG (d, ("cx_down\n"));
1026	cx_set_dtr (d->chan, 0);
1027	cx_set_rts (d->chan, 0);
1028	d->running = 0;
1029	splx (s);
1030}
1031
1032/*
1033 * Start the interface.  Called on splimp().
1034 */
1035static void cx_up (drv_t *d)
1036{
1037	int s = splhigh ();
1038	CX_DEBUG (d, ("cx_up\n"));
1039	cx_set_dtr (d->chan, 1);
1040	cx_set_rts (d->chan, 1);
1041	d->running = 1;
1042	splx (s);
1043}
1044
1045/*
1046 * Start output on the (slave) interface.  Get another datagram to send
1047 * off of the interface queue, and copy it to the interface
1048 * before starting the output.
1049 */
1050static void cx_send (drv_t *d)
1051{
1052	struct mbuf *m;
1053	u_short len;
1054
1055	CX_DEBUG2 (d, ("cx_send\n"));
1056
1057	/* No output if the interface is down. */
1058	if (! d->running)
1059		return;
1060
1061	/* No output if the modem is off. */
1062	if (! cx_get_dsr (d->chan) && ! cx_get_loop(d->chan))
1063		return;
1064
1065	if (cx_buf_free (d->chan)) {
1066		/* Get the packet to send. */
1067#ifdef NETGRAPH
1068		IF_DEQUEUE (&d->hi_queue, m);
1069		if (! m)
1070			IF_DEQUEUE (&d->lo_queue, m);
1071#else
1072		m = sppp_dequeue (&d->pp.pp_if);
1073#endif
1074		if (! m)
1075			return;
1076#ifndef NETGRAPH
1077		if (d->pp.pp_if.if_bpf)
1078			BPF_MTAP (&d->pp.pp_if, m);
1079#endif
1080		len = m->m_pkthdr.len;
1081		if (! m->m_next)
1082			cx_send_packet (d->chan, (u_char*)mtod (m, caddr_t),
1083				len, 0);
1084		else {
1085			u_char buf [DMABUFSZ];
1086			m_copydata (m, 0, len, buf);
1087			cx_send_packet (d->chan, buf, len, 0);
1088		}
1089		m_freem (m);
1090
1091		/* Set up transmit timeout, 10 seconds. */
1092#ifdef NETGRAPH
1093		d->timeout = 10;
1094#else
1095		d->pp.pp_if.if_timer = 10;
1096#endif
1097	}
1098#ifndef NETGRAPH
1099	d->pp.pp_if.if_flags |= IFF_OACTIVE;
1100#endif
1101}
1102
1103/*
1104 * Start output on the interface.
1105 * Always called on splimp().
1106 */
1107static void cx_start (drv_t *d)
1108{
1109	int s = splhigh ();
1110	if (d->running) {
1111		if (! d->chan->dtr)
1112			cx_set_dtr (d->chan, 1);
1113		if (! d->chan->rts)
1114			cx_set_rts (d->chan, 1);
1115		cx_send (d);
1116	}
1117	splx (s);
1118}
1119
1120/*
1121 * Handle transmit timeouts.
1122 * Recover after lost transmit interrupts.
1123 * Always called on splimp().
1124 */
1125static void cx_watchdog (drv_t *d)
1126{
1127	int s = splhigh ();
1128	CX_DEBUG (d, ("device timeout\n"));
1129	if (d->running) {
1130		cx_setup_chan (d->chan);
1131		cx_start_chan (d->chan, 0, 0);
1132		cx_set_dtr (d->chan, 1);
1133		cx_set_rts (d->chan, 1);
1134		cx_start (d);
1135	}
1136	splx (s);
1137}
1138
1139/*
1140 * Transmit callback function.
1141 */
1142static void cx_transmit (cx_chan_t *c, void *attachment, int len)
1143{
1144	drv_t *d = c->sys;
1145
1146	if (!d)
1147		return;
1148
1149	if (c->mode == M_ASYNC && d->tty) {
1150		d->tty->t_state &= ~(TS_BUSY | TS_FLUSH);
1151		d->atimeout = 0;
1152		if (d->tty->t_dev) {
1153			d->intr_action |= CX_WRITE;
1154			MY_SOFT_INTR = 1;
1155			swi_sched (cx_fast_ih, 0);
1156		}
1157		return;
1158	}
1159#ifdef NETGRAPH
1160	d->timeout = 0;
1161#else
1162	++d->pp.pp_if.if_opackets;
1163	d->pp.pp_if.if_flags &= ~IFF_OACTIVE;
1164	d->pp.pp_if.if_timer = 0;
1165#endif
1166	cx_start (d);
1167}
1168
1169/*
1170 * Process the received packet.
1171 */
1172static void cx_receive (cx_chan_t *c, char *data, int len)
1173{
1174	drv_t *d = c->sys;
1175	struct mbuf *m;
1176	char *cc = data;
1177#if defined NETGRAPH
1178	int error;
1179#endif
1180
1181	if (!d)
1182		return;
1183
1184	if (c->mode == M_ASYNC && d->tty) {
1185		if (d->tty->t_state & TS_ISOPEN) {
1186			async_q *q = &d->aqueue;
1187			int size = BF_SZ - 1 - AQ_GSZ (q);
1188
1189			if (len <= 0 && !size)
1190				return;
1191
1192			if (len > size) {
1193				c->ierrs++;
1194				cx_error (c, CX_OVERRUN);
1195				len = size - 1;
1196			}
1197
1198			while (len--) {
1199				AQ_PUSH (q, *(unsigned char *)cc);
1200				cc++;
1201			}
1202
1203			d->intr_action |= CX_READ;
1204			MY_SOFT_INTR = 1;
1205			swi_sched (cx_fast_ih, 0);
1206		}
1207		return;
1208	}
1209	if (! d->running)
1210		return;
1211
1212	m = makembuf (data, len);
1213	if (! m) {
1214		CX_DEBUG (d, ("no memory for packet\n"));
1215#ifndef NETGRAPH
1216		++d->pp.pp_if.if_iqdrops;
1217#endif
1218		return;
1219	}
1220	if (c->debug > 1)
1221		printmbuf (m);
1222#ifdef NETGRAPH
1223	m->m_pkthdr.rcvif = 0;
1224	NG_SEND_DATA_ONLY (error, d->hook, m);
1225#else
1226	++d->pp.pp_if.if_ipackets;
1227	m->m_pkthdr.rcvif = &d->pp.pp_if;
1228	/* Check if there's a BPF listener on this interface.
1229	 * If so, hand off the raw packet to bpf. */
1230	if (d->pp.pp_if.if_bpf)
1231		BPF_TAP (&d->pp.pp_if, data, len);
1232	sppp_input (&d->pp.pp_if, m);
1233#endif
1234}
1235
1236#define CONDITION(t,tp) (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))\
1237	    && (!(tp->t_iflag & BRKINT) || (tp->t_iflag & IGNBRK))\
1238	    && (!(tp->t_iflag & PARMRK)\
1239		|| (tp->t_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))\
1240	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))\
1241	    && linesw[tp->t_line]->l_rint == ttyinput)
1242
1243/*
1244 * Error callback function.
1245 */
1246static void cx_error (cx_chan_t *c, int data)
1247{
1248	drv_t *d = c->sys;
1249	async_q *q;
1250
1251	if (!d)
1252		return;
1253
1254	q = &(d->aqueue);
1255
1256	switch (data) {
1257	case CX_FRAME:
1258		CX_DEBUG (d, ("frame error\n"));
1259		if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN)
1260			&& (AQ_GSZ (q) < BF_SZ - 1)
1261			&& (!CONDITION((&d->tty->t_termios), (d->tty))
1262			|| !(d->tty->t_iflag & (IGNPAR | PARMRK)))) {
1263			AQ_PUSH (q, TTY_FE);
1264			d->intr_action |= CX_READ;
1265			MY_SOFT_INTR = 1;
1266			swi_sched (cx_fast_ih, 0);
1267		}
1268#ifndef NETGRAPH
1269		else
1270			++d->pp.pp_if.if_ierrors;
1271#endif
1272		break;
1273	case CX_CRC:
1274		CX_DEBUG (d, ("crc error\n"));
1275		if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN)
1276			&& (AQ_GSZ (q) < BF_SZ - 1)
1277			&& (!CONDITION((&d->tty->t_termios), (d->tty))
1278			|| !(d->tty->t_iflag & INPCK)
1279			|| !(d->tty->t_iflag & (IGNPAR | PARMRK)))) {
1280			AQ_PUSH (q, TTY_PE);
1281			d->intr_action |= CX_READ;
1282			MY_SOFT_INTR = 1;
1283			swi_sched (cx_fast_ih, 0);
1284		}
1285#ifndef NETGRAPH
1286		else
1287			++d->pp.pp_if.if_ierrors;
1288#endif
1289		break;
1290	case CX_OVERRUN:
1291		CX_DEBUG (d, ("overrun error\n"));
1292#ifdef TTY_OE
1293		if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN)
1294			&& (AQ_GSZ (q) < BF_SZ - 1)
1295			&& (!CONDITION((&d->tty->t_termios), (d->tty)))) {
1296			AQ_PUSH (q, TTY_OE);
1297			d->intr_action |= CX_READ;
1298			MY_SOFT_INTR = 1;
1299			swi_sched (cx_fast_ih, 0);
1300		}
1301#endif
1302#ifndef NETGRAPH
1303		else {
1304			++d->pp.pp_if.if_collisions;
1305			++d->pp.pp_if.if_ierrors;
1306		}
1307#endif
1308		break;
1309	case CX_OVERFLOW:
1310		CX_DEBUG (d, ("overflow error\n"));
1311#ifndef NETGRAPH
1312		if (c->mode != M_ASYNC)
1313			++d->pp.pp_if.if_ierrors;
1314#endif
1315		break;
1316	case CX_UNDERRUN:
1317		CX_DEBUG (d, ("underrun error\n"));
1318		if (c->mode != M_ASYNC) {
1319#ifdef NETGRAPH
1320			d->timeout = 0;
1321#else
1322			++d->pp.pp_if.if_oerrors;
1323			d->pp.pp_if.if_flags &= ~IFF_OACTIVE;
1324			d->pp.pp_if.if_timer = 0;
1325			cx_start (d);
1326#endif
1327		}
1328		break;
1329	case CX_BREAK:
1330		CX_DEBUG (d, ("break error\n"));
1331		if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN)
1332			&& (AQ_GSZ (q) < BF_SZ - 1)
1333			&& (!CONDITION((&d->tty->t_termios), (d->tty))
1334			|| !(d->tty->t_iflag & (IGNBRK | BRKINT | PARMRK)))) {
1335			AQ_PUSH (q, TTY_BI);
1336			d->intr_action |= CX_READ;
1337			MY_SOFT_INTR = 1;
1338			swi_sched (cx_fast_ih, 0);
1339		}
1340#ifndef NETGRAPH
1341		else
1342			++d->pp.pp_if.if_ierrors;
1343#endif
1344		break;
1345	default:
1346		CX_DEBUG (d, ("error #%d\n", data));
1347	}
1348}
1349
1350static int cx_topen (struct tty *tp, struct cdev *dev)
1351{
1352	drv_t *d;
1353
1354	d = tp->t_sc;
1355	if (d->chan->mode != M_ASYNC)
1356		return (EBUSY);
1357	d->open_dev |= 0x2;
1358	cx_start_chan (d->chan, 0, 0);
1359	cx_set_dtr (d->chan, 1);
1360	cx_set_rts (d->chan, 1);
1361	d->cd = cx_get_cd (d->chan);
1362	return (0);
1363}
1364
1365static void cx_tclose (struct tty *tp)
1366{
1367	drv_t *d;
1368
1369	d = tp->t_sc;
1370	/* Disable receiver.
1371	 * Transmitter continues sending the queued data. */
1372	cx_enable_receive (d->chan, 0);
1373	d->open_dev &= ~0x2;
1374}
1375
1376static int cx_tmodem (struct tty *tp, int sigon, int sigoff)
1377{
1378	drv_t *d;
1379
1380	d = tp->t_sc;
1381
1382	if (!sigon && !sigoff) {
1383		if (cx_get_dsr (d->chan)) sigon |= SER_DSR;
1384		if (cx_get_cd  (d->chan)) sigon |= SER_DCD;
1385		if (cx_get_cts (d->chan)) sigon |= SER_CTS;
1386		if (d->chan->dtr)	  sigon |= SER_DTR;
1387		if (d->chan->rts)	  sigon |= SER_RTS;
1388		return sigon;
1389	}
1390
1391	if (sigon & SER_DTR)
1392		cx_set_dtr (d->chan, 1);
1393	if (sigoff & SER_DTR)
1394		cx_set_dtr (d->chan, 0);
1395	if (sigon & SER_RTS)
1396		cx_set_rts (d->chan, 1);
1397	if (sigoff & SER_RTS)
1398		cx_set_rts (d->chan, 0);
1399	return (0);
1400}
1401
1402static int cx_open (struct cdev *dev, int flag, int mode, struct thread *td)
1403{
1404	int unit;
1405	drv_t *d;
1406
1407	d = dev->si_drv1;
1408	unit = d->chan->num;
1409	CX_DEBUG2 (d, ("cx_open unit=%d, flag=0x%x, mode=0x%x\n",
1410		    unit, flag, mode));
1411
1412	d->open_dev |= 0x1;
1413	return 0;
1414}
1415
1416static int cx_close (struct cdev *dev, int flag, int mode, struct thread *td)
1417{
1418	drv_t *d;
1419
1420	d = dev->si_drv1;
1421	CX_DEBUG2 (d, ("cx_close\n"));
1422	d->open_dev &= ~0x1;
1423	return 0;
1424}
1425
1426static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
1427{
1428	drv_t *d;
1429	cx_chan_t *c;
1430	struct serial_statistics *st;
1431	int error, s;
1432	char mask[16];
1433
1434	d = dev->si_drv1;
1435	c = d->chan;
1436
1437	switch (cmd) {
1438	case SERIAL_GETREGISTERED:
1439		CX_DEBUG2 (d, ("ioctl: getregistered\n"));
1440		bzero (mask, sizeof(mask));
1441		for (s=0; s<NCX*NCHAN; ++s)
1442			if (channel [s])
1443				mask [s/8] |= 1 << (s & 7);
1444		bcopy (mask, data, sizeof (mask));
1445		return 0;
1446
1447	case SERIAL_GETPORT:
1448		CX_DEBUG2 (d, ("ioctl: getport\n"));
1449		s = splhigh ();
1450		*(int *)data = cx_get_port (c);
1451		splx (s);
1452		if (*(int *)data<0)
1453			return (EINVAL);
1454		else
1455			return 0;
1456
1457	case SERIAL_SETPORT:
1458		CX_DEBUG2 (d, ("ioctl: setproto\n"));
1459		/* Only for superuser! */
1460		error = suser (td);
1461		if (error)
1462			return error;
1463
1464		s = splhigh ();
1465		cx_set_port (c, *(int *)data);
1466		splx (s);
1467		return 0;
1468
1469#ifndef NETGRAPH
1470	case SERIAL_GETPROTO:
1471		CX_DEBUG2 (d, ("ioctl: getproto\n"));
1472		s = splhigh ();
1473		strcpy ((char*)data, (c->mode == M_ASYNC) ? "async" :
1474			(d->pp.pp_flags & PP_FR) ? "fr" :
1475			(d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp");
1476		splx (s);
1477		return 0;
1478
1479	case SERIAL_SETPROTO:
1480		CX_DEBUG2 (d, ("ioctl: setproto\n"));
1481		/* Only for superuser! */
1482		error = suser (td);
1483		if (error)
1484			return error;
1485		if (c->mode == M_ASYNC)
1486			return EBUSY;
1487		if (d->pp.pp_if.if_flags & IFF_RUNNING)
1488			return EBUSY;
1489		if (! strcmp ("cisco", (char*)data)) {
1490			d->pp.pp_flags &= ~(PP_FR);
1491			d->pp.pp_flags |= PP_KEEPALIVE;
1492			d->pp.pp_if.if_flags |= PP_CISCO;
1493		} else if (! strcmp ("fr", (char*)data)) {
1494			d->pp.pp_if.if_flags &= ~(PP_CISCO);
1495			d->pp.pp_flags |= PP_FR | PP_KEEPALIVE;
1496		} else if (! strcmp ("ppp", (char*)data)) {
1497			d->pp.pp_flags &= ~(PP_FR | PP_KEEPALIVE);
1498			d->pp.pp_if.if_flags &= ~(PP_CISCO);
1499		} else
1500			return EINVAL;
1501		return 0;
1502
1503	case SERIAL_GETKEEPALIVE:
1504		CX_DEBUG2 (d, ("ioctl: getkeepalive\n"));
1505		if ((d->pp.pp_flags & PP_FR) ||
1506		    (d->pp.pp_if.if_flags & PP_CISCO) ||
1507		    (c->mode == M_ASYNC))
1508			return EINVAL;
1509		s = splhigh ();
1510		*(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0;
1511		splx (s);
1512		return 0;
1513
1514	case SERIAL_SETKEEPALIVE:
1515		CX_DEBUG2 (d, ("ioctl: setkeepalive\n"));
1516		/* Only for superuser! */
1517		error = suser (td);
1518		if (error)
1519			return error;
1520		if ((d->pp.pp_flags & PP_FR) ||
1521			(d->pp.pp_if.if_flags & PP_CISCO))
1522			return EINVAL;
1523		s = splhigh ();
1524		if (*(int*)data)
1525			d->pp.pp_flags |= PP_KEEPALIVE;
1526		else
1527			d->pp.pp_flags &= ~PP_KEEPALIVE;
1528		splx (s);
1529		return 0;
1530#endif /*NETGRAPH*/
1531
1532	case SERIAL_GETMODE:
1533		CX_DEBUG2 (d, ("ioctl: getmode\n"));
1534		s = splhigh ();
1535		*(int*)data = (c->mode == M_ASYNC) ?
1536			SERIAL_ASYNC : SERIAL_HDLC;
1537		splx (s);
1538		return 0;
1539
1540	case SERIAL_SETMODE:
1541		CX_DEBUG2 (d, ("ioctl: setmode\n"));
1542		/* Only for superuser! */
1543		error = suser (td);
1544		if (error)
1545			return error;
1546
1547		/* Somebody is waiting for carrier? */
1548		if (d->lock)
1549			return EBUSY;
1550		/* /dev/ttyXX is already opened by someone? */
1551		if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) &&
1552		    (d->open_dev|0x2))
1553			return EBUSY;
1554		/* Network interface is up?
1555		 * Cannot change to async mode. */
1556		if (c->mode != M_ASYNC && d->running &&
1557		    (*(int*)data == SERIAL_ASYNC))
1558			return EBUSY;
1559
1560		s = splhigh ();
1561		if (c->mode == M_HDLC && *(int*)data == SERIAL_ASYNC) {
1562			cx_set_mode (c, M_ASYNC);
1563			cx_enable_receive (c, 0);
1564			cx_enable_transmit (c, 0);
1565		} else if (c->mode == M_ASYNC && *(int*)data == SERIAL_HDLC) {
1566			cx_set_mode (c, M_HDLC);
1567			cx_enable_receive (c, 1);
1568			cx_enable_transmit (c, 1);
1569		}
1570		splx (s);
1571		return 0;
1572
1573	case SERIAL_GETSTAT:
1574		CX_DEBUG2 (d, ("ioctl: getestat\n"));
1575		st = (struct serial_statistics*) data;
1576		s = splhigh ();
1577		st->rintr  = c->rintr;
1578		st->tintr  = c->tintr;
1579		st->mintr  = c->mintr;
1580		st->ibytes = c->ibytes;
1581		st->ipkts  = c->ipkts;
1582		st->ierrs  = c->ierrs;
1583		st->obytes = c->obytes;
1584		st->opkts  = c->opkts;
1585		st->oerrs  = c->oerrs;
1586		splx (s);
1587		return 0;
1588
1589	case SERIAL_CLRSTAT:
1590		CX_DEBUG2 (d, ("ioctl: clrstat\n"));
1591		/* Only for superuser! */
1592		error = suser (td);
1593		if (error)
1594			return error;
1595		s = splhigh ();
1596		c->rintr = 0;
1597		c->tintr = 0;
1598		c->mintr = 0;
1599		c->ibytes = 0;
1600		c->ipkts = 0;
1601		c->ierrs = 0;
1602		c->obytes = 0;
1603		c->opkts = 0;
1604		c->oerrs = 0;
1605		splx (s);
1606		return 0;
1607
1608	case SERIAL_GETBAUD:
1609		CX_DEBUG2 (d, ("ioctl: getbaud\n"));
1610		if (c->mode == M_ASYNC)
1611			return EINVAL;
1612		s = splhigh ();
1613		*(long*)data = cx_get_baud(c);
1614		splx (s);
1615		return 0;
1616
1617	case SERIAL_SETBAUD:
1618		CX_DEBUG2 (d, ("ioctl: setbaud\n"));
1619		/* Only for superuser! */
1620		error = suser (td);
1621		if (error)
1622			return error;
1623		if (c->mode == M_ASYNC)
1624			return EINVAL;
1625		s = splhigh ();
1626		cx_set_baud (c, *(long*)data);
1627		splx (s);
1628		return 0;
1629
1630	case SERIAL_GETLOOP:
1631		CX_DEBUG2 (d, ("ioctl: getloop\n"));
1632		if (c->mode == M_ASYNC)
1633			return EINVAL;
1634		s = splhigh ();
1635		*(int*)data = cx_get_loop (c);
1636		splx (s);
1637		return 0;
1638
1639	case SERIAL_SETLOOP:
1640		CX_DEBUG2 (d, ("ioctl: setloop\n"));
1641		/* Only for superuser! */
1642		error = suser (td);
1643		if (error)
1644			return error;
1645		if (c->mode == M_ASYNC)
1646			return EINVAL;
1647		s = splhigh ();
1648		cx_set_loop (c, *(int*)data);
1649		splx (s);
1650		return 0;
1651
1652	case SERIAL_GETDPLL:
1653		CX_DEBUG2 (d, ("ioctl: getdpll\n"));
1654		if (c->mode == M_ASYNC)
1655			return EINVAL;
1656		s = splhigh ();
1657		*(int*)data = cx_get_dpll (c);
1658		splx (s);
1659		return 0;
1660
1661	case SERIAL_SETDPLL:
1662		CX_DEBUG2 (d, ("ioctl: setdpll\n"));
1663		/* Only for superuser! */
1664		error = suser (td);
1665		if (error)
1666			return error;
1667		if (c->mode == M_ASYNC)
1668			return EINVAL;
1669		s = splhigh ();
1670		cx_set_dpll (c, *(int*)data);
1671		splx (s);
1672		return 0;
1673
1674	case SERIAL_GETNRZI:
1675		CX_DEBUG2 (d, ("ioctl: getnrzi\n"));
1676		if (c->mode == M_ASYNC)
1677			return EINVAL;
1678		s = splhigh ();
1679		*(int*)data = cx_get_nrzi (c);
1680		splx (s);
1681		return 0;
1682
1683	case SERIAL_SETNRZI:
1684		CX_DEBUG2 (d, ("ioctl: setnrzi\n"));
1685		/* Only for superuser! */
1686		error = suser (td);
1687		if (error)
1688			return error;
1689		if (c->mode == M_ASYNC)
1690			return EINVAL;
1691		s = splhigh ();
1692		cx_set_nrzi (c, *(int*)data);
1693		splx (s);
1694		return 0;
1695
1696	case SERIAL_GETDEBUG:
1697		CX_DEBUG2 (d, ("ioctl: getdebug\n"));
1698		s = splhigh ();
1699		*(int*)data = c->debug;
1700		splx (s);
1701		return 0;
1702
1703	case SERIAL_SETDEBUG:
1704		CX_DEBUG2 (d, ("ioctl: setdebug\n"));
1705		/* Only for superuser! */
1706		error = suser (td);
1707		if (error)
1708			return error;
1709		s = splhigh ();
1710		c->debug = *(int*)data;
1711		splx (s);
1712#ifndef	NETGRAPH
1713		if (d->chan->debug)
1714			d->pp.pp_if.if_flags |= IFF_DEBUG;
1715		else
1716			d->pp.pp_if.if_flags &= (~IFF_DEBUG);
1717#endif
1718		return 0;
1719	}
1720
1721	CX_DEBUG2 (d, ("ioctl: 0x%lx\n", cmd));
1722	return ENOTTY;
1723}
1724
1725
1726void cx_softintr (void *unused)
1727{
1728	drv_t *d;
1729	async_q *q;
1730	int i, s, ic, k;
1731	while (MY_SOFT_INTR) {
1732		MY_SOFT_INTR = 0;
1733		for (i=0; i<NCX*NCHAN; ++i) {
1734			d = channel [i];
1735			if (!d || !d->chan || d->chan->type == T_NONE
1736			    || d->chan->mode != M_ASYNC || !d->tty
1737			    || !d->tty->t_dev)
1738				continue;
1739			s = splhigh ();
1740			if (d->intr_action & CX_READ) {
1741				q = &(d->aqueue);
1742				if (d->tty->t_state & TS_CAN_BYPASS_L_RINT) {
1743					k = AQ_GSZ(q);
1744					if (d->tty->t_rawq.c_cc + k >
1745						d->tty->t_ihiwat
1746					    && (d->tty->t_cflag & CRTS_IFLOW
1747						|| d->tty->t_iflag & IXOFF)
1748					    && !(d->tty->t_state & TS_TBLOCK))
1749						ttyblock(d->tty);
1750					d->tty->t_rawcc += k;
1751					while (k>0) {
1752						k--;
1753						AQ_POP (q, ic);
1754						splx (s);
1755						putc (ic, &d->tty->t_rawq);
1756						s = splhigh ();
1757					}
1758					ttwakeup(d->tty);
1759					if (d->tty->t_state & TS_TTSTOP
1760					    && (d->tty->t_iflag & IXANY
1761						|| d->tty->t_cc[VSTART] ==
1762						d->tty->t_cc[VSTOP])) {
1763						d->tty->t_state &= ~TS_TTSTOP;
1764						d->tty->t_lflag &= ~FLUSHO;
1765						d->intr_action |= CX_WRITE;
1766					}
1767				} else {
1768					while (q->end != q->beg) {
1769						AQ_POP (q, ic);
1770						splx (s);
1771						ttyld_rint (d->tty, ic);
1772						s = splhigh ();
1773					}
1774				}
1775				d->intr_action &= ~CX_READ;
1776			}
1777			splx (s);
1778
1779			s = splhigh ();
1780			if (d->intr_action & CX_WRITE) {
1781				if (d->tty->t_line)
1782					ttyld_start (d->tty);
1783				else
1784					cx_oproc (d->tty);
1785				d->intr_action &= ~CX_WRITE;
1786			}
1787			splx (s);
1788
1789		}
1790	}
1791}
1792
1793/*
1794 * Fill transmitter buffer with data.
1795 */
1796static void cx_oproc (struct tty *tp)
1797{
1798	int s, k;
1799	drv_t *d;
1800	static u_char buf[DMABUFSZ];
1801	u_char *p;
1802	u_short len = 0, sublen = 0;
1803
1804	s = splhigh();
1805
1806	d = tp->t_sc;
1807
1808	CX_DEBUG2 (d, ("cx_oproc\n"));
1809	if (tp->t_cflag & CRTSCTS && (tp->t_state & TS_TBLOCK) && d->chan->rts)
1810		cx_set_rts (d->chan, 0);
1811	else if (tp->t_cflag & CRTSCTS && ! (tp->t_state & TS_TBLOCK) && ! d->chan->rts)
1812		cx_set_rts (d->chan, 1);
1813
1814	if (! (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))) {
1815		/* Start transmitter. */
1816		cx_enable_transmit (d->chan, 1);
1817
1818		/* Is it busy? */
1819		if (! cx_buf_free (d->chan)) {
1820			tp->t_state |= TS_BUSY;
1821			splx (s);
1822			return;
1823		}
1824		if (tp->t_iflag & IXOFF) {
1825			p = (buf + (DMABUFSZ/2));
1826			sublen = q_to_b (&tp->t_outq, p, (DMABUFSZ/2));
1827			k = sublen;
1828			while (k--) {
1829				/* Send XON/XOFF out of band. */
1830				if (*p == tp->t_cc[VSTOP]) {
1831					cx_xflow_ctl (d->chan, 0);
1832					p++;
1833					continue;
1834				}
1835				if (*p == tp->t_cc[VSTART]) {
1836					cx_xflow_ctl (d->chan, 1);
1837					p++;
1838					continue;
1839				}
1840				buf[len] = *p;
1841				len++;
1842				p++;
1843			}
1844		} else {
1845			p = buf;
1846			len = q_to_b (&tp->t_outq, p, (DMABUFSZ/2));
1847		}
1848		if (len) {
1849			cx_send_packet (d->chan, buf, len, 0);
1850			tp->t_state |= TS_BUSY;
1851			d->atimeout = 10;
1852			CX_DEBUG2 (d, ("out %d bytes\n", len));
1853		}
1854	}
1855	ttwwakeup (tp);
1856	splx (s);
1857}
1858
1859static int cx_param (struct tty *tp, struct termios *t)
1860{
1861	drv_t *d;
1862	int s, bits, parity;
1863
1864	d = tp->t_sc;
1865
1866	s = splhigh ();
1867	if (t->c_ospeed == 0) {
1868		/* Clear DTR and RTS. */
1869		cx_set_dtr (d->chan, 0);
1870		splx (s);
1871		CX_DEBUG2 (d, ("cx_param (hangup)\n"));
1872		return 0;
1873	}
1874	CX_DEBUG2 (d, ("cx_param\n"));
1875
1876	/* Check requested parameters. */
1877	if (t->c_ospeed < 300 || t->c_ospeed > 256*1024) {
1878		splx (s);
1879		return EINVAL;
1880	}
1881	if (t->c_ispeed && (t->c_ispeed < 300 || t->c_ispeed > 256*1024)) {
1882		splx (s);
1883		return EINVAL;
1884	}
1885
1886  	/* And copy them to tty and channel structures. */
1887	tp->t_ispeed = t->c_ispeed = tp->t_ospeed = t->c_ospeed;
1888	tp->t_cflag = t->c_cflag;
1889
1890	/* Set character length and parity mode. */
1891	switch (t->c_cflag & CSIZE) {
1892	default:
1893	case CS8: bits = 8; break;
1894	case CS7: bits = 7; break;
1895	case CS6: bits = 6; break;
1896	case CS5: bits = 5; break;
1897	}
1898
1899	parity = ((t->c_cflag & PARENB) ? 1 : 0) *
1900		 (1 + ((t->c_cflag & PARODD) ? 0 : 1));
1901
1902	/* Set current channel number. */
1903	if (! d->chan->dtr)
1904		cx_set_dtr (d->chan, 1);
1905
1906	ttyldoptim (tp);
1907	cx_set_async_param (d->chan, t->c_ospeed, bits, parity, (t->c_cflag & CSTOPB),
1908		!(t->c_cflag & PARENB), (t->c_cflag & CRTSCTS),
1909		(t->c_iflag & IXON), (t->c_iflag & IXANY),
1910		t->c_cc[VSTART], t->c_cc[VSTOP]);
1911	splx (s);
1912	return 0;
1913}
1914
1915/*
1916 * Stop output on a line
1917 */
1918static void cx_stop (struct tty *tp, int flag)
1919{
1920	drv_t *d;
1921	int s;
1922
1923	d = tp->t_sc;
1924	s = splhigh ();
1925
1926	if (tp->t_state & TS_BUSY) {
1927		/* Stop transmitter */
1928		CX_DEBUG2 (d, ("cx_stop\n"));
1929		cx_transmitter_ctl (d->chan, 0);
1930	}
1931	splx (s);
1932}
1933
1934/*
1935 * Process the (delayed) carrier signal setup.
1936 */
1937static void cx_carrier (void *arg)
1938{
1939	drv_t *d = arg;
1940	cx_chan_t *c = d->chan;
1941	int s, cd;
1942
1943	s = splhigh ();
1944	cd = cx_get_cd (c);
1945	if (d->cd != cd) {
1946		if (cd) {
1947			CX_DEBUG (d, ("carrier on\n"));
1948			d->cd = 1;
1949			splx (s);
1950			if (d->tty)
1951				ttyld_modem(d->tty, 1);
1952		} else {
1953			CX_DEBUG (d, ("carrier loss\n"));
1954			d->cd = 0;
1955			splx (s);
1956			if (d->tty)
1957				ttyld_modem(d->tty, 0);
1958		}
1959	}
1960}
1961
1962/*
1963 * Modem signal callback function.
1964 */
1965static void cx_modem (cx_chan_t *c)
1966{
1967	drv_t *d = c->sys;
1968
1969	if (!d || c->mode != M_ASYNC)
1970		return;
1971	/* Handle carrier detect/loss. */
1972	untimeout (cx_carrier, c, d->dcd_timeout_handle);
1973	/* Carrier changed - delay processing DCD for a while
1974	 * to give both sides some time to initialize. */
1975	d->dcd_timeout_handle = timeout (cx_carrier, d, hz/2);
1976}
1977
1978static struct cdevsw cx_cdevsw = {
1979	.d_version  = D_VERSION,
1980	.d_open     = cx_open,
1981	.d_close    = cx_close,
1982	.d_ioctl    = cx_ioctl,
1983	.d_name     = "cx",
1984	.d_flags    = D_TTY | D_NEEDGIANT,
1985};
1986
1987#ifdef NETGRAPH
1988static int ng_cx_constructor (node_p node)
1989{
1990	drv_t *d = NG_NODE_PRIVATE (node);
1991	CX_DEBUG (d, ("Constructor\n"));
1992	return EINVAL;
1993}
1994
1995static int ng_cx_newhook (node_p node, hook_p hook, const char *name)
1996{
1997	int s;
1998	drv_t *d = NG_NODE_PRIVATE (node);
1999
2000	if (d->chan->mode == M_ASYNC)
2001		return EINVAL;
2002
2003	/* Attach debug hook */
2004	if (strcmp (name, NG_CX_HOOK_DEBUG) == 0) {
2005		NG_HOOK_SET_PRIVATE (hook, NULL);
2006		d->debug_hook = hook;
2007		return 0;
2008	}
2009
2010	/* Check for raw hook */
2011	if (strcmp (name, NG_CX_HOOK_RAW) != 0)
2012		return EINVAL;
2013
2014	NG_HOOK_SET_PRIVATE (hook, d);
2015	d->hook = hook;
2016	s = splhigh ();
2017	cx_up (d);
2018	splx (s);
2019	return 0;
2020}
2021
2022static int print_modems (char *s, cx_chan_t *c, int need_header)
2023{
2024	int status = cx_modem_status (c->sys);
2025	int length = 0;
2026
2027	if (need_header)
2028		length += sprintf (s + length, "  LE   DTR  DSR  RTS  CTS  CD\n");
2029	length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n",
2030		status & TIOCM_LE  ? "On" : "-",
2031		status & TIOCM_DTR ? "On" : "-",
2032		status & TIOCM_DSR ? "On" : "-",
2033		status & TIOCM_RTS ? "On" : "-",
2034		status & TIOCM_CTS ? "On" : "-",
2035		status & TIOCM_CD  ? "On" : "-");
2036	return length;
2037}
2038
2039static int print_stats (char *s, cx_chan_t *c, int need_header)
2040{
2041	int length = 0;
2042
2043	if (need_header)
2044		length += sprintf (s + length, "  Rintr   Tintr   Mintr   Ibytes   Ipkts   Ierrs   Obytes   Opkts   Oerrs\n");
2045	length += sprintf (s + length, "%7ld %7ld %7ld %8ld %7ld %7ld %8ld %7ld %7ld\n",
2046		c->rintr, c->tintr, c->mintr, c->ibytes, c->ipkts,
2047		c->ierrs, c->obytes, c->opkts, c->oerrs);
2048	return length;
2049}
2050
2051static int print_chan (char *s, cx_chan_t *c)
2052{
2053	drv_t *d = c->sys;
2054	int length = 0;
2055
2056	length += sprintf (s + length, "cx%d", c->board->num * NCHAN + c->num);
2057	if (d->chan->debug)
2058		length += sprintf (s + length, " debug=%d", d->chan->debug);
2059
2060	if (cx_get_baud (c))
2061		length += sprintf (s + length, " %ld", cx_get_baud (c));
2062	else
2063		length += sprintf (s + length, " extclock");
2064
2065	if (c->mode == M_HDLC) {
2066		length += sprintf (s + length, " dpll=%s", cx_get_dpll (c) ? "on" : "off");
2067		length += sprintf (s + length, " nrzi=%s", cx_get_nrzi (c) ? "on" : "off");
2068	}
2069
2070	length += sprintf (s + length, " loop=%s", cx_get_loop (c) ? "on\n" : "off\n");
2071	return length;
2072}
2073
2074static int ng_cx_rcvmsg (node_p node, item_p item, hook_p lasthook)
2075{
2076	drv_t *d = NG_NODE_PRIVATE (node);
2077	struct ng_mesg *msg;
2078	struct ng_mesg *resp = NULL;
2079	int error = 0;
2080
2081	if (!d)
2082		return EINVAL;
2083
2084	CX_DEBUG (d, ("Rcvmsg\n"));
2085	NGI_GET_MSG (item, msg);
2086	switch (msg->header.typecookie) {
2087	default:
2088		error = EINVAL;
2089		break;
2090
2091	case NGM_CX_COOKIE:
2092		printf ("Don't forget to implement\n");
2093		error = EINVAL;
2094		break;
2095
2096	case NGM_GENERIC_COOKIE:
2097		switch (msg->header.cmd) {
2098		default:
2099			error = EINVAL;
2100			break;
2101
2102		case NGM_TEXT_STATUS: {
2103			char *s;
2104			int l = 0;
2105			int dl = sizeof (struct ng_mesg) + 730;
2106
2107			NG_MKRESPONSE (resp, msg, dl, M_NOWAIT);
2108			if (! resp) {
2109				error = ENOMEM;
2110				break;
2111			}
2112			bzero (resp, dl);
2113			s = (resp)->data;
2114			l += print_chan (s + l, d->chan);
2115			l += print_stats (s + l, d->chan, 1);
2116			l += print_modems (s + l, d->chan, 1);
2117			strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN);
2118			}
2119			break;
2120		}
2121		break;
2122	}
2123	NG_RESPOND_MSG (error, node, item, resp);
2124	NG_FREE_MSG (msg);
2125	return error;
2126}
2127
2128static int ng_cx_rcvdata (hook_p hook, item_p item)
2129{
2130	drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook));
2131	struct mbuf *m;
2132	struct ng_tag_prio *ptag;
2133	struct ifqueue *q;
2134	int s;
2135
2136	NGI_GET_M (item, m);
2137	NG_FREE_ITEM (item);
2138	if (! NG_HOOK_PRIVATE (hook) || ! d) {
2139		NG_FREE_M (m);
2140		return ENETDOWN;
2141	}
2142
2143	/* Check for high priority data */
2144	if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE,
2145	    NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) )
2146		q = &d->hi_queue;
2147	else
2148		q = &d->lo_queue;
2149
2150	s = splhigh ();
2151	IF_LOCK (q);
2152	if (_IF_QFULL (q)) {
2153		_IF_DROP (q);
2154		IF_UNLOCK (q);
2155		splx (s);
2156		NG_FREE_M (m);
2157		return ENOBUFS;
2158	}
2159	_IF_ENQUEUE (q, m);
2160	IF_UNLOCK (q);
2161	cx_start (d);
2162	splx (s);
2163	return 0;
2164}
2165
2166static int ng_cx_rmnode (node_p node)
2167{
2168	drv_t *d = NG_NODE_PRIVATE (node);
2169
2170	CX_DEBUG (d, ("Rmnode\n"));
2171	if (d && d->running) {
2172		int s = splhigh ();
2173		cx_down (d);
2174		splx (s);
2175	}
2176#ifdef	KLD_MODULE
2177	if (node->nd_flags & NGF_REALLY_DIE) {
2178		NG_NODE_SET_PRIVATE (node, NULL);
2179		NG_NODE_UNREF (node);
2180	}
2181	NG_NODE_REVIVE(node);		/* Persistant node */
2182#endif
2183	return 0;
2184}
2185
2186static void ng_cx_watchdog (void *arg)
2187{
2188	drv_t *d = arg;
2189
2190	if (d->timeout == 1)
2191		cx_watchdog (d);
2192	if (d->timeout)
2193		d->timeout--;
2194	d->timeout_handle = timeout (ng_cx_watchdog, d, hz);
2195}
2196
2197static int ng_cx_connect (hook_p hook)
2198{
2199	drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook));
2200
2201	d->timeout_handle = timeout (ng_cx_watchdog, d, hz);
2202	return 0;
2203}
2204
2205static int ng_cx_disconnect (hook_p hook)
2206{
2207	drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook));
2208	int s;
2209
2210	s = splhigh ();
2211	if (NG_HOOK_PRIVATE (hook))
2212		cx_down (d);
2213	splx (s);
2214	untimeout (ng_cx_watchdog, d, d->timeout_handle);
2215	return 0;
2216}
2217#endif /*NETGRAPH*/
2218
2219static int cx_modevent (module_t mod, int type, void *unused)
2220{
2221	static int load_count = 0;
2222
2223	switch (type) {
2224	case MOD_LOAD:
2225#if defined NETGRAPH
2226		if (ng_newtype (&typestruct))
2227			printf ("Failed to register ng_cx\n");
2228#endif
2229		++load_count;
2230		timeout_handle = timeout (cx_timeout, 0, hz*5);
2231		/* Software interrupt. */
2232		swi_add(&tty_ithd, "cx", cx_softintr, NULL, SWI_TTY, 0,
2233		    &cx_fast_ih);
2234		break;
2235	case MOD_UNLOAD:
2236		if (load_count == 1) {
2237			printf ("Removing device entry for Sigma\n");
2238#if defined NETGRAPH
2239			ng_rmtype (&typestruct);
2240#endif
2241		}
2242		if (timeout_handle.callout)
2243			untimeout (cx_timeout, 0, timeout_handle);
2244		ithread_remove_handler (cx_fast_ih);
2245		--load_count;
2246		break;
2247	case MOD_SHUTDOWN:
2248		break;
2249	}
2250	return 0;
2251}
2252
2253#ifdef NETGRAPH
2254static struct ng_type typestruct = {
2255	.version	= NG_ABI_VERSION,
2256	.name		= NG_CX_NODE_TYPE,
2257	.constructor	= ng_cx_constructor,
2258	.rcvmsg		= ng_cx_rcvmsg,
2259	.shutdown	= ng_cx_rmnode,
2260	.newhook	= ng_cx_newhook,
2261	.connect	= ng_cx_connect,
2262	.rcvdata	= ng_cx_rcvdata,
2263	.disconnect	= ng_cx_disconnect,
2264};
2265#endif /*NETGRAPH*/
2266
2267#ifdef NETGRAPH
2268MODULE_DEPEND (ng_cx, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
2269#else
2270MODULE_DEPEND (isa_cx, sppp, 1, 1, 1);
2271#endif
2272#ifdef KLD_MODULE
2273DRIVER_MODULE (cxmod, isa, cx_isa_driver, cx_devclass, cx_modevent, NULL);
2274#else
2275DRIVER_MODULE (cx, isa, cx_isa_driver, cx_devclass, cx_modevent, NULL);
2276#endif
2277