if_cp.c revision 138673
1128967Srik/* 2128967Srik * Cronyx-Tau-PCI adapter driver for FreeBSD. 3128967Srik * Supports PPP/HDLC, Cisco/HDLC and FrameRelay protocol in synchronous mode, 4128967Srik * and asyncronous channels with full modem control. 5128967Srik * Keepalive protocol implemented in both Cisco and PPP modes. 6128967Srik * 7128967Srik * Copyright (C) 1999-2004 Cronyx Engineering. 8128967Srik * Author: Kurakin Roman, <rik@cronyx.ru> 9128967Srik * 10128967Srik * Copyright (C) 1999-2002 Cronyx Engineering. 11128967Srik * Author: Serge Vakulenko, <vak@cronyx.ru> 12128967Srik * 13128967Srik * This software is distributed with NO WARRANTIES, not even the implied 14128967Srik * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15128967Srik * 16128967Srik * Authors grant any other persons or organisations a permission to use, 17128967Srik * modify and redistribute this software in source and binary forms, 18128967Srik * as long as this message is kept with the software, all derivative 19128967Srik * works or modified versions. 20128967Srik * 21130985Srik * Cronyx Id: if_cp.c,v 1.1.2.41 2004/06/23 17:09:13 rik Exp $ 22128967Srik */ 23128967Srik 24128967Srik#include <sys/cdefs.h> 25128967Srik__FBSDID("$FreeBSD: head/sys/dev/cp/if_cp.c 138673 2004-12-11 05:38:16Z rik $"); 26128967Srik 27128967Srik#include <sys/param.h> 28128967Srik#include <sys/ucred.h> 29128967Srik#include <sys/proc.h> 30128967Srik#include <sys/systm.h> 31128967Srik#include <sys/mbuf.h> 32128967Srik#include <sys/kernel.h> 33129879Sphk#include <sys/module.h> 34128967Srik#include <sys/conf.h> 35128967Srik#include <sys/malloc.h> 36128967Srik#include <sys/socket.h> 37128967Srik#include <sys/sockio.h> 38128967Srik#include <sys/tty.h> 39130971Srik#include <sys/bus.h> 40128967Srik#include <vm/vm.h> 41128967Srik#include <vm/pmap.h> 42128967Srik#include <net/if.h> 43138673Srik#include <dev/pci/pcivar.h> 44138673Srik#include <dev/pci/pcireg.h> 45128967Srik#include <machine/bus.h> 46128967Srik#include <sys/rman.h> 47128967Srik#include "opt_ng_cronyx.h" 48128967Srik#ifdef NETGRAPH_CRONYX 49128967Srik# include "opt_netgraph.h" 50128967Srik# ifndef NETGRAPH 51133646Srik# error #option NETGRAPH missed from configuration 52128967Srik# endif 53128967Srik# include <netgraph/ng_message.h> 54128967Srik# include <netgraph/netgraph.h> 55130985Srik# include <dev/cp/ng_cp.h> 56128967Srik#else 57128967Srik# include <net/if_sppp.h> 58128967Srik# define PP_CISCO IFF_LINK2 59130971Srik# include <net/bpf.h> 60128967Srik#endif 61128967Srik#include <dev/cx/machdep.h> 62128967Srik#include <dev/cp/cpddk.h> 63128967Srik#include <machine/cserial.h> 64128967Srik#include <machine/resource.h> 65128967Srik#include <machine/pmap.h> 66128967Srik 67128967Srik/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 68128967Srik#ifndef PP_FR 69128967Srik#define PP_FR 0 70128967Srik#endif 71128967Srik 72128967Srik#define CP_DEBUG(d,s) ({if (d->chan->debug) {\ 73128967Srik printf ("%s: ", d->name); printf s;}}) 74128967Srik#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 75128967Srik printf ("%s: ", d->name); printf s;}}) 76128967Srik 77128967Srik#define CDEV_MAJOR 134 78128967Srik 79128967Srikstatic int cp_probe __P((device_t)); 80128967Srikstatic int cp_attach __P((device_t)); 81128967Srikstatic int cp_detach __P((device_t)); 82128967Srik 83128967Srikstatic device_method_t cp_methods[] = { 84128967Srik /* Device interface */ 85128967Srik DEVMETHOD(device_probe, cp_probe), 86128967Srik DEVMETHOD(device_attach, cp_attach), 87128967Srik DEVMETHOD(device_detach, cp_detach), 88128967Srik 89128967Srik {0, 0} 90128967Srik}; 91128967Srik 92130985Sriktypedef struct _cp_dma_mem_t { 93130985Srik unsigned long phys; 94130985Srik void *virt; 95130985Srik size_t size; 96130985Srik bus_dma_tag_t dmat; 97130985Srik bus_dmamap_t mapp; 98130985Srik} cp_dma_mem_t; 99128967Srik 100128967Sriktypedef struct _drv_t { 101128967Srik char name [8]; 102128967Srik cp_chan_t *chan; 103128967Srik cp_board_t *board; 104130985Srik cp_dma_mem_t dmamem; 105128967Srik int running; 106128967Srik#ifdef NETGRAPH 107128967Srik char nodename [NG_NODELEN+1]; 108128967Srik hook_p hook; 109128967Srik hook_p debug_hook; 110128967Srik node_p node; 111128967Srik struct ifqueue queue; 112128967Srik struct ifqueue hi_queue; 113128967Srik short timeout; 114128967Srik struct callout_handle timeout_handle; 115128967Srik#else 116128967Srik struct sppp pp; 117128967Srik#endif 118130585Sphk struct cdev *devt; 119128967Srik} drv_t; 120128967Srik 121130985Sriktypedef struct _bdrv_t { 122130985Srik cp_board_t *board; 123130985Srik struct resource *cp_res; 124130985Srik struct resource *cp_irq; 125130985Srik void *cp_intrhand; 126130985Srik cp_dma_mem_t dmamem; 127130985Srik drv_t channel [NCHAN]; 128130985Srik} bdrv_t; 129130985Srik 130130985Srikstatic driver_t cp_driver = { 131130985Srik "cp", 132130985Srik cp_methods, 133130985Srik sizeof(bdrv_t), 134130985Srik}; 135130985Srik 136130985Srikstatic devclass_t cp_devclass; 137130985Srik 138128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len); 139128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len); 140128967Srikstatic void cp_error (cp_chan_t *c, int data); 141128967Srikstatic void cp_up (drv_t *d); 142128967Srikstatic void cp_start (drv_t *d); 143128967Srikstatic void cp_down (drv_t *d); 144128967Srikstatic void cp_watchdog (drv_t *d); 145128967Srik#ifdef NETGRAPH 146128967Srikextern struct ng_type typestruct; 147128967Srik#else 148128967Srikstatic void cp_ifstart (struct ifnet *ifp); 149128967Srikstatic void cp_tlf (struct sppp *sp); 150128967Srikstatic void cp_tls (struct sppp *sp); 151128967Srikstatic void cp_ifwatchdog (struct ifnet *ifp); 152128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 153128967Srikstatic void cp_initialize (void *softc); 154128967Srik#endif 155128967Srik 156128967Srikstatic cp_board_t *adapter [NBRD]; 157128967Srikstatic drv_t *channel [NBRD*NCHAN]; 158128967Srikstatic struct callout_handle led_timo [NBRD]; 159128967Srikstatic struct callout_handle timeout_handle; 160128967Srik 161128967Srikstatic int cp_destroy = 0; 162128967Srik 163128967Srik/* 164128967Srik * Print the mbuf chain, for debug purposes only. 165128967Srik */ 166128967Srikstatic void printmbuf (struct mbuf *m) 167128967Srik{ 168128967Srik printf ("mbuf:"); 169128967Srik for (; m; m=m->m_next) { 170128967Srik if (m->m_flags & M_PKTHDR) 171128967Srik printf (" HDR %d:", m->m_pkthdr.len); 172128967Srik if (m->m_flags & M_EXT) 173128967Srik printf (" EXT:"); 174128967Srik printf (" %d", m->m_len); 175128967Srik } 176128967Srik printf ("\n"); 177128967Srik} 178128967Srik 179128967Srik/* 180128967Srik * Make an mbuf from data. 181128967Srik */ 182128967Srikstatic struct mbuf *makembuf (void *buf, unsigned len) 183128967Srik{ 184128967Srik struct mbuf *m; 185128967Srik 186128967Srik MGETHDR (m, M_DONTWAIT, MT_DATA); 187128967Srik if (! m) 188128967Srik return 0; 189128967Srik MCLGET (m, M_DONTWAIT); 190128967Srik if (! (m->m_flags & M_EXT)) { 191128967Srik m_freem (m); 192128967Srik return 0; 193128967Srik } 194128967Srik m->m_pkthdr.len = m->m_len = len; 195128967Srik bcopy (buf, mtod (m, caddr_t), len); 196128967Srik return m; 197128967Srik} 198128967Srik 199128967Srikstatic int cp_probe (device_t dev) 200128967Srik{ 201128967Srik if ((pci_get_vendor (dev) == cp_vendor_id) && 202128967Srik (pci_get_device (dev) == cp_device_id)) { 203128967Srik device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 204128967Srik return 0; 205128967Srik } 206128967Srik return ENXIO; 207128967Srik} 208128967Srik 209128967Srikstatic void cp_timeout (void *arg) 210128967Srik{ 211128967Srik drv_t *d; 212128967Srik int s, i; 213128967Srik 214128967Srik for (i=0; i<NBRD*NCHAN; ++i) { 215128967Srik s = splimp (); 216128967Srik if (cp_destroy) { 217128967Srik splx (s); 218128967Srik return; 219128967Srik } 220128967Srik d = channel[i]; 221128967Srik if (!d) { 222128967Srik splx (s); 223128967Srik continue; 224128967Srik } 225128967Srik switch (d->chan->type) { 226128967Srik case T_G703: 227128967Srik cp_g703_timer (d->chan); 228128967Srik break; 229128967Srik case T_E1: 230128967Srik cp_e1_timer (d->chan); 231128967Srik break; 232128967Srik case T_E3: 233128967Srik case T_T3: 234128967Srik case T_STS1: 235128967Srik cp_e3_timer (d->chan); 236128967Srik break; 237128967Srik default: 238128967Srik break; 239128967Srik } 240128967Srik splx (s); 241128967Srik } 242128967Srik s = splimp (); 243128967Srik if (!cp_destroy) 244128967Srik timeout_handle = timeout (cp_timeout, 0, hz); 245128967Srik splx (s); 246128967Srik} 247128967Srik 248128967Srikstatic void cp_led_off (void *arg) 249128967Srik{ 250128967Srik cp_board_t *b = arg; 251128967Srik int s = splimp (); 252128967Srik if (cp_destroy) { 253128967Srik splx (s); 254128967Srik return; 255128967Srik } 256128967Srik cp_led (b, 0); 257128967Srik led_timo[b->num].callout = 0; 258128967Srik splx (s); 259128967Srik} 260128967Srik 261128967Srikstatic void cp_intr (void *arg) 262128967Srik{ 263128967Srik bdrv_t *bd = arg; 264128967Srik cp_board_t *b = bd->board; 265128967Srik int s = splimp (); 266128967Srik if (cp_destroy) { 267128967Srik splx (s); 268128967Srik return; 269128967Srik } 270128967Srik /* Turn LED on. */ 271128967Srik cp_led (b, 1); 272128967Srik 273128967Srik cp_interrupt (b); 274128967Srik 275128967Srik /* Turn LED off 50 msec later. */ 276128967Srik if (!led_timo[b->num].callout) 277128967Srik led_timo[b->num] = timeout (cp_led_off, b, hz/20); 278128967Srik splx (s); 279128967Srik} 280128967Srik 281128967Srikextern struct cdevsw cp_cdevsw; 282128967Srik 283130985Srikstatic void 284130985Srikcp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 285130985Srik{ 286130985Srik unsigned long *addr; 287130985Srik 288130985Srik if (error) 289130985Srik return; 290130985Srik 291130985Srik KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 292130985Srik addr = arg; 293130985Srik *addr = segs->ds_addr; 294130985Srik} 295130985Srik 296130985Srikstatic int 297130985Srikcp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 298130985Srik{ 299130985Srik int error; 300130985Srik 301130985Srik error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 302130985Srik BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 303130985Srik dmem->size, 0, NULL, NULL, &dmem->dmat); 304130985Srik if (error) { 305130985Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 306130985Srik else printf ("cp%d: ", bnum); 307130985Srik printf ("couldn't allocate tag for dma memory\n"); 308130985Srik return 0; 309130985Srik } 310130985Srik error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 311130985Srik BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 312130985Srik if (error) { 313130985Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 314130985Srik else printf ("cp%d: ", bnum); 315130985Srik printf ("couldn't allocate mem for dma memory\n"); 316130985Srik bus_dma_tag_destroy (dmem->dmat); 317130985Srik return 0; 318130985Srik } 319130985Srik error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 320130985Srik dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); 321130985Srik if (error) { 322130985Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 323130985Srik else printf ("cp%d: ", bnum); 324130985Srik printf ("couldn't load mem map for dma memory\n"); 325130985Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 326130985Srik bus_dma_tag_destroy (dmem->dmat); 327130985Srik return 0; 328130985Srik } 329130985Srik return 1; 330130985Srik} 331130985Srik 332130985Srikstatic void 333130985Srikcp_bus_dma_mem_free (cp_dma_mem_t *dmem) 334130985Srik{ 335130985Srik bus_dmamap_unload (dmem->dmat, dmem->mapp); 336130985Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 337130985Srik bus_dma_tag_destroy (dmem->dmat); 338130985Srik} 339130985Srik 340128967Srik/* 341128967Srik * Called if the probe succeeded. 342128967Srik */ 343128967Srikstatic int cp_attach (device_t dev) 344128967Srik{ 345128967Srik bdrv_t *bd = device_get_softc (dev); 346128967Srik int unit = device_get_unit (dev); 347130985Srik unsigned short res; 348130985Srik vm_offset_t vbase; 349128967Srik int rid, error; 350130985Srik cp_board_t *b; 351128967Srik cp_chan_t *c; 352130985Srik drv_t *d; 353128967Srik int s = splimp (); 354128967Srik 355128967Srik b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 356128967Srik if (!b) { 357128967Srik printf ("cp%d: couldn't allocate memory\n", unit); 358128967Srik splx (s); 359128967Srik return (ENXIO); 360128967Srik } 361128967Srik adapter[unit] = b; 362128967Srik bzero (b, sizeof(cp_board_t)); 363128967Srik 364128967Srik bd->board = b; 365128967Srik b->sys = bd; 366129673Sjhb rid = PCIR_BAR(0); 367128967Srik bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 368128967Srik 0, ~0, 1, RF_ACTIVE); 369128967Srik if (! bd->cp_res) { 370128967Srik printf ("cp%d: cannot map memory\n", unit); 371128967Srik free (b, M_DEVBUF); 372128967Srik splx (s); 373128967Srik return (ENXIO); 374128967Srik } 375128967Srik vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 376128967Srik 377128967Srik res = cp_init (b, unit, (u_char*) vbase); 378128967Srik if (res) { 379128967Srik printf ("cp%d: can't init, error code:%x\n", unit, res); 380129673Sjhb bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 381128967Srik free (b, M_DEVBUF); 382128967Srik splx (s); 383128967Srik return (ENXIO); 384128967Srik } 385130985Srik 386130985Srik bd->dmamem.size = sizeof(cp_qbuf_t); 387130985Srik if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 388128967Srik free (b, M_DEVBUF); 389128967Srik splx (s); 390128967Srik return (ENXIO); 391128967Srik } 392130985Srik cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); 393128967Srik 394128967Srik rid = 0; 395128967Srik bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 396128967Srik RF_SHAREABLE | RF_ACTIVE); 397133646Srik if (! bd->cp_irq) { 398128967Srik printf ("cp%d: cannot map interrupt\n", unit); 399128967Srik bus_release_resource (dev, SYS_RES_MEMORY, 400129673Sjhb PCIR_BAR(0), bd->cp_res); 401128967Srik free (b, M_DEVBUF); 402128967Srik splx (s); 403128967Srik return (ENXIO); 404128967Srik } 405128967Srik error = bus_setup_intr (dev, bd->cp_irq, INTR_TYPE_NET, cp_intr, bd, 406128967Srik &bd->cp_intrhand); 407128967Srik if (error) { 408128967Srik printf ("cp%d: cannot set up irq\n", unit); 409128967Srik bus_release_resource (dev, SYS_RES_MEMORY, 410129673Sjhb PCIR_BAR(0), bd->cp_res); 411128967Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 412128967Srik free (b, M_DEVBUF); 413128967Srik splx (s); 414128967Srik return (ENXIO); 415128967Srik } 416128967Srik printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 417128967Srik 418128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 419128967Srik if (! c->type) 420128967Srik continue; 421130985Srik d = &bd->channel[c->num]; 422130985Srik d->dmamem.size = sizeof(cp_buf_t); 423130985Srik if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 424130985Srik continue; 425128967Srik channel [b->num*NCHAN + c->num] = d; 426128967Srik sprintf (d->name, "cp%d.%d", b->num, c->num); 427128967Srik d->board = b; 428128967Srik d->chan = c; 429128967Srik c->sys = d; 430128967Srik#ifdef NETGRAPH 431128967Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 432128967Srik printf ("%s: cannot make common node\n", d->name); 433128967Srik d->node = NULL; 434128967Srik continue; 435128967Srik } 436128967Srik NG_NODE_SET_PRIVATE (d->node, d); 437128967Srik sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 438128967Srik c->board->num*NCHAN + c->num); 439128967Srik if (ng_name_node (d->node, d->nodename)) { 440128967Srik printf ("%s: cannot name node\n", d->nodename); 441128967Srik NG_NODE_UNREF (d->node); 442128967Srik continue; 443128967Srik } 444128967Srik d->queue.ifq_maxlen = IFQ_MAXLEN; 445128967Srik d->hi_queue.ifq_maxlen = IFQ_MAXLEN; 446128967Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 447128967Srik mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 448128967Srik#else /*NETGRAPH*/ 449133646Srik d->pp.pp_if.if_softc = d; 450128967Srik if_initname (&d->pp.pp_if, "cp", b->num * NCHAN + c->num); 451133646Srik d->pp.pp_if.if_mtu = PP_MTU; 452133680Srwatson d->pp.pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST | 453133680Srwatson IFF_NEEDSGIANT; 454133646Srik d->pp.pp_if.if_ioctl = cp_sioctl; 455133646Srik d->pp.pp_if.if_start = cp_ifstart; 456133646Srik d->pp.pp_if.if_watchdog = cp_ifwatchdog; 457133646Srik d->pp.pp_if.if_init = cp_initialize; 458128967Srik sppp_attach (&d->pp.pp_if); 459128967Srik if_attach (&d->pp.pp_if); 460128967Srik d->pp.pp_tlf = cp_tlf; 461128967Srik d->pp.pp_tls = cp_tls; 462128967Srik /* If BPF is in the kernel, call the attach for it. 463128967Srik * The header size of PPP or Cisco/HDLC is 4 bytes. */ 464128967Srik bpfattach (&d->pp.pp_if, DLT_PPP, 4); 465128967Srik#endif /*NETGRAPH*/ 466128967Srik cp_start_e1 (c); 467130985Srik cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 468128967Srik 469128967Srik /* Register callback functions. */ 470128967Srik cp_register_transmit (c, &cp_transmit); 471128967Srik cp_register_receive (c, &cp_receive); 472128967Srik cp_register_error (c, &cp_error); 473128967Srik d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 474128967Srik GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 475128967Srik } 476128967Srik splx (s); 477128967Srik return 0; 478128967Srik} 479128967Srik 480128967Srikstatic int cp_detach (device_t dev) 481128967Srik{ 482128967Srik bdrv_t *bd = device_get_softc (dev); 483133646Srik cp_board_t *b = bd->board; 484128967Srik cp_chan_t *c; 485128967Srik int s = splimp (); 486128967Srik 487128967Srik /* Check if the device is busy (open). */ 488128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 489128967Srik drv_t *d = (drv_t*) c->sys; 490128967Srik 491128967Srik if (! d || ! d->chan->type) 492128967Srik continue; 493128967Srik if (d->running) { 494128967Srik splx (s); 495128967Srik return EBUSY; 496128967Srik } 497128967Srik } 498128967Srik 499128967Srik /* Ok, we can unload driver */ 500128967Srik /* At first we should stop all channels */ 501128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 502128967Srik drv_t *d = (drv_t*) c->sys; 503128967Srik 504128967Srik if (! d || ! d->chan->type) 505128967Srik continue; 506128967Srik 507128967Srik cp_stop_chan (c); 508128967Srik cp_stop_e1 (c); 509128967Srik cp_set_dtr (d->chan, 0); 510128967Srik cp_set_rts (d->chan, 0); 511128967Srik } 512128967Srik 513128967Srik /* Reset the adapter. */ 514128967Srik cp_destroy = 1; 515128967Srik cp_interrupt_poll (b, 1); 516128967Srik cp_led_off (b); 517128967Srik cp_reset (b, 0 ,0); 518128967Srik if (led_timo[b->num].callout) 519128967Srik untimeout (cp_led_off, b, led_timo[b->num]); 520128967Srik 521128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 522128967Srik drv_t *d = (drv_t*) c->sys; 523128967Srik 524128967Srik if (! d || ! d->chan->type) 525128967Srik continue; 526128967Srik#ifndef NETGRAPH 527128967Srik /* Detach from the packet filter list of interfaces. */ 528128967Srik bpfdetach (&d->pp.pp_if); 529128967Srik /* Detach from the sync PPP list. */ 530128967Srik sppp_detach (&d->pp.pp_if); 531128967Srik 532128967Srik /* Detach from the system list of interfaces. */ 533128967Srik if_detach (&d->pp.pp_if); 534128967Srik#else 535128967Srik if (d->node) { 536128967Srik ng_rmnode_self (d->node); 537128967Srik NG_NODE_UNREF (d->node); 538128967Srik d->node = NULL; 539128967Srik } 540128967Srik mtx_destroy (&d->queue.ifq_mtx); 541128967Srik mtx_destroy (&d->hi_queue.ifq_mtx); 542128967Srik#endif 543128967Srik destroy_dev (d->devt); 544128967Srik } 545128967Srik 546128967Srik /* Disable the interrupt request. */ 547128967Srik bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 548128967Srik bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 549128967Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 550129673Sjhb bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 551128967Srik cp_led_off (b); 552128967Srik if (led_timo[b->num].callout) 553128967Srik untimeout (cp_led_off, b, led_timo[b->num]); 554128967Srik splx (s); 555128967Srik 556128967Srik s = splimp (); 557128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 558128967Srik drv_t *d = (drv_t*) c->sys; 559128967Srik 560128967Srik if (! d || ! d->chan->type) 561128967Srik continue; 562128967Srik channel [b->num*NCHAN + c->num] = 0; 563128967Srik /* Deallocate buffers. */ 564130985Srik cp_bus_dma_mem_free (&d->dmamem); 565128967Srik } 566128967Srik adapter [b->num] = 0; 567130985Srik cp_bus_dma_mem_free (&bd->dmamem); 568128967Srik free (b, M_DEVBUF); 569128967Srik splx (s); 570128967Srik return 0; 571128967Srik} 572128967Srik 573128967Srik#ifndef NETGRAPH 574128967Srikstatic void cp_ifstart (struct ifnet *ifp) 575128967Srik{ 576133646Srik drv_t *d = ifp->if_softc; 577128967Srik 578128967Srik cp_start (d); 579128967Srik} 580128967Srik 581128967Srikstatic void cp_ifwatchdog (struct ifnet *ifp) 582128967Srik{ 583133646Srik drv_t *d = ifp->if_softc; 584128967Srik 585128967Srik cp_watchdog (d); 586128967Srik} 587128967Srik 588128967Srikstatic void cp_tlf (struct sppp *sp) 589128967Srik{ 590128967Srik drv_t *d = sp->pp_if.if_softc; 591128967Srik 592128967Srik CP_DEBUG2 (d, ("cp_tlf\n")); 593128967Srik/* cp_set_dtr (d->chan, 0);*/ 594128967Srik/* cp_set_rts (d->chan, 0);*/ 595138352Srik if (!(d->pp.pp_flags & PP_FR) && !(d->pp.pp_if.if_flags & PP_CISCO)) 596138352Srik sp->pp_down (sp); 597128967Srik} 598128967Srik 599128967Srikstatic void cp_tls (struct sppp *sp) 600128967Srik{ 601128967Srik drv_t *d = sp->pp_if.if_softc; 602128967Srik 603128967Srik CP_DEBUG2 (d, ("cp_tls\n")); 604138352Srik if (!(d->pp.pp_flags & PP_FR) && !(d->pp.pp_if.if_flags & PP_CISCO)) 605138352Srik sp->pp_up (sp); 606128967Srik} 607128967Srik 608128967Srik/* 609128967Srik * Process an ioctl request. 610128967Srik */ 611128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 612128967Srik{ 613128967Srik drv_t *d = ifp->if_softc; 614128967Srik int error, s, was_up, should_be_up; 615128967Srik 616128967Srik was_up = (ifp->if_flags & IFF_RUNNING) != 0; 617128967Srik error = sppp_ioctl (ifp, cmd, data); 618128967Srik 619128967Srik if (error) 620128967Srik return error; 621128967Srik 622128967Srik if (! (ifp->if_flags & IFF_DEBUG)) 623128967Srik d->chan->debug = 0; 624128967Srik else if (! d->chan->debug) 625128967Srik d->chan->debug = 1; 626128967Srik 627128967Srik switch (cmd) { 628133646Srik default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 629128967Srik case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 630128967Srik case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 631128967Srik case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 632128967Srik case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 633128967Srik } 634128967Srik 635128967Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 636128967Srik s = splimp (); 637128967Srik should_be_up = (ifp->if_flags & IFF_RUNNING) != 0; 638128967Srik if (! was_up && should_be_up) { 639128967Srik /* Interface goes up -- start it. */ 640128967Srik cp_up (d); 641128967Srik cp_start (d); 642128967Srik } else if (was_up && ! should_be_up) { 643128967Srik /* Interface is going down -- stop it. */ 644128967Srik/* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 645128967Srik cp_down (d); 646128967Srik } 647128967Srik CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 648128967Srik splx (s); 649128967Srik return 0; 650128967Srik} 651128967Srik 652128967Srik/* 653128967Srik * Initialization of interface. 654128967Srik * It seems to be never called by upper level? 655128967Srik */ 656128967Srikstatic void cp_initialize (void *softc) 657128967Srik{ 658128967Srik drv_t *d = softc; 659128967Srik 660128967Srik CP_DEBUG (d, ("cp_initialize\n")); 661128967Srik} 662128967Srik#endif /*NETGRAPH*/ 663128967Srik 664128967Srik/* 665128967Srik * Stop the interface. Called on splimp(). 666128967Srik */ 667128967Srikstatic void cp_down (drv_t *d) 668128967Srik{ 669128967Srik CP_DEBUG (d, ("cp_down\n")); 670128967Srik /* Interface is going down -- stop it. */ 671128967Srik cp_set_dtr (d->chan, 0); 672128967Srik cp_set_rts (d->chan, 0); 673128967Srik 674128967Srik d->running = 0; 675128967Srik} 676128967Srik 677128967Srik/* 678128967Srik * Start the interface. Called on splimp(). 679128967Srik */ 680128967Srikstatic void cp_up (drv_t *d) 681128967Srik{ 682128967Srik CP_DEBUG (d, ("cp_up\n")); 683128967Srik cp_set_dtr (d->chan, 1); 684128967Srik cp_set_rts (d->chan, 1); 685128967Srik d->running = 1; 686128967Srik} 687128967Srik 688128967Srik/* 689128967Srik * Start output on the interface. Get another datagram to send 690128967Srik * off of the interface queue, and copy it to the interface 691128967Srik * before starting the output. 692128967Srik */ 693128967Srikstatic void cp_send (drv_t *d) 694128967Srik{ 695128967Srik struct mbuf *m; 696128967Srik u_short len; 697128967Srik 698128967Srik CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 699128967Srik 700128967Srik /* No output if the interface is down. */ 701128967Srik if (! d->running) 702128967Srik return; 703128967Srik 704128967Srik /* No output if the modem is off. */ 705128967Srik if (! (d->chan->lloop || d->chan->type != T_SERIAL || 706128967Srik cp_get_dsr (d->chan))) 707128967Srik return; 708128967Srik 709128967Srik while (cp_transmit_space (d->chan)) { 710128967Srik /* Get the packet to send. */ 711128967Srik#ifdef NETGRAPH 712128967Srik IF_DEQUEUE (&d->hi_queue, m); 713128967Srik if (! m) 714128967Srik IF_DEQUEUE (&d->queue, m); 715128967Srik#else 716128967Srik m = sppp_dequeue (&d->pp.pp_if); 717128967Srik#endif 718128967Srik if (! m) 719128967Srik return; 720130971Srik#ifndef NETGRAPH 721128967Srik if (d->pp.pp_if.if_bpf) 722128967Srik BPF_MTAP (&d->pp.pp_if, m); 723128967Srik#endif 724128967Srik len = m->m_pkthdr.len; 725128967Srik if (len >= BUFSZ) 726128967Srik printf ("%s: too long packet: %d bytes: ", 727128967Srik d->name, len); 728128967Srik else if (! m->m_next) 729128967Srik cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 730128967Srik else { 731128967Srik u_char *buf = d->chan->tbuf[d->chan->te]; 732128967Srik m_copydata (m, 0, len, buf); 733128967Srik cp_send_packet (d->chan, buf, len, 0); 734128967Srik } 735128967Srik m_freem (m); 736128967Srik /* Set up transmit timeout, if the transmit ring is not empty.*/ 737128967Srik#ifdef NETGRAPH 738128967Srik d->timeout = 10; 739128967Srik#else 740128967Srik d->pp.pp_if.if_timer = 10; 741128967Srik#endif 742128967Srik } 743128967Srik#ifndef NETGRAPH 744128967Srik d->pp.pp_if.if_flags |= IFF_OACTIVE; 745128967Srik#endif 746128967Srik} 747128967Srik 748128967Srik/* 749128967Srik * Start output on the interface. 750128967Srik * Always called on splimp(). 751128967Srik */ 752128967Srikstatic void cp_start (drv_t *d) 753128967Srik{ 754133646Srik if (d->running) { 755128967Srik if (! d->chan->dtr) 756128967Srik cp_set_dtr (d->chan, 1); 757128967Srik if (! d->chan->rts) 758128967Srik cp_set_rts (d->chan, 1); 759128967Srik cp_send (d); 760128967Srik } 761128967Srik} 762128967Srik 763128967Srik/* 764128967Srik * Handle transmit timeouts. 765128967Srik * Recover after lost transmit interrupts. 766128967Srik * Always called on splimp(). 767128967Srik */ 768128967Srikstatic void cp_watchdog (drv_t *d) 769128967Srik{ 770128967Srik CP_DEBUG (d, ("device timeout\n")); 771128967Srik if (d->running) { 772128967Srik int s = splimp (); 773128967Srik 774128967Srik cp_stop_chan (d->chan); 775128967Srik cp_stop_e1 (d->chan); 776128967Srik cp_start_e1 (d->chan); 777128967Srik cp_start_chan (d->chan, 1, 1, 0, 0); 778128967Srik cp_set_dtr (d->chan, 1); 779128967Srik cp_set_rts (d->chan, 1); 780128967Srik cp_start (d); 781128967Srik splx (s); 782128967Srik } 783128967Srik} 784128967Srik 785128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len) 786128967Srik{ 787128967Srik drv_t *d = c->sys; 788128967Srik 789128967Srik#ifdef NETGRAPH 790128967Srik d->timeout = 0; 791128967Srik#else 792128967Srik ++d->pp.pp_if.if_opackets; 793128967Srik d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 794128967Srik d->pp.pp_if.if_timer = 0; 795128967Srik#endif 796128967Srik cp_start (d); 797128967Srik} 798128967Srik 799128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len) 800128967Srik{ 801128967Srik drv_t *d = c->sys; 802128967Srik struct mbuf *m; 803138673Srik#ifdef NETGRAPH 804128967Srik int error; 805128967Srik#endif 806128967Srik 807128967Srik if (! d->running) 808128967Srik return; 809128967Srik 810128967Srik m = makembuf (data, len); 811128967Srik if (! m) { 812128967Srik CP_DEBUG (d, ("no memory for packet\n")); 813128967Srik#ifndef NETGRAPH 814128967Srik ++d->pp.pp_if.if_iqdrops; 815128967Srik#endif 816128967Srik return; 817128967Srik } 818128967Srik if (c->debug > 1) 819128967Srik printmbuf (m); 820128967Srik#ifdef NETGRAPH 821128967Srik m->m_pkthdr.rcvif = 0; 822128967Srik NG_SEND_DATA_ONLY (error, d->hook, m); 823128967Srik#else 824128967Srik ++d->pp.pp_if.if_ipackets; 825128967Srik m->m_pkthdr.rcvif = &d->pp.pp_if; 826128967Srik /* Check if there's a BPF listener on this interface. 827128967Srik * If so, hand off the raw packet to bpf. */ 828128967Srik if (d->pp.pp_if.if_bpf) 829128967Srik BPF_TAP (&d->pp.pp_if, data, len); 830128967Srik sppp_input (&d->pp.pp_if, m); 831128967Srik#endif 832128967Srik} 833128967Srik 834128967Srikstatic void cp_error (cp_chan_t *c, int data) 835128967Srik{ 836128967Srik drv_t *d = c->sys; 837128967Srik 838128967Srik switch (data) { 839128967Srik case CP_FRAME: 840128967Srik CP_DEBUG (d, ("frame error\n")); 841128967Srik#ifndef NETGRAPH 842128967Srik ++d->pp.pp_if.if_ierrors; 843128967Srik#endif 844128967Srik break; 845128967Srik case CP_CRC: 846128967Srik CP_DEBUG (d, ("crc error\n")); 847128967Srik#ifndef NETGRAPH 848128967Srik ++d->pp.pp_if.if_ierrors; 849128967Srik#endif 850128967Srik break; 851128967Srik case CP_OVERRUN: 852128967Srik CP_DEBUG (d, ("overrun error\n")); 853128967Srik#ifndef NETGRAPH 854128967Srik ++d->pp.pp_if.if_collisions; 855128967Srik ++d->pp.pp_if.if_ierrors; 856128967Srik#endif 857128967Srik break; 858128967Srik case CP_OVERFLOW: 859128967Srik CP_DEBUG (d, ("overflow error\n")); 860128967Srik#ifndef NETGRAPH 861128967Srik ++d->pp.pp_if.if_ierrors; 862128967Srik#endif 863128967Srik break; 864128967Srik case CP_UNDERRUN: 865128967Srik CP_DEBUG (d, ("underrun error\n")); 866128967Srik#ifdef NETGRAPH 867128967Srik d->timeout = 0; 868128967Srik#else 869128967Srik ++d->pp.pp_if.if_oerrors; 870128967Srik d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 871128967Srik d->pp.pp_if.if_timer = 0; 872128967Srik#endif 873128967Srik cp_start (d); 874128967Srik break; 875128967Srik default: 876128967Srik CP_DEBUG (d, ("error #%d\n", data)); 877128967Srik break; 878128967Srik } 879128967Srik} 880128967Srik 881128967Srik/* 882128967Srik * You also need read, write, open, close routines. 883128967Srik * This should get you started 884128967Srik */ 885130585Sphkstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 886128967Srik{ 887128967Srik int unit = minor (dev); 888128967Srik drv_t *d; 889128967Srik 890128967Srik if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 891128967Srik return ENXIO; 892128967Srik CP_DEBUG2 (d, ("cp_open\n")); 893128967Srik return 0; 894128967Srik} 895128967Srik 896128967Srik/* 897128967Srik * Only called on the LAST close. 898128967Srik */ 899130585Sphkstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 900128967Srik{ 901128967Srik drv_t *d = channel [minor (dev)]; 902128967Srik 903128967Srik CP_DEBUG2 (d, ("cp_close\n")); 904128967Srik return 0; 905128967Srik} 906128967Srik 907128967Srikstatic int cp_modem_status (cp_chan_t *c) 908128967Srik{ 909128967Srik drv_t *d = c->sys; 910128967Srik int status, s; 911128967Srik 912128967Srik status = d->running ? TIOCM_LE : 0; 913128967Srik s = splimp (); 914128967Srik if (cp_get_cd (c)) status |= TIOCM_CD; 915128967Srik if (cp_get_cts (c)) status |= TIOCM_CTS; 916128967Srik if (cp_get_dsr (c)) status |= TIOCM_DSR; 917128967Srik if (c->dtr) status |= TIOCM_DTR; 918128967Srik if (c->rts) status |= TIOCM_RTS; 919128967Srik splx (s); 920128967Srik return status; 921128967Srik} 922128967Srik 923130585Sphkstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 924128967Srik{ 925133646Srik drv_t *d = channel [minor (dev)]; 926128967Srik cp_chan_t *c = d->chan; 927128967Srik struct serial_statistics *st; 928128967Srik struct e1_statistics *opte1; 929128967Srik struct e3_statistics *opte3; 930128967Srik int error, s; 931128967Srik char mask[16]; 932128967Srik 933128967Srik switch (cmd) { 934128967Srik case SERIAL_GETREGISTERED: 935133646Srik CP_DEBUG2 (d, ("ioctl: getregistered\n")); 936128967Srik bzero (mask, sizeof(mask)); 937128967Srik for (s=0; s<NBRD*NCHAN; ++s) 938128967Srik if (channel [s]) 939128967Srik mask [s/8] |= 1 << (s & 7); 940133646Srik bcopy (mask, data, sizeof (mask)); 941128967Srik return 0; 942128967Srik 943128967Srik#ifndef NETGRAPH 944128967Srik case SERIAL_GETPROTO: 945133646Srik CP_DEBUG2 (d, ("ioctl: getproto\n")); 946133646Srik strcpy ((char*)data, (d->pp.pp_flags & PP_FR) ? "fr" : 947128967Srik (d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp"); 948133646Srik return 0; 949128967Srik 950128967Srik case SERIAL_SETPROTO: 951133646Srik CP_DEBUG2 (d, ("ioctl: setproto\n")); 952133646Srik /* Only for superuser! */ 953133646Srik error = suser (td); 954133646Srik if (error) 955133646Srik return error; 956128967Srik if (d->pp.pp_if.if_flags & IFF_RUNNING) 957128967Srik return EBUSY; 958133646Srik if (! strcmp ("cisco", (char*)data)) { 959133646Srik d->pp.pp_flags &= ~(PP_FR); 960133646Srik d->pp.pp_flags |= PP_KEEPALIVE; 961133646Srik d->pp.pp_if.if_flags |= PP_CISCO; 962133646Srik } else if (! strcmp ("fr", (char*)data) && !PP_FR) { 963133646Srik d->pp.pp_if.if_flags &= ~(PP_CISCO); 964133646Srik d->pp.pp_flags |= PP_FR | PP_KEEPALIVE; 965133646Srik } else if (! strcmp ("ppp", (char*)data)) { 966133646Srik d->pp.pp_flags &= ~PP_FR; 967133646Srik d->pp.pp_flags &= ~PP_KEEPALIVE; 968133646Srik d->pp.pp_if.if_flags &= ~(PP_CISCO); 969133646Srik } else 970128967Srik return EINVAL; 971133646Srik return 0; 972128967Srik 973128967Srik case SERIAL_GETKEEPALIVE: 974133646Srik CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 975133646Srik if ((d->pp.pp_flags & PP_FR) || 976128967Srik (d->pp.pp_if.if_flags & PP_CISCO)) 977128967Srik return EINVAL; 978133646Srik *(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0; 979133646Srik return 0; 980128967Srik 981128967Srik case SERIAL_SETKEEPALIVE: 982133646Srik CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 983133646Srik /* Only for superuser! */ 984133646Srik error = suser (td); 985133646Srik if (error) 986133646Srik return error; 987133646Srik if ((d->pp.pp_flags & PP_FR) || 988128967Srik (d->pp.pp_if.if_flags & PP_CISCO)) 989128967Srik return EINVAL; 990128967Srik s = splimp (); 991133646Srik if (*(int*)data) 992133646Srik d->pp.pp_flags |= PP_KEEPALIVE; 993128967Srik else 994133646Srik d->pp.pp_flags &= ~PP_KEEPALIVE; 995128967Srik splx (s); 996133646Srik return 0; 997128967Srik#endif /*NETGRAPH*/ 998128967Srik 999128967Srik case SERIAL_GETMODE: 1000133646Srik CP_DEBUG2 (d, ("ioctl: getmode\n")); 1001128967Srik *(int*)data = SERIAL_HDLC; 1002133646Srik return 0; 1003128967Srik 1004128967Srik case SERIAL_SETMODE: 1005133646Srik /* Only for superuser! */ 1006133646Srik error = suser (td); 1007133646Srik if (error) 1008133646Srik return error; 1009128967Srik if (*(int*)data != SERIAL_HDLC) 1010128967Srik return EINVAL; 1011133646Srik return 0; 1012128967Srik 1013128967Srik case SERIAL_GETCFG: 1014133646Srik CP_DEBUG2 (d, ("ioctl: getcfg\n")); 1015128967Srik if (c->type != T_E1 || c->unfram) 1016128967Srik return EINVAL; 1017128967Srik *(char*)data = c->board->mux ? 'c' : 'a'; 1018133646Srik return 0; 1019128967Srik 1020128967Srik case SERIAL_SETCFG: 1021133646Srik CP_DEBUG2 (d, ("ioctl: setcfg\n")); 1022133646Srik error = suser (td); 1023133646Srik if (error) 1024133646Srik return error; 1025128967Srik if (c->type != T_E1) 1026128967Srik return EINVAL; 1027133646Srik s = splimp (); 1028128967Srik cp_set_mux (c->board, *((char*)data) == 'c'); 1029133646Srik splx (s); 1030133646Srik return 0; 1031128967Srik 1032128967Srik case SERIAL_GETSTAT: 1033133646Srik CP_DEBUG2 (d, ("ioctl: getstat\n")); 1034133646Srik st = (struct serial_statistics*) data; 1035133646Srik st->rintr = c->rintr; 1036133646Srik st->tintr = c->tintr; 1037133646Srik st->mintr = 0; 1038133646Srik st->ibytes = c->ibytes; 1039133646Srik st->ipkts = c->ipkts; 1040133646Srik st->obytes = c->obytes; 1041133646Srik st->opkts = c->opkts; 1042128967Srik st->ierrs = c->overrun + c->frame + c->crc; 1043128967Srik st->oerrs = c->underrun; 1044133646Srik return 0; 1045128967Srik 1046128967Srik case SERIAL_GETESTAT: 1047133646Srik CP_DEBUG2 (d, ("ioctl: getestat\n")); 1048128967Srik if (c->type != T_E1 && c->type != T_G703) 1049128967Srik return EINVAL; 1050128967Srik opte1 = (struct e1_statistics*) data; 1051128967Srik opte1->status = c->status; 1052128967Srik opte1->cursec = c->cursec; 1053128967Srik opte1->totsec = c->totsec + c->cursec; 1054128967Srik 1055128967Srik opte1->currnt.bpv = c->currnt.bpv; 1056128967Srik opte1->currnt.fse = c->currnt.fse; 1057128967Srik opte1->currnt.crce = c->currnt.crce; 1058128967Srik opte1->currnt.rcrce = c->currnt.rcrce; 1059128967Srik opte1->currnt.uas = c->currnt.uas; 1060128967Srik opte1->currnt.les = c->currnt.les; 1061128967Srik opte1->currnt.es = c->currnt.es; 1062128967Srik opte1->currnt.bes = c->currnt.bes; 1063128967Srik opte1->currnt.ses = c->currnt.ses; 1064128967Srik opte1->currnt.oofs = c->currnt.oofs; 1065128967Srik opte1->currnt.css = c->currnt.css; 1066128967Srik opte1->currnt.dm = c->currnt.dm; 1067128967Srik 1068128967Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1069128967Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1070128967Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1071128967Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1072128967Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1073128967Srik opte1->total.les = c->total.les + c->currnt.les; 1074128967Srik opte1->total.es = c->total.es + c->currnt.es; 1075128967Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1076128967Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1077128967Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1078128967Srik opte1->total.css = c->total.css + c->currnt.css; 1079128967Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1080128967Srik for (s=0; s<48; ++s) { 1081128967Srik opte1->interval[s].bpv = c->interval[s].bpv; 1082128967Srik opte1->interval[s].fse = c->interval[s].fse; 1083128967Srik opte1->interval[s].crce = c->interval[s].crce; 1084128967Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1085128967Srik opte1->interval[s].uas = c->interval[s].uas; 1086128967Srik opte1->interval[s].les = c->interval[s].les; 1087128967Srik opte1->interval[s].es = c->interval[s].es; 1088128967Srik opte1->interval[s].bes = c->interval[s].bes; 1089128967Srik opte1->interval[s].ses = c->interval[s].ses; 1090128967Srik opte1->interval[s].oofs = c->interval[s].oofs; 1091128967Srik opte1->interval[s].css = c->interval[s].css; 1092128967Srik opte1->interval[s].dm = c->interval[s].dm; 1093128967Srik } 1094128967Srik return 0; 1095128967Srik 1096128967Srik case SERIAL_GETE3STAT: 1097133646Srik CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 1098128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1099128967Srik return EINVAL; 1100133646Srik opte3 = (struct e3_statistics*) data; 1101128967Srik 1102128967Srik opte3->status = c->e3status; 1103128967Srik opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 1104128967Srik opte3->totsec = c->e3tsec + opte3->cursec; 1105128967Srik 1106128967Srik opte3->ccv = c->e3ccv; 1107128967Srik opte3->tcv = c->e3tcv + opte3->ccv; 1108128967Srik 1109128967Srik for (s = 0; s < 48; ++s) { 1110128967Srik opte3->icv[s] = c->e3icv[s]; 1111128967Srik } 1112133646Srik return 0; 1113128967Srik 1114128967Srik case SERIAL_CLRSTAT: 1115133646Srik CP_DEBUG2 (d, ("ioctl: clrstat\n")); 1116133646Srik /* Only for superuser! */ 1117133646Srik error = suser (td); 1118133646Srik if (error) 1119133646Srik return error; 1120128967Srik c->rintr = 0; 1121128967Srik c->tintr = 0; 1122128967Srik c->ibytes = 0; 1123128967Srik c->obytes = 0; 1124128967Srik c->ipkts = 0; 1125128967Srik c->opkts = 0; 1126128967Srik c->overrun = 0; 1127128967Srik c->frame = 0; 1128133646Srik c->crc = 0; 1129128967Srik c->underrun = 0; 1130128967Srik bzero (&c->currnt, sizeof (c->currnt)); 1131128967Srik bzero (&c->total, sizeof (c->total)); 1132128967Srik bzero (c->interval, sizeof (c->interval)); 1133128967Srik c->e3ccv = 0; 1134128967Srik c->e3tcv = 0; 1135128967Srik bzero (c->e3icv, sizeof (c->e3icv)); 1136133646Srik return 0; 1137128967Srik 1138128967Srik case SERIAL_GETBAUD: 1139133646Srik CP_DEBUG2 (d, ("ioctl: getbaud\n")); 1140133646Srik *(long*)data = c->baud; 1141133646Srik return 0; 1142128967Srik 1143128967Srik case SERIAL_SETBAUD: 1144133646Srik CP_DEBUG2 (d, ("ioctl: setbaud\n")); 1145133646Srik /* Only for superuser! */ 1146133646Srik error = suser (td); 1147133646Srik if (error) 1148133646Srik return error; 1149133646Srik s = splimp (); 1150133646Srik cp_set_baud (c, *(long*)data); 1151133646Srik splx (s); 1152133646Srik return 0; 1153128967Srik 1154128967Srik case SERIAL_GETLOOP: 1155133646Srik CP_DEBUG2 (d, ("ioctl: getloop\n")); 1156133646Srik *(int*)data = c->lloop; 1157133646Srik return 0; 1158128967Srik 1159128967Srik case SERIAL_SETLOOP: 1160133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1161133646Srik /* Only for superuser! */ 1162133646Srik error = suser (td); 1163133646Srik if (error) 1164133646Srik return error; 1165133646Srik s = splimp (); 1166128967Srik cp_set_lloop (c, *(int*)data); 1167133646Srik splx (s); 1168133646Srik return 0; 1169128967Srik 1170128967Srik case SERIAL_GETDPLL: 1171133646Srik CP_DEBUG2 (d, ("ioctl: getdpll\n")); 1172133646Srik if (c->type != T_SERIAL) 1173133646Srik return EINVAL; 1174133646Srik *(int*)data = c->dpll; 1175133646Srik return 0; 1176128967Srik 1177128967Srik case SERIAL_SETDPLL: 1178133646Srik CP_DEBUG2 (d, ("ioctl: setdpll\n")); 1179133646Srik /* Only for superuser! */ 1180133646Srik error = suser (td); 1181133646Srik if (error) 1182133646Srik return error; 1183133646Srik if (c->type != T_SERIAL) 1184133646Srik return EINVAL; 1185133646Srik s = splimp (); 1186133646Srik cp_set_dpll (c, *(int*)data); 1187133646Srik splx (s); 1188133646Srik return 0; 1189128967Srik 1190128967Srik case SERIAL_GETNRZI: 1191133646Srik CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 1192133646Srik if (c->type != T_SERIAL) 1193133646Srik return EINVAL; 1194133646Srik *(int*)data = c->nrzi; 1195133646Srik return 0; 1196128967Srik 1197128967Srik case SERIAL_SETNRZI: 1198133646Srik CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 1199133646Srik /* Only for superuser! */ 1200133646Srik error = suser (td); 1201133646Srik if (error) 1202133646Srik return error; 1203133646Srik if (c->type != T_SERIAL) 1204133646Srik return EINVAL; 1205133646Srik s = splimp (); 1206133646Srik cp_set_nrzi (c, *(int*)data); 1207133646Srik splx (s); 1208133646Srik return 0; 1209128967Srik 1210128967Srik case SERIAL_GETDEBUG: 1211133646Srik CP_DEBUG2 (d, ("ioctl: getdebug\n")); 1212133646Srik *(int*)data = d->chan->debug; 1213133646Srik return 0; 1214128967Srik 1215128967Srik case SERIAL_SETDEBUG: 1216133646Srik CP_DEBUG2 (d, ("ioctl: setdebug\n")); 1217133646Srik /* Only for superuser! */ 1218133646Srik error = suser (td); 1219133646Srik if (error) 1220133646Srik return error; 1221133646Srik d->chan->debug = *(int*)data; 1222128967Srik#ifndef NETGRAPH 1223128967Srik if (d->chan->debug) 1224128967Srik d->pp.pp_if.if_flags |= IFF_DEBUG; 1225128967Srik else 1226128967Srik d->pp.pp_if.if_flags &= ~IFF_DEBUG; 1227128967Srik#endif 1228133646Srik return 0; 1229128967Srik 1230128967Srik case SERIAL_GETHIGAIN: 1231133646Srik CP_DEBUG2 (d, ("ioctl: gethigain\n")); 1232133646Srik if (c->type != T_E1) 1233133646Srik return EINVAL; 1234133646Srik *(int*)data = c->higain; 1235128967Srik return 0; 1236128967Srik 1237128967Srik case SERIAL_SETHIGAIN: 1238133646Srik CP_DEBUG2 (d, ("ioctl: sethigain\n")); 1239133646Srik /* Only for superuser! */ 1240133646Srik error = suser (td); 1241133646Srik if (error) 1242133646Srik return error; 1243133646Srik if (c->type != T_E1) 1244133646Srik return EINVAL; 1245128967Srik s = splimp (); 1246128967Srik cp_set_higain (c, *(int*)data); 1247128967Srik splx (s); 1248128967Srik return 0; 1249128967Srik 1250128967Srik case SERIAL_GETPHONY: 1251128967Srik CP_DEBUG2 (d, ("ioctl: getphony\n")); 1252133646Srik if (c->type != T_E1) 1253133646Srik return EINVAL; 1254133646Srik *(int*)data = c->phony; 1255128967Srik return 0; 1256128967Srik 1257128967Srik case SERIAL_SETPHONY: 1258128967Srik CP_DEBUG2 (d, ("ioctl: setphony\n")); 1259133646Srik /* Only for superuser! */ 1260133646Srik error = suser (td); 1261133646Srik if (error) 1262133646Srik return error; 1263133646Srik if (c->type != T_E1) 1264133646Srik return EINVAL; 1265128967Srik s = splimp (); 1266128967Srik cp_set_phony (c, *(int*)data); 1267128967Srik splx (s); 1268128967Srik return 0; 1269128967Srik 1270128967Srik case SERIAL_GETUNFRAM: 1271128967Srik CP_DEBUG2 (d, ("ioctl: getunfram\n")); 1272133646Srik if (c->type != T_E1) 1273133646Srik return EINVAL; 1274133646Srik *(int*)data = c->unfram; 1275128967Srik return 0; 1276128967Srik 1277128967Srik case SERIAL_SETUNFRAM: 1278128967Srik CP_DEBUG2 (d, ("ioctl: setunfram\n")); 1279133646Srik /* Only for superuser! */ 1280133646Srik error = suser (td); 1281133646Srik if (error) 1282133646Srik return error; 1283133646Srik if (c->type != T_E1) 1284133646Srik return EINVAL; 1285128967Srik s = splimp (); 1286128967Srik cp_set_unfram (c, *(int*)data); 1287128967Srik splx (s); 1288128967Srik return 0; 1289128967Srik 1290128967Srik case SERIAL_GETSCRAMBLER: 1291128967Srik CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 1292133646Srik if (c->type != T_G703 && !c->unfram) 1293133646Srik return EINVAL; 1294133646Srik *(int*)data = c->scrambler; 1295128967Srik return 0; 1296128967Srik 1297128967Srik case SERIAL_SETSCRAMBLER: 1298128967Srik CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 1299133646Srik /* Only for superuser! */ 1300133646Srik error = suser (td); 1301133646Srik if (error) 1302133646Srik return error; 1303133646Srik if (c->type != T_G703 && !c->unfram) 1304133646Srik return EINVAL; 1305128967Srik s = splimp (); 1306128967Srik cp_set_scrambler (c, *(int*)data); 1307128967Srik splx (s); 1308128967Srik return 0; 1309128967Srik 1310128967Srik case SERIAL_GETMONITOR: 1311128967Srik CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 1312133646Srik if (c->type != T_E1 && 1313128967Srik c->type != T_E3 && 1314128967Srik c->type != T_T3 && 1315128967Srik c->type != T_STS1) 1316133646Srik return EINVAL; 1317133646Srik *(int*)data = c->monitor; 1318128967Srik return 0; 1319128967Srik 1320128967Srik case SERIAL_SETMONITOR: 1321128967Srik CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 1322133646Srik /* Only for superuser! */ 1323133646Srik error = suser (td); 1324133646Srik if (error) 1325133646Srik return error; 1326133646Srik if (c->type != T_E1) 1327133646Srik return EINVAL; 1328128967Srik s = splimp (); 1329128967Srik cp_set_monitor (c, *(int*)data); 1330128967Srik splx (s); 1331128967Srik return 0; 1332128967Srik 1333128967Srik case SERIAL_GETUSE16: 1334133646Srik CP_DEBUG2 (d, ("ioctl: getuse16\n")); 1335133646Srik if (c->type != T_E1 || c->unfram) 1336133646Srik return EINVAL; 1337133646Srik *(int*)data = c->use16; 1338128967Srik return 0; 1339128967Srik 1340128967Srik case SERIAL_SETUSE16: 1341133646Srik CP_DEBUG2 (d, ("ioctl: setuse16\n")); 1342133646Srik /* Only for superuser! */ 1343133646Srik error = suser (td); 1344133646Srik if (error) 1345133646Srik return error; 1346133646Srik if (c->type != T_E1) 1347133646Srik return EINVAL; 1348128967Srik s = splimp (); 1349128967Srik cp_set_use16 (c, *(int*)data); 1350128967Srik splx (s); 1351128967Srik return 0; 1352128967Srik 1353128967Srik case SERIAL_GETCRC4: 1354133646Srik CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 1355133646Srik if (c->type != T_E1 || c->unfram) 1356133646Srik return EINVAL; 1357133646Srik *(int*)data = c->crc4; 1358128967Srik return 0; 1359128967Srik 1360128967Srik case SERIAL_SETCRC4: 1361133646Srik CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 1362133646Srik /* Only for superuser! */ 1363133646Srik error = suser (td); 1364133646Srik if (error) 1365133646Srik return error; 1366133646Srik if (c->type != T_E1) 1367133646Srik return EINVAL; 1368128967Srik s = splimp (); 1369128967Srik cp_set_crc4 (c, *(int*)data); 1370128967Srik splx (s); 1371128967Srik return 0; 1372128967Srik 1373128967Srik case SERIAL_GETCLK: 1374133646Srik CP_DEBUG2 (d, ("ioctl: getclk\n")); 1375133646Srik if (c->type != T_E1 && 1376128967Srik c->type != T_G703 && 1377128967Srik c->type != T_E3 && 1378128967Srik c->type != T_T3 && 1379128967Srik c->type != T_STS1) 1380133646Srik return EINVAL; 1381128967Srik switch (c->gsyn) { 1382128967Srik default: *(int*)data = E1CLK_INTERNAL; break; 1383128967Srik case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1384128967Srik case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1385128967Srik case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1386128967Srik case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 1387128967Srik case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 1388128967Srik } 1389128967Srik return 0; 1390128967Srik 1391128967Srik case SERIAL_SETCLK: 1392133646Srik CP_DEBUG2 (d, ("ioctl: setclk\n")); 1393133646Srik /* Only for superuser! */ 1394133646Srik error = suser (td); 1395133646Srik if (error) 1396133646Srik return error; 1397128967Srik if (c->type != T_E1 && 1398128967Srik c->type != T_G703 && 1399128967Srik c->type != T_E3 && 1400128967Srik c->type != T_T3 && 1401128967Srik c->type != T_STS1) 1402133646Srik return EINVAL; 1403128967Srik s = splimp (); 1404128967Srik switch (*(int*)data) { 1405128967Srik default: cp_set_gsyn (c, GSYN_INT); break; 1406128967Srik case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 1407128967Srik case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 1408128967Srik case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 1409128967Srik case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 1410128967Srik case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 1411128967Srik } 1412128967Srik splx (s); 1413128967Srik return 0; 1414128967Srik 1415128967Srik case SERIAL_GETTIMESLOTS: 1416133646Srik CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1417133646Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1418133646Srik return EINVAL; 1419133646Srik *(u_long*)data = c->ts; 1420128967Srik return 0; 1421128967Srik 1422128967Srik case SERIAL_SETTIMESLOTS: 1423133646Srik CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 1424133646Srik /* Only for superuser! */ 1425133646Srik error = suser (td); 1426133646Srik if (error) 1427133646Srik return error; 1428128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1429133646Srik return EINVAL; 1430128967Srik s = splimp (); 1431128967Srik cp_set_ts (c, *(u_long*)data); 1432128967Srik splx (s); 1433128967Srik return 0; 1434128967Srik 1435128967Srik case SERIAL_GETINVCLK: 1436133646Srik CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 1437128967Srik#if 1 1438128967Srik return EINVAL; 1439128967Srik#else 1440133646Srik if (c->type != T_SERIAL) 1441133646Srik return EINVAL; 1442133646Srik *(int*)data = c->invtxc; 1443128967Srik return 0; 1444128967Srik#endif 1445128967Srik 1446128967Srik case SERIAL_SETINVCLK: 1447133646Srik CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 1448133646Srik /* Only for superuser! */ 1449133646Srik error = suser (td); 1450133646Srik if (error) 1451133646Srik return error; 1452133646Srik if (c->type != T_SERIAL) 1453133646Srik return EINVAL; 1454128967Srik s = splimp (); 1455128967Srik cp_set_invtxc (c, *(int*)data); 1456128967Srik cp_set_invrxc (c, *(int*)data); 1457128967Srik splx (s); 1458128967Srik return 0; 1459128967Srik 1460128967Srik case SERIAL_GETINVTCLK: 1461133646Srik CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 1462133646Srik if (c->type != T_SERIAL) 1463133646Srik return EINVAL; 1464133646Srik *(int*)data = c->invtxc; 1465128967Srik return 0; 1466128967Srik 1467128967Srik case SERIAL_SETINVTCLK: 1468133646Srik CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 1469133646Srik /* Only for superuser! */ 1470133646Srik error = suser (td); 1471133646Srik if (error) 1472133646Srik return error; 1473133646Srik if (c->type != T_SERIAL) 1474133646Srik return EINVAL; 1475128967Srik s = splimp (); 1476128967Srik cp_set_invtxc (c, *(int*)data); 1477128967Srik splx (s); 1478128967Srik return 0; 1479128967Srik 1480128967Srik case SERIAL_GETINVRCLK: 1481133646Srik CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 1482133646Srik if (c->type != T_SERIAL) 1483133646Srik return EINVAL; 1484133646Srik *(int*)data = c->invrxc; 1485128967Srik return 0; 1486128967Srik 1487128967Srik case SERIAL_SETINVRCLK: 1488133646Srik CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 1489133646Srik /* Only for superuser! */ 1490133646Srik error = suser (td); 1491133646Srik if (error) 1492133646Srik return error; 1493133646Srik if (c->type != T_SERIAL) 1494133646Srik return EINVAL; 1495128967Srik s = splimp (); 1496128967Srik cp_set_invrxc (c, *(int*)data); 1497128967Srik splx (s); 1498128967Srik return 0; 1499128967Srik 1500128967Srik case SERIAL_GETLEVEL: 1501133646Srik CP_DEBUG2 (d, ("ioctl: getlevel\n")); 1502133646Srik if (c->type != T_G703) 1503133646Srik return EINVAL; 1504128967Srik s = splimp (); 1505133646Srik *(int*)data = cp_get_lq (c); 1506128967Srik splx (s); 1507128967Srik return 0; 1508128967Srik 1509128967Srik#if 0 1510128967Srik case SERIAL_RESET: 1511133646Srik CP_DEBUG2 (d, ("ioctl: reset\n")); 1512133646Srik /* Only for superuser! */ 1513133646Srik error = suser (td); 1514133646Srik if (error) 1515133646Srik return error; 1516128967Srik s = splimp (); 1517128967Srik cp_reset (c->board, 0, 0); 1518128967Srik splx (s); 1519128967Srik return 0; 1520128967Srik 1521128967Srik case SERIAL_HARDRESET: 1522133646Srik CP_DEBUG2 (d, ("ioctl: hardreset\n")); 1523133646Srik /* Only for superuser! */ 1524133646Srik error = suser (td); 1525133646Srik if (error) 1526133646Srik return error; 1527128967Srik s = splimp (); 1528128967Srik /* hard_reset (c->board); */ 1529128967Srik splx (s); 1530128967Srik return 0; 1531128967Srik#endif 1532128967Srik 1533128967Srik case SERIAL_GETCABLE: 1534133646Srik CP_DEBUG2 (d, ("ioctl: getcable\n")); 1535133646Srik if (c->type != T_SERIAL) 1536133646Srik return EINVAL; 1537128967Srik s = splimp (); 1538128967Srik *(int*)data = cp_get_cable (c); 1539128967Srik splx (s); 1540128967Srik return 0; 1541128967Srik 1542128967Srik case SERIAL_GETDIR: 1543133646Srik CP_DEBUG2 (d, ("ioctl: getdir\n")); 1544133646Srik if (c->type != T_E1 && c->type != T_DATA) 1545133646Srik return EINVAL; 1546128967Srik *(int*)data = c->dir; 1547128967Srik return 0; 1548128967Srik 1549128967Srik case SERIAL_SETDIR: 1550133646Srik CP_DEBUG2 (d, ("ioctl: setdir\n")); 1551133646Srik /* Only for superuser! */ 1552133646Srik error = suser (td); 1553133646Srik if (error) 1554133646Srik return error; 1555128967Srik s = splimp (); 1556128967Srik cp_set_dir (c, *(int*)data); 1557128967Srik splx (s); 1558128967Srik return 0; 1559128967Srik 1560128967Srik case SERIAL_GETRLOOP: 1561133646Srik CP_DEBUG2 (d, ("ioctl: getrloop\n")); 1562133646Srik if (c->type != T_G703 && 1563128967Srik c->type != T_E3 && 1564128967Srik c->type != T_T3 && 1565128967Srik c->type != T_STS1) 1566133646Srik return EINVAL; 1567133646Srik *(int*)data = cp_get_rloop (c); 1568133646Srik return 0; 1569128967Srik 1570128967Srik case SERIAL_SETRLOOP: 1571133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1572133646Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1573133646Srik return EINVAL; 1574133646Srik /* Only for superuser! */ 1575133646Srik error = suser (td); 1576133646Srik if (error) 1577133646Srik return error; 1578133646Srik s = splimp (); 1579128967Srik cp_set_rloop (c, *(int*)data); 1580133646Srik splx (s); 1581133646Srik return 0; 1582128967Srik 1583128967Srik case SERIAL_GETCABLEN: 1584133646Srik CP_DEBUG2 (d, ("ioctl: getcablen\n")); 1585133646Srik if (c->type != T_T3 && c->type != T_STS1) 1586133646Srik return EINVAL; 1587133646Srik *(int*)data = c->cablen; 1588133646Srik return 0; 1589128967Srik 1590128967Srik case SERIAL_SETCABLEN: 1591133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1592133646Srik if (c->type != T_T3 && c->type != T_STS1) 1593133646Srik return EINVAL; 1594133646Srik /* Only for superuser! */ 1595133646Srik error = suser (td); 1596133646Srik if (error) 1597133646Srik return error; 1598133646Srik s = splimp (); 1599128967Srik cp_set_cablen (c, *(int*)data); 1600133646Srik splx (s); 1601133646Srik return 0; 1602128967Srik 1603133646Srik case TIOCSDTR: /* Set DTR */ 1604128967Srik s = splimp (); 1605128967Srik cp_set_dtr (c, 1); 1606128967Srik splx (s); 1607128967Srik return 0; 1608128967Srik 1609133646Srik case TIOCCDTR: /* Clear DTR */ 1610128967Srik s = splimp (); 1611128967Srik cp_set_dtr (c, 0); 1612128967Srik splx (s); 1613128967Srik return 0; 1614128967Srik 1615133646Srik case TIOCMSET: /* Set DTR/RTS */ 1616128967Srik s = splimp (); 1617128967Srik cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1618128967Srik cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1619128967Srik splx (s); 1620128967Srik return 0; 1621128967Srik 1622133646Srik case TIOCMBIS: /* Add DTR/RTS */ 1623128967Srik s = splimp (); 1624128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 1625128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 1626128967Srik splx (s); 1627128967Srik return 0; 1628128967Srik 1629133646Srik case TIOCMBIC: /* Clear DTR/RTS */ 1630128967Srik s = splimp (); 1631128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1632128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1633128967Srik splx (s); 1634128967Srik return 0; 1635128967Srik 1636133646Srik case TIOCMGET: /* Get modem status */ 1637128967Srik *(int*)data = cp_modem_status (c); 1638128967Srik return 0; 1639128967Srik } 1640128967Srik return ENOTTY; 1641128967Srik} 1642128967Srik 1643128967Srikstatic struct cdevsw cp_cdevsw = { 1644128967Srik .d_version = D_VERSION, 1645128967Srik .d_open = cp_open, 1646128967Srik .d_close = cp_close, 1647128967Srik .d_ioctl = cp_ioctl, 1648128967Srik .d_name = "cp", 1649128967Srik .d_maj = CDEV_MAJOR, 1650128967Srik .d_flags = D_NEEDGIANT, 1651128967Srik}; 1652128967Srik 1653128967Srik#ifdef NETGRAPH 1654128967Srikstatic int ng_cp_constructor (node_p node) 1655128967Srik{ 1656128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1657128967Srik CP_DEBUG (d, ("Constructor\n")); 1658128967Srik return EINVAL; 1659128967Srik} 1660128967Srik 1661128967Srikstatic int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1662128967Srik{ 1663128967Srik int s; 1664128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1665128967Srik 1666128967Srik CP_DEBUG (d, ("Newhook\n")); 1667128967Srik /* Attach debug hook */ 1668128967Srik if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1669128967Srik NG_HOOK_SET_PRIVATE (hook, NULL); 1670128967Srik d->debug_hook = hook; 1671128967Srik return 0; 1672128967Srik } 1673128967Srik 1674128967Srik /* Check for raw hook */ 1675128967Srik if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1676128967Srik return EINVAL; 1677128967Srik 1678128967Srik NG_HOOK_SET_PRIVATE (hook, d); 1679128967Srik d->hook = hook; 1680128967Srik s = splimp (); 1681128967Srik cp_up (d); 1682128967Srik splx (s); 1683128967Srik return 0; 1684128967Srik} 1685128967Srik 1686128967Srikstatic char *format_timeslots (u_long s) 1687128967Srik{ 1688128967Srik static char buf [100]; 1689128967Srik char *p = buf; 1690128967Srik int i; 1691128967Srik 1692128967Srik for (i=1; i<32; ++i) 1693128967Srik if ((s >> i) & 1) { 1694128967Srik int prev = (i > 1) & (s >> (i-1)); 1695128967Srik int next = (i < 31) & (s >> (i+1)); 1696128967Srik 1697128967Srik if (prev) { 1698128967Srik if (next) 1699128967Srik continue; 1700128967Srik *p++ = '-'; 1701128967Srik } else if (p > buf) 1702128967Srik *p++ = ','; 1703128967Srik 1704128967Srik if (i >= 10) 1705128967Srik *p++ = '0' + i / 10; 1706128967Srik *p++ = '0' + i % 10; 1707128967Srik } 1708128967Srik *p = 0; 1709128967Srik return buf; 1710128967Srik} 1711128967Srik 1712128967Srikstatic int print_modems (char *s, cp_chan_t *c, int need_header) 1713128967Srik{ 1714128967Srik int status = cp_modem_status (c); 1715128967Srik int length = 0; 1716128967Srik 1717128967Srik if (need_header) 1718128967Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1719128967Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1720128967Srik status & TIOCM_LE ? "On" : "-", 1721128967Srik status & TIOCM_DTR ? "On" : "-", 1722128967Srik status & TIOCM_DSR ? "On" : "-", 1723128967Srik status & TIOCM_RTS ? "On" : "-", 1724128967Srik status & TIOCM_CTS ? "On" : "-", 1725128967Srik status & TIOCM_CD ? "On" : "-"); 1726128967Srik return length; 1727128967Srik} 1728128967Srik 1729128967Srikstatic int print_stats (char *s, cp_chan_t *c, int need_header) 1730128967Srik{ 1731128967Srik int length = 0; 1732128967Srik 1733128967Srik if (need_header) 1734128967Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1735128967Srik length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1736128967Srik c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1737128967Srik c->ipkts, c->overrun + c->frame + c->crc, 1738128967Srik (unsigned long) c->obytes, c->opkts, c->underrun); 1739128967Srik return length; 1740128967Srik} 1741128967Srik 1742128967Srikstatic char *format_e1_status (u_char status) 1743128967Srik{ 1744128967Srik static char buf [80]; 1745128967Srik 1746128967Srik if (status & E1_NOALARM) 1747128967Srik return "Ok"; 1748128967Srik buf[0] = 0; 1749128967Srik if (status & E1_LOS) strcat (buf, ",LOS"); 1750128967Srik if (status & E1_AIS) strcat (buf, ",AIS"); 1751128967Srik if (status & E1_LOF) strcat (buf, ",LOF"); 1752128967Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 1753128967Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1754128967Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 1755128967Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1756128967Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1757128967Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1758128967Srik if (buf[0] == ',') 1759128967Srik return buf+1; 1760128967Srik return "Unknown"; 1761128967Srik} 1762128967Srik 1763128967Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1764128967Srik{ 1765128967Srik int n, length = 0; 1766128967Srik 1767128967Srik if (numerator < 1 || divider < 1) { 1768128967Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 1769128967Srik return length; 1770128967Srik } 1771128967Srik n = (int) (0.5 + 1000.0 * numerator / divider); 1772128967Srik if (n < 1000) { 1773128967Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1774128967Srik return length; 1775128967Srik } 1776128967Srik *(s + length) = leftalign ? '/' : ' '; 1777128967Srik length ++; 1778128967Srik 1779128967Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 1780128967Srik else if (n >= 100000) n = (n+50) / 100 * 100; 1781128967Srik else if (n >= 10000) n = (n+5) / 10 * 10; 1782128967Srik 1783128967Srik switch (n) { 1784128967Srik case 1000: length += printf (s+length, ".999"); return length; 1785128967Srik case 10000: n = 9990; break; 1786128967Srik case 100000: n = 99900; break; 1787128967Srik case 1000000: n = 999000; break; 1788128967Srik } 1789133646Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1790128967Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1791128967Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1792133646Srik else length += sprintf (s+length, "%d", n/1000); 1793128967Srik 1794128967Srik return length; 1795128967Srik} 1796128967Srik 1797128967Srikstatic int print_e1_stats (char *s, cp_chan_t *c) 1798128967Srik{ 1799128967Srik struct e1_counters total; 1800128967Srik u_long totsec; 1801128967Srik int length = 0; 1802128967Srik 1803128967Srik totsec = c->totsec + c->cursec; 1804128967Srik total.bpv = c->total.bpv + c->currnt.bpv; 1805128967Srik total.fse = c->total.fse + c->currnt.fse; 1806128967Srik total.crce = c->total.crce + c->currnt.crce; 1807128967Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 1808128967Srik total.uas = c->total.uas + c->currnt.uas; 1809128967Srik total.les = c->total.les + c->currnt.les; 1810128967Srik total.es = c->total.es + c->currnt.es; 1811128967Srik total.bes = c->total.bes + c->currnt.bes; 1812128967Srik total.ses = c->total.ses + c->currnt.ses; 1813128967Srik total.oofs = c->total.oofs + c->currnt.oofs; 1814128967Srik total.css = c->total.css + c->currnt.css; 1815128967Srik total.dm = c->total.dm + c->currnt.dm; 1816128967Srik 1817128967Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1818128967Srik 1819128967Srik /* Unavailable seconds, degraded minutes */ 1820128967Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1821128967Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1822128967Srik 1823128967Srik /* Bipolar violations, frame sync errors */ 1824128967Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1825128967Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1826128967Srik 1827128967Srik /* CRC errors, remote CRC errors (E-bit) */ 1828128967Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 1829128967Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 1830128967Srik 1831128967Srik /* Errored seconds, line errored seconds */ 1832128967Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 1833128967Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 1834128967Srik 1835128967Srik /* Severely errored seconds, burst errored seconds */ 1836128967Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 1837128967Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 1838128967Srik 1839128967Srik /* Out of frame seconds, controlled slip seconds */ 1840128967Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 1841128967Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 1842128967Srik 1843128967Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 1844128967Srik 1845128967Srik /* Print total statistics. */ 1846128967Srik length += print_frac (s + length, 0, total.uas, totsec); 1847128967Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 1848128967Srik 1849128967Srik length += print_frac (s + length, 0, total.bpv, totsec); 1850128967Srik length += print_frac (s + length, 1, total.fse, totsec); 1851128967Srik 1852128967Srik length += print_frac (s + length, 0, total.crce, totsec); 1853128967Srik length += print_frac (s + length, 1, total.rcrce, totsec); 1854128967Srik 1855128967Srik length += print_frac (s + length, 0, total.es, totsec); 1856128967Srik length += print_frac (s + length, 1, total.les, totsec); 1857128967Srik 1858128967Srik length += print_frac (s + length, 0, total.ses, totsec); 1859128967Srik length += print_frac (s + length, 1, total.bes, totsec); 1860128967Srik 1861128967Srik length += print_frac (s + length, 0, total.oofs, totsec); 1862128967Srik length += print_frac (s + length, 1, total.css, totsec); 1863128967Srik 1864128967Srik length += sprintf (s + length, " -- Total\n"); 1865128967Srik return length; 1866128967Srik} 1867128967Srik 1868128967Srikstatic int print_chan (char *s, cp_chan_t *c) 1869128967Srik{ 1870128967Srik drv_t *d = c->sys; 1871128967Srik int length = 0; 1872128967Srik 1873128967Srik length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 1874128967Srik if (d->chan->debug) 1875128967Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 1876128967Srik 1877128967Srik if (c->board->mux) { 1878128967Srik length += sprintf (s + length, " cfg=C"); 1879128967Srik } else { 1880128967Srik length += sprintf (s + length, " cfg=A"); 1881128967Srik } 1882128967Srik 1883128967Srik if (c->baud) 1884128967Srik length += sprintf (s + length, " %ld", c->baud); 1885128967Srik else 1886128967Srik length += sprintf (s + length, " extclock"); 1887128967Srik 1888128967Srik if (c->type == T_E1 || c->type == T_G703) 1889128967Srik switch (c->gsyn) { 1890128967Srik case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 1891128967Srik case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 1892128967Srik case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 1893128967Srik case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 1894128967Srik case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 1895128967Srik case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 1896128967Srik } 1897128967Srik if (c->type == T_SERIAL) { 1898128967Srik length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 1899128967Srik length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 1900128967Srik length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 1901128967Srik } 1902128967Srik if (c->type == T_E1) 1903128967Srik length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 1904128967Srik 1905128967Srik length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 1906128967Srik 1907128967Srik if (c->type == T_E1) 1908128967Srik length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 1909128967Srik if (c->type == T_G703) { 1910128967Srik int lq, x; 1911128967Srik 1912128967Srik x = splimp (); 1913128967Srik lq = cp_get_lq (c); 1914128967Srik splx (x); 1915128967Srik length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 1916128967Srik } 1917128967Srik length += sprintf (s + length, "\n"); 1918128967Srik return length; 1919128967Srik} 1920128967Srik 1921128967Srikstatic int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 1922128967Srik{ 1923128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1924128967Srik struct ng_mesg *msg; 1925128967Srik struct ng_mesg *resp = NULL; 1926128967Srik int error = 0; 1927128967Srik 1928128967Srik CP_DEBUG (d, ("Rcvmsg\n")); 1929128967Srik NGI_GET_MSG (item, msg); 1930128967Srik switch (msg->header.typecookie) { 1931128967Srik default: 1932128967Srik error = EINVAL; 1933128967Srik break; 1934128967Srik 1935128967Srik case NGM_CP_COOKIE: 1936128967Srik printf ("Not implemented yet\n"); 1937128967Srik error = EINVAL; 1938128967Srik break; 1939128967Srik 1940128967Srik case NGM_GENERIC_COOKIE: 1941128967Srik switch (msg->header.cmd) { 1942128967Srik default: 1943128967Srik error = EINVAL; 1944128967Srik break; 1945128967Srik 1946128967Srik case NGM_TEXT_STATUS: { 1947128967Srik char *s; 1948128967Srik int l = 0; 1949128967Srik int dl = sizeof (struct ng_mesg) + 730; 1950128967Srik 1951128967Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 1952128967Srik if (! resp) { 1953128967Srik error = ENOMEM; 1954128967Srik break; 1955128967Srik } 1956128967Srik s = (resp)->data; 1957128967Srik if (d) { 1958128967Srik l += print_chan (s + l, d->chan); 1959128967Srik l += print_stats (s + l, d->chan, 1); 1960128967Srik l += print_modems (s + l, d->chan, 1); 1961128967Srik l += print_e1_stats (s + l, d->chan); 1962128967Srik } else 1963128967Srik l += sprintf (s + l, "Error: node not connect to channel"); 1964128967Srik strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 1965128967Srik } 1966128967Srik break; 1967128967Srik } 1968128967Srik break; 1969128967Srik } 1970128967Srik NG_RESPOND_MSG (error, node, item, resp); 1971128967Srik NG_FREE_MSG (msg); 1972128967Srik return error; 1973128967Srik} 1974128967Srik 1975128967Srikstatic int ng_cp_rcvdata (hook_p hook, item_p item) 1976128967Srik{ 1977128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 1978128967Srik struct mbuf *m; 1979131108Sjulian struct ng_tag_prio *ptag; 1980128967Srik struct ifqueue *q; 1981128967Srik int s; 1982128967Srik 1983128967Srik CP_DEBUG2 (d, ("Rcvdata\n")); 1984128967Srik NGI_GET_M (item, m); 1985128967Srik NG_FREE_ITEM (item); 1986128967Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 1987128967Srik NG_FREE_M (m); 1988128967Srik return ENETDOWN; 1989128967Srik } 1990131108Sjulian 1991131108Sjulian /* Check for high priority data */ 1992131108Sjulian if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 1993131108Sjulian NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 1994131108Sjulian q = &d->hi_queue; 1995131108Sjulian else 1996131108Sjulian q = &d->queue; 1997131108Sjulian 1998128967Srik s = splimp (); 1999128967Srik IF_LOCK (q); 2000128967Srik if (_IF_QFULL (q)) { 2001128967Srik _IF_DROP (q); 2002128967Srik IF_UNLOCK (q); 2003128967Srik splx (s); 2004128967Srik NG_FREE_M (m); 2005128967Srik return ENOBUFS; 2006128967Srik } 2007128967Srik _IF_ENQUEUE (q, m); 2008128967Srik IF_UNLOCK (q); 2009128967Srik cp_start (d); 2010128967Srik splx (s); 2011128967Srik return 0; 2012128967Srik} 2013128967Srik 2014128967Srikstatic int ng_cp_rmnode (node_p node) 2015128967Srik{ 2016128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2017128967Srik 2018128967Srik CP_DEBUG (d, ("Rmnode\n")); 2019128967Srik if (d && d->running) { 2020128967Srik int s = splimp (); 2021128967Srik cp_down (d); 2022128967Srik splx (s); 2023128967Srik } 2024128967Srik#ifdef KLD_MODULE 2025132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 2026128967Srik NG_NODE_SET_PRIVATE (node, NULL); 2027128967Srik NG_NODE_UNREF (node); 2028128967Srik } 2029132464Sjulian NG_NODE_REVIVE(node); /* Persistant node */ 2030128967Srik#endif 2031128967Srik return 0; 2032128967Srik} 2033128967Srik 2034128967Srikstatic void ng_cp_watchdog (void *arg) 2035128967Srik{ 2036128967Srik drv_t *d = arg; 2037128967Srik 2038128967Srik if (d) { 2039128967Srik if (d->timeout == 1) 2040128967Srik cp_watchdog (d); 2041128967Srik if (d->timeout) 2042128967Srik d->timeout--; 2043128967Srik d->timeout_handle = timeout (ng_cp_watchdog, d, hz); 2044128967Srik } 2045128967Srik} 2046128967Srik 2047128967Srikstatic int ng_cp_connect (hook_p hook) 2048128967Srik{ 2049128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2050128967Srik 2051128967Srik if (d) { 2052128967Srik CP_DEBUG (d, ("Connect\n")); 2053128967Srik d->timeout_handle = timeout (ng_cp_watchdog, d, hz); 2054128967Srik } 2055128967Srik 2056128967Srik return 0; 2057128967Srik} 2058128967Srik 2059128967Srikstatic int ng_cp_disconnect (hook_p hook) 2060128967Srik{ 2061128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2062128967Srik 2063128967Srik if (d) { 2064128967Srik CP_DEBUG (d, ("Disconnect\n")); 2065128967Srik if (NG_HOOK_PRIVATE (hook)) 2066128967Srik { 2067128967Srik int s = splimp (); 2068128967Srik cp_down (d); 2069128967Srik splx (s); 2070128967Srik } 2071128967Srik untimeout (ng_cp_watchdog, d, d->timeout_handle); 2072128967Srik } 2073128967Srik return 0; 2074128967Srik} 2075128967Srik#endif 2076128967Srik 2077128967Srikstatic int cp_modevent (module_t mod, int type, void *unused) 2078128967Srik{ 2079128967Srik static int load_count = 0; 2080128967Srik 2081128967Srik switch (type) { 2082128967Srik case MOD_LOAD: 2083138673Srik#ifdef NETGRAPH 2084128967Srik if (ng_newtype (&typestruct)) 2085128967Srik printf ("Failed to register ng_cp\n"); 2086128967Srik#endif 2087128967Srik ++load_count; 2088128967Srik timeout_handle = timeout (cp_timeout, 0, hz*5); 2089128967Srik break; 2090128967Srik case MOD_UNLOAD: 2091128967Srik if (load_count == 1) { 2092128967Srik printf ("Removing device entry for Tau-PCI\n"); 2093138673Srik#ifdef NETGRAPH 2094128967Srik ng_rmtype (&typestruct); 2095128967Srik#endif 2096128967Srik } 2097128967Srik untimeout (cp_timeout, 0, timeout_handle); 2098128967Srik --load_count; 2099128967Srik break; 2100128967Srik case MOD_SHUTDOWN: 2101128967Srik break; 2102128967Srik } 2103128967Srik return 0; 2104128967Srik} 2105128967Srik 2106128967Srik#ifdef NETGRAPH 2107128967Srikstatic struct ng_type typestruct = { 2108129837Srik .version = NG_ABI_VERSION, 2109129837Srik .name = NG_CP_NODE_TYPE, 2110129837Srik .constructor = ng_cp_constructor, 2111129837Srik .rcvmsg = ng_cp_rcvmsg, 2112129837Srik .shutdown = ng_cp_rmnode, 2113129837Srik .newhook = ng_cp_newhook, 2114129837Srik .connect = ng_cp_connect, 2115129837Srik .rcvdata = ng_cp_rcvdata, 2116129837Srik .disconnect = ng_cp_disconnect, 2117128967Srik}; 2118128967Srik#endif /*NETGRAPH*/ 2119128967Srik 2120128967Srik#ifdef NETGRAPH 2121128967SrikMODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2122128967Srik#else 2123128967SrikMODULE_DEPEND (cp, sppp, 1, 1, 1); 2124128967Srik#endif 2125128967Srik#ifdef KLD_MODULE 2126128967SrikDRIVER_MODULE (cpmod, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2127128967Srik#else 2128128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2129128967Srik#endif 2130