The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/cp/if_cp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: ed0f2312c1963c7c3cb05c81df857f93


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.