1/*
2 * Cronyx-Tau-PCI adapter driver for FreeBSD.
3 * Supports PPP/HDLC, Cisco/HDLC and FrameRelay protocol in synchronous mode,
4 * and asyncronous channels with full modem control.
5 * Keepalive protocol implemented in both Cisco and PPP modes.
6 *
7 * Copyright (C) 1999-2004 Cronyx Engineering.
8 * Author: Kurakin Roman, <rik@cronyx.ru>
9 *
10 * Copyright (C) 1999-2002 Cronyx Engineering.
11 * Author: Serge Vakulenko, <vak@cronyx.ru>
12 *
13 * This software is distributed with NO WARRANTIES, not even the implied
14 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * Authors grant any other persons or organisations a permission to use,
17 * modify and redistribute this software in source and binary forms,
18 * as long as this message is kept with the software, all derivative
19 * works or modified versions.
20 *
21 * $Cronyx: if_cp.c,v 1.1.2.32 2004/02/26 17:56:39 rik Exp $
22 */
23
24#include <sys/cdefs.h>
25__FBSDID("$FreeBSD: head/sys/dev/cp/if_cp.c 130585 2004-06-16 09:47:26Z phk $");
26
27#include <sys/param.h>
28
29#if __FreeBSD_version >= 500000
30# define NPCI 1
31#else
32# include "pci.h"
33#endif
34
35#if NPCI > 0
36
37#include <sys/ucred.h>
38#include <sys/proc.h>
39#include <sys/systm.h>
40#include <sys/mbuf.h>
41#include <sys/kernel.h>
42#include <sys/module.h>
43#include <sys/conf.h>
44#include <sys/malloc.h>
45#include <sys/socket.h>
46#include <sys/sockio.h>
47#include <sys/tty.h>
48#if __FreeBSD_version >= 400000
49# include <sys/bus.h>
50#endif
51#include <vm/vm.h>
52#include <vm/pmap.h>
53#include <net/if.h>
54#if __FreeBSD_version > 501000
55# include <dev/pci/pcivar.h>
56# include <dev/pci/pcireg.h>
57#else
58# include <pci/pcivar.h>
59# include <pci/pcireg.h>
60#endif
61#include <machine/bus.h>
62#include <sys/rman.h>
63#include "opt_ng_cronyx.h"
64#ifdef NETGRAPH_CRONYX
65# include "opt_netgraph.h"
66# ifndef NETGRAPH
67# error #option NETGRAPH missed from configuration
68# endif
69# include <netgraph/ng_message.h>
70# include <netgraph/netgraph.h>
71# if __FreeBSD_version >= 500000
72# include <dev/cp/ng_cp.h>
73# else
74# include <netgraph/ng_cp.h>
75# endif
76#else
77# include <net/if_sppp.h>
78# define PP_CISCO IFF_LINK2
79# if __FreeBSD_version < 400000
80# include <bpfilter.h>
81# if NBPFILTER > 0
82# include <net/bpf.h>
83# endif
84# else
85# if __FreeBSD_version < 500000
86# include <bpf.h>
87# endif
88# include <net/bpf.h>
89# define NBPFILTER NBPF
90#endif
91#endif
92#if __FreeBSD_version >= 500000
93#include <dev/cx/machdep.h>
94#include <dev/cp/cpddk.h>
95#else
96#include <i386/isa/cronyx/machdep.h>
97#include <pci/cpddk.h>
98#endif
99#include <machine/cserial.h>
100#include <machine/resource.h>
101#include <machine/pmap.h>
102
103/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */
104#ifndef PP_FR
105#define PP_FR 0
106#endif
107
108#define CP_DEBUG(d,s) ({if (d->chan->debug) {\
109 printf ("%s: ", d->name); printf s;}})
110#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\
111 printf ("%s: ", d->name); printf s;}})
112
113#define CDEV_MAJOR 134
114
115#if __FreeBSD_version >= 400000
116static int cp_probe __P((device_t));
117static int cp_attach __P((device_t));
118static int cp_detach __P((device_t));
119
120static device_method_t cp_methods[] = {
121 /* Device interface */
122 DEVMETHOD(device_probe, cp_probe),
123 DEVMETHOD(device_attach, cp_attach),
124 DEVMETHOD(device_detach, cp_detach),
125
126 {0, 0}
127};
128
129typedef struct _bdrv_t {
130 cp_board_t *board;
131 struct resource *cp_res;
132 struct resource *cp_irq;
133 void *cp_intrhand;
134} bdrv_t;
135
136static driver_t cp_driver = {
137 "cp",
138 cp_methods,
139 sizeof(bdrv_t),
140};
141
142static devclass_t cp_devclass;
143#endif
144
145typedef struct _drv_t {
146 char name [8];
147 cp_chan_t *chan;
148 cp_board_t *board;
149 cp_buf_t buf;
150 int running;
151#ifdef NETGRAPH
152 char nodename [NG_NODELEN+1];
153 hook_p hook;
154 hook_p debug_hook;
155 node_p node;
156 struct ifqueue queue;
157 struct ifqueue hi_queue;
158 short timeout;
159 struct callout_handle timeout_handle;
160#else
161 struct sppp pp;
162#endif
163#if __FreeBSD_version >= 400000
164 struct cdev *devt;
165#endif
166} drv_t;
167
168static void cp_receive (cp_chan_t *c, unsigned char *data, int len);
169static void cp_transmit (cp_chan_t *c, void *attachment, int len);
170static void cp_error (cp_chan_t *c, int data);
171static void cp_up (drv_t *d);
172static void cp_start (drv_t *d);
173static void cp_down (drv_t *d);
174static void cp_watchdog (drv_t *d);
175#ifdef NETGRAPH
176extern struct ng_type typestruct;
177#else
178static void cp_ifstart (struct ifnet *ifp);
179static void cp_tlf (struct sppp *sp);
180static void cp_tls (struct sppp *sp);
181static void cp_ifwatchdog (struct ifnet *ifp);
182static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data);
183static void cp_initialize (void *softc);
184#endif
185
186static cp_board_t *adapter [NBRD];
187static drv_t *channel [NBRD*NCHAN];
188static cp_qbuf_t *queue [NBRD];
189static struct callout_handle led_timo [NBRD];
190static struct callout_handle timeout_handle;
191
192static int cp_destroy = 0;
193
194/*
195 * Print the mbuf chain, for debug purposes only.
196 */
197static void printmbuf (struct mbuf *m)
198{
199 printf ("mbuf:");
200 for (; m; m=m->m_next) {
201 if (m->m_flags & M_PKTHDR)
202 printf (" HDR %d:", m->m_pkthdr.len);
203 if (m->m_flags & M_EXT)
204 printf (" EXT:");
205 printf (" %d", m->m_len);
206 }
207 printf ("\n");
208}
209
210/*
211 * Make an mbuf from data.
212 */
213static struct mbuf *makembuf (void *buf, unsigned len)
214{
215 struct mbuf *m;
216
217 MGETHDR (m, M_DONTWAIT, MT_DATA);
218 if (! m)
219 return 0;
220 MCLGET (m, M_DONTWAIT);
221 if (! (m->m_flags & M_EXT)) {
222 m_freem (m);
223 return 0;
224 }
225 m->m_pkthdr.len = m->m_len = len;
226 bcopy (buf, mtod (m, caddr_t), len);
227 return m;
228}
229
230#if __FreeBSD_version < 400000
231static const char *cp_probe (pcici_t tag, pcidi_t type)
232{
233 if (tag->vendor == cp_vendor_id && tag->device == cp_device_id)
234 return "Cronyx-Tau-PCI serial adapter";
235 return 0;
236}
237#else
238static int cp_probe (device_t dev)
239{
240 if ((pci_get_vendor (dev) == cp_vendor_id) &&
241 (pci_get_device (dev) == cp_device_id)) {
242 device_set_desc (dev, "Cronyx-Tau-PCI serial adapter");
243 return 0;
244 }
245 return ENXIO;
246}
247#endif
248
249static void cp_timeout (void *arg)
250{
251 drv_t *d;
252 int s, i;
253
254 for (i=0; i<NBRD*NCHAN; ++i) {
255 s = splimp ();
256 if (cp_destroy) {
257 splx (s);
258 return;
259 }
260 d = channel[i];
261 if (!d) {
262 splx (s);
263 continue;
264 }
265 switch (d->chan->type) {
266 case T_G703:
267 cp_g703_timer (d->chan);
268 break;
269 case T_E1:
270 cp_e1_timer (d->chan);
271 break;
272 case T_E3:
273 case T_T3:
274 case T_STS1:
275 cp_e3_timer (d->chan);
276 break;
277 default:
278 break;
279 }
280 splx (s);
281 }
282 s = splimp ();
283 if (!cp_destroy)
284 timeout_handle = timeout (cp_timeout, 0, hz);
285 splx (s);
286}
287
288static void cp_led_off (void *arg)
289{
290 cp_board_t *b = arg;
291 int s = splimp ();
292 if (cp_destroy) {
293 splx (s);
294 return;
295 }
296 cp_led (b, 0);
297 led_timo[b->num].callout = 0;
298 splx (s);
299}
300
301static void cp_intr (void *arg)
302{
303#if __FreeBSD_version < 400000
304 cp_board_t *b = arg;
305#else
306 bdrv_t *bd = arg;
307 cp_board_t *b = bd->board;
308#endif
309 int s = splimp ();
310 if (cp_destroy) {
311 splx (s);
312 return;
313 }
314 /* Turn LED on. */
315 cp_led (b, 1);
316
317 cp_interrupt (b);
318
319 /* Turn LED off 50 msec later. */
320 if (!led_timo[b->num].callout)
321 led_timo[b->num] = timeout (cp_led_off, b, hz/20);
322 splx (s);
323}
324
325extern struct cdevsw cp_cdevsw;
326
327/*
328 * Called if the probe succeeded.
329 */
330#if __FreeBSD_version < 400000
331static void cp_attach (pcici_t tag, int unit)
332{
333 vm_offset_t pbase;
334#else
335static int cp_attach (device_t dev)
336{
337 bdrv_t *bd = device_get_softc (dev);
338 int unit = device_get_unit (dev);
339 int rid, error;
340#endif
341 vm_offset_t vbase;
342 cp_board_t *b;
343 cp_chan_t *c;
344 drv_t *d;
345 unsigned short res;
346 int s = splimp ();
347
348 b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK);
349 if (!b) {
350 printf ("cp%d: couldn't allocate memory\n", unit);
351#if __FreeBSD_version < 400000
352 splx (s);
353 return;
354#else
355 splx (s);
356 return (ENXIO);
357#endif
358 }
359 adapter[unit] = b;
360 bzero (b, sizeof(cp_board_t));
361
362#if __FreeBSD_version < 400000
363 if (! pci_map_mem (tag, PCIR_MAPS, &vbase, &pbase)) {
364 printf ("cp%d: cannot map memory\n", unit);
365 free (b, M_DEVBUF);
366 splx (s);
367 return;
368 }
369#else
370 bd->board = b;
371 b->sys = bd;
372 rid = PCIR_BAR(0);
373 bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid,
374 0, ~0, 1, RF_ACTIVE);
375 if (! bd->cp_res) {
376 printf ("cp%d: cannot map memory\n", unit);
377 free (b, M_DEVBUF);
378 splx (s);
379 return (ENXIO);
380 }
381 vbase = (vm_offset_t) rman_get_virtual (bd->cp_res);
382#endif
383
384 res = cp_init (b, unit, (u_char*) vbase);
385 if (res) {
386 printf ("cp%d: can't init, error code:%x\n", unit, res);
387#if __FreeBSD_version >= 400000
388 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
389#endif
390 free (b, M_DEVBUF);
391 splx (s);
392#if __FreeBSD_version >= 400000
393 return (ENXIO);
394#else
395 return;
396#endif
397 }
398 queue[unit] = contigmalloc (sizeof(cp_qbuf_t), M_DEVBUF, M_WAITOK,
399 0x100000, 0xffffffff, 16, 0);
400 if (queue[unit] == NULL) {
401 printf ("cp%d: allocate memory for qbuf_t\n", unit);
402 free (b, M_DEVBUF);
403 splx (s);
404#if __FreeBSD_version >= 400000
405 return (ENXIO);
406#else
407 return;
408#endif
409 }
410 cp_reset (b, queue[unit], vtophys (queue[unit]));
411
412#if __FreeBSD_version < 400000
413 if (! pci_map_int (tag, cp_intr, b, &net_imask))
414 printf ("cp%d: cannot map interrupt\n", unit);
415#else
416 rid = 0;
417 bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
418 RF_SHAREABLE | RF_ACTIVE);
419 if (! bd->cp_irq) {
420 printf ("cp%d: cannot map interrupt\n", unit);
421 bus_release_resource (dev, SYS_RES_MEMORY,
422 PCIR_BAR(0), bd->cp_res);
423 free (b, M_DEVBUF);
424 splx (s);
425 return (ENXIO);
426 }
427 error = bus_setup_intr (dev, bd->cp_irq, INTR_TYPE_NET, cp_intr, bd,
428 &bd->cp_intrhand);
429 if (error) {
430 printf ("cp%d: cannot set up irq\n", unit);
431 bus_release_resource (dev, SYS_RES_MEMORY,
432 PCIR_BAR(0), bd->cp_res);
433 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
434 free (b, M_DEVBUF);
435 splx (s);
436 return (ENXIO);
437 }
438#endif
439 printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000);
440
441 for (c=b->chan; c<b->chan+NCHAN; ++c) {
442 if (! c->type)
443 continue;
444 d = contigmalloc (sizeof(drv_t), M_DEVBUF, M_WAITOK,
445 0x100000, 0xffffffff, 16, 0);
446 if (d == NULL) {
447 printf ("cp%d-%d: cannot allocate memory for drv_t\n",
448 unit, c->num);
449 }
450 channel [b->num*NCHAN + c->num] = d;
451 bzero (d, sizeof(drv_t));
452 sprintf (d->name, "cp%d.%d", b->num, c->num);
453 d->board = b;
454 d->chan = c;
455 c->sys = d;
456#ifdef NETGRAPH
457 if (ng_make_node_common (&typestruct, &d->node) != 0) {
458 printf ("%s: cannot make common node\n", d->name);
459 d->node = NULL;
460 continue;
461 }
462#if __FreeBSD_version >= 500000
463 NG_NODE_SET_PRIVATE (d->node, d);
464#else
465 d->node->private = d;
466#endif
467 sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE,
468 c->board->num*NCHAN + c->num);
469 if (ng_name_node (d->node, d->nodename)) {
470 printf ("%s: cannot name node\n", d->nodename);
471#if __FreeBSD_version >= 500000
472 NG_NODE_UNREF (d->node);
473#else
474 ng_rmnode (d->node);
475 ng_unref (d->node);
476#endif
477 continue;
478 }
479 d->queue.ifq_maxlen = IFQ_MAXLEN;
480 d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
481#if __FreeBSD_version >= 500000
482 mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF);
483 mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF);
484#endif
485#else /*NETGRAPH*/
486 d->pp.pp_if.if_softc = d;
487#if __FreeBSD_version > 501000
488 if_initname (&d->pp.pp_if, "cp", b->num * NCHAN + c->num);
489#else
490 d->pp.pp_if.if_unit = b->num * NCHAN + c->num;
491 d->pp.pp_if.if_name = "cp";
492#endif
493 d->pp.pp_if.if_mtu = PP_MTU;
494 d->pp.pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
495 d->pp.pp_if.if_ioctl = cp_sioctl;
496 d->pp.pp_if.if_start = cp_ifstart;
497 d->pp.pp_if.if_watchdog = cp_ifwatchdog;
498 d->pp.pp_if.if_init = cp_initialize;
499 sppp_attach (&d->pp.pp_if);
500 if_attach (&d->pp.pp_if);
501 d->pp.pp_tlf = cp_tlf;
502 d->pp.pp_tls = cp_tls;
503#if __FreeBSD_version >= 400000 || NBPFILTER > 0
504 /* If BPF is in the kernel, call the attach for it.
505 * The header size of PPP or Cisco/HDLC is 4 bytes. */
506 bpfattach (&d->pp.pp_if, DLT_PPP, 4);
507#endif
508#endif /*NETGRAPH*/
509 cp_start_e1 (c);
510 cp_start_chan (c, 1, 1, &d->buf, vtophys (&d->buf));
511
512 /* Register callback functions. */
513 cp_register_transmit (c, &cp_transmit);
514 cp_register_receive (c, &cp_receive);
515 cp_register_error (c, &cp_error);
516#if __FreeBSD_version >= 400000
517 d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT,
518 GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num);
519#endif
520 }
521 splx (s);
522#if __FreeBSD_version >= 400000
523 return 0;
524#endif
525}
526
527#if __FreeBSD_version >= 400000
528static int cp_detach (device_t dev)
529{
530 bdrv_t *bd = device_get_softc (dev);
531 cp_board_t *b = bd->board;
532 cp_chan_t *c;
533 int s = splimp ();
534
535 /* Check if the device is busy (open). */
536 for (c=b->chan; c<b->chan+NCHAN; ++c) {
537 drv_t *d = (drv_t*) c->sys;
538
539 if (! d || ! d->chan->type)
540 continue;
541 if (d->running) {
542 splx (s);
543 return EBUSY;
544 }
545 }
546
547 /* Ok, we can unload driver */
548 /* At first we should stop all channels */
549 for (c=b->chan; c<b->chan+NCHAN; ++c) {
550 drv_t *d = (drv_t*) c->sys;
551
552 if (! d || ! d->chan->type)
553 continue;
554
555 cp_stop_chan (c);
556 cp_stop_e1 (c);
557 cp_set_dtr (d->chan, 0);
558 cp_set_rts (d->chan, 0);
559 }
560
561 /* Reset the adapter. */
562 cp_destroy = 1;
563 cp_interrupt_poll (b, 1);
564 cp_led_off (b);
565 cp_reset (b, 0 ,0);
566 if (led_timo[b->num].callout)
567 untimeout (cp_led_off, b, led_timo[b->num]);
568
569 for (c=b->chan; c<b->chan+NCHAN; ++c) {
570 drv_t *d = (drv_t*) c->sys;
571
572 if (! d || ! d->chan->type)
573 continue;
574#ifndef NETGRAPH
575#if __FreeBSD_version >= 410000 && NBPFILTER > 0
576 /* Detach from the packet filter list of interfaces. */
577 bpfdetach (&d->pp.pp_if);
578#endif
579 /* Detach from the sync PPP list. */
580 sppp_detach (&d->pp.pp_if);
581
582 /* Detach from the system list of interfaces. */
583 if_detach (&d->pp.pp_if);
584#else
585#if __FreeBSD_version >= 500000
586 if (d->node) {
587 ng_rmnode_self (d->node);
588 NG_NODE_UNREF (d->node);
589 d->node = NULL;
590 }
591 mtx_destroy (&d->queue.ifq_mtx);
592 mtx_destroy (&d->hi_queue.ifq_mtx);
593#else
594 ng_rmnode (d->node);
595 d->node = 0;
596#endif
597#endif
598 destroy_dev (d->devt);
599 }
600
601 /* Disable the interrupt request. */
602 bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand);
603 bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
604 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
605 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
606 cp_led_off (b);
607 if (led_timo[b->num].callout)
608 untimeout (cp_led_off, b, led_timo[b->num]);
609 splx (s);
610
611 s = splimp ();
612 for (c=b->chan; c<b->chan+NCHAN; ++c) {
613 drv_t *d = (drv_t*) c->sys;
614
615 if (! d || ! d->chan->type)
616 continue;
617 channel [b->num*NCHAN + c->num] = 0;
618 /* Deallocate buffers. */
619#if __FreeBSD_version < 400000
620 free (d, M_DEVBUF);
621#else
622 contigfree (d, sizeof (*d), M_DEVBUF);
623#endif
624 }
625 adapter [b->num] = 0;
626#if __FreeBSD_version < 400000
627 free (queue[b->num], M_DEVBUF);
628#else
629 contigfree (queue[b->num], sizeof (cp_qbuf_t), M_DEVBUF);
630#endif
631 free (b, M_DEVBUF);
632 splx (s);
633 return 0;
634}
635#endif
636
637#if __FreeBSD_version < 400000
638static u_long cp_count;
639static struct pci_device cp_driver = {"cp", cp_probe, cp_attach, &cp_count, 0};
640DATA_SET (pcidevice_set, cp_driver);
641#endif
642
643#ifndef NETGRAPH
644static void cp_ifstart (struct ifnet *ifp)
645{
646 drv_t *d = ifp->if_softc;
647
648 cp_start (d);
649}
650
651static void cp_ifwatchdog (struct ifnet *ifp)
652{
653 drv_t *d = ifp->if_softc;
654
655 cp_watchdog (d);
656}
657
658static void cp_tlf (struct sppp *sp)
659{
660 drv_t *d = sp->pp_if.if_softc;
661
662 CP_DEBUG2 (d, ("cp_tlf\n"));
663/* cp_set_dtr (d->chan, 0);*/
664/* cp_set_rts (d->chan, 0);*/
665 sp->pp_down (sp);
666}
667
668static void cp_tls (struct sppp *sp)
669{
670 drv_t *d = sp->pp_if.if_softc;
671
672 CP_DEBUG2 (d, ("cp_tls\n"));
673 sp->pp_up (sp);
674}
675
676/*
677 * Process an ioctl request.
678 */
679static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
680{
681 drv_t *d = ifp->if_softc;
682 int error, s, was_up, should_be_up;
683
684 was_up = (ifp->if_flags & IFF_RUNNING) != 0;
685 error = sppp_ioctl (ifp, cmd, data);
686
687 if (error)
688 return error;
689
690 if (! (ifp->if_flags & IFF_DEBUG))
691 d->chan->debug = 0;
692 else if (! d->chan->debug)
693 d->chan->debug = 1;
694
695 switch (cmd) {
696 default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0;
697 case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0;
698 case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0;
699 case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break;
700 case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break;
701 }
702
703 /* We get here only in case of SIFFLAGS or SIFADDR. */
704 s = splimp ();
705 should_be_up = (ifp->if_flags & IFF_RUNNING) != 0;
706 if (! was_up && should_be_up) {
707 /* Interface goes up -- start it. */
708 cp_up (d);
709 cp_start (d);
710 } else if (was_up && ! should_be_up) {
711 /* Interface is going down -- stop it. */
712/* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/
713 cp_down (d);
714 }
715 CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd));
716 splx (s);
717 return 0;
718}
719
720/*
721 * Initialization of interface.
722 * It seems to be never called by upper level?
723 */
724static void cp_initialize (void *softc)
725{
726 drv_t *d = softc;
727
728 CP_DEBUG (d, ("cp_initialize\n"));
729}
730#endif /*NETGRAPH*/
731
732/*
733 * Stop the interface. Called on splimp().
734 */
735static void cp_down (drv_t *d)
736{
737 CP_DEBUG (d, ("cp_down\n"));
738 /* Interface is going down -- stop it. */
739 cp_set_dtr (d->chan, 0);
740 cp_set_rts (d->chan, 0);
741
742 d->running = 0;
743}
744
745/*
746 * Start the interface. Called on splimp().
747 */
748static void cp_up (drv_t *d)
749{
750 CP_DEBUG (d, ("cp_up\n"));
751 cp_set_dtr (d->chan, 1);
752 cp_set_rts (d->chan, 1);
753 d->running = 1;
754}
755
756/*
757 * Start output on the interface. Get another datagram to send
758 * off of the interface queue, and copy it to the interface
759 * before starting the output.
760 */
761static void cp_send (drv_t *d)
762{
763 struct mbuf *m;
764 u_short len;
765
766 CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te));
767
768 /* No output if the interface is down. */
769 if (! d->running)
770 return;
771
772 /* No output if the modem is off. */
773 if (! (d->chan->lloop || d->chan->type != T_SERIAL ||
774 cp_get_dsr (d->chan)))
775 return;
776
777 while (cp_transmit_space (d->chan)) {
778 /* Get the packet to send. */
779#ifdef NETGRAPH
780 IF_DEQUEUE (&d->hi_queue, m);
781 if (! m)
782 IF_DEQUEUE (&d->queue, m);
783#else
784 m = sppp_dequeue (&d->pp.pp_if);
785#endif
786 if (! m)
787 return;
788#if (__FreeBSD_version >= 400000 || NBPFILTER > 0) && !defined (NETGRAPH)
789 if (d->pp.pp_if.if_bpf)
790#if __FreeBSD_version >= 500000
791 BPF_MTAP (&d->pp.pp_if, m);
792#else
793 bpf_mtap (&d->pp.pp_if, m);
794#endif
795#endif
796 len = m->m_pkthdr.len;
797 if (len >= BUFSZ)
798 printf ("%s: too long packet: %d bytes: ",
799 d->name, len);
800 else if (! m->m_next)
801 cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0);
802 else {
803 u_char *buf = d->chan->tbuf[d->chan->te];
804 m_copydata (m, 0, len, buf);
805 cp_send_packet (d->chan, buf, len, 0);
806 }
807 m_freem (m);
808 /* Set up transmit timeout, if the transmit ring is not empty.*/
809#ifdef NETGRAPH
810 d->timeout = 10;
811#else
812 d->pp.pp_if.if_timer = 10;
813#endif
814 }
815#ifndef NETGRAPH
816 d->pp.pp_if.if_flags |= IFF_OACTIVE;
817#endif
818}
819
820/*
821 * Start output on the interface.
822 * Always called on splimp().
823 */
824static void cp_start (drv_t *d)
825{
826 if (d->running) {
827 if (! d->chan->dtr)
828 cp_set_dtr (d->chan, 1);
829 if (! d->chan->rts)
830 cp_set_rts (d->chan, 1);
831 cp_send (d);
832 }
833}
834
835/*
836 * Handle transmit timeouts.
837 * Recover after lost transmit interrupts.
838 * Always called on splimp().
839 */
840static void cp_watchdog (drv_t *d)
841{
842 CP_DEBUG (d, ("device timeout\n"));
843 if (d->running) {
844 int s = splimp ();
845
846 cp_stop_chan (d->chan);
847 cp_stop_e1 (d->chan);
848 cp_start_e1 (d->chan);
849 cp_start_chan (d->chan, 1, 1, 0, 0);
850 cp_set_dtr (d->chan, 1);
851 cp_set_rts (d->chan, 1);
852 cp_start (d);
853 splx (s);
854 }
855}
856
857static void cp_transmit (cp_chan_t *c, void *attachment, int len)
858{
859 drv_t *d = c->sys;
860
861#ifdef NETGRAPH
862 d->timeout = 0;
863#else
864 ++d->pp.pp_if.if_opackets;
865 d->pp.pp_if.if_flags &= ~IFF_OACTIVE;
866 d->pp.pp_if.if_timer = 0;
867#endif
868 cp_start (d);
869}
870
871static void cp_receive (cp_chan_t *c, unsigned char *data, int len)
872{
873 drv_t *d = c->sys;
874 struct mbuf *m;
875#if __FreeBSD_version >= 500000 && defined NETGRAPH
876 int error;
877#endif
878
879 if (! d->running)
880 return;
881
882 m = makembuf (data, len);
883 if (! m) {
884 CP_DEBUG (d, ("no memory for packet\n"));
885#ifndef NETGRAPH
886 ++d->pp.pp_if.if_iqdrops;
887#endif
888 return;
889 }
890 if (c->debug > 1)
891 printmbuf (m);
892#ifdef NETGRAPH
893 m->m_pkthdr.rcvif = 0;
894#if __FreeBSD_version >= 500000
895 NG_SEND_DATA_ONLY (error, d->hook, m);
896#else
897 ng_queue_data (d->hook, m, 0);
898#endif
899#else
900 ++d->pp.pp_if.if_ipackets;
901 m->m_pkthdr.rcvif = &d->pp.pp_if;
902#if __FreeBSD_version >= 400000 || NBPFILTER > 0
903 /* Check if there's a BPF listener on this interface.
904 * If so, hand off the raw packet to bpf. */
905 if (d->pp.pp_if.if_bpf)
906#if __FreeBSD_version >= 500000
907 BPF_TAP (&d->pp.pp_if, data, len);
908#else
909 bpf_tap (&d->pp.pp_if, data, len);
910#endif
911#endif
912 sppp_input (&d->pp.pp_if, m);
913#endif
914}
915
916static void cp_error (cp_chan_t *c, int data)
917{
918 drv_t *d = c->sys;
919
920 switch (data) {
921 case CP_FRAME:
922 CP_DEBUG (d, ("frame error\n"));
923#ifndef NETGRAPH
924 ++d->pp.pp_if.if_ierrors;
925#endif
926 break;
927 case CP_CRC:
928 CP_DEBUG (d, ("crc error\n"));
929#ifndef NETGRAPH
930 ++d->pp.pp_if.if_ierrors;
931#endif
932 break;
933 case CP_OVERRUN:
934 CP_DEBUG (d, ("overrun error\n"));
935#ifndef NETGRAPH
936 ++d->pp.pp_if.if_collisions;
937 ++d->pp.pp_if.if_ierrors;
938#endif
939 break;
940 case CP_OVERFLOW:
941 CP_DEBUG (d, ("overflow error\n"));
942#ifndef NETGRAPH
943 ++d->pp.pp_if.if_ierrors;
944#endif
945 break;
946 case CP_UNDERRUN:
947 CP_DEBUG (d, ("underrun error\n"));
948#ifdef NETGRAPH
949 d->timeout = 0;
950#else
951 ++d->pp.pp_if.if_oerrors;
952 d->pp.pp_if.if_flags &= ~IFF_OACTIVE;
953 d->pp.pp_if.if_timer = 0;
954#endif
955 cp_start (d);
956 break;
957 default:
958 CP_DEBUG (d, ("error #%d\n", data));
959 break;
960 }
961}
962
963/*
964 * You also need read, write, open, close routines.
965 * This should get you started
966 */
967#if __FreeBSD_version < 500000
968static int cp_open (dev_t dev, int oflags, int devtype, struct proc *p)
969#else
970static int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td)
971#endif
972{
973 int unit = minor (dev);
974 drv_t *d;
975
976 if (unit >= NBRD*NCHAN || ! (d = channel[unit]))
977 return ENXIO;
978 CP_DEBUG2 (d, ("cp_open\n"));
979 return 0;
980}
981
982/*
983 * Only called on the LAST close.
984 */
985#if __FreeBSD_version < 500000
986static int cp_close (dev_t dev, int fflag, int devtype, struct proc *p)
987#else
988static int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td)
989#endif
990{
991 drv_t *d = channel [minor (dev)];
992
993 CP_DEBUG2 (d, ("cp_close\n"));
994 return 0;
995}
996
997static int cp_modem_status (cp_chan_t *c)
998{
999 drv_t *d = c->sys;
1000 int status, s;
1001
1002 status = d->running ? TIOCM_LE : 0;
1003 s = splimp ();
1004 if (cp_get_cd (c)) status |= TIOCM_CD;
1005 if (cp_get_cts (c)) status |= TIOCM_CTS;
1006 if (cp_get_dsr (c)) status |= TIOCM_DSR;
1007 if (c->dtr) status |= TIOCM_DTR;
1008 if (c->rts) status |= TIOCM_RTS;
1009 splx (s);
1010 return status;
1011}
1012
1013#if __FreeBSD_version < 500000
1014static int cp_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
1015#else
1016static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
1017#endif
1018{
1019 drv_t *d = channel [minor (dev)];
1020 cp_chan_t *c = d->chan;
1021 struct serial_statistics *st;
1022 struct e1_statistics *opte1;
1023 struct e3_statistics *opte3;
1024 int error, s;
1025 char mask[16];
1026
1027 switch (cmd) {
1028 case SERIAL_GETREGISTERED:
1029 CP_DEBUG2 (d, ("ioctl: getregistered\n"));
1030 bzero (mask, sizeof(mask));
1031 for (s=0; s<NBRD*NCHAN; ++s)
1032 if (channel [s])
1033 mask [s/8] |= 1 << (s & 7);
1034 bcopy (mask, data, sizeof (mask));
1035 return 0;
1036
1037#ifndef NETGRAPH
1038 case SERIAL_GETPROTO:
1039 CP_DEBUG2 (d, ("ioctl: getproto\n"));
1040 strcpy ((char*)data, (d->pp.pp_flags & PP_FR) ? "fr" :
1041 (d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp");
1042 return 0;
1043
1044 case SERIAL_SETPROTO:
1045 CP_DEBUG2 (d, ("ioctl: setproto\n"));
1046 /* Only for superuser! */
1047#if __FreeBSD_version < 400000
1048 error = suser (p->p_ucred, &p->p_acflag);
1049#elif __FreeBSD_version < 500000
1050 error = suser (p);
1051#else /* __FreeBSD_version >= 500000 */
1052 error = suser (td);
1053#endif /* __FreeBSD_version >= 500000 */
1054 if (error)
1055 return error;
1056 if (d->pp.pp_if.if_flags & IFF_RUNNING)
1057 return EBUSY;
1058 if (! strcmp ("cisco", (char*)data)) {
1059 d->pp.pp_flags &= ~(PP_FR);
1060 d->pp.pp_flags |= PP_KEEPALIVE;
1061 d->pp.pp_if.if_flags |= PP_CISCO;
1062 } else if (! strcmp ("fr", (char*)data) && !PP_FR) {
1063 d->pp.pp_if.if_flags &= ~(PP_CISCO);
1064 d->pp.pp_flags |= PP_FR | PP_KEEPALIVE;
1065 } else if (! strcmp ("ppp", (char*)data)) {
1066 d->pp.pp_flags &= ~PP_FR;
1067 d->pp.pp_flags &= ~PP_KEEPALIVE;
1068 d->pp.pp_if.if_flags &= ~(PP_CISCO);
1069 } else
1070 return EINVAL;
1071 return 0;
1072
1073 case SERIAL_GETKEEPALIVE:
1074 CP_DEBUG2 (d, ("ioctl: getkeepalive\n"));
1075 if ((d->pp.pp_flags & PP_FR) ||
1076 (d->pp.pp_if.if_flags & PP_CISCO))
1077 return EINVAL;
1078 *(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0;
1079 return 0;
1080
1081 case SERIAL_SETKEEPALIVE:
1082 CP_DEBUG2 (d, ("ioctl: setkeepalive\n"));
1083 /* Only for superuser! */
1084#if __FreeBSD_version < 400000
1085 error = suser (p->p_ucred, &p->p_acflag);
1086#elif __FreeBSD_version < 500000
1087 error = suser (p);
1088#else
1089 error = suser (td);
1090#endif
1091 if (error)
1092 return error;
1093 if ((d->pp.pp_flags & PP_FR) ||
1094 (d->pp.pp_if.if_flags & PP_CISCO))
1095 return EINVAL;
1096 s = splimp ();
1097 if (*(int*)data)
1098 d->pp.pp_flags |= PP_KEEPALIVE;
1099 else
1100 d->pp.pp_flags &= ~PP_KEEPALIVE;
1101 splx (s);
1102 return 0;
1103#endif /*NETGRAPH*/
1104
1105 case SERIAL_GETMODE:
1106 CP_DEBUG2 (d, ("ioctl: getmode\n"));
1107 *(int*)data = SERIAL_HDLC;
1108 return 0;
1109
1110 case SERIAL_SETMODE:
1111 /* Only for superuser! */
1112#if __FreeBSD_version < 400000
1113 error = suser (p->p_ucred, &p->p_acflag);
1114#elif __FreeBSD_version < 500000
1115 error = suser (p);
1116#else
1117 error = suser (td);
1118#endif
1119 if (error)
1120 return error;
1121 if (*(int*)data != SERIAL_HDLC)
1122 return EINVAL;
1123 return 0;
1124
1125 case SERIAL_GETCFG:
1126 CP_DEBUG2 (d, ("ioctl: getcfg\n"));
1127 if (c->type != T_E1 || c->unfram)
1128 return EINVAL;
1129 *(char*)data = c->board->mux ? 'c' : 'a';
1130 return 0;
1131
1132 case SERIAL_SETCFG:
1133 CP_DEBUG2 (d, ("ioctl: setcfg\n"));
1134#if __FreeBSD_version < 400000
1135 error = suser (p->p_ucred, &p->p_acflag);
1136#elif __FreeBSD_version < 500000
1137 error = suser (p);
1138#else
1139 error = suser (td);
1140#endif
1141 if (error)
1142 return error;
1143 if (c->type != T_E1)
1144 return EINVAL;
1145 s = splimp ();
1146 cp_set_mux (c->board, *((char*)data) == 'c');
1147 splx (s);
1148 return 0;
1149
1150 case SERIAL_GETSTAT:
1151 CP_DEBUG2 (d, ("ioctl: getstat\n"));
1152 st = (struct serial_statistics*) data;
1153 st->rintr = c->rintr;
1154 st->tintr = c->tintr;
1155 st->mintr = 0;
1156 st->ibytes = c->ibytes;
1157 st->ipkts = c->ipkts;
1158 st->obytes = c->obytes;
1159 st->opkts = c->opkts;
1160 st->ierrs = c->overrun + c->frame + c->crc;
1161 st->oerrs = c->underrun;
1162 return 0;
1163
1164 case SERIAL_GETESTAT:
1165 CP_DEBUG2 (d, ("ioctl: getestat\n"));
1166 if (c->type != T_E1 && c->type != T_G703)
1167 return EINVAL;
1168 opte1 = (struct e1_statistics*) data;
1169 opte1->status = c->status;
1170 opte1->cursec = c->cursec;
1171 opte1->totsec = c->totsec + c->cursec;
1172
1173 opte1->currnt.bpv = c->currnt.bpv;
1174 opte1->currnt.fse = c->currnt.fse;
1175 opte1->currnt.crce = c->currnt.crce;
1176 opte1->currnt.rcrce = c->currnt.rcrce;
1177 opte1->currnt.uas = c->currnt.uas;
1178 opte1->currnt.les = c->currnt.les;
1179 opte1->currnt.es = c->currnt.es;
1180 opte1->currnt.bes = c->currnt.bes;
1181 opte1->currnt.ses = c->currnt.ses;
1182 opte1->currnt.oofs = c->currnt.oofs;
1183 opte1->currnt.css = c->currnt.css;
1184 opte1->currnt.dm = c->currnt.dm;
1185
1186 opte1->total.bpv = c->total.bpv + c->currnt.bpv;
1187 opte1->total.fse = c->total.fse + c->currnt.fse;
1188 opte1->total.crce = c->total.crce + c->currnt.crce;
1189 opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce;
1190 opte1->total.uas = c->total.uas + c->currnt.uas;
1191 opte1->total.les = c->total.les + c->currnt.les;
1192 opte1->total.es = c->total.es + c->currnt.es;
1193 opte1->total.bes = c->total.bes + c->currnt.bes;
1194 opte1->total.ses = c->total.ses + c->currnt.ses;
1195 opte1->total.oofs = c->total.oofs + c->currnt.oofs;
1196 opte1->total.css = c->total.css + c->currnt.css;
1197 opte1->total.dm = c->total.dm + c->currnt.dm;
1198 for (s=0; s<48; ++s) {
1199 opte1->interval[s].bpv = c->interval[s].bpv;
1200 opte1->interval[s].fse = c->interval[s].fse;
1201 opte1->interval[s].crce = c->interval[s].crce;
1202 opte1->interval[s].rcrce = c->interval[s].rcrce;
1203 opte1->interval[s].uas = c->interval[s].uas;
1204 opte1->interval[s].les = c->interval[s].les;
1205 opte1->interval[s].es = c->interval[s].es;
1206 opte1->interval[s].bes = c->interval[s].bes;
1207 opte1->interval[s].ses = c->interval[s].ses;
1208 opte1->interval[s].oofs = c->interval[s].oofs;
1209 opte1->interval[s].css = c->interval[s].css;
1210 opte1->interval[s].dm = c->interval[s].dm;
1211 }
1212 return 0;
1213
1214 case SERIAL_GETE3STAT:
1215 CP_DEBUG2 (d, ("ioctl: gete3stat\n"));
1216 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1)
1217 return EINVAL;
1218 opte3 = (struct e3_statistics*) data;
1219
1220 opte3->status = c->e3status;
1221 opte3->cursec = (c->e3csec_5 * 2 + 1) / 10;
1222 opte3->totsec = c->e3tsec + opte3->cursec;
1223
1224 opte3->ccv = c->e3ccv;
1225 opte3->tcv = c->e3tcv + opte3->ccv;
1226
1227 for (s = 0; s < 48; ++s) {
1228 opte3->icv[s] = c->e3icv[s];
1229 }
1230 return 0;
1231
1232 case SERIAL_CLRSTAT:
1233 CP_DEBUG2 (d, ("ioctl: clrstat\n"));
1234 /* Only for superuser! */
1235#if __FreeBSD_version < 400000
1236 error = suser (p->p_ucred, &p->p_acflag);
1237#elif __FreeBSD_version < 500000
1238 error = suser (p);
1239#else
1240 error = suser (td);
1241#endif
1242 if (error)
1243 return error;
1244 c->rintr = 0;
1245 c->tintr = 0;
1246 c->ibytes = 0;
1247 c->obytes = 0;
1248 c->ipkts = 0;
1249 c->opkts = 0;
1250 c->overrun = 0;
1251 c->frame = 0;
1252 c->crc = 0;
1253 c->underrun = 0;
1254 bzero (&c->currnt, sizeof (c->currnt));
1255 bzero (&c->total, sizeof (c->total));
1256 bzero (c->interval, sizeof (c->interval));
1257 c->e3ccv = 0;
1258 c->e3tcv = 0;
1259 bzero (c->e3icv, sizeof (c->e3icv));
1260 return 0;
1261
1262 case SERIAL_GETBAUD:
1263 CP_DEBUG2 (d, ("ioctl: getbaud\n"));
1264 *(long*)data = c->baud;
1265 return 0;
1266
1267 case SERIAL_SETBAUD:
1268 CP_DEBUG2 (d, ("ioctl: setbaud\n"));
1269 /* Only for superuser! */
1270#if __FreeBSD_version < 400000
1271 error = suser (p->p_ucred, &p->p_acflag);
1272#elif __FreeBSD_version < 500000
1273 error = suser (p);
1274#else
1275 error = suser (td);
1276#endif
1277 if (error)
1278 return error;
1279 s = splimp ();
1280 cp_set_baud (c, *(long*)data);
1281 splx (s);
1282 return 0;
1283
1284 case SERIAL_GETLOOP:
1285 CP_DEBUG2 (d, ("ioctl: getloop\n"));
1286 *(int*)data = c->lloop;
1287 return 0;
1288
1289 case SERIAL_SETLOOP:
1290 CP_DEBUG2 (d, ("ioctl: setloop\n"));
1291 /* Only for superuser! */
1292#if __FreeBSD_version < 400000
1293 error = suser (p->p_ucred, &p->p_acflag);
1294#elif __FreeBSD_version < 500000
1295 error = suser (p);
1296#else
1297 error = suser (td);
1298#endif
1299 if (error)
1300 return error;
1301 s = splimp ();
1302 cp_set_lloop (c, *(int*)data);
1303 splx (s);
1304 return 0;
1305
1306 case SERIAL_GETDPLL:
1307 CP_DEBUG2 (d, ("ioctl: getdpll\n"));
1308 if (c->type != T_SERIAL)
1309 return EINVAL;
1310 *(int*)data = c->dpll;
1311 return 0;
1312
1313 case SERIAL_SETDPLL:
1314 CP_DEBUG2 (d, ("ioctl: setdpll\n"));
1315 /* Only for superuser! */
1316#if __FreeBSD_version < 400000
1317 error = suser (p->p_ucred, &p->p_acflag);
1318#elif __FreeBSD_version < 500000
1319 error = suser (p);
1320#else
1321 error = suser (td);
1322#endif
1323 if (error)
1324 return error;
1325 if (c->type != T_SERIAL)
1326 return EINVAL;
1327 s = splimp ();
1328 cp_set_dpll (c, *(int*)data);
1329 splx (s);
1330 return 0;
1331
1332 case SERIAL_GETNRZI:
1333 CP_DEBUG2 (d, ("ioctl: getnrzi\n"));
1334 if (c->type != T_SERIAL)
1335 return EINVAL;
1336 *(int*)data = c->nrzi;
1337 return 0;
1338
1339 case SERIAL_SETNRZI:
1340 CP_DEBUG2 (d, ("ioctl: setnrzi\n"));
1341 /* Only for superuser! */
1342#if __FreeBSD_version < 400000
1343 error = suser (p->p_ucred, &p->p_acflag);
1344#elif __FreeBSD_version < 500000
1345 error = suser (p);
1346#else
1347 error = suser (td);
1348#endif
1349 if (error)
1350 return error;
1351 if (c->type != T_SERIAL)
1352 return EINVAL;
1353 s = splimp ();
1354 cp_set_nrzi (c, *(int*)data);
1355 splx (s);
1356 return 0;
1357
1358 case SERIAL_GETDEBUG:
1359 CP_DEBUG2 (d, ("ioctl: getdebug\n"));
1360 *(int*)data = d->chan->debug;
1361 return 0;
1362
1363 case SERIAL_SETDEBUG:
1364 CP_DEBUG2 (d, ("ioctl: setdebug\n"));
1365 /* Only for superuser! */
1366#if __FreeBSD_version < 400000
1367 error = suser (p->p_ucred, &p->p_acflag);
1368#elif __FreeBSD_version < 500000
1369 error = suser (p);
1370#else
1371 error = suser (td);
1372#endif
1373 if (error)
1374 return error;
1375 d->chan->debug = *(int*)data;
1376#ifndef NETGRAPH
1377 if (d->chan->debug)
1378 d->pp.pp_if.if_flags |= IFF_DEBUG;
1379 else
1380 d->pp.pp_if.if_flags &= ~IFF_DEBUG;
1381#endif
1382 return 0;
1383
1384 case SERIAL_GETHIGAIN:
1385 CP_DEBUG2 (d, ("ioctl: gethigain\n"));
1386 if (c->type != T_E1)
1387 return EINVAL;
1388 *(int*)data = c->higain;
1389 return 0;
1390
1391 case SERIAL_SETHIGAIN:
1392 CP_DEBUG2 (d, ("ioctl: sethigain\n"));
1393 /* Only for superuser! */
1394#if __FreeBSD_version < 400000
1395 error = suser (p->p_ucred, &p->p_acflag);
1396#elif __FreeBSD_version < 500000
1397 error = suser (p);
1398#else
1399 error = suser (td);
1400#endif
1401 if (error)
1402 return error;
1403 if (c->type != T_E1)
1404 return EINVAL;
1405 s = splimp ();
1406 cp_set_higain (c, *(int*)data);
1407 splx (s);
1408 return 0;
1409
1410 case SERIAL_GETPHONY:
1411 CP_DEBUG2 (d, ("ioctl: getphony\n"));
1412 if (c->type != T_E1)
1413 return EINVAL;
1414 *(int*)data = c->phony;
1415 return 0;
1416
1417 case SERIAL_SETPHONY:
1418 CP_DEBUG2 (d, ("ioctl: setphony\n"));
1419 /* Only for superuser! */
1420#if __FreeBSD_version < 400000
1421 error = suser (p->p_ucred, &p->p_acflag);
1422#elif __FreeBSD_version < 500000
1423 error = suser (p);
1424#else
1425 error = suser (td);
1426#endif
1427 if (error)
1428 return error;
1429 if (c->type != T_E1)
1430 return EINVAL;
1431 s = splimp ();
1432 cp_set_phony (c, *(int*)data);
1433 splx (s);
1434 return 0;
1435
1436 case SERIAL_GETUNFRAM:
1437 CP_DEBUG2 (d, ("ioctl: getunfram\n"));
1438 if (c->type != T_E1)
1439 return EINVAL;
1440 *(int*)data = c->unfram;
1441 return 0;
1442
1443 case SERIAL_SETUNFRAM:
1444 CP_DEBUG2 (d, ("ioctl: setunfram\n"));
1445 /* Only for superuser! */
1446#if __FreeBSD_version < 400000
1447 error = suser (p->p_ucred, &p->p_acflag);
1448#elif __FreeBSD_version < 500000
1449 error = suser (p);
1450#else
1451 error = suser (td);
1452#endif
1453 if (error)
1454 return error;
1455 if (c->type != T_E1)
1456 return EINVAL;
1457 s = splimp ();
1458 cp_set_unfram (c, *(int*)data);
1459 splx (s);
1460 return 0;
1461
1462 case SERIAL_GETSCRAMBLER:
1463 CP_DEBUG2 (d, ("ioctl: getscrambler\n"));
1464 if (c->type != T_G703 && !c->unfram)
1465 return EINVAL;
1466 *(int*)data = c->scrambler;
1467 return 0;
1468
1469 case SERIAL_SETSCRAMBLER:
1470 CP_DEBUG2 (d, ("ioctl: setscrambler\n"));
1471 /* Only for superuser! */
1472#if __FreeBSD_version < 400000
1473 error = suser (p->p_ucred, &p->p_acflag);
1474#elif __FreeBSD_version < 500000
1475 error = suser (p);
1476#else
1477 error = suser (td);
1478#endif
1479 if (error)
1480 return error;
1481 if (c->type != T_G703 && !c->unfram)
1482 return EINVAL;
1483 s = splimp ();
1484 cp_set_scrambler (c, *(int*)data);
1485 splx (s);
1486 return 0;
1487
1488 case SERIAL_GETMONITOR:
1489 CP_DEBUG2 (d, ("ioctl: getmonitor\n"));
1490 if (c->type != T_E1 &&
1491 c->type != T_E3 &&
1492 c->type != T_T3 &&
1493 c->type != T_STS1)
1494 return EINVAL;
1495 *(int*)data = c->monitor;
1496 return 0;
1497
1498 case SERIAL_SETMONITOR:
1499 CP_DEBUG2 (d, ("ioctl: setmonitor\n"));
1500 /* Only for superuser! */
1501#if __FreeBSD_version < 400000
1502 error = suser (p->p_ucred, &p->p_acflag);
1503#elif __FreeBSD_version < 500000
1504 error = suser (p);
1505#else
1506 error = suser (td);
1507#endif
1508 if (error)
1509 return error;
1510 if (c->type != T_E1)
1511 return EINVAL;
1512 s = splimp ();
1513 cp_set_monitor (c, *(int*)data);
1514 splx (s);
1515 return 0;
1516
1517 case SERIAL_GETUSE16:
1518 CP_DEBUG2 (d, ("ioctl: getuse16\n"));
1519 if (c->type != T_E1 || c->unfram)
1520 return EINVAL;
1521 *(int*)data = c->use16;
1522 return 0;
1523
1524 case SERIAL_SETUSE16:
1525 CP_DEBUG2 (d, ("ioctl: setuse16\n"));
1526 /* Only for superuser! */
1527#if __FreeBSD_version < 400000
1528 error = suser (p->p_ucred, &p->p_acflag);
1529#elif __FreeBSD_version < 500000
1530 error = suser (p);
1531#else
1532 error = suser (td);
1533#endif
1534 if (error)
1535 return error;
1536 if (c->type != T_E1)
1537 return EINVAL;
1538 s = splimp ();
1539 cp_set_use16 (c, *(int*)data);
1540 splx (s);
1541 return 0;
1542
1543 case SERIAL_GETCRC4:
1544 CP_DEBUG2 (d, ("ioctl: getcrc4\n"));
1545 if (c->type != T_E1 || c->unfram)
1546 return EINVAL;
1547 *(int*)data = c->crc4;
1548 return 0;
1549
1550 case SERIAL_SETCRC4:
1551 CP_DEBUG2 (d, ("ioctl: setcrc4\n"));
1552 /* Only for superuser! */
1553#if __FreeBSD_version < 400000
1554 error = suser (p->p_ucred, &p->p_acflag);
1555#elif __FreeBSD_version < 500000
1556 error = suser (p);
1557#else
1558 error = suser (td);
1559#endif
1560 if (error)
1561 return error;
1562 if (c->type != T_E1)
1563 return EINVAL;
1564 s = splimp ();
1565 cp_set_crc4 (c, *(int*)data);
1566 splx (s);
1567 return 0;
1568
1569 case SERIAL_GETCLK:
1570 CP_DEBUG2 (d, ("ioctl: getclk\n"));
1571 if (c->type != T_E1 &&
1572 c->type != T_G703 &&
1573 c->type != T_E3 &&
1574 c->type != T_T3 &&
1575 c->type != T_STS1)
1576 return EINVAL;
1577 switch (c->gsyn) {
1578 default: *(int*)data = E1CLK_INTERNAL; break;
1579 case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break;
1580 case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break;
1581 case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break;
1582 case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break;
1583 case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break;
1584 }
1585 return 0;
1586
1587 case SERIAL_SETCLK:
1588 CP_DEBUG2 (d, ("ioctl: setclk\n"));
1589 /* Only for superuser! */
1590#if __FreeBSD_version < 400000
1591 error = suser (p->p_ucred, &p->p_acflag);
1592#elif __FreeBSD_version < 500000
1593 error = suser (p);
1594#else
1595 error = suser (td);
1596#endif
1597 if (error)
1598 return error;
1599 if (c->type != T_E1 &&
1600 c->type != T_G703 &&
1601 c->type != T_E3 &&
1602 c->type != T_T3 &&
1603 c->type != T_STS1)
1604 return EINVAL;
1605 s = splimp ();
1606 switch (*(int*)data) {
1607 default: cp_set_gsyn (c, GSYN_INT); break;
1608 case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break;
1609 case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break;
1610 case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break;
1611 case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break;
1612 case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break;
1613 }
1614 splx (s);
1615 return 0;
1616
1617 case SERIAL_GETTIMESLOTS:
1618 CP_DEBUG2 (d, ("ioctl: gettimeslots\n"));
1619 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA)
1620 return EINVAL;
1621 *(u_long*)data = c->ts;
1622 return 0;
1623
1624 case SERIAL_SETTIMESLOTS:
1625 CP_DEBUG2 (d, ("ioctl: settimeslots\n"));
1626 /* Only for superuser! */
1627#if __FreeBSD_version < 400000
1628 error = suser (p->p_ucred, &p->p_acflag);
1629#elif __FreeBSD_version < 500000
1630 error = suser (p);
1631#else
1632 error = suser (td);
1633#endif
1634 if (error)
1635 return error;
1636 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA)
1637 return EINVAL;
1638 s = splimp ();
1639 cp_set_ts (c, *(u_long*)data);
1640 splx (s);
1641 return 0;
1642
1643 case SERIAL_GETINVCLK:
1644 CP_DEBUG2 (d, ("ioctl: getinvclk\n"));
1645#if 1
1646 return EINVAL;
1647#else
1648 if (c->type != T_SERIAL)
1649 return EINVAL;
1650 *(int*)data = c->invtxc;
1651 return 0;
1652#endif
1653
1654 case SERIAL_SETINVCLK:
1655 CP_DEBUG2 (d, ("ioctl: setinvclk\n"));
1656 /* Only for superuser! */
1657#if __FreeBSD_version < 400000
1658 error = suser (p->p_ucred, &p->p_acflag);
1659#elif __FreeBSD_version < 500000
1660 error = suser (p);
1661#else
1662 error = suser (td);
1663#endif
1664 if (error)
1665 return error;
1666 if (c->type != T_SERIAL)
1667 return EINVAL;
1668 s = splimp ();
1669 cp_set_invtxc (c, *(int*)data);
1670 cp_set_invrxc (c, *(int*)data);
1671 splx (s);
1672 return 0;
1673
1674 case SERIAL_GETINVTCLK:
1675 CP_DEBUG2 (d, ("ioctl: getinvtclk\n"));
1676 if (c->type != T_SERIAL)
1677 return EINVAL;
1678 *(int*)data = c->invtxc;
1679 return 0;
1680
1681 case SERIAL_SETINVTCLK:
1682 CP_DEBUG2 (d, ("ioctl: setinvtclk\n"));
1683 /* Only for superuser! */
1684#if __FreeBSD_version < 400000
1685 error = suser (p->p_ucred, &p->p_acflag);
1686#elif __FreeBSD_version < 500000
1687 error = suser (p);
1688#else
1689 error = suser (td);
1690#endif
1691 if (error)
1692 return error;
1693 if (c->type != T_SERIAL)
1694 return EINVAL;
1695 s = splimp ();
1696 cp_set_invtxc (c, *(int*)data);
1697 splx (s);
1698 return 0;
1699
1700 case SERIAL_GETINVRCLK:
1701 CP_DEBUG2 (d, ("ioctl: getinvrclk\n"));
1702 if (c->type != T_SERIAL)
1703 return EINVAL;
1704 *(int*)data = c->invrxc;
1705 return 0;
1706
1707 case SERIAL_SETINVRCLK:
1708 CP_DEBUG2 (d, ("ioctl: setinvrclk\n"));
1709 /* Only for superuser! */
1710#if __FreeBSD_version < 400000
1711 error = suser (p->p_ucred, &p->p_acflag);
1712#elif __FreeBSD_version < 500000
1713 error = suser (p);
1714#else
1715 error = suser (td);
1716#endif
1717 if (error)
1718 return error;
1719 if (c->type != T_SERIAL)
1720 return EINVAL;
1721 s = splimp ();
1722 cp_set_invrxc (c, *(int*)data);
1723 splx (s);
1724 return 0;
1725
1726 case SERIAL_GETLEVEL:
1727 CP_DEBUG2 (d, ("ioctl: getlevel\n"));
1728 if (c->type != T_G703)
1729 return EINVAL;
1730 s = splimp ();
1731 *(int*)data = cp_get_lq (c);
1732 splx (s);
1733 return 0;
1734
1735#if 0
1736 case SERIAL_RESET:
1737 CP_DEBUG2 (d, ("ioctl: reset\n"));
1738 /* Only for superuser! */
1739#if __FreeBSD_version < 400000
1740 error = suser (p->p_ucred, &p->p_acflag);
1741#elif __FreeBSD_version < 500000
1742 error = suser (p);
1743#else
1744 error = suser (td);
1745#endif
1746 if (error)
1747 return error;
1748 s = splimp ();
1749 cp_reset (c->board, 0, 0);
1750 splx (s);
1751 return 0;
1752
1753 case SERIAL_HARDRESET:
1754 CP_DEBUG2 (d, ("ioctl: hardreset\n"));
1755 /* Only for superuser! */
1756#if __FreeBSD_version < 400000
1757 error = suser (p->p_ucred, &p->p_acflag);
1758#elif __FreeBSD_version < 500000
1759 error = suser (p);
1760#else
1761 error = suser (td);
1762#endif
1763 if (error)
1764 return error;
1765 s = splimp ();
1766 /* hard_reset (c->board); */
1767 splx (s);
1768 return 0;
1769#endif
1770
1771 case SERIAL_GETCABLE:
1772 CP_DEBUG2 (d, ("ioctl: getcable\n"));
1773 if (c->type != T_SERIAL)
1774 return EINVAL;
1775 s = splimp ();
1776 *(int*)data = cp_get_cable (c);
1777 splx (s);
1778 return 0;
1779
1780 case SERIAL_GETDIR:
1781 CP_DEBUG2 (d, ("ioctl: getdir\n"));
1782 if (c->type != T_E1 && c->type != T_DATA)
1783 return EINVAL;
1784 *(int*)data = c->dir;
1785 return 0;
1786
1787 case SERIAL_SETDIR:
1788 CP_DEBUG2 (d, ("ioctl: setdir\n"));
1789 /* Only for superuser! */
1790#if __FreeBSD_version < 400000
1791 error = suser (p->p_ucred, &p->p_acflag);
1792#elif __FreeBSD_version < 500000
1793 error = suser (p);
1794#else
1795 error = suser (td);
1796#endif
1797 if (error)
1798 return error;
1799 s = splimp ();
1800 cp_set_dir (c, *(int*)data);
1801 splx (s);
1802 return 0;
1803
1804 case SERIAL_GETRLOOP:
1805 CP_DEBUG2 (d, ("ioctl: getrloop\n"));
1806 if (c->type != T_G703 &&
1807 c->type != T_E3 &&
1808 c->type != T_T3 &&
1809 c->type != T_STS1)
1810 return EINVAL;
1811 *(int*)data = cp_get_rloop (c);
1812 return 0;
1813
1814 case SERIAL_SETRLOOP:
1815 CP_DEBUG2 (d, ("ioctl: setloop\n"));
1816 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1)
1817 return EINVAL;
1818 /* Only for superuser! */
1819#if __FreeBSD_version < 400000
1820 error = suser (p->p_ucred, &p->p_acflag);
1821#elif __FreeBSD_version < 500000
1822 error = suser (p);
1823#else
1824 error = suser (td);
1825#endif
1826 if (error)
1827 return error;
1828 s = splimp ();
1829 cp_set_rloop (c, *(int*)data);
1830 splx (s);
1831 return 0;
1832
1833 case SERIAL_GETCABLEN:
1834 CP_DEBUG2 (d, ("ioctl: getcablen\n"));
1835 if (c->type != T_T3 && c->type != T_STS1)
1836 return EINVAL;
1837 *(int*)data = c->cablen;
1838 return 0;
1839
1840 case SERIAL_SETCABLEN:
1841 CP_DEBUG2 (d, ("ioctl: setloop\n"));
1842 if (c->type != T_T3 && c->type != T_STS1)
1843 return EINVAL;
1844 /* Only for superuser! */
1845#if __FreeBSD_version < 400000
1846 error = suser (p->p_ucred, &p->p_acflag);
1847#elif __FreeBSD_version < 500000
1848 error = suser (p);
1849#else
1850 error = suser (td);
1851#endif
1852 if (error)
1853 return error;
1854 s = splimp ();
1855 cp_set_cablen (c, *(int*)data);
1856 splx (s);
1857 return 0;
1858
1859 case TIOCSDTR: /* Set DTR */
1860 s = splimp ();
1861 cp_set_dtr (c, 1);
1862 splx (s);
1863 return 0;
1864
1865 case TIOCCDTR: /* Clear DTR */
1866 s = splimp ();
1867 cp_set_dtr (c, 0);
1868 splx (s);
1869 return 0;
1870
1871 case TIOCMSET: /* Set DTR/RTS */
1872 s = splimp ();
1873 cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0);
1874 cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0);
1875 splx (s);
1876 return 0;
1877
1878 case TIOCMBIS: /* Add DTR/RTS */
1879 s = splimp ();
1880 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1);
1881 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1);
1882 splx (s);
1883 return 0;
1884
1885 case TIOCMBIC: /* Clear DTR/RTS */
1886 s = splimp ();
1887 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0);
1888 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0);
1889 splx (s);
1890 return 0;
1891
1892 case TIOCMGET: /* Get modem status */
1893 *(int*)data = cp_modem_status (c);
1894 return 0;
1895 }
1896 return ENOTTY;
1897}
1898
1899#if __FreeBSD_version < 400000
1900static struct cdevsw cp_cdevsw = {
1901 cp_open, cp_close, noread, nowrite,
1902 cp_ioctl, nullstop, nullreset, nodevtotty,
1903 seltrue, nommap, NULL, "cp",
1904 NULL, -1
1905 };
1906#elif __FreeBSD_version < 500000
1907static struct cdevsw cp_cdevsw = {
1908 cp_open, cp_close, noread, nowrite,
1909 cp_ioctl, nopoll, nommap, nostrategy,
1910 "cp", CDEV_MAJOR, nodump, nopsize,
1911 D_NAGGED, -1
1912 };
1913#elif __FreeBSD_version == 500000
1914static struct cdevsw cp_cdevsw = {
1915 cp_open, cp_close, noread, nowrite,
1916 cp_ioctl, nopoll, nommap, nostrategy,
1917 "cp", CDEV_MAJOR, nodump, nopsize,
1918 D_NAGGED,
1919 };
1920#elif __FreeBSD_version <= 501000
1921static struct cdevsw cp_cdevsw = {
1922 .d_open = cp_open,
1923 .d_close = cp_close,
1924 .d_read = noread,
1925 .d_write = nowrite,
1926 .d_ioctl = cp_ioctl,
1927 .d_poll = nopoll,
1928 .d_mmap = nommap,
1929 .d_strategy = nostrategy,
1930 .d_name = "cp",
1931 .d_maj = CDEV_MAJOR,
1932 .d_dump = nodump,
1933 .d_flags = D_NAGGED,
1934};
1935#elif __FreeBSD_version < 502103
1936static struct cdevsw cp_cdevsw = {
1937 .d_open = cp_open,
1938 .d_close = cp_close,
1939 .d_ioctl = cp_ioctl,
1940 .d_name = "cp",
1941 .d_maj = CDEV_MAJOR,
1942 .d_flags = D_NAGGED,
1943};
1944#else /* __FreeBSD_version >= 502103 */
1945static struct cdevsw cp_cdevsw = {
1946 .d_version = D_VERSION,
1947 .d_open = cp_open,
1948 .d_close = cp_close,
1949 .d_ioctl = cp_ioctl,
1950 .d_name = "cp",
1951 .d_maj = CDEV_MAJOR,
1952 .d_flags = D_NEEDGIANT,
1953};
1954#endif
1955
1956#ifdef NETGRAPH
1957#if __FreeBSD_version >= 500000
1958static int ng_cp_constructor (node_p node)
1959{
1960 drv_t *d = NG_NODE_PRIVATE (node);
1961#else
1962static int ng_cp_constructor (node_p *node)
1963{
1964 drv_t *d = (*node)->private;
1965#endif
1966 CP_DEBUG (d, ("Constructor\n"));
1967 return EINVAL;
1968}
1969
1970static int ng_cp_newhook (node_p node, hook_p hook, const char *name)
1971{
1972 int s;
1973#if __FreeBSD_version >= 500000
1974 drv_t *d = NG_NODE_PRIVATE (node);
1975#else
1976 drv_t *d = node->private;
1977#endif
1978
1979 CP_DEBUG (d, ("Newhook\n"));
1980 /* Attach debug hook */
1981 if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) {
1982#if __FreeBSD_version >= 500000
1983 NG_HOOK_SET_PRIVATE (hook, NULL);
1984#else
1985 hook->private = 0;
1986#endif
1987 d->debug_hook = hook;
1988 return 0;
1989 }
1990
1991 /* Check for raw hook */
1992 if (strcmp (name, NG_CP_HOOK_RAW) != 0)
1993 return EINVAL;
1994
1995#if __FreeBSD_version >= 500000
1996 NG_HOOK_SET_PRIVATE (hook, d);
1997#else
1998 hook->private = d;
1999#endif
2000 d->hook = hook;
2001 s = splimp ();
2002 cp_up (d);
2003 splx (s);
2004 return 0;
2005}
2006
2007static char *format_timeslots (u_long s)
2008{
2009 static char buf [100];
2010 char *p = buf;
2011 int i;
2012
2013 for (i=1; i<32; ++i)
2014 if ((s >> i) & 1) {
2015 int prev = (i > 1) & (s >> (i-1));
2016 int next = (i < 31) & (s >> (i+1));
2017
2018 if (prev) {
2019 if (next)
2020 continue;
2021 *p++ = '-';
2022 } else if (p > buf)
2023 *p++ = ',';
2024
2025 if (i >= 10)
2026 *p++ = '0' + i / 10;
2027 *p++ = '0' + i % 10;
2028 }
2029 *p = 0;
2030 return buf;
2031}
2032
2033static int print_modems (char *s, cp_chan_t *c, int need_header)
2034{
2035 int status = cp_modem_status (c);
2036 int length = 0;
2037
2038 if (need_header)
2039 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n");
2040 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n",
2041 status & TIOCM_LE ? "On" : "-",
2042 status & TIOCM_DTR ? "On" : "-",
2043 status & TIOCM_DSR ? "On" : "-",
2044 status & TIOCM_RTS ? "On" : "-",
2045 status & TIOCM_CTS ? "On" : "-",
2046 status & TIOCM_CD ? "On" : "-");
2047 return length;
2048}
2049
2050static int print_stats (char *s, cp_chan_t *c, int need_header)
2051{
2052 int length = 0;
2053
2054 if (need_header)
2055 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n");
2056 length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n",
2057 c->rintr, c->tintr, 0l, (unsigned long) c->ibytes,
2058 c->ipkts, c->overrun + c->frame + c->crc,
2059 (unsigned long) c->obytes, c->opkts, c->underrun);
2060 return length;
2061}
2062
2063static char *format_e1_status (u_char status)
2064{
2065 static char buf [80];
2066
2067 if (status & E1_NOALARM)
2068 return "Ok";
2069 buf[0] = 0;
2070 if (status & E1_LOS) strcat (buf, ",LOS");
2071 if (status & E1_AIS) strcat (buf, ",AIS");
2072 if (status & E1_LOF) strcat (buf, ",LOF");
2073 if (status & E1_LOMF) strcat (buf, ",LOMF");
2074 if (status & E1_FARLOF) strcat (buf, ",FARLOF");
2075 if (status & E1_AIS16) strcat (buf, ",AIS16");
2076 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF");
2077 if (status & E1_TSTREQ) strcat (buf, ",TSTREQ");
2078 if (status & E1_TSTERR) strcat (buf, ",TSTERR");
2079 if (buf[0] == ',')
2080 return buf+1;
2081 return "Unknown";
2082}
2083
2084static int print_frac (char *s, int leftalign, u_long numerator, u_long divider)
2085{
2086 int n, length = 0;
2087
2088 if (numerator < 1 || divider < 1) {
2089 length += sprintf (s+length, leftalign ? "/- " : " -");
2090 return length;
2091 }
2092 n = (int) (0.5 + 1000.0 * numerator / divider);
2093 if (n < 1000) {
2094 length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n);
2095 return length;
2096 }
2097 *(s + length) = leftalign ? '/' : ' ';
2098 length ++;
2099
2100 if (n >= 1000000) n = (n+500) / 1000 * 1000;
2101 else if (n >= 100000) n = (n+50) / 100 * 100;
2102 else if (n >= 10000) n = (n+5) / 10 * 10;
2103
2104 switch (n) {
2105 case 1000: length += printf (s+length, ".999"); return length;
2106 case 10000: n = 9990; break;
2107 case 100000: n = 99900; break;
2108 case 1000000: n = 999000; break;
2109 }
2110 if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100);
2111 else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10);
2112 else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000);
2113 else length += sprintf (s+length, "%d", n/1000);
2114
2115 return length;
2116}
2117
2118static int print_e1_stats (char *s, cp_chan_t *c)
2119{
2120 struct e1_counters total;
2121 u_long totsec;
2122 int length = 0;
2123
2124 totsec = c->totsec + c->cursec;
2125 total.bpv = c->total.bpv + c->currnt.bpv;
2126 total.fse = c->total.fse + c->currnt.fse;
2127 total.crce = c->total.crce + c->currnt.crce;
2128 total.rcrce = c->total.rcrce + c->currnt.rcrce;
2129 total.uas = c->total.uas + c->currnt.uas;
2130 total.les = c->total.les + c->currnt.les;
2131 total.es = c->total.es + c->currnt.es;
2132 total.bes = c->total.bes + c->currnt.bes;
2133 total.ses = c->total.ses + c->currnt.ses;
2134 total.oofs = c->total.oofs + c->currnt.oofs;
2135 total.css = c->total.css + c->currnt.css;
2136 total.dm = c->total.dm + c->currnt.dm;
2137
2138 length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n");
2139
2140 /* Unavailable seconds, degraded minutes */
2141 length += print_frac (s + length, 0, c->currnt.uas, c->cursec);
2142 length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec);
2143
2144 /* Bipolar violations, frame sync errors */
2145 length += print_frac (s + length, 0, c->currnt.bpv, c->cursec);
2146 length += print_frac (s + length, 1, c->currnt.fse, c->cursec);
2147
2148 /* CRC errors, remote CRC errors (E-bit) */
2149 length += print_frac (s + length, 0, c->currnt.crce, c->cursec);
2150 length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec);
2151
2152 /* Errored seconds, line errored seconds */
2153 length += print_frac (s + length, 0, c->currnt.es, c->cursec);
2154 length += print_frac (s + length, 1, c->currnt.les, c->cursec);
2155
2156 /* Severely errored seconds, burst errored seconds */
2157 length += print_frac (s + length, 0, c->currnt.ses, c->cursec);
2158 length += print_frac (s + length, 1, c->currnt.bes, c->cursec);
2159
2160 /* Out of frame seconds, controlled slip seconds */
2161 length += print_frac (s + length, 0, c->currnt.oofs, c->cursec);
2162 length += print_frac (s + length, 1, c->currnt.css, c->cursec);
2163
2164 length += sprintf (s + length, " %s\n", format_e1_status (c->status));
2165
2166 /* Print total statistics. */
2167 length += print_frac (s + length, 0, total.uas, totsec);
2168 length += print_frac (s + length, 1, 60 * total.dm, totsec);
2169
2170 length += print_frac (s + length, 0, total.bpv, totsec);
2171 length += print_frac (s + length, 1, total.fse, totsec);
2172
2173 length += print_frac (s + length, 0, total.crce, totsec);
2174 length += print_frac (s + length, 1, total.rcrce, totsec);
2175
2176 length += print_frac (s + length, 0, total.es, totsec);
2177 length += print_frac (s + length, 1, total.les, totsec);
2178
2179 length += print_frac (s + length, 0, total.ses, totsec);
2180 length += print_frac (s + length, 1, total.bes, totsec);
2181
2182 length += print_frac (s + length, 0, total.oofs, totsec);
2183 length += print_frac (s + length, 1, total.css, totsec);
2184
2185 length += sprintf (s + length, " -- Total\n");
2186 return length;
2187}
2188
2189static int print_chan (char *s, cp_chan_t *c)
2190{
2191 drv_t *d = c->sys;
2192 int length = 0;
2193
2194 length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num);
2195 if (d->chan->debug)
2196 length += sprintf (s + length, " debug=%d", d->chan->debug);
2197
2198 if (c->board->mux) {
2199 length += sprintf (s + length, " cfg=C");
2200 } else {
2201 length += sprintf (s + length, " cfg=A");
2202 }
2203
2204 if (c->baud)
2205 length += sprintf (s + length, " %ld", c->baud);
2206 else
2207 length += sprintf (s + length, " extclock");
2208
2209 if (c->type == T_E1 || c->type == T_G703)
2210 switch (c->gsyn) {
2211 case GSYN_INT : length += sprintf (s + length, " syn=int"); break;
2212 case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break;
2213 case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break;
2214 case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break;
2215 case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break;
2216 case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break;
2217 }
2218 if (c->type == T_SERIAL) {
2219 length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off");
2220 length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off");
2221 length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off");
2222 }
2223 if (c->type == T_E1)
2224 length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off");
2225
2226 length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off");
2227
2228 if (c->type == T_E1)
2229 length += sprintf (s + length, " ts=%s", format_timeslots (c->ts));
2230 if (c->type == T_G703) {
2231 int lq, x;
2232
2233 x = splimp ();
2234 lq = cp_get_lq (c);
2235 splx (x);
2236 length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0);
2237 }
2238 length += sprintf (s + length, "\n");
2239 return length;
2240}
2241
2242#if __FreeBSD_version >= 500000
2243static int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook)
2244{
2245 drv_t *d = NG_NODE_PRIVATE (node);
2246 struct ng_mesg *msg;
2247#else
2248static int ng_cp_rcvmsg (node_p node, struct ng_mesg *msg,
2249 const char *retaddr, struct ng_mesg **rptr)
2250{
2251 drv_t *d = node->private;
2252#endif
2253 struct ng_mesg *resp = NULL;
2254 int error = 0;
2255
2256 CP_DEBUG (d, ("Rcvmsg\n"));
2257#if __FreeBSD_version >= 500000
2258 NGI_GET_MSG (item, msg);
2259#endif
2260 switch (msg->header.typecookie) {
2261 default:
2262 error = EINVAL;
2263 break;
2264
2265 case NGM_CP_COOKIE:
2266 printf ("Not implemented yet\n");
2267 error = EINVAL;
2268 break;
2269
2270 case NGM_GENERIC_COOKIE:
2271 switch (msg->header.cmd) {
2272 default:
2273 error = EINVAL;
2274 break;
2275
2276 case NGM_TEXT_STATUS: {
2277 char *s;
2278 int l = 0;
2279 int dl = sizeof (struct ng_mesg) + 730;
2280
2281#if __FreeBSD_version >= 500000
2282 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT);
2283 if (! resp) {
2284 error = ENOMEM;
2285 break;
2286 }
2287#else
2288 MALLOC (resp, struct ng_mesg *, dl,
2289 M_NETGRAPH, M_NOWAIT);
2290 if (! resp) {
2291 error = ENOMEM;
2292 break;
2293 }
2294 bzero (resp, dl);
2295#endif
2296 s = (resp)->data;
2297 if (d) {
2298 l += print_chan (s + l, d->chan);
2299 l += print_stats (s + l, d->chan, 1);
2300 l += print_modems (s + l, d->chan, 1);
2301 l += print_e1_stats (s + l, d->chan);
2302 } else
2303 l += sprintf (s + l, "Error: node not connect to channel");
2304#if __FreeBSD_version < 500000
2305 (resp)->header.version = NG_VERSION;
2306 (resp)->header.arglen = strlen (s) + 1;
2307 (resp)->header.token = msg->header.token;
2308 (resp)->header.typecookie = NGM_CP_COOKIE;
2309 (resp)->header.cmd = msg->header.cmd;
2310#endif
2311 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN);
2312 }
2313 break;
2314 }
2315 break;
2316 }
2317#if __FreeBSD_version >= 500000
2318 NG_RESPOND_MSG (error, node, item, resp);
2319 NG_FREE_MSG (msg);
2320#else
2321 *rptr = resp;
2322 FREE (msg, M_NETGRAPH);
2323#endif
2324 return error;
2325}
2326
2327#if __FreeBSD_version >= 500000
2328static int ng_cp_rcvdata (hook_p hook, item_p item)
2329{
2330 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook));
2331 struct mbuf *m;
2332 meta_p meta;
2333#else
2334static int ng_cp_rcvdata (hook_p hook, struct mbuf *m, meta_p meta)
2335{
2336 drv_t *d = hook->node->private;
2337#endif
2338 struct ifqueue *q;
2339 int s;
2340
2341 CP_DEBUG2 (d, ("Rcvdata\n"));
2342#if __FreeBSD_version >= 500000
2343 NGI_GET_M (item, m);
2344 NGI_GET_META (item, meta);
2345 NG_FREE_ITEM (item);
2346 if (! NG_HOOK_PRIVATE (hook) || ! d) {
2347 NG_FREE_M (m);
2348 NG_FREE_META (meta);
2349#else
2350 if (! hook->private || ! d) {
2351 NG_FREE_DATA (m,meta);
2352#endif
2353 return ENETDOWN;
2354 }
2355 q = (meta && meta->priority > 0) ? &d->hi_queue : &d->queue;
2356 s = splimp ();
2357#if __FreeBSD_version >= 500000
2358 IF_LOCK (q);
2359 if (_IF_QFULL (q)) {
2360 _IF_DROP (q);
2361 IF_UNLOCK (q);
2362 splx (s);
2363 NG_FREE_M (m);
2364 NG_FREE_META (meta);
2365 return ENOBUFS;
2366 }
2367 _IF_ENQUEUE (q, m);
2368 IF_UNLOCK (q);
2369#else
2370 if (IF_QFULL (q)) {
2371 IF_DROP (q);
2372 splx (s);
2373 NG_FREE_DATA (m, meta);
2374 return ENOBUFS;
2375 }
2376 IF_ENQUEUE (q, m);
2377#endif
2378 cp_start (d);
2379 splx (s);
2380 return 0;
2381}
2382
2383static int ng_cp_rmnode (node_p node)
2384{
2385#if __FreeBSD_version >= 500000
2386 drv_t *d = NG_NODE_PRIVATE (node);
2387
2388 CP_DEBUG (d, ("Rmnode\n"));
2389 if (d && d->running) {
2390 int s = splimp ();
2391 cp_down (d);
2392 splx (s);
2393 }
2394#ifdef KLD_MODULE
2395 if (node->nd_flags & NG_REALLY_DIE) {
2396 NG_NODE_SET_PRIVATE (node, NULL);
2397 NG_NODE_UNREF (node);
2398 }
2399 node->nd_flags &= ~NG_INVALID;
2400#endif
2401#else /* __FreeBSD_version < 500000 */
2402 drv_t *d = node->private;
2403
2404 if (d && d->running) {
2405 int s = splimp ();
2406 cp_down (d);
2407 splx (s);
2408 }
2409
2410 node->flags |= NG_INVALID;
2411 ng_cutlinks (node);
2412#ifdef KLD_MODULE
2413#if __FreeBSD_version >= 400000
2414 /* We do so because of pci module problem, see also comment in
2415 cp_unload. Not in 4.x. */
2416 ng_unname (node);
2417 ng_unref (node);
2418#else
2419 node->flags &= ~NG_INVALID;
2420#endif
2421#endif
2422#endif
2423 return 0;
2424}
2425
2426static void ng_cp_watchdog (void *arg)
2427{
2428 drv_t *d = arg;
2429
2430 if (d) {
2431 if (d->timeout == 1)
2432 cp_watchdog (d);
2433 if (d->timeout)
2434 d->timeout--;
2435 d->timeout_handle = timeout (ng_cp_watchdog, d, hz);
2436 }
2437}
2438
2439static int ng_cp_connect (hook_p hook)
2440{
2441#if __FreeBSD_version >= 500000
2442 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook));
2443#else
2444 drv_t *d = hook->node->private;
2445#endif
2446
2447 if (d) {
2448 CP_DEBUG (d, ("Connect\n"));
2449 d->timeout_handle = timeout (ng_cp_watchdog, d, hz);
2450 }
2451
2452 return 0;
2453}
2454
2455static int ng_cp_disconnect (hook_p hook)
2456{
2457#if __FreeBSD_version >= 500000
2458 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook));
2459#else
2460 drv_t *d = hook->node->private;
2461#endif
2462
2463 if (d) {
2464 CP_DEBUG (d, ("Disconnect\n"));
2465#if __FreeBSD_version >= 500000
2466 if (NG_HOOK_PRIVATE (hook))
2467#else
2468 if (hook->private)
2469#endif
2470 {
2471 int s = splimp ();
2472 cp_down (d);
2473 splx (s);
2474 }
2475 untimeout (ng_cp_watchdog, d, d->timeout_handle);
2476 }
2477 return 0;
2478}
2479#endif
2480
2481#if __FreeBSD_version < 400000
2482
2483#ifdef KLD_MODULE
2484extern STAILQ_HEAD(devlist, pci_devinfo) pci_devq;
2485
2486static
2487struct pci_devinfo *pci_device_find (u_int16_t device, u_int16_t vendor, int unit)
2488{
2489 pcicfgregs *cfg;
2490 struct pci_devinfo *dinfo;
2491 int u=0,i;
2492
2493 for (dinfo = STAILQ_FIRST (&pci_devq), i=0;
2494 dinfo && (i < pci_numdevs);
2495 dinfo = STAILQ_NEXT (dinfo, pci_links), i++) {
2496 cfg = &dinfo->cfg;
2497 if ((device == cfg->device) && (vendor == cfg->vendor)) {
2498 if (u == unit)
2499 return dinfo;
2500 u++;
2501 }
2502 }
2503 return 0;
2504}
2505
2506/*
2507 * Function called when loading the driver.
2508 */
2509static int cp_load (void)
2510{
2511 int i, s;
2512 pcicfgregs *cfg;
2513 struct pci_devinfo *dinfo;
2514
2515 s = splimp ();
2516 for (i=0; i<NBRD; ++i) {
2517 dinfo = pci_device_find (cp_device_id, cp_vendor_id, i);
2518 if (! dinfo)
2519 break;
2520
2521 cfg = &dinfo->cfg;
2522 cp_attach (cfg, i);
2523 dinfo->device = &cp_driver;
2524 strncpy (dinfo->conf.pd_name, cp_driver.pd_name,
2525 sizeof(dinfo->conf.pd_name));
2526 dinfo->conf.pd_name[sizeof(dinfo->conf.pd_name) - 1] = 0;
2527 dinfo->conf.pd_unit = i;
2528 }
2529 splx (s);
2530 if (! i) {
2531 /* Deactivate the timeout routine. */
2532 untimeout (cp_timeout, 0, timeout_handle);
2533 return ENXIO;
2534 }
2535 return 0;
2536}
2537
2538/*
2539 * Function called when unloading the driver.
2540 */
2541static int cp_unload (void)
2542{
2543#if 1
2544 /* Currently pci loadable module not fully supported, so we just
2545 return EBUSY. Do not forget to correct ng_cp_rmnode then probelm
2546 would be solved. */
2547 return EBUSY;
2548#else
2549 int i, s;
2550
2551 /* Check if the device is busy (open). */
2552 for (i=0; i<NBRD*NCHAN; ++i) {
2553 drv_t *d = channel[i];
2554
2555 if (d && d->chan->type && d->running)
2556 return EBUSY;
2557 }
2558
2559 s = splimp ();
2560
2561 /* Deactivate the timeout routine. */
2562 untimeout (cp_timeout, 0, timeout_handle);
2563
2564 /* OK to unload the driver, unregister the interrupt first. */
2565 for (i=0; i<NBRD; ++i) {
2566 cp_board_t *b = adapter [i];
2567
2568 if (!b || ! b->type)
2569 continue;
2570
2571 cp_reset (b, 0 ,0);
2572/* pci_unmap_int (tag, cp_intr, b, &net_imask);*/
2573 /* Here should be something like pci_unmap_mem ()*/
2574 }
2575
2576 for (i=0; i<NBRD; i++)
2577 if (led_timo[i].callout)
2578 untimeout (cp_led_off, adapter + i, led_timo[i]);
2579
2580 /* Detach the interfaces, free buffer memory. */
2581 for (i=0; i<NBRD*NCHAN; ++i) {
2582 drv_t *d = channel[i];
2583
2584 if (! d)
2585 continue;
2586#ifndef NETGRAPH
2587#if __FreeBSD_version >= 400000 || NBPFILTER > 0
2588 /* Detach from the packet filter list of interfaces. */
2589 {
2590 struct bpf_if *q, **b = &bpf_iflist;
2591
2592 while ((q = *b)) {
2593 if (q->bif_ifp == d->pp.pp_if) {
2594 *b = q->bif_next;
2595 free (q, M_DEVBUF);
2596 }
2597 b = &(q->bif_next);
2598 }
2599 }
2600#endif
2601 /* Detach from the sync PPP list. */
2602 sppp_detach (&d->pp.pp_if);
2603
2604 /* Detach from the system list of interfaces. */
2605 {
2606 struct ifaddr *ifa;
2607 TAILQ_FOREACH (ifa, &d->pp.pp_if.if_addrhead, ifa_link) {
2608 TAILQ_REMOVE (&d->pp.pp_if.if_addrhead, ifa, ifa_link);
2609 free (ifa, M_IFADDR);
2610 }
2611 TAILQ_REMOVE (&ifnet, &d->pp.pp_if, if_link);
2612 }
2613#endif
2614 /* Deallocate buffers. */
2615/* free (d, M_DEVBUF);*/
2616 }
2617
2618 for (i=0; i<NBRD; ++i) {
2619 cp_board_t *b = adapter + i;
2620
2621 if (b && b->type)
2622 free (b, M_DEVBUF);
2623 }
2624 splx (s);
2625 return 0;
2626#endif
2627}
2628#endif
2629#endif
2630
2631#if __FreeBSD_version < 400000
2632#ifdef KLD_MODULE
2633static int cp_modevent (module_t mod, int type, void *unused)
2634{
2635 dev_t dev;
2636
2637 switch (type) {
2638 case MOD_LOAD:
2639 dev = makedev (CDEV_MAJOR, 0);
2640 cdevsw_add (&dev, &cp_cdevsw, 0);
2641 timeout_handle = timeout (cp_timeout, 0, hz*5);
2642 return cp_load ();
2643 case MOD_UNLOAD:
2644 return cp_unload ();
2645 case MOD_SHUTDOWN:
2646 break;
2647 }
2648 return 0;
2649}
2650#endif /* KLD_MODULE */
2651
2652#else /* __FreeBSD_version >= 400000 */
2653static int cp_modevent (module_t mod, int type, void *unused)
2654{
2655 struct cdev *dev;
2656 static int load_count = 0;
2657 struct cdevsw *cdsw;
2658
2659#if __FreeBSD_version >= 502103
2660 dev = udev2dev (makeudev(CDEV_MAJOR, 0));
2661#else
2662 dev = makedev (CDEV_MAJOR, 0);
2663#endif
2664 switch (type) {
2665 case MOD_LOAD:
2666 if (dev != NODEV &&
2667 (cdsw = devsw (dev)) &&
2668 cdsw->d_maj == CDEV_MAJOR) {
2669 printf ("Tau-PCI driver is already in system\n");
2670 return (ENXIO);
2671 }
2672#if __FreeBSD_version >= 500000 && defined NETGRAPH
2673 if (ng_newtype (&typestruct))
2674 printf ("Failed to register ng_cp\n");
2675#endif
2676 ++load_count;
2677#if __FreeBSD_version <= 500000
2678 cdevsw_add (&cp_cdevsw);
2679#endif
2680 timeout_handle = timeout (cp_timeout, 0, hz*5);
2681 break;
2682 case MOD_UNLOAD:
2683 if (load_count == 1) {
2684 printf ("Removing device entry for Tau-PCI\n");
2685#if __FreeBSD_version <= 500000
2686 cdevsw_remove (&cp_cdevsw);
2687#endif
2688#if __FreeBSD_version >= 500000 && defined NETGRAPH
2689 ng_rmtype (&typestruct);
2690#endif
2691 }
2692 untimeout (cp_timeout, 0, timeout_handle);
2693 --load_count;
2694 break;
2695 case MOD_SHUTDOWN:
2696 break;
2697 }
2698 return 0;
2699}
2700#endif /* __FreeBSD_version < 400000 */
2701
2702#ifdef NETGRAPH
2703static struct ng_type typestruct = {
2704 .version = NG_ABI_VERSION,
2705 .name = NG_CP_NODE_TYPE,
2706 .constructor = ng_cp_constructor,
2707 .rcvmsg = ng_cp_rcvmsg,
2708 .shutdown = ng_cp_rmnode,
2709 .newhook = ng_cp_newhook,
2710 .connect = ng_cp_connect,
2711 .rcvdata = ng_cp_rcvdata,
2712 .disconnect = ng_cp_disconnect,
2713};
2714#if __FreeBSD_version < 400000
2715NETGRAPH_INIT_ORDERED (cp, &typestruct, SI_SUB_DRIVERS,\
2716 SI_ORDER_MIDDLE + CDEV_MAJOR);
2717#endif
2718#endif /*NETGRAPH*/
2719
2720#if __FreeBSD_version >= 500000
2721#ifdef NETGRAPH
2722MODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
2723#else
2724MODULE_DEPEND (cp, sppp, 1, 1, 1);
2725#endif
2726#ifdef KLD_MODULE
2727DRIVER_MODULE (cpmod, pci, cp_driver, cp_devclass, cp_modevent, NULL);
2728#else
2729DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL);
2730#endif
2731#elif __FreeBSD_version >= 400000
2732#ifdef NETGRAPH
2733DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, ng_mod_event, &typestruct);
2734#else
2735DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL);
2736#endif
2737#else /* __FreeBSD_version < 400000 */
2738#ifdef KLD_MODULE
2739#ifndef NETGRAPH
2740static moduledata_t cpmod = { "cp", cp_modevent, NULL};
2741DECLARE_MODULE (cp, cpmod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR);
2742#endif
2743#else /* KLD_MODULE */
2744
2745/*
2746 * Now for some driver initialisation.
2747 * Occurs ONCE during boot (very early).
2748 * This is if we are NOT a loadable module.
2749 */
2750static void cp_drvinit (void *unused)
2751{
2752 dev_t dev;
2753
2754 dev = makedev (CDEV_MAJOR, 0);
2755 cdevsw_add (&dev, &cp_cdevsw, 0);
2756
2757 /* Activate the timeout routine. */
2758 timeout_handle = timeout (cp_timeout, 0, hz);
2759#ifdef NETGRAPH
2760#if 0
2761 /* Register our node type in netgraph */
2762 if (ng_newtype (&typestruct))
2763 printf ("Failed to register ng_cp\n");
2764#endif
2765#endif
2766}
2767
2768SYSINIT (cpdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, cp_drvinit, 0)
2769#endif /* KLD_MODULE */
2770#endif /* __FreeBSD_version < 400000 */
2771#endif /* NPCI */
2 * Cronyx-Tau-PCI adapter driver for FreeBSD.
3 * Supports PPP/HDLC, Cisco/HDLC and FrameRelay protocol in synchronous mode,
4 * and asyncronous channels with full modem control.
5 * Keepalive protocol implemented in both Cisco and PPP modes.
6 *
7 * Copyright (C) 1999-2004 Cronyx Engineering.
8 * Author: Kurakin Roman, <rik@cronyx.ru>
9 *
10 * Copyright (C) 1999-2002 Cronyx Engineering.
11 * Author: Serge Vakulenko, <vak@cronyx.ru>
12 *
13 * This software is distributed with NO WARRANTIES, not even the implied
14 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * Authors grant any other persons or organisations a permission to use,
17 * modify and redistribute this software in source and binary forms,
18 * as long as this message is kept with the software, all derivative
19 * works or modified versions.
20 *
21 * $Cronyx: if_cp.c,v 1.1.2.32 2004/02/26 17:56:39 rik Exp $
22 */
23
24#include <sys/cdefs.h>
25__FBSDID("$FreeBSD: head/sys/dev/cp/if_cp.c 130585 2004-06-16 09:47:26Z phk $");
26
27#include <sys/param.h>
28
29#if __FreeBSD_version >= 500000
30# define NPCI 1
31#else
32# include "pci.h"
33#endif
34
35#if NPCI > 0
36
37#include <sys/ucred.h>
38#include <sys/proc.h>
39#include <sys/systm.h>
40#include <sys/mbuf.h>
41#include <sys/kernel.h>
42#include <sys/module.h>
43#include <sys/conf.h>
44#include <sys/malloc.h>
45#include <sys/socket.h>
46#include <sys/sockio.h>
47#include <sys/tty.h>
48#if __FreeBSD_version >= 400000
49# include <sys/bus.h>
50#endif
51#include <vm/vm.h>
52#include <vm/pmap.h>
53#include <net/if.h>
54#if __FreeBSD_version > 501000
55# include <dev/pci/pcivar.h>
56# include <dev/pci/pcireg.h>
57#else
58# include <pci/pcivar.h>
59# include <pci/pcireg.h>
60#endif
61#include <machine/bus.h>
62#include <sys/rman.h>
63#include "opt_ng_cronyx.h"
64#ifdef NETGRAPH_CRONYX
65# include "opt_netgraph.h"
66# ifndef NETGRAPH
67# error #option NETGRAPH missed from configuration
68# endif
69# include <netgraph/ng_message.h>
70# include <netgraph/netgraph.h>
71# if __FreeBSD_version >= 500000
72# include <dev/cp/ng_cp.h>
73# else
74# include <netgraph/ng_cp.h>
75# endif
76#else
77# include <net/if_sppp.h>
78# define PP_CISCO IFF_LINK2
79# if __FreeBSD_version < 400000
80# include <bpfilter.h>
81# if NBPFILTER > 0
82# include <net/bpf.h>
83# endif
84# else
85# if __FreeBSD_version < 500000
86# include <bpf.h>
87# endif
88# include <net/bpf.h>
89# define NBPFILTER NBPF
90#endif
91#endif
92#if __FreeBSD_version >= 500000
93#include <dev/cx/machdep.h>
94#include <dev/cp/cpddk.h>
95#else
96#include <i386/isa/cronyx/machdep.h>
97#include <pci/cpddk.h>
98#endif
99#include <machine/cserial.h>
100#include <machine/resource.h>
101#include <machine/pmap.h>
102
103/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */
104#ifndef PP_FR
105#define PP_FR 0
106#endif
107
108#define CP_DEBUG(d,s) ({if (d->chan->debug) {\
109 printf ("%s: ", d->name); printf s;}})
110#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\
111 printf ("%s: ", d->name); printf s;}})
112
113#define CDEV_MAJOR 134
114
115#if __FreeBSD_version >= 400000
116static int cp_probe __P((device_t));
117static int cp_attach __P((device_t));
118static int cp_detach __P((device_t));
119
120static device_method_t cp_methods[] = {
121 /* Device interface */
122 DEVMETHOD(device_probe, cp_probe),
123 DEVMETHOD(device_attach, cp_attach),
124 DEVMETHOD(device_detach, cp_detach),
125
126 {0, 0}
127};
128
129typedef struct _bdrv_t {
130 cp_board_t *board;
131 struct resource *cp_res;
132 struct resource *cp_irq;
133 void *cp_intrhand;
134} bdrv_t;
135
136static driver_t cp_driver = {
137 "cp",
138 cp_methods,
139 sizeof(bdrv_t),
140};
141
142static devclass_t cp_devclass;
143#endif
144
145typedef struct _drv_t {
146 char name [8];
147 cp_chan_t *chan;
148 cp_board_t *board;
149 cp_buf_t buf;
150 int running;
151#ifdef NETGRAPH
152 char nodename [NG_NODELEN+1];
153 hook_p hook;
154 hook_p debug_hook;
155 node_p node;
156 struct ifqueue queue;
157 struct ifqueue hi_queue;
158 short timeout;
159 struct callout_handle timeout_handle;
160#else
161 struct sppp pp;
162#endif
163#if __FreeBSD_version >= 400000
164 struct cdev *devt;
165#endif
166} drv_t;
167
168static void cp_receive (cp_chan_t *c, unsigned char *data, int len);
169static void cp_transmit (cp_chan_t *c, void *attachment, int len);
170static void cp_error (cp_chan_t *c, int data);
171static void cp_up (drv_t *d);
172static void cp_start (drv_t *d);
173static void cp_down (drv_t *d);
174static void cp_watchdog (drv_t *d);
175#ifdef NETGRAPH
176extern struct ng_type typestruct;
177#else
178static void cp_ifstart (struct ifnet *ifp);
179static void cp_tlf (struct sppp *sp);
180static void cp_tls (struct sppp *sp);
181static void cp_ifwatchdog (struct ifnet *ifp);
182static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data);
183static void cp_initialize (void *softc);
184#endif
185
186static cp_board_t *adapter [NBRD];
187static drv_t *channel [NBRD*NCHAN];
188static cp_qbuf_t *queue [NBRD];
189static struct callout_handle led_timo [NBRD];
190static struct callout_handle timeout_handle;
191
192static int cp_destroy = 0;
193
194/*
195 * Print the mbuf chain, for debug purposes only.
196 */
197static void printmbuf (struct mbuf *m)
198{
199 printf ("mbuf:");
200 for (; m; m=m->m_next) {
201 if (m->m_flags & M_PKTHDR)
202 printf (" HDR %d:", m->m_pkthdr.len);
203 if (m->m_flags & M_EXT)
204 printf (" EXT:");
205 printf (" %d", m->m_len);
206 }
207 printf ("\n");
208}
209
210/*
211 * Make an mbuf from data.
212 */
213static struct mbuf *makembuf (void *buf, unsigned len)
214{
215 struct mbuf *m;
216
217 MGETHDR (m, M_DONTWAIT, MT_DATA);
218 if (! m)
219 return 0;
220 MCLGET (m, M_DONTWAIT);
221 if (! (m->m_flags & M_EXT)) {
222 m_freem (m);
223 return 0;
224 }
225 m->m_pkthdr.len = m->m_len = len;
226 bcopy (buf, mtod (m, caddr_t), len);
227 return m;
228}
229
230#if __FreeBSD_version < 400000
231static const char *cp_probe (pcici_t tag, pcidi_t type)
232{
233 if (tag->vendor == cp_vendor_id && tag->device == cp_device_id)
234 return "Cronyx-Tau-PCI serial adapter";
235 return 0;
236}
237#else
238static int cp_probe (device_t dev)
239{
240 if ((pci_get_vendor (dev) == cp_vendor_id) &&
241 (pci_get_device (dev) == cp_device_id)) {
242 device_set_desc (dev, "Cronyx-Tau-PCI serial adapter");
243 return 0;
244 }
245 return ENXIO;
246}
247#endif
248
249static void cp_timeout (void *arg)
250{
251 drv_t *d;
252 int s, i;
253
254 for (i=0; i<NBRD*NCHAN; ++i) {
255 s = splimp ();
256 if (cp_destroy) {
257 splx (s);
258 return;
259 }
260 d = channel[i];
261 if (!d) {
262 splx (s);
263 continue;
264 }
265 switch (d->chan->type) {
266 case T_G703:
267 cp_g703_timer (d->chan);
268 break;
269 case T_E1:
270 cp_e1_timer (d->chan);
271 break;
272 case T_E3:
273 case T_T3:
274 case T_STS1:
275 cp_e3_timer (d->chan);
276 break;
277 default:
278 break;
279 }
280 splx (s);
281 }
282 s = splimp ();
283 if (!cp_destroy)
284 timeout_handle = timeout (cp_timeout, 0, hz);
285 splx (s);
286}
287
288static void cp_led_off (void *arg)
289{
290 cp_board_t *b = arg;
291 int s = splimp ();
292 if (cp_destroy) {
293 splx (s);
294 return;
295 }
296 cp_led (b, 0);
297 led_timo[b->num].callout = 0;
298 splx (s);
299}
300
301static void cp_intr (void *arg)
302{
303#if __FreeBSD_version < 400000
304 cp_board_t *b = arg;
305#else
306 bdrv_t *bd = arg;
307 cp_board_t *b = bd->board;
308#endif
309 int s = splimp ();
310 if (cp_destroy) {
311 splx (s);
312 return;
313 }
314 /* Turn LED on. */
315 cp_led (b, 1);
316
317 cp_interrupt (b);
318
319 /* Turn LED off 50 msec later. */
320 if (!led_timo[b->num].callout)
321 led_timo[b->num] = timeout (cp_led_off, b, hz/20);
322 splx (s);
323}
324
325extern struct cdevsw cp_cdevsw;
326
327/*
328 * Called if the probe succeeded.
329 */
330#if __FreeBSD_version < 400000
331static void cp_attach (pcici_t tag, int unit)
332{
333 vm_offset_t pbase;
334#else
335static int cp_attach (device_t dev)
336{
337 bdrv_t *bd = device_get_softc (dev);
338 int unit = device_get_unit (dev);
339 int rid, error;
340#endif
341 vm_offset_t vbase;
342 cp_board_t *b;
343 cp_chan_t *c;
344 drv_t *d;
345 unsigned short res;
346 int s = splimp ();
347
348 b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK);
349 if (!b) {
350 printf ("cp%d: couldn't allocate memory\n", unit);
351#if __FreeBSD_version < 400000
352 splx (s);
353 return;
354#else
355 splx (s);
356 return (ENXIO);
357#endif
358 }
359 adapter[unit] = b;
360 bzero (b, sizeof(cp_board_t));
361
362#if __FreeBSD_version < 400000
363 if (! pci_map_mem (tag, PCIR_MAPS, &vbase, &pbase)) {
364 printf ("cp%d: cannot map memory\n", unit);
365 free (b, M_DEVBUF);
366 splx (s);
367 return;
368 }
369#else
370 bd->board = b;
371 b->sys = bd;
372 rid = PCIR_BAR(0);
373 bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid,
374 0, ~0, 1, RF_ACTIVE);
375 if (! bd->cp_res) {
376 printf ("cp%d: cannot map memory\n", unit);
377 free (b, M_DEVBUF);
378 splx (s);
379 return (ENXIO);
380 }
381 vbase = (vm_offset_t) rman_get_virtual (bd->cp_res);
382#endif
383
384 res = cp_init (b, unit, (u_char*) vbase);
385 if (res) {
386 printf ("cp%d: can't init, error code:%x\n", unit, res);
387#if __FreeBSD_version >= 400000
388 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
389#endif
390 free (b, M_DEVBUF);
391 splx (s);
392#if __FreeBSD_version >= 400000
393 return (ENXIO);
394#else
395 return;
396#endif
397 }
398 queue[unit] = contigmalloc (sizeof(cp_qbuf_t), M_DEVBUF, M_WAITOK,
399 0x100000, 0xffffffff, 16, 0);
400 if (queue[unit] == NULL) {
401 printf ("cp%d: allocate memory for qbuf_t\n", unit);
402 free (b, M_DEVBUF);
403 splx (s);
404#if __FreeBSD_version >= 400000
405 return (ENXIO);
406#else
407 return;
408#endif
409 }
410 cp_reset (b, queue[unit], vtophys (queue[unit]));
411
412#if __FreeBSD_version < 400000
413 if (! pci_map_int (tag, cp_intr, b, &net_imask))
414 printf ("cp%d: cannot map interrupt\n", unit);
415#else
416 rid = 0;
417 bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
418 RF_SHAREABLE | RF_ACTIVE);
419 if (! bd->cp_irq) {
420 printf ("cp%d: cannot map interrupt\n", unit);
421 bus_release_resource (dev, SYS_RES_MEMORY,
422 PCIR_BAR(0), bd->cp_res);
423 free (b, M_DEVBUF);
424 splx (s);
425 return (ENXIO);
426 }
427 error = bus_setup_intr (dev, bd->cp_irq, INTR_TYPE_NET, cp_intr, bd,
428 &bd->cp_intrhand);
429 if (error) {
430 printf ("cp%d: cannot set up irq\n", unit);
431 bus_release_resource (dev, SYS_RES_MEMORY,
432 PCIR_BAR(0), bd->cp_res);
433 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
434 free (b, M_DEVBUF);
435 splx (s);
436 return (ENXIO);
437 }
438#endif
439 printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000);
440
441 for (c=b->chan; c<b->chan+NCHAN; ++c) {
442 if (! c->type)
443 continue;
444 d = contigmalloc (sizeof(drv_t), M_DEVBUF, M_WAITOK,
445 0x100000, 0xffffffff, 16, 0);
446 if (d == NULL) {
447 printf ("cp%d-%d: cannot allocate memory for drv_t\n",
448 unit, c->num);
449 }
450 channel [b->num*NCHAN + c->num] = d;
451 bzero (d, sizeof(drv_t));
452 sprintf (d->name, "cp%d.%d", b->num, c->num);
453 d->board = b;
454 d->chan = c;
455 c->sys = d;
456#ifdef NETGRAPH
457 if (ng_make_node_common (&typestruct, &d->node) != 0) {
458 printf ("%s: cannot make common node\n", d->name);
459 d->node = NULL;
460 continue;
461 }
462#if __FreeBSD_version >= 500000
463 NG_NODE_SET_PRIVATE (d->node, d);
464#else
465 d->node->private = d;
466#endif
467 sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE,
468 c->board->num*NCHAN + c->num);
469 if (ng_name_node (d->node, d->nodename)) {
470 printf ("%s: cannot name node\n", d->nodename);
471#if __FreeBSD_version >= 500000
472 NG_NODE_UNREF (d->node);
473#else
474 ng_rmnode (d->node);
475 ng_unref (d->node);
476#endif
477 continue;
478 }
479 d->queue.ifq_maxlen = IFQ_MAXLEN;
480 d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
481#if __FreeBSD_version >= 500000
482 mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF);
483 mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF);
484#endif
485#else /*NETGRAPH*/
486 d->pp.pp_if.if_softc = d;
487#if __FreeBSD_version > 501000
488 if_initname (&d->pp.pp_if, "cp", b->num * NCHAN + c->num);
489#else
490 d->pp.pp_if.if_unit = b->num * NCHAN + c->num;
491 d->pp.pp_if.if_name = "cp";
492#endif
493 d->pp.pp_if.if_mtu = PP_MTU;
494 d->pp.pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
495 d->pp.pp_if.if_ioctl = cp_sioctl;
496 d->pp.pp_if.if_start = cp_ifstart;
497 d->pp.pp_if.if_watchdog = cp_ifwatchdog;
498 d->pp.pp_if.if_init = cp_initialize;
499 sppp_attach (&d->pp.pp_if);
500 if_attach (&d->pp.pp_if);
501 d->pp.pp_tlf = cp_tlf;
502 d->pp.pp_tls = cp_tls;
503#if __FreeBSD_version >= 400000 || NBPFILTER > 0
504 /* If BPF is in the kernel, call the attach for it.
505 * The header size of PPP or Cisco/HDLC is 4 bytes. */
506 bpfattach (&d->pp.pp_if, DLT_PPP, 4);
507#endif
508#endif /*NETGRAPH*/
509 cp_start_e1 (c);
510 cp_start_chan (c, 1, 1, &d->buf, vtophys (&d->buf));
511
512 /* Register callback functions. */
513 cp_register_transmit (c, &cp_transmit);
514 cp_register_receive (c, &cp_receive);
515 cp_register_error (c, &cp_error);
516#if __FreeBSD_version >= 400000
517 d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT,
518 GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num);
519#endif
520 }
521 splx (s);
522#if __FreeBSD_version >= 400000
523 return 0;
524#endif
525}
526
527#if __FreeBSD_version >= 400000
528static int cp_detach (device_t dev)
529{
530 bdrv_t *bd = device_get_softc (dev);
531 cp_board_t *b = bd->board;
532 cp_chan_t *c;
533 int s = splimp ();
534
535 /* Check if the device is busy (open). */
536 for (c=b->chan; c<b->chan+NCHAN; ++c) {
537 drv_t *d = (drv_t*) c->sys;
538
539 if (! d || ! d->chan->type)
540 continue;
541 if (d->running) {
542 splx (s);
543 return EBUSY;
544 }
545 }
546
547 /* Ok, we can unload driver */
548 /* At first we should stop all channels */
549 for (c=b->chan; c<b->chan+NCHAN; ++c) {
550 drv_t *d = (drv_t*) c->sys;
551
552 if (! d || ! d->chan->type)
553 continue;
554
555 cp_stop_chan (c);
556 cp_stop_e1 (c);
557 cp_set_dtr (d->chan, 0);
558 cp_set_rts (d->chan, 0);
559 }
560
561 /* Reset the adapter. */
562 cp_destroy = 1;
563 cp_interrupt_poll (b, 1);
564 cp_led_off (b);
565 cp_reset (b, 0 ,0);
566 if (led_timo[b->num].callout)
567 untimeout (cp_led_off, b, led_timo[b->num]);
568
569 for (c=b->chan; c<b->chan+NCHAN; ++c) {
570 drv_t *d = (drv_t*) c->sys;
571
572 if (! d || ! d->chan->type)
573 continue;
574#ifndef NETGRAPH
575#if __FreeBSD_version >= 410000 && NBPFILTER > 0
576 /* Detach from the packet filter list of interfaces. */
577 bpfdetach (&d->pp.pp_if);
578#endif
579 /* Detach from the sync PPP list. */
580 sppp_detach (&d->pp.pp_if);
581
582 /* Detach from the system list of interfaces. */
583 if_detach (&d->pp.pp_if);
584#else
585#if __FreeBSD_version >= 500000
586 if (d->node) {
587 ng_rmnode_self (d->node);
588 NG_NODE_UNREF (d->node);
589 d->node = NULL;
590 }
591 mtx_destroy (&d->queue.ifq_mtx);
592 mtx_destroy (&d->hi_queue.ifq_mtx);
593#else
594 ng_rmnode (d->node);
595 d->node = 0;
596#endif
597#endif
598 destroy_dev (d->devt);
599 }
600
601 /* Disable the interrupt request. */
602 bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand);
603 bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
604 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
605 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
606 cp_led_off (b);
607 if (led_timo[b->num].callout)
608 untimeout (cp_led_off, b, led_timo[b->num]);
609 splx (s);
610
611 s = splimp ();
612 for (c=b->chan; c<b->chan+NCHAN; ++c) {
613 drv_t *d = (drv_t*) c->sys;
614
615 if (! d || ! d->chan->type)
616 continue;
617 channel [b->num*NCHAN + c->num] = 0;
618 /* Deallocate buffers. */
619#if __FreeBSD_version < 400000
620 free (d, M_DEVBUF);
621#else
622 contigfree (d, sizeof (*d), M_DEVBUF);
623#endif
624 }
625 adapter [b->num] = 0;
626#if __FreeBSD_version < 400000
627 free (queue[b->num], M_DEVBUF);
628#else
629 contigfree (queue[b->num], sizeof (cp_qbuf_t), M_DEVBUF);
630#endif
631 free (b, M_DEVBUF);
632 splx (s);
633 return 0;
634}
635#endif
636
637#if __FreeBSD_version < 400000
638static u_long cp_count;
639static struct pci_device cp_driver = {"cp", cp_probe, cp_attach, &cp_count, 0};
640DATA_SET (pcidevice_set, cp_driver);
641#endif
642
643#ifndef NETGRAPH
644static void cp_ifstart (struct ifnet *ifp)
645{
646 drv_t *d = ifp->if_softc;
647
648 cp_start (d);
649}
650
651static void cp_ifwatchdog (struct ifnet *ifp)
652{
653 drv_t *d = ifp->if_softc;
654
655 cp_watchdog (d);
656}
657
658static void cp_tlf (struct sppp *sp)
659{
660 drv_t *d = sp->pp_if.if_softc;
661
662 CP_DEBUG2 (d, ("cp_tlf\n"));
663/* cp_set_dtr (d->chan, 0);*/
664/* cp_set_rts (d->chan, 0);*/
665 sp->pp_down (sp);
666}
667
668static void cp_tls (struct sppp *sp)
669{
670 drv_t *d = sp->pp_if.if_softc;
671
672 CP_DEBUG2 (d, ("cp_tls\n"));
673 sp->pp_up (sp);
674}
675
676/*
677 * Process an ioctl request.
678 */
679static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
680{
681 drv_t *d = ifp->if_softc;
682 int error, s, was_up, should_be_up;
683
684 was_up = (ifp->if_flags & IFF_RUNNING) != 0;
685 error = sppp_ioctl (ifp, cmd, data);
686
687 if (error)
688 return error;
689
690 if (! (ifp->if_flags & IFF_DEBUG))
691 d->chan->debug = 0;
692 else if (! d->chan->debug)
693 d->chan->debug = 1;
694
695 switch (cmd) {
696 default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0;
697 case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0;
698 case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0;
699 case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break;
700 case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break;
701 }
702
703 /* We get here only in case of SIFFLAGS or SIFADDR. */
704 s = splimp ();
705 should_be_up = (ifp->if_flags & IFF_RUNNING) != 0;
706 if (! was_up && should_be_up) {
707 /* Interface goes up -- start it. */
708 cp_up (d);
709 cp_start (d);
710 } else if (was_up && ! should_be_up) {
711 /* Interface is going down -- stop it. */
712/* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/
713 cp_down (d);
714 }
715 CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd));
716 splx (s);
717 return 0;
718}
719
720/*
721 * Initialization of interface.
722 * It seems to be never called by upper level?
723 */
724static void cp_initialize (void *softc)
725{
726 drv_t *d = softc;
727
728 CP_DEBUG (d, ("cp_initialize\n"));
729}
730#endif /*NETGRAPH*/
731
732/*
733 * Stop the interface. Called on splimp().
734 */
735static void cp_down (drv_t *d)
736{
737 CP_DEBUG (d, ("cp_down\n"));
738 /* Interface is going down -- stop it. */
739 cp_set_dtr (d->chan, 0);
740 cp_set_rts (d->chan, 0);
741
742 d->running = 0;
743}
744
745/*
746 * Start the interface. Called on splimp().
747 */
748static void cp_up (drv_t *d)
749{
750 CP_DEBUG (d, ("cp_up\n"));
751 cp_set_dtr (d->chan, 1);
752 cp_set_rts (d->chan, 1);
753 d->running = 1;
754}
755
756/*
757 * Start output on the interface. Get another datagram to send
758 * off of the interface queue, and copy it to the interface
759 * before starting the output.
760 */
761static void cp_send (drv_t *d)
762{
763 struct mbuf *m;
764 u_short len;
765
766 CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te));
767
768 /* No output if the interface is down. */
769 if (! d->running)
770 return;
771
772 /* No output if the modem is off. */
773 if (! (d->chan->lloop || d->chan->type != T_SERIAL ||
774 cp_get_dsr (d->chan)))
775 return;
776
777 while (cp_transmit_space (d->chan)) {
778 /* Get the packet to send. */
779#ifdef NETGRAPH
780 IF_DEQUEUE (&d->hi_queue, m);
781 if (! m)
782 IF_DEQUEUE (&d->queue, m);
783#else
784 m = sppp_dequeue (&d->pp.pp_if);
785#endif
786 if (! m)
787 return;
788#if (__FreeBSD_version >= 400000 || NBPFILTER > 0) && !defined (NETGRAPH)
789 if (d->pp.pp_if.if_bpf)
790#if __FreeBSD_version >= 500000
791 BPF_MTAP (&d->pp.pp_if, m);
792#else
793 bpf_mtap (&d->pp.pp_if, m);
794#endif
795#endif
796 len = m->m_pkthdr.len;
797 if (len >= BUFSZ)
798 printf ("%s: too long packet: %d bytes: ",
799 d->name, len);
800 else if (! m->m_next)
801 cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0);
802 else {
803 u_char *buf = d->chan->tbuf[d->chan->te];
804 m_copydata (m, 0, len, buf);
805 cp_send_packet (d->chan, buf, len, 0);
806 }
807 m_freem (m);
808 /* Set up transmit timeout, if the transmit ring is not empty.*/
809#ifdef NETGRAPH
810 d->timeout = 10;
811#else
812 d->pp.pp_if.if_timer = 10;
813#endif
814 }
815#ifndef NETGRAPH
816 d->pp.pp_if.if_flags |= IFF_OACTIVE;
817#endif
818}
819
820/*
821 * Start output on the interface.
822 * Always called on splimp().
823 */
824static void cp_start (drv_t *d)
825{
826 if (d->running) {
827 if (! d->chan->dtr)
828 cp_set_dtr (d->chan, 1);
829 if (! d->chan->rts)
830 cp_set_rts (d->chan, 1);
831 cp_send (d);
832 }
833}
834
835/*
836 * Handle transmit timeouts.
837 * Recover after lost transmit interrupts.
838 * Always called on splimp().
839 */
840static void cp_watchdog (drv_t *d)
841{
842 CP_DEBUG (d, ("device timeout\n"));
843 if (d->running) {
844 int s = splimp ();
845
846 cp_stop_chan (d->chan);
847 cp_stop_e1 (d->chan);
848 cp_start_e1 (d->chan);
849 cp_start_chan (d->chan, 1, 1, 0, 0);
850 cp_set_dtr (d->chan, 1);
851 cp_set_rts (d->chan, 1);
852 cp_start (d);
853 splx (s);
854 }
855}
856
857static void cp_transmit (cp_chan_t *c, void *attachment, int len)
858{
859 drv_t *d = c->sys;
860
861#ifdef NETGRAPH
862 d->timeout = 0;
863#else
864 ++d->pp.pp_if.if_opackets;
865 d->pp.pp_if.if_flags &= ~IFF_OACTIVE;
866 d->pp.pp_if.if_timer = 0;
867#endif
868 cp_start (d);
869}
870
871static void cp_receive (cp_chan_t *c, unsigned char *data, int len)
872{
873 drv_t *d = c->sys;
874 struct mbuf *m;
875#if __FreeBSD_version >= 500000 && defined NETGRAPH
876 int error;
877#endif
878
879 if (! d->running)
880 return;
881
882 m = makembuf (data, len);
883 if (! m) {
884 CP_DEBUG (d, ("no memory for packet\n"));
885#ifndef NETGRAPH
886 ++d->pp.pp_if.if_iqdrops;
887#endif
888 return;
889 }
890 if (c->debug > 1)
891 printmbuf (m);
892#ifdef NETGRAPH
893 m->m_pkthdr.rcvif = 0;
894#if __FreeBSD_version >= 500000
895 NG_SEND_DATA_ONLY (error, d->hook, m);
896#else
897 ng_queue_data (d->hook, m, 0);
898#endif
899#else
900 ++d->pp.pp_if.if_ipackets;
901 m->m_pkthdr.rcvif = &d->pp.pp_if;
902#if __FreeBSD_version >= 400000 || NBPFILTER > 0
903 /* Check if there's a BPF listener on this interface.
904 * If so, hand off the raw packet to bpf. */
905 if (d->pp.pp_if.if_bpf)
906#if __FreeBSD_version >= 500000
907 BPF_TAP (&d->pp.pp_if, data, len);
908#else
909 bpf_tap (&d->pp.pp_if, data, len);
910#endif
911#endif
912 sppp_input (&d->pp.pp_if, m);
913#endif
914}
915
916static void cp_error (cp_chan_t *c, int data)
917{
918 drv_t *d = c->sys;
919
920 switch (data) {
921 case CP_FRAME:
922 CP_DEBUG (d, ("frame error\n"));
923#ifndef NETGRAPH
924 ++d->pp.pp_if.if_ierrors;
925#endif
926 break;
927 case CP_CRC:
928 CP_DEBUG (d, ("crc error\n"));
929#ifndef NETGRAPH
930 ++d->pp.pp_if.if_ierrors;
931#endif
932 break;
933 case CP_OVERRUN:
934 CP_DEBUG (d, ("overrun error\n"));
935#ifndef NETGRAPH
936 ++d->pp.pp_if.if_collisions;
937 ++d->pp.pp_if.if_ierrors;
938#endif
939 break;
940 case CP_OVERFLOW:
941 CP_DEBUG (d, ("overflow error\n"));
942#ifndef NETGRAPH
943 ++d->pp.pp_if.if_ierrors;
944#endif
945 break;
946 case CP_UNDERRUN:
947 CP_DEBUG (d, ("underrun error\n"));
948#ifdef NETGRAPH
949 d->timeout = 0;
950#else
951 ++d->pp.pp_if.if_oerrors;
952 d->pp.pp_if.if_flags &= ~IFF_OACTIVE;
953 d->pp.pp_if.if_timer = 0;
954#endif
955 cp_start (d);
956 break;
957 default:
958 CP_DEBUG (d, ("error #%d\n", data));
959 break;
960 }
961}
962
963/*
964 * You also need read, write, open, close routines.
965 * This should get you started
966 */
967#if __FreeBSD_version < 500000
968static int cp_open (dev_t dev, int oflags, int devtype, struct proc *p)
969#else
970static int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td)
971#endif
972{
973 int unit = minor (dev);
974 drv_t *d;
975
976 if (unit >= NBRD*NCHAN || ! (d = channel[unit]))
977 return ENXIO;
978 CP_DEBUG2 (d, ("cp_open\n"));
979 return 0;
980}
981
982/*
983 * Only called on the LAST close.
984 */
985#if __FreeBSD_version < 500000
986static int cp_close (dev_t dev, int fflag, int devtype, struct proc *p)
987#else
988static int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td)
989#endif
990{
991 drv_t *d = channel [minor (dev)];
992
993 CP_DEBUG2 (d, ("cp_close\n"));
994 return 0;
995}
996
997static int cp_modem_status (cp_chan_t *c)
998{
999 drv_t *d = c->sys;
1000 int status, s;
1001
1002 status = d->running ? TIOCM_LE : 0;
1003 s = splimp ();
1004 if (cp_get_cd (c)) status |= TIOCM_CD;
1005 if (cp_get_cts (c)) status |= TIOCM_CTS;
1006 if (cp_get_dsr (c)) status |= TIOCM_DSR;
1007 if (c->dtr) status |= TIOCM_DTR;
1008 if (c->rts) status |= TIOCM_RTS;
1009 splx (s);
1010 return status;
1011}
1012
1013#if __FreeBSD_version < 500000
1014static int cp_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
1015#else
1016static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
1017#endif
1018{
1019 drv_t *d = channel [minor (dev)];
1020 cp_chan_t *c = d->chan;
1021 struct serial_statistics *st;
1022 struct e1_statistics *opte1;
1023 struct e3_statistics *opte3;
1024 int error, s;
1025 char mask[16];
1026
1027 switch (cmd) {
1028 case SERIAL_GETREGISTERED:
1029 CP_DEBUG2 (d, ("ioctl: getregistered\n"));
1030 bzero (mask, sizeof(mask));
1031 for (s=0; s<NBRD*NCHAN; ++s)
1032 if (channel [s])
1033 mask [s/8] |= 1 << (s & 7);
1034 bcopy (mask, data, sizeof (mask));
1035 return 0;
1036
1037#ifndef NETGRAPH
1038 case SERIAL_GETPROTO:
1039 CP_DEBUG2 (d, ("ioctl: getproto\n"));
1040 strcpy ((char*)data, (d->pp.pp_flags & PP_FR) ? "fr" :
1041 (d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp");
1042 return 0;
1043
1044 case SERIAL_SETPROTO:
1045 CP_DEBUG2 (d, ("ioctl: setproto\n"));
1046 /* Only for superuser! */
1047#if __FreeBSD_version < 400000
1048 error = suser (p->p_ucred, &p->p_acflag);
1049#elif __FreeBSD_version < 500000
1050 error = suser (p);
1051#else /* __FreeBSD_version >= 500000 */
1052 error = suser (td);
1053#endif /* __FreeBSD_version >= 500000 */
1054 if (error)
1055 return error;
1056 if (d->pp.pp_if.if_flags & IFF_RUNNING)
1057 return EBUSY;
1058 if (! strcmp ("cisco", (char*)data)) {
1059 d->pp.pp_flags &= ~(PP_FR);
1060 d->pp.pp_flags |= PP_KEEPALIVE;
1061 d->pp.pp_if.if_flags |= PP_CISCO;
1062 } else if (! strcmp ("fr", (char*)data) && !PP_FR) {
1063 d->pp.pp_if.if_flags &= ~(PP_CISCO);
1064 d->pp.pp_flags |= PP_FR | PP_KEEPALIVE;
1065 } else if (! strcmp ("ppp", (char*)data)) {
1066 d->pp.pp_flags &= ~PP_FR;
1067 d->pp.pp_flags &= ~PP_KEEPALIVE;
1068 d->pp.pp_if.if_flags &= ~(PP_CISCO);
1069 } else
1070 return EINVAL;
1071 return 0;
1072
1073 case SERIAL_GETKEEPALIVE:
1074 CP_DEBUG2 (d, ("ioctl: getkeepalive\n"));
1075 if ((d->pp.pp_flags & PP_FR) ||
1076 (d->pp.pp_if.if_flags & PP_CISCO))
1077 return EINVAL;
1078 *(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0;
1079 return 0;
1080
1081 case SERIAL_SETKEEPALIVE:
1082 CP_DEBUG2 (d, ("ioctl: setkeepalive\n"));
1083 /* Only for superuser! */
1084#if __FreeBSD_version < 400000
1085 error = suser (p->p_ucred, &p->p_acflag);
1086#elif __FreeBSD_version < 500000
1087 error = suser (p);
1088#else
1089 error = suser (td);
1090#endif
1091 if (error)
1092 return error;
1093 if ((d->pp.pp_flags & PP_FR) ||
1094 (d->pp.pp_if.if_flags & PP_CISCO))
1095 return EINVAL;
1096 s = splimp ();
1097 if (*(int*)data)
1098 d->pp.pp_flags |= PP_KEEPALIVE;
1099 else
1100 d->pp.pp_flags &= ~PP_KEEPALIVE;
1101 splx (s);
1102 return 0;
1103#endif /*NETGRAPH*/
1104
1105 case SERIAL_GETMODE:
1106 CP_DEBUG2 (d, ("ioctl: getmode\n"));
1107 *(int*)data = SERIAL_HDLC;
1108 return 0;
1109
1110 case SERIAL_SETMODE:
1111 /* Only for superuser! */
1112#if __FreeBSD_version < 400000
1113 error = suser (p->p_ucred, &p->p_acflag);
1114#elif __FreeBSD_version < 500000
1115 error = suser (p);
1116#else
1117 error = suser (td);
1118#endif
1119 if (error)
1120 return error;
1121 if (*(int*)data != SERIAL_HDLC)
1122 return EINVAL;
1123 return 0;
1124
1125 case SERIAL_GETCFG:
1126 CP_DEBUG2 (d, ("ioctl: getcfg\n"));
1127 if (c->type != T_E1 || c->unfram)
1128 return EINVAL;
1129 *(char*)data = c->board->mux ? 'c' : 'a';
1130 return 0;
1131
1132 case SERIAL_SETCFG:
1133 CP_DEBUG2 (d, ("ioctl: setcfg\n"));
1134#if __FreeBSD_version < 400000
1135 error = suser (p->p_ucred, &p->p_acflag);
1136#elif __FreeBSD_version < 500000
1137 error = suser (p);
1138#else
1139 error = suser (td);
1140#endif
1141 if (error)
1142 return error;
1143 if (c->type != T_E1)
1144 return EINVAL;
1145 s = splimp ();
1146 cp_set_mux (c->board, *((char*)data) == 'c');
1147 splx (s);
1148 return 0;
1149
1150 case SERIAL_GETSTAT:
1151 CP_DEBUG2 (d, ("ioctl: getstat\n"));
1152 st = (struct serial_statistics*) data;
1153 st->rintr = c->rintr;
1154 st->tintr = c->tintr;
1155 st->mintr = 0;
1156 st->ibytes = c->ibytes;
1157 st->ipkts = c->ipkts;
1158 st->obytes = c->obytes;
1159 st->opkts = c->opkts;
1160 st->ierrs = c->overrun + c->frame + c->crc;
1161 st->oerrs = c->underrun;
1162 return 0;
1163
1164 case SERIAL_GETESTAT:
1165 CP_DEBUG2 (d, ("ioctl: getestat\n"));
1166 if (c->type != T_E1 && c->type != T_G703)
1167 return EINVAL;
1168 opte1 = (struct e1_statistics*) data;
1169 opte1->status = c->status;
1170 opte1->cursec = c->cursec;
1171 opte1->totsec = c->totsec + c->cursec;
1172
1173 opte1->currnt.bpv = c->currnt.bpv;
1174 opte1->currnt.fse = c->currnt.fse;
1175 opte1->currnt.crce = c->currnt.crce;
1176 opte1->currnt.rcrce = c->currnt.rcrce;
1177 opte1->currnt.uas = c->currnt.uas;
1178 opte1->currnt.les = c->currnt.les;
1179 opte1->currnt.es = c->currnt.es;
1180 opte1->currnt.bes = c->currnt.bes;
1181 opte1->currnt.ses = c->currnt.ses;
1182 opte1->currnt.oofs = c->currnt.oofs;
1183 opte1->currnt.css = c->currnt.css;
1184 opte1->currnt.dm = c->currnt.dm;
1185
1186 opte1->total.bpv = c->total.bpv + c->currnt.bpv;
1187 opte1->total.fse = c->total.fse + c->currnt.fse;
1188 opte1->total.crce = c->total.crce + c->currnt.crce;
1189 opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce;
1190 opte1->total.uas = c->total.uas + c->currnt.uas;
1191 opte1->total.les = c->total.les + c->currnt.les;
1192 opte1->total.es = c->total.es + c->currnt.es;
1193 opte1->total.bes = c->total.bes + c->currnt.bes;
1194 opte1->total.ses = c->total.ses + c->currnt.ses;
1195 opte1->total.oofs = c->total.oofs + c->currnt.oofs;
1196 opte1->total.css = c->total.css + c->currnt.css;
1197 opte1->total.dm = c->total.dm + c->currnt.dm;
1198 for (s=0; s<48; ++s) {
1199 opte1->interval[s].bpv = c->interval[s].bpv;
1200 opte1->interval[s].fse = c->interval[s].fse;
1201 opte1->interval[s].crce = c->interval[s].crce;
1202 opte1->interval[s].rcrce = c->interval[s].rcrce;
1203 opte1->interval[s].uas = c->interval[s].uas;
1204 opte1->interval[s].les = c->interval[s].les;
1205 opte1->interval[s].es = c->interval[s].es;
1206 opte1->interval[s].bes = c->interval[s].bes;
1207 opte1->interval[s].ses = c->interval[s].ses;
1208 opte1->interval[s].oofs = c->interval[s].oofs;
1209 opte1->interval[s].css = c->interval[s].css;
1210 opte1->interval[s].dm = c->interval[s].dm;
1211 }
1212 return 0;
1213
1214 case SERIAL_GETE3STAT:
1215 CP_DEBUG2 (d, ("ioctl: gete3stat\n"));
1216 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1)
1217 return EINVAL;
1218 opte3 = (struct e3_statistics*) data;
1219
1220 opte3->status = c->e3status;
1221 opte3->cursec = (c->e3csec_5 * 2 + 1) / 10;
1222 opte3->totsec = c->e3tsec + opte3->cursec;
1223
1224 opte3->ccv = c->e3ccv;
1225 opte3->tcv = c->e3tcv + opte3->ccv;
1226
1227 for (s = 0; s < 48; ++s) {
1228 opte3->icv[s] = c->e3icv[s];
1229 }
1230 return 0;
1231
1232 case SERIAL_CLRSTAT:
1233 CP_DEBUG2 (d, ("ioctl: clrstat\n"));
1234 /* Only for superuser! */
1235#if __FreeBSD_version < 400000
1236 error = suser (p->p_ucred, &p->p_acflag);
1237#elif __FreeBSD_version < 500000
1238 error = suser (p);
1239#else
1240 error = suser (td);
1241#endif
1242 if (error)
1243 return error;
1244 c->rintr = 0;
1245 c->tintr = 0;
1246 c->ibytes = 0;
1247 c->obytes = 0;
1248 c->ipkts = 0;
1249 c->opkts = 0;
1250 c->overrun = 0;
1251 c->frame = 0;
1252 c->crc = 0;
1253 c->underrun = 0;
1254 bzero (&c->currnt, sizeof (c->currnt));
1255 bzero (&c->total, sizeof (c->total));
1256 bzero (c->interval, sizeof (c->interval));
1257 c->e3ccv = 0;
1258 c->e3tcv = 0;
1259 bzero (c->e3icv, sizeof (c->e3icv));
1260 return 0;
1261
1262 case SERIAL_GETBAUD:
1263 CP_DEBUG2 (d, ("ioctl: getbaud\n"));
1264 *(long*)data = c->baud;
1265 return 0;
1266
1267 case SERIAL_SETBAUD:
1268 CP_DEBUG2 (d, ("ioctl: setbaud\n"));
1269 /* Only for superuser! */
1270#if __FreeBSD_version < 400000
1271 error = suser (p->p_ucred, &p->p_acflag);
1272#elif __FreeBSD_version < 500000
1273 error = suser (p);
1274#else
1275 error = suser (td);
1276#endif
1277 if (error)
1278 return error;
1279 s = splimp ();
1280 cp_set_baud (c, *(long*)data);
1281 splx (s);
1282 return 0;
1283
1284 case SERIAL_GETLOOP:
1285 CP_DEBUG2 (d, ("ioctl: getloop\n"));
1286 *(int*)data = c->lloop;
1287 return 0;
1288
1289 case SERIAL_SETLOOP:
1290 CP_DEBUG2 (d, ("ioctl: setloop\n"));
1291 /* Only for superuser! */
1292#if __FreeBSD_version < 400000
1293 error = suser (p->p_ucred, &p->p_acflag);
1294#elif __FreeBSD_version < 500000
1295 error = suser (p);
1296#else
1297 error = suser (td);
1298#endif
1299 if (error)
1300 return error;
1301 s = splimp ();
1302 cp_set_lloop (c, *(int*)data);
1303 splx (s);
1304 return 0;
1305
1306 case SERIAL_GETDPLL:
1307 CP_DEBUG2 (d, ("ioctl: getdpll\n"));
1308 if (c->type != T_SERIAL)
1309 return EINVAL;
1310 *(int*)data = c->dpll;
1311 return 0;
1312
1313 case SERIAL_SETDPLL:
1314 CP_DEBUG2 (d, ("ioctl: setdpll\n"));
1315 /* Only for superuser! */
1316#if __FreeBSD_version < 400000
1317 error = suser (p->p_ucred, &p->p_acflag);
1318#elif __FreeBSD_version < 500000
1319 error = suser (p);
1320#else
1321 error = suser (td);
1322#endif
1323 if (error)
1324 return error;
1325 if (c->type != T_SERIAL)
1326 return EINVAL;
1327 s = splimp ();
1328 cp_set_dpll (c, *(int*)data);
1329 splx (s);
1330 return 0;
1331
1332 case SERIAL_GETNRZI:
1333 CP_DEBUG2 (d, ("ioctl: getnrzi\n"));
1334 if (c->type != T_SERIAL)
1335 return EINVAL;
1336 *(int*)data = c->nrzi;
1337 return 0;
1338
1339 case SERIAL_SETNRZI:
1340 CP_DEBUG2 (d, ("ioctl: setnrzi\n"));
1341 /* Only for superuser! */
1342#if __FreeBSD_version < 400000
1343 error = suser (p->p_ucred, &p->p_acflag);
1344#elif __FreeBSD_version < 500000
1345 error = suser (p);
1346#else
1347 error = suser (td);
1348#endif
1349 if (error)
1350 return error;
1351 if (c->type != T_SERIAL)
1352 return EINVAL;
1353 s = splimp ();
1354 cp_set_nrzi (c, *(int*)data);
1355 splx (s);
1356 return 0;
1357
1358 case SERIAL_GETDEBUG:
1359 CP_DEBUG2 (d, ("ioctl: getdebug\n"));
1360 *(int*)data = d->chan->debug;
1361 return 0;
1362
1363 case SERIAL_SETDEBUG:
1364 CP_DEBUG2 (d, ("ioctl: setdebug\n"));
1365 /* Only for superuser! */
1366#if __FreeBSD_version < 400000
1367 error = suser (p->p_ucred, &p->p_acflag);
1368#elif __FreeBSD_version < 500000
1369 error = suser (p);
1370#else
1371 error = suser (td);
1372#endif
1373 if (error)
1374 return error;
1375 d->chan->debug = *(int*)data;
1376#ifndef NETGRAPH
1377 if (d->chan->debug)
1378 d->pp.pp_if.if_flags |= IFF_DEBUG;
1379 else
1380 d->pp.pp_if.if_flags &= ~IFF_DEBUG;
1381#endif
1382 return 0;
1383
1384 case SERIAL_GETHIGAIN:
1385 CP_DEBUG2 (d, ("ioctl: gethigain\n"));
1386 if (c->type != T_E1)
1387 return EINVAL;
1388 *(int*)data = c->higain;
1389 return 0;
1390
1391 case SERIAL_SETHIGAIN:
1392 CP_DEBUG2 (d, ("ioctl: sethigain\n"));
1393 /* Only for superuser! */
1394#if __FreeBSD_version < 400000
1395 error = suser (p->p_ucred, &p->p_acflag);
1396#elif __FreeBSD_version < 500000
1397 error = suser (p);
1398#else
1399 error = suser (td);
1400#endif
1401 if (error)
1402 return error;
1403 if (c->type != T_E1)
1404 return EINVAL;
1405 s = splimp ();
1406 cp_set_higain (c, *(int*)data);
1407 splx (s);
1408 return 0;
1409
1410 case SERIAL_GETPHONY:
1411 CP_DEBUG2 (d, ("ioctl: getphony\n"));
1412 if (c->type != T_E1)
1413 return EINVAL;
1414 *(int*)data = c->phony;
1415 return 0;
1416
1417 case SERIAL_SETPHONY:
1418 CP_DEBUG2 (d, ("ioctl: setphony\n"));
1419 /* Only for superuser! */
1420#if __FreeBSD_version < 400000
1421 error = suser (p->p_ucred, &p->p_acflag);
1422#elif __FreeBSD_version < 500000
1423 error = suser (p);
1424#else
1425 error = suser (td);
1426#endif
1427 if (error)
1428 return error;
1429 if (c->type != T_E1)
1430 return EINVAL;
1431 s = splimp ();
1432 cp_set_phony (c, *(int*)data);
1433 splx (s);
1434 return 0;
1435
1436 case SERIAL_GETUNFRAM:
1437 CP_DEBUG2 (d, ("ioctl: getunfram\n"));
1438 if (c->type != T_E1)
1439 return EINVAL;
1440 *(int*)data = c->unfram;
1441 return 0;
1442
1443 case SERIAL_SETUNFRAM:
1444 CP_DEBUG2 (d, ("ioctl: setunfram\n"));
1445 /* Only for superuser! */
1446#if __FreeBSD_version < 400000
1447 error = suser (p->p_ucred, &p->p_acflag);
1448#elif __FreeBSD_version < 500000
1449 error = suser (p);
1450#else
1451 error = suser (td);
1452#endif
1453 if (error)
1454 return error;
1455 if (c->type != T_E1)
1456 return EINVAL;
1457 s = splimp ();
1458 cp_set_unfram (c, *(int*)data);
1459 splx (s);
1460 return 0;
1461
1462 case SERIAL_GETSCRAMBLER:
1463 CP_DEBUG2 (d, ("ioctl: getscrambler\n"));
1464 if (c->type != T_G703 && !c->unfram)
1465 return EINVAL;
1466 *(int*)data = c->scrambler;
1467 return 0;
1468
1469 case SERIAL_SETSCRAMBLER:
1470 CP_DEBUG2 (d, ("ioctl: setscrambler\n"));
1471 /* Only for superuser! */
1472#if __FreeBSD_version < 400000
1473 error = suser (p->p_ucred, &p->p_acflag);
1474#elif __FreeBSD_version < 500000
1475 error = suser (p);
1476#else
1477 error = suser (td);
1478#endif
1479 if (error)
1480 return error;
1481 if (c->type != T_G703 && !c->unfram)
1482 return EINVAL;
1483 s = splimp ();
1484 cp_set_scrambler (c, *(int*)data);
1485 splx (s);
1486 return 0;
1487
1488 case SERIAL_GETMONITOR:
1489 CP_DEBUG2 (d, ("ioctl: getmonitor\n"));
1490 if (c->type != T_E1 &&
1491 c->type != T_E3 &&
1492 c->type != T_T3 &&
1493 c->type != T_STS1)
1494 return EINVAL;
1495 *(int*)data = c->monitor;
1496 return 0;
1497
1498 case SERIAL_SETMONITOR:
1499 CP_DEBUG2 (d, ("ioctl: setmonitor\n"));
1500 /* Only for superuser! */
1501#if __FreeBSD_version < 400000
1502 error = suser (p->p_ucred, &p->p_acflag);
1503#elif __FreeBSD_version < 500000
1504 error = suser (p);
1505#else
1506 error = suser (td);
1507#endif
1508 if (error)
1509 return error;
1510 if (c->type != T_E1)
1511 return EINVAL;
1512 s = splimp ();
1513 cp_set_monitor (c, *(int*)data);
1514 splx (s);
1515 return 0;
1516
1517 case SERIAL_GETUSE16:
1518 CP_DEBUG2 (d, ("ioctl: getuse16\n"));
1519 if (c->type != T_E1 || c->unfram)
1520 return EINVAL;
1521 *(int*)data = c->use16;
1522 return 0;
1523
1524 case SERIAL_SETUSE16:
1525 CP_DEBUG2 (d, ("ioctl: setuse16\n"));
1526 /* Only for superuser! */
1527#if __FreeBSD_version < 400000
1528 error = suser (p->p_ucred, &p->p_acflag);
1529#elif __FreeBSD_version < 500000
1530 error = suser (p);
1531#else
1532 error = suser (td);
1533#endif
1534 if (error)
1535 return error;
1536 if (c->type != T_E1)
1537 return EINVAL;
1538 s = splimp ();
1539 cp_set_use16 (c, *(int*)data);
1540 splx (s);
1541 return 0;
1542
1543 case SERIAL_GETCRC4:
1544 CP_DEBUG2 (d, ("ioctl: getcrc4\n"));
1545 if (c->type != T_E1 || c->unfram)
1546 return EINVAL;
1547 *(int*)data = c->crc4;
1548 return 0;
1549
1550 case SERIAL_SETCRC4:
1551 CP_DEBUG2 (d, ("ioctl: setcrc4\n"));
1552 /* Only for superuser! */
1553#if __FreeBSD_version < 400000
1554 error = suser (p->p_ucred, &p->p_acflag);
1555#elif __FreeBSD_version < 500000
1556 error = suser (p);
1557#else
1558 error = suser (td);
1559#endif
1560 if (error)
1561 return error;
1562 if (c->type != T_E1)
1563 return EINVAL;
1564 s = splimp ();
1565 cp_set_crc4 (c, *(int*)data);
1566 splx (s);
1567 return 0;
1568
1569 case SERIAL_GETCLK:
1570 CP_DEBUG2 (d, ("ioctl: getclk\n"));
1571 if (c->type != T_E1 &&
1572 c->type != T_G703 &&
1573 c->type != T_E3 &&
1574 c->type != T_T3 &&
1575 c->type != T_STS1)
1576 return EINVAL;
1577 switch (c->gsyn) {
1578 default: *(int*)data = E1CLK_INTERNAL; break;
1579 case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break;
1580 case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break;
1581 case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break;
1582 case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break;
1583 case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break;
1584 }
1585 return 0;
1586
1587 case SERIAL_SETCLK:
1588 CP_DEBUG2 (d, ("ioctl: setclk\n"));
1589 /* Only for superuser! */
1590#if __FreeBSD_version < 400000
1591 error = suser (p->p_ucred, &p->p_acflag);
1592#elif __FreeBSD_version < 500000
1593 error = suser (p);
1594#else
1595 error = suser (td);
1596#endif
1597 if (error)
1598 return error;
1599 if (c->type != T_E1 &&
1600 c->type != T_G703 &&
1601 c->type != T_E3 &&
1602 c->type != T_T3 &&
1603 c->type != T_STS1)
1604 return EINVAL;
1605 s = splimp ();
1606 switch (*(int*)data) {
1607 default: cp_set_gsyn (c, GSYN_INT); break;
1608 case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break;
1609 case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break;
1610 case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break;
1611 case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break;
1612 case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break;
1613 }
1614 splx (s);
1615 return 0;
1616
1617 case SERIAL_GETTIMESLOTS:
1618 CP_DEBUG2 (d, ("ioctl: gettimeslots\n"));
1619 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA)
1620 return EINVAL;
1621 *(u_long*)data = c->ts;
1622 return 0;
1623
1624 case SERIAL_SETTIMESLOTS:
1625 CP_DEBUG2 (d, ("ioctl: settimeslots\n"));
1626 /* Only for superuser! */
1627#if __FreeBSD_version < 400000
1628 error = suser (p->p_ucred, &p->p_acflag);
1629#elif __FreeBSD_version < 500000
1630 error = suser (p);
1631#else
1632 error = suser (td);
1633#endif
1634 if (error)
1635 return error;
1636 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA)
1637 return EINVAL;
1638 s = splimp ();
1639 cp_set_ts (c, *(u_long*)data);
1640 splx (s);
1641 return 0;
1642
1643 case SERIAL_GETINVCLK:
1644 CP_DEBUG2 (d, ("ioctl: getinvclk\n"));
1645#if 1
1646 return EINVAL;
1647#else
1648 if (c->type != T_SERIAL)
1649 return EINVAL;
1650 *(int*)data = c->invtxc;
1651 return 0;
1652#endif
1653
1654 case SERIAL_SETINVCLK:
1655 CP_DEBUG2 (d, ("ioctl: setinvclk\n"));
1656 /* Only for superuser! */
1657#if __FreeBSD_version < 400000
1658 error = suser (p->p_ucred, &p->p_acflag);
1659#elif __FreeBSD_version < 500000
1660 error = suser (p);
1661#else
1662 error = suser (td);
1663#endif
1664 if (error)
1665 return error;
1666 if (c->type != T_SERIAL)
1667 return EINVAL;
1668 s = splimp ();
1669 cp_set_invtxc (c, *(int*)data);
1670 cp_set_invrxc (c, *(int*)data);
1671 splx (s);
1672 return 0;
1673
1674 case SERIAL_GETINVTCLK:
1675 CP_DEBUG2 (d, ("ioctl: getinvtclk\n"));
1676 if (c->type != T_SERIAL)
1677 return EINVAL;
1678 *(int*)data = c->invtxc;
1679 return 0;
1680
1681 case SERIAL_SETINVTCLK:
1682 CP_DEBUG2 (d, ("ioctl: setinvtclk\n"));
1683 /* Only for superuser! */
1684#if __FreeBSD_version < 400000
1685 error = suser (p->p_ucred, &p->p_acflag);
1686#elif __FreeBSD_version < 500000
1687 error = suser (p);
1688#else
1689 error = suser (td);
1690#endif
1691 if (error)
1692 return error;
1693 if (c->type != T_SERIAL)
1694 return EINVAL;
1695 s = splimp ();
1696 cp_set_invtxc (c, *(int*)data);
1697 splx (s);
1698 return 0;
1699
1700 case SERIAL_GETINVRCLK:
1701 CP_DEBUG2 (d, ("ioctl: getinvrclk\n"));
1702 if (c->type != T_SERIAL)
1703 return EINVAL;
1704 *(int*)data = c->invrxc;
1705 return 0;
1706
1707 case SERIAL_SETINVRCLK:
1708 CP_DEBUG2 (d, ("ioctl: setinvrclk\n"));
1709 /* Only for superuser! */
1710#if __FreeBSD_version < 400000
1711 error = suser (p->p_ucred, &p->p_acflag);
1712#elif __FreeBSD_version < 500000
1713 error = suser (p);
1714#else
1715 error = suser (td);
1716#endif
1717 if (error)
1718 return error;
1719 if (c->type != T_SERIAL)
1720 return EINVAL;
1721 s = splimp ();
1722 cp_set_invrxc (c, *(int*)data);
1723 splx (s);
1724 return 0;
1725
1726 case SERIAL_GETLEVEL:
1727 CP_DEBUG2 (d, ("ioctl: getlevel\n"));
1728 if (c->type != T_G703)
1729 return EINVAL;
1730 s = splimp ();
1731 *(int*)data = cp_get_lq (c);
1732 splx (s);
1733 return 0;
1734
1735#if 0
1736 case SERIAL_RESET:
1737 CP_DEBUG2 (d, ("ioctl: reset\n"));
1738 /* Only for superuser! */
1739#if __FreeBSD_version < 400000
1740 error = suser (p->p_ucred, &p->p_acflag);
1741#elif __FreeBSD_version < 500000
1742 error = suser (p);
1743#else
1744 error = suser (td);
1745#endif
1746 if (error)
1747 return error;
1748 s = splimp ();
1749 cp_reset (c->board, 0, 0);
1750 splx (s);
1751 return 0;
1752
1753 case SERIAL_HARDRESET:
1754 CP_DEBUG2 (d, ("ioctl: hardreset\n"));
1755 /* Only for superuser! */
1756#if __FreeBSD_version < 400000
1757 error = suser (p->p_ucred, &p->p_acflag);
1758#elif __FreeBSD_version < 500000
1759 error = suser (p);
1760#else
1761 error = suser (td);
1762#endif
1763 if (error)
1764 return error;
1765 s = splimp ();
1766 /* hard_reset (c->board); */
1767 splx (s);
1768 return 0;
1769#endif
1770
1771 case SERIAL_GETCABLE:
1772 CP_DEBUG2 (d, ("ioctl: getcable\n"));
1773 if (c->type != T_SERIAL)
1774 return EINVAL;
1775 s = splimp ();
1776 *(int*)data = cp_get_cable (c);
1777 splx (s);
1778 return 0;
1779
1780 case SERIAL_GETDIR:
1781 CP_DEBUG2 (d, ("ioctl: getdir\n"));
1782 if (c->type != T_E1 && c->type != T_DATA)
1783 return EINVAL;
1784 *(int*)data = c->dir;
1785 return 0;
1786
1787 case SERIAL_SETDIR:
1788 CP_DEBUG2 (d, ("ioctl: setdir\n"));
1789 /* Only for superuser! */
1790#if __FreeBSD_version < 400000
1791 error = suser (p->p_ucred, &p->p_acflag);
1792#elif __FreeBSD_version < 500000
1793 error = suser (p);
1794#else
1795 error = suser (td);
1796#endif
1797 if (error)
1798 return error;
1799 s = splimp ();
1800 cp_set_dir (c, *(int*)data);
1801 splx (s);
1802 return 0;
1803
1804 case SERIAL_GETRLOOP:
1805 CP_DEBUG2 (d, ("ioctl: getrloop\n"));
1806 if (c->type != T_G703 &&
1807 c->type != T_E3 &&
1808 c->type != T_T3 &&
1809 c->type != T_STS1)
1810 return EINVAL;
1811 *(int*)data = cp_get_rloop (c);
1812 return 0;
1813
1814 case SERIAL_SETRLOOP:
1815 CP_DEBUG2 (d, ("ioctl: setloop\n"));
1816 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1)
1817 return EINVAL;
1818 /* Only for superuser! */
1819#if __FreeBSD_version < 400000
1820 error = suser (p->p_ucred, &p->p_acflag);
1821#elif __FreeBSD_version < 500000
1822 error = suser (p);
1823#else
1824 error = suser (td);
1825#endif
1826 if (error)
1827 return error;
1828 s = splimp ();
1829 cp_set_rloop (c, *(int*)data);
1830 splx (s);
1831 return 0;
1832
1833 case SERIAL_GETCABLEN:
1834 CP_DEBUG2 (d, ("ioctl: getcablen\n"));
1835 if (c->type != T_T3 && c->type != T_STS1)
1836 return EINVAL;
1837 *(int*)data = c->cablen;
1838 return 0;
1839
1840 case SERIAL_SETCABLEN:
1841 CP_DEBUG2 (d, ("ioctl: setloop\n"));
1842 if (c->type != T_T3 && c->type != T_STS1)
1843 return EINVAL;
1844 /* Only for superuser! */
1845#if __FreeBSD_version < 400000
1846 error = suser (p->p_ucred, &p->p_acflag);
1847#elif __FreeBSD_version < 500000
1848 error = suser (p);
1849#else
1850 error = suser (td);
1851#endif
1852 if (error)
1853 return error;
1854 s = splimp ();
1855 cp_set_cablen (c, *(int*)data);
1856 splx (s);
1857 return 0;
1858
1859 case TIOCSDTR: /* Set DTR */
1860 s = splimp ();
1861 cp_set_dtr (c, 1);
1862 splx (s);
1863 return 0;
1864
1865 case TIOCCDTR: /* Clear DTR */
1866 s = splimp ();
1867 cp_set_dtr (c, 0);
1868 splx (s);
1869 return 0;
1870
1871 case TIOCMSET: /* Set DTR/RTS */
1872 s = splimp ();
1873 cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0);
1874 cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0);
1875 splx (s);
1876 return 0;
1877
1878 case TIOCMBIS: /* Add DTR/RTS */
1879 s = splimp ();
1880 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1);
1881 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1);
1882 splx (s);
1883 return 0;
1884
1885 case TIOCMBIC: /* Clear DTR/RTS */
1886 s = splimp ();
1887 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0);
1888 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0);
1889 splx (s);
1890 return 0;
1891
1892 case TIOCMGET: /* Get modem status */
1893 *(int*)data = cp_modem_status (c);
1894 return 0;
1895 }
1896 return ENOTTY;
1897}
1898
1899#if __FreeBSD_version < 400000
1900static struct cdevsw cp_cdevsw = {
1901 cp_open, cp_close, noread, nowrite,
1902 cp_ioctl, nullstop, nullreset, nodevtotty,
1903 seltrue, nommap, NULL, "cp",
1904 NULL, -1
1905 };
1906#elif __FreeBSD_version < 500000
1907static struct cdevsw cp_cdevsw = {
1908 cp_open, cp_close, noread, nowrite,
1909 cp_ioctl, nopoll, nommap, nostrategy,
1910 "cp", CDEV_MAJOR, nodump, nopsize,
1911 D_NAGGED, -1
1912 };
1913#elif __FreeBSD_version == 500000
1914static struct cdevsw cp_cdevsw = {
1915 cp_open, cp_close, noread, nowrite,
1916 cp_ioctl, nopoll, nommap, nostrategy,
1917 "cp", CDEV_MAJOR, nodump, nopsize,
1918 D_NAGGED,
1919 };
1920#elif __FreeBSD_version <= 501000
1921static struct cdevsw cp_cdevsw = {
1922 .d_open = cp_open,
1923 .d_close = cp_close,
1924 .d_read = noread,
1925 .d_write = nowrite,
1926 .d_ioctl = cp_ioctl,
1927 .d_poll = nopoll,
1928 .d_mmap = nommap,
1929 .d_strategy = nostrategy,
1930 .d_name = "cp",
1931 .d_maj = CDEV_MAJOR,
1932 .d_dump = nodump,
1933 .d_flags = D_NAGGED,
1934};
1935#elif __FreeBSD_version < 502103
1936static struct cdevsw cp_cdevsw = {
1937 .d_open = cp_open,
1938 .d_close = cp_close,
1939 .d_ioctl = cp_ioctl,
1940 .d_name = "cp",
1941 .d_maj = CDEV_MAJOR,
1942 .d_flags = D_NAGGED,
1943};
1944#else /* __FreeBSD_version >= 502103 */
1945static struct cdevsw cp_cdevsw = {
1946 .d_version = D_VERSION,
1947 .d_open = cp_open,
1948 .d_close = cp_close,
1949 .d_ioctl = cp_ioctl,
1950 .d_name = "cp",
1951 .d_maj = CDEV_MAJOR,
1952 .d_flags = D_NEEDGIANT,
1953};
1954#endif
1955
1956#ifdef NETGRAPH
1957#if __FreeBSD_version >= 500000
1958static int ng_cp_constructor (node_p node)
1959{
1960 drv_t *d = NG_NODE_PRIVATE (node);
1961#else
1962static int ng_cp_constructor (node_p *node)
1963{
1964 drv_t *d = (*node)->private;
1965#endif
1966 CP_DEBUG (d, ("Constructor\n"));
1967 return EINVAL;
1968}
1969
1970static int ng_cp_newhook (node_p node, hook_p hook, const char *name)
1971{
1972 int s;
1973#if __FreeBSD_version >= 500000
1974 drv_t *d = NG_NODE_PRIVATE (node);
1975#else
1976 drv_t *d = node->private;
1977#endif
1978
1979 CP_DEBUG (d, ("Newhook\n"));
1980 /* Attach debug hook */
1981 if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) {
1982#if __FreeBSD_version >= 500000
1983 NG_HOOK_SET_PRIVATE (hook, NULL);
1984#else
1985 hook->private = 0;
1986#endif
1987 d->debug_hook = hook;
1988 return 0;
1989 }
1990
1991 /* Check for raw hook */
1992 if (strcmp (name, NG_CP_HOOK_RAW) != 0)
1993 return EINVAL;
1994
1995#if __FreeBSD_version >= 500000
1996 NG_HOOK_SET_PRIVATE (hook, d);
1997#else
1998 hook->private = d;
1999#endif
2000 d->hook = hook;
2001 s = splimp ();
2002 cp_up (d);
2003 splx (s);
2004 return 0;
2005}
2006
2007static char *format_timeslots (u_long s)
2008{
2009 static char buf [100];
2010 char *p = buf;
2011 int i;
2012
2013 for (i=1; i<32; ++i)
2014 if ((s >> i) & 1) {
2015 int prev = (i > 1) & (s >> (i-1));
2016 int next = (i < 31) & (s >> (i+1));
2017
2018 if (prev) {
2019 if (next)
2020 continue;
2021 *p++ = '-';
2022 } else if (p > buf)
2023 *p++ = ',';
2024
2025 if (i >= 10)
2026 *p++ = '0' + i / 10;
2027 *p++ = '0' + i % 10;
2028 }
2029 *p = 0;
2030 return buf;
2031}
2032
2033static int print_modems (char *s, cp_chan_t *c, int need_header)
2034{
2035 int status = cp_modem_status (c);
2036 int length = 0;
2037
2038 if (need_header)
2039 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n");
2040 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n",
2041 status & TIOCM_LE ? "On" : "-",
2042 status & TIOCM_DTR ? "On" : "-",
2043 status & TIOCM_DSR ? "On" : "-",
2044 status & TIOCM_RTS ? "On" : "-",
2045 status & TIOCM_CTS ? "On" : "-",
2046 status & TIOCM_CD ? "On" : "-");
2047 return length;
2048}
2049
2050static int print_stats (char *s, cp_chan_t *c, int need_header)
2051{
2052 int length = 0;
2053
2054 if (need_header)
2055 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n");
2056 length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n",
2057 c->rintr, c->tintr, 0l, (unsigned long) c->ibytes,
2058 c->ipkts, c->overrun + c->frame + c->crc,
2059 (unsigned long) c->obytes, c->opkts, c->underrun);
2060 return length;
2061}
2062
2063static char *format_e1_status (u_char status)
2064{
2065 static char buf [80];
2066
2067 if (status & E1_NOALARM)
2068 return "Ok";
2069 buf[0] = 0;
2070 if (status & E1_LOS) strcat (buf, ",LOS");
2071 if (status & E1_AIS) strcat (buf, ",AIS");
2072 if (status & E1_LOF) strcat (buf, ",LOF");
2073 if (status & E1_LOMF) strcat (buf, ",LOMF");
2074 if (status & E1_FARLOF) strcat (buf, ",FARLOF");
2075 if (status & E1_AIS16) strcat (buf, ",AIS16");
2076 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF");
2077 if (status & E1_TSTREQ) strcat (buf, ",TSTREQ");
2078 if (status & E1_TSTERR) strcat (buf, ",TSTERR");
2079 if (buf[0] == ',')
2080 return buf+1;
2081 return "Unknown";
2082}
2083
2084static int print_frac (char *s, int leftalign, u_long numerator, u_long divider)
2085{
2086 int n, length = 0;
2087
2088 if (numerator < 1 || divider < 1) {
2089 length += sprintf (s+length, leftalign ? "/- " : " -");
2090 return length;
2091 }
2092 n = (int) (0.5 + 1000.0 * numerator / divider);
2093 if (n < 1000) {
2094 length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n);
2095 return length;
2096 }
2097 *(s + length) = leftalign ? '/' : ' ';
2098 length ++;
2099
2100 if (n >= 1000000) n = (n+500) / 1000 * 1000;
2101 else if (n >= 100000) n = (n+50) / 100 * 100;
2102 else if (n >= 10000) n = (n+5) / 10 * 10;
2103
2104 switch (n) {
2105 case 1000: length += printf (s+length, ".999"); return length;
2106 case 10000: n = 9990; break;
2107 case 100000: n = 99900; break;
2108 case 1000000: n = 999000; break;
2109 }
2110 if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100);
2111 else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10);
2112 else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000);
2113 else length += sprintf (s+length, "%d", n/1000);
2114
2115 return length;
2116}
2117
2118static int print_e1_stats (char *s, cp_chan_t *c)
2119{
2120 struct e1_counters total;
2121 u_long totsec;
2122 int length = 0;
2123
2124 totsec = c->totsec + c->cursec;
2125 total.bpv = c->total.bpv + c->currnt.bpv;
2126 total.fse = c->total.fse + c->currnt.fse;
2127 total.crce = c->total.crce + c->currnt.crce;
2128 total.rcrce = c->total.rcrce + c->currnt.rcrce;
2129 total.uas = c->total.uas + c->currnt.uas;
2130 total.les = c->total.les + c->currnt.les;
2131 total.es = c->total.es + c->currnt.es;
2132 total.bes = c->total.bes + c->currnt.bes;
2133 total.ses = c->total.ses + c->currnt.ses;
2134 total.oofs = c->total.oofs + c->currnt.oofs;
2135 total.css = c->total.css + c->currnt.css;
2136 total.dm = c->total.dm + c->currnt.dm;
2137
2138 length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n");
2139
2140 /* Unavailable seconds, degraded minutes */
2141 length += print_frac (s + length, 0, c->currnt.uas, c->cursec);
2142 length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec);
2143
2144 /* Bipolar violations, frame sync errors */
2145 length += print_frac (s + length, 0, c->currnt.bpv, c->cursec);
2146 length += print_frac (s + length, 1, c->currnt.fse, c->cursec);
2147
2148 /* CRC errors, remote CRC errors (E-bit) */
2149 length += print_frac (s + length, 0, c->currnt.crce, c->cursec);
2150 length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec);
2151
2152 /* Errored seconds, line errored seconds */
2153 length += print_frac (s + length, 0, c->currnt.es, c->cursec);
2154 length += print_frac (s + length, 1, c->currnt.les, c->cursec);
2155
2156 /* Severely errored seconds, burst errored seconds */
2157 length += print_frac (s + length, 0, c->currnt.ses, c->cursec);
2158 length += print_frac (s + length, 1, c->currnt.bes, c->cursec);
2159
2160 /* Out of frame seconds, controlled slip seconds */
2161 length += print_frac (s + length, 0, c->currnt.oofs, c->cursec);
2162 length += print_frac (s + length, 1, c->currnt.css, c->cursec);
2163
2164 length += sprintf (s + length, " %s\n", format_e1_status (c->status));
2165
2166 /* Print total statistics. */
2167 length += print_frac (s + length, 0, total.uas, totsec);
2168 length += print_frac (s + length, 1, 60 * total.dm, totsec);
2169
2170 length += print_frac (s + length, 0, total.bpv, totsec);
2171 length += print_frac (s + length, 1, total.fse, totsec);
2172
2173 length += print_frac (s + length, 0, total.crce, totsec);
2174 length += print_frac (s + length, 1, total.rcrce, totsec);
2175
2176 length += print_frac (s + length, 0, total.es, totsec);
2177 length += print_frac (s + length, 1, total.les, totsec);
2178
2179 length += print_frac (s + length, 0, total.ses, totsec);
2180 length += print_frac (s + length, 1, total.bes, totsec);
2181
2182 length += print_frac (s + length, 0, total.oofs, totsec);
2183 length += print_frac (s + length, 1, total.css, totsec);
2184
2185 length += sprintf (s + length, " -- Total\n");
2186 return length;
2187}
2188
2189static int print_chan (char *s, cp_chan_t *c)
2190{
2191 drv_t *d = c->sys;
2192 int length = 0;
2193
2194 length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num);
2195 if (d->chan->debug)
2196 length += sprintf (s + length, " debug=%d", d->chan->debug);
2197
2198 if (c->board->mux) {
2199 length += sprintf (s + length, " cfg=C");
2200 } else {
2201 length += sprintf (s + length, " cfg=A");
2202 }
2203
2204 if (c->baud)
2205 length += sprintf (s + length, " %ld", c->baud);
2206 else
2207 length += sprintf (s + length, " extclock");
2208
2209 if (c->type == T_E1 || c->type == T_G703)
2210 switch (c->gsyn) {
2211 case GSYN_INT : length += sprintf (s + length, " syn=int"); break;
2212 case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break;
2213 case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break;
2214 case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break;
2215 case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break;
2216 case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break;
2217 }
2218 if (c->type == T_SERIAL) {
2219 length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off");
2220 length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off");
2221 length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off");
2222 }
2223 if (c->type == T_E1)
2224 length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off");
2225
2226 length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off");
2227
2228 if (c->type == T_E1)
2229 length += sprintf (s + length, " ts=%s", format_timeslots (c->ts));
2230 if (c->type == T_G703) {
2231 int lq, x;
2232
2233 x = splimp ();
2234 lq = cp_get_lq (c);
2235 splx (x);
2236 length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0);
2237 }
2238 length += sprintf (s + length, "\n");
2239 return length;
2240}
2241
2242#if __FreeBSD_version >= 500000
2243static int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook)
2244{
2245 drv_t *d = NG_NODE_PRIVATE (node);
2246 struct ng_mesg *msg;
2247#else
2248static int ng_cp_rcvmsg (node_p node, struct ng_mesg *msg,
2249 const char *retaddr, struct ng_mesg **rptr)
2250{
2251 drv_t *d = node->private;
2252#endif
2253 struct ng_mesg *resp = NULL;
2254 int error = 0;
2255
2256 CP_DEBUG (d, ("Rcvmsg\n"));
2257#if __FreeBSD_version >= 500000
2258 NGI_GET_MSG (item, msg);
2259#endif
2260 switch (msg->header.typecookie) {
2261 default:
2262 error = EINVAL;
2263 break;
2264
2265 case NGM_CP_COOKIE:
2266 printf ("Not implemented yet\n");
2267 error = EINVAL;
2268 break;
2269
2270 case NGM_GENERIC_COOKIE:
2271 switch (msg->header.cmd) {
2272 default:
2273 error = EINVAL;
2274 break;
2275
2276 case NGM_TEXT_STATUS: {
2277 char *s;
2278 int l = 0;
2279 int dl = sizeof (struct ng_mesg) + 730;
2280
2281#if __FreeBSD_version >= 500000
2282 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT);
2283 if (! resp) {
2284 error = ENOMEM;
2285 break;
2286 }
2287#else
2288 MALLOC (resp, struct ng_mesg *, dl,
2289 M_NETGRAPH, M_NOWAIT);
2290 if (! resp) {
2291 error = ENOMEM;
2292 break;
2293 }
2294 bzero (resp, dl);
2295#endif
2296 s = (resp)->data;
2297 if (d) {
2298 l += print_chan (s + l, d->chan);
2299 l += print_stats (s + l, d->chan, 1);
2300 l += print_modems (s + l, d->chan, 1);
2301 l += print_e1_stats (s + l, d->chan);
2302 } else
2303 l += sprintf (s + l, "Error: node not connect to channel");
2304#if __FreeBSD_version < 500000
2305 (resp)->header.version = NG_VERSION;
2306 (resp)->header.arglen = strlen (s) + 1;
2307 (resp)->header.token = msg->header.token;
2308 (resp)->header.typecookie = NGM_CP_COOKIE;
2309 (resp)->header.cmd = msg->header.cmd;
2310#endif
2311 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN);
2312 }
2313 break;
2314 }
2315 break;
2316 }
2317#if __FreeBSD_version >= 500000
2318 NG_RESPOND_MSG (error, node, item, resp);
2319 NG_FREE_MSG (msg);
2320#else
2321 *rptr = resp;
2322 FREE (msg, M_NETGRAPH);
2323#endif
2324 return error;
2325}
2326
2327#if __FreeBSD_version >= 500000
2328static int ng_cp_rcvdata (hook_p hook, item_p item)
2329{
2330 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook));
2331 struct mbuf *m;
2332 meta_p meta;
2333#else
2334static int ng_cp_rcvdata (hook_p hook, struct mbuf *m, meta_p meta)
2335{
2336 drv_t *d = hook->node->private;
2337#endif
2338 struct ifqueue *q;
2339 int s;
2340
2341 CP_DEBUG2 (d, ("Rcvdata\n"));
2342#if __FreeBSD_version >= 500000
2343 NGI_GET_M (item, m);
2344 NGI_GET_META (item, meta);
2345 NG_FREE_ITEM (item);
2346 if (! NG_HOOK_PRIVATE (hook) || ! d) {
2347 NG_FREE_M (m);
2348 NG_FREE_META (meta);
2349#else
2350 if (! hook->private || ! d) {
2351 NG_FREE_DATA (m,meta);
2352#endif
2353 return ENETDOWN;
2354 }
2355 q = (meta && meta->priority > 0) ? &d->hi_queue : &d->queue;
2356 s = splimp ();
2357#if __FreeBSD_version >= 500000
2358 IF_LOCK (q);
2359 if (_IF_QFULL (q)) {
2360 _IF_DROP (q);
2361 IF_UNLOCK (q);
2362 splx (s);
2363 NG_FREE_M (m);
2364 NG_FREE_META (meta);
2365 return ENOBUFS;
2366 }
2367 _IF_ENQUEUE (q, m);
2368 IF_UNLOCK (q);
2369#else
2370 if (IF_QFULL (q)) {
2371 IF_DROP (q);
2372 splx (s);
2373 NG_FREE_DATA (m, meta);
2374 return ENOBUFS;
2375 }
2376 IF_ENQUEUE (q, m);
2377#endif
2378 cp_start (d);
2379 splx (s);
2380 return 0;
2381}
2382
2383static int ng_cp_rmnode (node_p node)
2384{
2385#if __FreeBSD_version >= 500000
2386 drv_t *d = NG_NODE_PRIVATE (node);
2387
2388 CP_DEBUG (d, ("Rmnode\n"));
2389 if (d && d->running) {
2390 int s = splimp ();
2391 cp_down (d);
2392 splx (s);
2393 }
2394#ifdef KLD_MODULE
2395 if (node->nd_flags & NG_REALLY_DIE) {
2396 NG_NODE_SET_PRIVATE (node, NULL);
2397 NG_NODE_UNREF (node);
2398 }
2399 node->nd_flags &= ~NG_INVALID;
2400#endif
2401#else /* __FreeBSD_version < 500000 */
2402 drv_t *d = node->private;
2403
2404 if (d && d->running) {
2405 int s = splimp ();
2406 cp_down (d);
2407 splx (s);
2408 }
2409
2410 node->flags |= NG_INVALID;
2411 ng_cutlinks (node);
2412#ifdef KLD_MODULE
2413#if __FreeBSD_version >= 400000
2414 /* We do so because of pci module problem, see also comment in
2415 cp_unload. Not in 4.x. */
2416 ng_unname (node);
2417 ng_unref (node);
2418#else
2419 node->flags &= ~NG_INVALID;
2420#endif
2421#endif
2422#endif
2423 return 0;
2424}
2425
2426static void ng_cp_watchdog (void *arg)
2427{
2428 drv_t *d = arg;
2429
2430 if (d) {
2431 if (d->timeout == 1)
2432 cp_watchdog (d);
2433 if (d->timeout)
2434 d->timeout--;
2435 d->timeout_handle = timeout (ng_cp_watchdog, d, hz);
2436 }
2437}
2438
2439static int ng_cp_connect (hook_p hook)
2440{
2441#if __FreeBSD_version >= 500000
2442 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook));
2443#else
2444 drv_t *d = hook->node->private;
2445#endif
2446
2447 if (d) {
2448 CP_DEBUG (d, ("Connect\n"));
2449 d->timeout_handle = timeout (ng_cp_watchdog, d, hz);
2450 }
2451
2452 return 0;
2453}
2454
2455static int ng_cp_disconnect (hook_p hook)
2456{
2457#if __FreeBSD_version >= 500000
2458 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook));
2459#else
2460 drv_t *d = hook->node->private;
2461#endif
2462
2463 if (d) {
2464 CP_DEBUG (d, ("Disconnect\n"));
2465#if __FreeBSD_version >= 500000
2466 if (NG_HOOK_PRIVATE (hook))
2467#else
2468 if (hook->private)
2469#endif
2470 {
2471 int s = splimp ();
2472 cp_down (d);
2473 splx (s);
2474 }
2475 untimeout (ng_cp_watchdog, d, d->timeout_handle);
2476 }
2477 return 0;
2478}
2479#endif
2480
2481#if __FreeBSD_version < 400000
2482
2483#ifdef KLD_MODULE
2484extern STAILQ_HEAD(devlist, pci_devinfo) pci_devq;
2485
2486static
2487struct pci_devinfo *pci_device_find (u_int16_t device, u_int16_t vendor, int unit)
2488{
2489 pcicfgregs *cfg;
2490 struct pci_devinfo *dinfo;
2491 int u=0,i;
2492
2493 for (dinfo = STAILQ_FIRST (&pci_devq), i=0;
2494 dinfo && (i < pci_numdevs);
2495 dinfo = STAILQ_NEXT (dinfo, pci_links), i++) {
2496 cfg = &dinfo->cfg;
2497 if ((device == cfg->device) && (vendor == cfg->vendor)) {
2498 if (u == unit)
2499 return dinfo;
2500 u++;
2501 }
2502 }
2503 return 0;
2504}
2505
2506/*
2507 * Function called when loading the driver.
2508 */
2509static int cp_load (void)
2510{
2511 int i, s;
2512 pcicfgregs *cfg;
2513 struct pci_devinfo *dinfo;
2514
2515 s = splimp ();
2516 for (i=0; i<NBRD; ++i) {
2517 dinfo = pci_device_find (cp_device_id, cp_vendor_id, i);
2518 if (! dinfo)
2519 break;
2520
2521 cfg = &dinfo->cfg;
2522 cp_attach (cfg, i);
2523 dinfo->device = &cp_driver;
2524 strncpy (dinfo->conf.pd_name, cp_driver.pd_name,
2525 sizeof(dinfo->conf.pd_name));
2526 dinfo->conf.pd_name[sizeof(dinfo->conf.pd_name) - 1] = 0;
2527 dinfo->conf.pd_unit = i;
2528 }
2529 splx (s);
2530 if (! i) {
2531 /* Deactivate the timeout routine. */
2532 untimeout (cp_timeout, 0, timeout_handle);
2533 return ENXIO;
2534 }
2535 return 0;
2536}
2537
2538/*
2539 * Function called when unloading the driver.
2540 */
2541static int cp_unload (void)
2542{
2543#if 1
2544 /* Currently pci loadable module not fully supported, so we just
2545 return EBUSY. Do not forget to correct ng_cp_rmnode then probelm
2546 would be solved. */
2547 return EBUSY;
2548#else
2549 int i, s;
2550
2551 /* Check if the device is busy (open). */
2552 for (i=0; i<NBRD*NCHAN; ++i) {
2553 drv_t *d = channel[i];
2554
2555 if (d && d->chan->type && d->running)
2556 return EBUSY;
2557 }
2558
2559 s = splimp ();
2560
2561 /* Deactivate the timeout routine. */
2562 untimeout (cp_timeout, 0, timeout_handle);
2563
2564 /* OK to unload the driver, unregister the interrupt first. */
2565 for (i=0; i<NBRD; ++i) {
2566 cp_board_t *b = adapter [i];
2567
2568 if (!b || ! b->type)
2569 continue;
2570
2571 cp_reset (b, 0 ,0);
2572/* pci_unmap_int (tag, cp_intr, b, &net_imask);*/
2573 /* Here should be something like pci_unmap_mem ()*/
2574 }
2575
2576 for (i=0; i<NBRD; i++)
2577 if (led_timo[i].callout)
2578 untimeout (cp_led_off, adapter + i, led_timo[i]);
2579
2580 /* Detach the interfaces, free buffer memory. */
2581 for (i=0; i<NBRD*NCHAN; ++i) {
2582 drv_t *d = channel[i];
2583
2584 if (! d)
2585 continue;
2586#ifndef NETGRAPH
2587#if __FreeBSD_version >= 400000 || NBPFILTER > 0
2588 /* Detach from the packet filter list of interfaces. */
2589 {
2590 struct bpf_if *q, **b = &bpf_iflist;
2591
2592 while ((q = *b)) {
2593 if (q->bif_ifp == d->pp.pp_if) {
2594 *b = q->bif_next;
2595 free (q, M_DEVBUF);
2596 }
2597 b = &(q->bif_next);
2598 }
2599 }
2600#endif
2601 /* Detach from the sync PPP list. */
2602 sppp_detach (&d->pp.pp_if);
2603
2604 /* Detach from the system list of interfaces. */
2605 {
2606 struct ifaddr *ifa;
2607 TAILQ_FOREACH (ifa, &d->pp.pp_if.if_addrhead, ifa_link) {
2608 TAILQ_REMOVE (&d->pp.pp_if.if_addrhead, ifa, ifa_link);
2609 free (ifa, M_IFADDR);
2610 }
2611 TAILQ_REMOVE (&ifnet, &d->pp.pp_if, if_link);
2612 }
2613#endif
2614 /* Deallocate buffers. */
2615/* free (d, M_DEVBUF);*/
2616 }
2617
2618 for (i=0; i<NBRD; ++i) {
2619 cp_board_t *b = adapter + i;
2620
2621 if (b && b->type)
2622 free (b, M_DEVBUF);
2623 }
2624 splx (s);
2625 return 0;
2626#endif
2627}
2628#endif
2629#endif
2630
2631#if __FreeBSD_version < 400000
2632#ifdef KLD_MODULE
2633static int cp_modevent (module_t mod, int type, void *unused)
2634{
2635 dev_t dev;
2636
2637 switch (type) {
2638 case MOD_LOAD:
2639 dev = makedev (CDEV_MAJOR, 0);
2640 cdevsw_add (&dev, &cp_cdevsw, 0);
2641 timeout_handle = timeout (cp_timeout, 0, hz*5);
2642 return cp_load ();
2643 case MOD_UNLOAD:
2644 return cp_unload ();
2645 case MOD_SHUTDOWN:
2646 break;
2647 }
2648 return 0;
2649}
2650#endif /* KLD_MODULE */
2651
2652#else /* __FreeBSD_version >= 400000 */
2653static int cp_modevent (module_t mod, int type, void *unused)
2654{
2655 struct cdev *dev;
2656 static int load_count = 0;
2657 struct cdevsw *cdsw;
2658
2659#if __FreeBSD_version >= 502103
2660 dev = udev2dev (makeudev(CDEV_MAJOR, 0));
2661#else
2662 dev = makedev (CDEV_MAJOR, 0);
2663#endif
2664 switch (type) {
2665 case MOD_LOAD:
2666 if (dev != NODEV &&
2667 (cdsw = devsw (dev)) &&
2668 cdsw->d_maj == CDEV_MAJOR) {
2669 printf ("Tau-PCI driver is already in system\n");
2670 return (ENXIO);
2671 }
2672#if __FreeBSD_version >= 500000 && defined NETGRAPH
2673 if (ng_newtype (&typestruct))
2674 printf ("Failed to register ng_cp\n");
2675#endif
2676 ++load_count;
2677#if __FreeBSD_version <= 500000
2678 cdevsw_add (&cp_cdevsw);
2679#endif
2680 timeout_handle = timeout (cp_timeout, 0, hz*5);
2681 break;
2682 case MOD_UNLOAD:
2683 if (load_count == 1) {
2684 printf ("Removing device entry for Tau-PCI\n");
2685#if __FreeBSD_version <= 500000
2686 cdevsw_remove (&cp_cdevsw);
2687#endif
2688#if __FreeBSD_version >= 500000 && defined NETGRAPH
2689 ng_rmtype (&typestruct);
2690#endif
2691 }
2692 untimeout (cp_timeout, 0, timeout_handle);
2693 --load_count;
2694 break;
2695 case MOD_SHUTDOWN:
2696 break;
2697 }
2698 return 0;
2699}
2700#endif /* __FreeBSD_version < 400000 */
2701
2702#ifdef NETGRAPH
2703static struct ng_type typestruct = {
2704 .version = NG_ABI_VERSION,
2705 .name = NG_CP_NODE_TYPE,
2706 .constructor = ng_cp_constructor,
2707 .rcvmsg = ng_cp_rcvmsg,
2708 .shutdown = ng_cp_rmnode,
2709 .newhook = ng_cp_newhook,
2710 .connect = ng_cp_connect,
2711 .rcvdata = ng_cp_rcvdata,
2712 .disconnect = ng_cp_disconnect,
2713};
2714#if __FreeBSD_version < 400000
2715NETGRAPH_INIT_ORDERED (cp, &typestruct, SI_SUB_DRIVERS,\
2716 SI_ORDER_MIDDLE + CDEV_MAJOR);
2717#endif
2718#endif /*NETGRAPH*/
2719
2720#if __FreeBSD_version >= 500000
2721#ifdef NETGRAPH
2722MODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
2723#else
2724MODULE_DEPEND (cp, sppp, 1, 1, 1);
2725#endif
2726#ifdef KLD_MODULE
2727DRIVER_MODULE (cpmod, pci, cp_driver, cp_devclass, cp_modevent, NULL);
2728#else
2729DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL);
2730#endif
2731#elif __FreeBSD_version >= 400000
2732#ifdef NETGRAPH
2733DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, ng_mod_event, &typestruct);
2734#else
2735DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL);
2736#endif
2737#else /* __FreeBSD_version < 400000 */
2738#ifdef KLD_MODULE
2739#ifndef NETGRAPH
2740static moduledata_t cpmod = { "cp", cp_modevent, NULL};
2741DECLARE_MODULE (cp, cpmod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR);
2742#endif
2743#else /* KLD_MODULE */
2744
2745/*
2746 * Now for some driver initialisation.
2747 * Occurs ONCE during boot (very early).
2748 * This is if we are NOT a loadable module.
2749 */
2750static void cp_drvinit (void *unused)
2751{
2752 dev_t dev;
2753
2754 dev = makedev (CDEV_MAJOR, 0);
2755 cdevsw_add (&dev, &cp_cdevsw, 0);
2756
2757 /* Activate the timeout routine. */
2758 timeout_handle = timeout (cp_timeout, 0, hz);
2759#ifdef NETGRAPH
2760#if 0
2761 /* Register our node type in netgraph */
2762 if (ng_newtype (&typestruct))
2763 printf ("Failed to register ng_cp\n");
2764#endif
2765#endif
2766}
2767
2768SYSINIT (cpdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, cp_drvinit, 0)
2769#endif /* KLD_MODULE */
2770#endif /* __FreeBSD_version < 400000 */
2771#endif /* NPCI */