if_cp.c revision 129837
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 * 21128967Srik * $Cronyx: if_cp.c,v 1.1.2.32 2004/02/26 17:56:39 rik Exp $ 22128967Srik */ 23128967Srik 24128967Srik#include <sys/cdefs.h> 25128967Srik__FBSDID("$FreeBSD: head/sys/dev/cp/if_cp.c 129837 2004-05-29 13:17:28Z rik $"); 26128967Srik 27128967Srik#include <sys/param.h> 28128967Srik 29128967Srik#if __FreeBSD_version >= 500000 30128967Srik# define NPCI 1 31128967Srik#else 32128967Srik# include "pci.h" 33128967Srik#endif 34128967Srik 35128967Srik#if NPCI > 0 36128967Srik 37128967Srik#include <sys/ucred.h> 38128967Srik#include <sys/proc.h> 39128967Srik#include <sys/systm.h> 40128967Srik#include <sys/mbuf.h> 41128967Srik#include <sys/kernel.h> 42128967Srik#include <sys/conf.h> 43128967Srik#include <sys/malloc.h> 44128967Srik#include <sys/socket.h> 45128967Srik#include <sys/sockio.h> 46128967Srik#include <sys/tty.h> 47128967Srik#if __FreeBSD_version >= 400000 48128967Srik# include <sys/bus.h> 49128967Srik#endif 50128967Srik#include <vm/vm.h> 51128967Srik#include <vm/pmap.h> 52128967Srik#include <net/if.h> 53128967Srik#if __FreeBSD_version > 501000 54128967Srik# include <dev/pci/pcivar.h> 55128967Srik# include <dev/pci/pcireg.h> 56128967Srik#else 57128967Srik# include <pci/pcivar.h> 58128967Srik# include <pci/pcireg.h> 59128967Srik#endif 60128967Srik#include <machine/bus.h> 61128967Srik#include <sys/rman.h> 62128967Srik#include "opt_ng_cronyx.h" 63128967Srik#ifdef NETGRAPH_CRONYX 64128967Srik# include "opt_netgraph.h" 65128967Srik# ifndef NETGRAPH 66128967Srik# error #option NETGRAPH missed from configuration 67128967Srik# endif 68128967Srik# include <netgraph/ng_message.h> 69128967Srik# include <netgraph/netgraph.h> 70128967Srik# if __FreeBSD_version >= 500000 71128967Srik# include <dev/cp/ng_cp.h> 72128967Srik# else 73128967Srik# include <netgraph/ng_cp.h> 74128967Srik# endif 75128967Srik#else 76128967Srik# include <net/if_sppp.h> 77128967Srik# define PP_CISCO IFF_LINK2 78128967Srik# if __FreeBSD_version < 400000 79128967Srik# include <bpfilter.h> 80128967Srik# if NBPFILTER > 0 81128967Srik# include <net/bpf.h> 82128967Srik# endif 83128967Srik# else 84128967Srik# if __FreeBSD_version < 500000 85128967Srik# include <bpf.h> 86128967Srik# endif 87128967Srik# include <net/bpf.h> 88128967Srik# define NBPFILTER NBPF 89128967Srik#endif 90128967Srik#endif 91128967Srik#if __FreeBSD_version >= 500000 92128967Srik#include <dev/cx/machdep.h> 93128967Srik#include <dev/cp/cpddk.h> 94128967Srik#else 95128967Srik#include <i386/isa/cronyx/machdep.h> 96128967Srik#include <pci/cpddk.h> 97128967Srik#endif 98128967Srik#include <machine/cserial.h> 99128967Srik#include <machine/resource.h> 100128967Srik#include <machine/pmap.h> 101128967Srik 102128967Srik/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 103128967Srik#ifndef PP_FR 104128967Srik#define PP_FR 0 105128967Srik#endif 106128967Srik 107128967Srik#define CP_DEBUG(d,s) ({if (d->chan->debug) {\ 108128967Srik printf ("%s: ", d->name); printf s;}}) 109128967Srik#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 110128967Srik printf ("%s: ", d->name); printf s;}}) 111128967Srik 112128967Srik#define CDEV_MAJOR 134 113128967Srik 114128967Srik#if __FreeBSD_version >= 400000 115128967Srikstatic int cp_probe __P((device_t)); 116128967Srikstatic int cp_attach __P((device_t)); 117128967Srikstatic int cp_detach __P((device_t)); 118128967Srik 119128967Srikstatic device_method_t cp_methods[] = { 120128967Srik /* Device interface */ 121128967Srik DEVMETHOD(device_probe, cp_probe), 122128967Srik DEVMETHOD(device_attach, cp_attach), 123128967Srik DEVMETHOD(device_detach, cp_detach), 124128967Srik 125128967Srik {0, 0} 126128967Srik}; 127128967Srik 128128967Sriktypedef struct _bdrv_t { 129128967Srik cp_board_t *board; 130128967Srik struct resource *cp_res; 131128967Srik struct resource *cp_irq; 132128967Srik void *cp_intrhand; 133128967Srik} bdrv_t; 134128967Srik 135128967Srikstatic driver_t cp_driver = { 136128967Srik "cp", 137128967Srik cp_methods, 138128967Srik sizeof(bdrv_t), 139128967Srik}; 140128967Srik 141128967Srikstatic devclass_t cp_devclass; 142128967Srik#endif 143128967Srik 144128967Sriktypedef struct _drv_t { 145128967Srik char name [8]; 146128967Srik cp_chan_t *chan; 147128967Srik cp_board_t *board; 148128967Srik cp_buf_t buf; 149128967Srik int running; 150128967Srik#ifdef NETGRAPH 151128967Srik char nodename [NG_NODELEN+1]; 152128967Srik hook_p hook; 153128967Srik hook_p debug_hook; 154128967Srik node_p node; 155128967Srik struct ifqueue queue; 156128967Srik struct ifqueue hi_queue; 157128967Srik short timeout; 158128967Srik struct callout_handle timeout_handle; 159128967Srik#else 160128967Srik struct sppp pp; 161128967Srik#endif 162128967Srik#if __FreeBSD_version >= 400000 163128967Srik dev_t devt; 164128967Srik#endif 165128967Srik} drv_t; 166128967Srik 167128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len); 168128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len); 169128967Srikstatic void cp_error (cp_chan_t *c, int data); 170128967Srikstatic void cp_up (drv_t *d); 171128967Srikstatic void cp_start (drv_t *d); 172128967Srikstatic void cp_down (drv_t *d); 173128967Srikstatic void cp_watchdog (drv_t *d); 174128967Srik#ifdef NETGRAPH 175128967Srikextern struct ng_type typestruct; 176128967Srik#else 177128967Srikstatic void cp_ifstart (struct ifnet *ifp); 178128967Srikstatic void cp_tlf (struct sppp *sp); 179128967Srikstatic void cp_tls (struct sppp *sp); 180128967Srikstatic void cp_ifwatchdog (struct ifnet *ifp); 181128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 182128967Srikstatic void cp_initialize (void *softc); 183128967Srik#endif 184128967Srik 185128967Srikstatic cp_board_t *adapter [NBRD]; 186128967Srikstatic drv_t *channel [NBRD*NCHAN]; 187128967Srikstatic cp_qbuf_t *queue [NBRD]; 188128967Srikstatic struct callout_handle led_timo [NBRD]; 189128967Srikstatic struct callout_handle timeout_handle; 190128967Srik 191128967Srikstatic int cp_destroy = 0; 192128967Srik 193128967Srik/* 194128967Srik * Print the mbuf chain, for debug purposes only. 195128967Srik */ 196128967Srikstatic void printmbuf (struct mbuf *m) 197128967Srik{ 198128967Srik printf ("mbuf:"); 199128967Srik for (; m; m=m->m_next) { 200128967Srik if (m->m_flags & M_PKTHDR) 201128967Srik printf (" HDR %d:", m->m_pkthdr.len); 202128967Srik if (m->m_flags & M_EXT) 203128967Srik printf (" EXT:"); 204128967Srik printf (" %d", m->m_len); 205128967Srik } 206128967Srik printf ("\n"); 207128967Srik} 208128967Srik 209128967Srik/* 210128967Srik * Make an mbuf from data. 211128967Srik */ 212128967Srikstatic struct mbuf *makembuf (void *buf, unsigned len) 213128967Srik{ 214128967Srik struct mbuf *m; 215128967Srik 216128967Srik MGETHDR (m, M_DONTWAIT, MT_DATA); 217128967Srik if (! m) 218128967Srik return 0; 219128967Srik MCLGET (m, M_DONTWAIT); 220128967Srik if (! (m->m_flags & M_EXT)) { 221128967Srik m_freem (m); 222128967Srik return 0; 223128967Srik } 224128967Srik m->m_pkthdr.len = m->m_len = len; 225128967Srik bcopy (buf, mtod (m, caddr_t), len); 226128967Srik return m; 227128967Srik} 228128967Srik 229128967Srik#if __FreeBSD_version < 400000 230128967Srikstatic const char *cp_probe (pcici_t tag, pcidi_t type) 231128967Srik{ 232128967Srik if (tag->vendor == cp_vendor_id && tag->device == cp_device_id) 233128967Srik return "Cronyx-Tau-PCI serial adapter"; 234128967Srik return 0; 235128967Srik} 236128967Srik#else 237128967Srikstatic int cp_probe (device_t dev) 238128967Srik{ 239128967Srik if ((pci_get_vendor (dev) == cp_vendor_id) && 240128967Srik (pci_get_device (dev) == cp_device_id)) { 241128967Srik device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 242128967Srik return 0; 243128967Srik } 244128967Srik return ENXIO; 245128967Srik} 246128967Srik#endif 247128967Srik 248128967Srikstatic void cp_timeout (void *arg) 249128967Srik{ 250128967Srik drv_t *d; 251128967Srik int s, i; 252128967Srik 253128967Srik for (i=0; i<NBRD*NCHAN; ++i) { 254128967Srik s = splimp (); 255128967Srik if (cp_destroy) { 256128967Srik splx (s); 257128967Srik return; 258128967Srik } 259128967Srik d = channel[i]; 260128967Srik if (!d) { 261128967Srik splx (s); 262128967Srik continue; 263128967Srik } 264128967Srik switch (d->chan->type) { 265128967Srik case T_G703: 266128967Srik cp_g703_timer (d->chan); 267128967Srik break; 268128967Srik case T_E1: 269128967Srik cp_e1_timer (d->chan); 270128967Srik break; 271128967Srik case T_E3: 272128967Srik case T_T3: 273128967Srik case T_STS1: 274128967Srik cp_e3_timer (d->chan); 275128967Srik break; 276128967Srik default: 277128967Srik break; 278128967Srik } 279128967Srik splx (s); 280128967Srik } 281128967Srik s = splimp (); 282128967Srik if (!cp_destroy) 283128967Srik timeout_handle = timeout (cp_timeout, 0, hz); 284128967Srik splx (s); 285128967Srik} 286128967Srik 287128967Srikstatic void cp_led_off (void *arg) 288128967Srik{ 289128967Srik cp_board_t *b = arg; 290128967Srik int s = splimp (); 291128967Srik if (cp_destroy) { 292128967Srik splx (s); 293128967Srik return; 294128967Srik } 295128967Srik cp_led (b, 0); 296128967Srik led_timo[b->num].callout = 0; 297128967Srik splx (s); 298128967Srik} 299128967Srik 300128967Srikstatic void cp_intr (void *arg) 301128967Srik{ 302128967Srik#if __FreeBSD_version < 400000 303128967Srik cp_board_t *b = arg; 304128967Srik#else 305128967Srik bdrv_t *bd = arg; 306128967Srik cp_board_t *b = bd->board; 307128967Srik#endif 308128967Srik int s = splimp (); 309128967Srik if (cp_destroy) { 310128967Srik splx (s); 311128967Srik return; 312128967Srik } 313128967Srik /* Turn LED on. */ 314128967Srik cp_led (b, 1); 315128967Srik 316128967Srik cp_interrupt (b); 317128967Srik 318128967Srik /* Turn LED off 50 msec later. */ 319128967Srik if (!led_timo[b->num].callout) 320128967Srik led_timo[b->num] = timeout (cp_led_off, b, hz/20); 321128967Srik splx (s); 322128967Srik} 323128967Srik 324128967Srikextern struct cdevsw cp_cdevsw; 325128967Srik 326128967Srik/* 327128967Srik * Called if the probe succeeded. 328128967Srik */ 329128967Srik#if __FreeBSD_version < 400000 330128967Srikstatic void cp_attach (pcici_t tag, int unit) 331128967Srik{ 332128967Srik vm_offset_t pbase; 333128967Srik#else 334128967Srikstatic int cp_attach (device_t dev) 335128967Srik{ 336128967Srik bdrv_t *bd = device_get_softc (dev); 337128967Srik int unit = device_get_unit (dev); 338128967Srik int rid, error; 339128967Srik#endif 340128967Srik vm_offset_t vbase; 341128967Srik cp_board_t *b; 342128967Srik cp_chan_t *c; 343128967Srik drv_t *d; 344128967Srik unsigned short res; 345128967Srik int s = splimp (); 346128967Srik 347128967Srik b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 348128967Srik if (!b) { 349128967Srik printf ("cp%d: couldn't allocate memory\n", unit); 350128967Srik#if __FreeBSD_version < 400000 351128967Srik splx (s); 352128967Srik return; 353128967Srik#else 354128967Srik splx (s); 355128967Srik return (ENXIO); 356128967Srik#endif 357128967Srik } 358128967Srik adapter[unit] = b; 359128967Srik bzero (b, sizeof(cp_board_t)); 360128967Srik 361128967Srik#if __FreeBSD_version < 400000 362128967Srik if (! pci_map_mem (tag, PCIR_MAPS, &vbase, &pbase)) { 363128967Srik printf ("cp%d: cannot map memory\n", unit); 364128967Srik free (b, M_DEVBUF); 365128967Srik splx (s); 366128967Srik return; 367128967Srik } 368128967Srik#else 369128967Srik bd->board = b; 370128967Srik b->sys = bd; 371129673Sjhb rid = PCIR_BAR(0); 372128967Srik bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 373128967Srik 0, ~0, 1, RF_ACTIVE); 374128967Srik if (! bd->cp_res) { 375128967Srik printf ("cp%d: cannot map memory\n", unit); 376128967Srik free (b, M_DEVBUF); 377128967Srik splx (s); 378128967Srik return (ENXIO); 379128967Srik } 380128967Srik vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 381128967Srik#endif 382128967Srik 383128967Srik res = cp_init (b, unit, (u_char*) vbase); 384128967Srik if (res) { 385128967Srik printf ("cp%d: can't init, error code:%x\n", unit, res); 386128967Srik#if __FreeBSD_version >= 400000 387129673Sjhb bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 388128967Srik#endif 389128967Srik free (b, M_DEVBUF); 390128967Srik splx (s); 391128967Srik#if __FreeBSD_version >= 400000 392128967Srik return (ENXIO); 393128967Srik#else 394128967Srik return; 395128967Srik#endif 396128967Srik } 397128967Srik queue[unit] = contigmalloc (sizeof(cp_qbuf_t), M_DEVBUF, M_WAITOK, 398128967Srik 0x100000, 0xffffffff, 16, 0); 399128967Srik if (queue[unit] == NULL) { 400128967Srik printf ("cp%d: allocate memory for qbuf_t\n", unit); 401128967Srik free (b, M_DEVBUF); 402128967Srik splx (s); 403128967Srik#if __FreeBSD_version >= 400000 404128967Srik return (ENXIO); 405128967Srik#else 406128967Srik return; 407128967Srik#endif 408128967Srik } 409128967Srik cp_reset (b, queue[unit], vtophys (queue[unit])); 410128967Srik 411128967Srik#if __FreeBSD_version < 400000 412128967Srik if (! pci_map_int (tag, cp_intr, b, &net_imask)) 413128967Srik printf ("cp%d: cannot map interrupt\n", unit); 414128967Srik#else 415128967Srik rid = 0; 416128967Srik bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 417128967Srik RF_SHAREABLE | RF_ACTIVE); 418128967Srik if (! bd->cp_irq) { 419128967Srik printf ("cp%d: cannot map interrupt\n", unit); 420128967Srik bus_release_resource (dev, SYS_RES_MEMORY, 421129673Sjhb PCIR_BAR(0), bd->cp_res); 422128967Srik free (b, M_DEVBUF); 423128967Srik splx (s); 424128967Srik return (ENXIO); 425128967Srik } 426128967Srik error = bus_setup_intr (dev, bd->cp_irq, INTR_TYPE_NET, cp_intr, bd, 427128967Srik &bd->cp_intrhand); 428128967Srik if (error) { 429128967Srik printf ("cp%d: cannot set up irq\n", unit); 430128967Srik bus_release_resource (dev, SYS_RES_MEMORY, 431129673Sjhb PCIR_BAR(0), bd->cp_res); 432128967Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 433128967Srik free (b, M_DEVBUF); 434128967Srik splx (s); 435128967Srik return (ENXIO); 436128967Srik } 437128967Srik#endif 438128967Srik printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 439128967Srik 440128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 441128967Srik if (! c->type) 442128967Srik continue; 443128967Srik d = contigmalloc (sizeof(drv_t), M_DEVBUF, M_WAITOK, 444128967Srik 0x100000, 0xffffffff, 16, 0); 445128967Srik if (d == NULL) { 446128967Srik printf ("cp%d-%d: cannot allocate memory for drv_t\n", 447128967Srik unit, c->num); 448128967Srik } 449128967Srik channel [b->num*NCHAN + c->num] = d; 450128967Srik bzero (d, sizeof(drv_t)); 451128967Srik sprintf (d->name, "cp%d.%d", b->num, c->num); 452128967Srik d->board = b; 453128967Srik d->chan = c; 454128967Srik c->sys = d; 455128967Srik#ifdef NETGRAPH 456128967Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 457128967Srik printf ("%s: cannot make common node\n", d->name); 458128967Srik d->node = NULL; 459128967Srik continue; 460128967Srik } 461128967Srik#if __FreeBSD_version >= 500000 462128967Srik NG_NODE_SET_PRIVATE (d->node, d); 463128967Srik#else 464128967Srik d->node->private = d; 465128967Srik#endif 466128967Srik sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 467128967Srik c->board->num*NCHAN + c->num); 468128967Srik if (ng_name_node (d->node, d->nodename)) { 469128967Srik printf ("%s: cannot name node\n", d->nodename); 470128967Srik#if __FreeBSD_version >= 500000 471128967Srik NG_NODE_UNREF (d->node); 472128967Srik#else 473128967Srik ng_rmnode (d->node); 474128967Srik ng_unref (d->node); 475128967Srik#endif 476128967Srik continue; 477128967Srik } 478128967Srik d->queue.ifq_maxlen = IFQ_MAXLEN; 479128967Srik d->hi_queue.ifq_maxlen = IFQ_MAXLEN; 480128967Srik#if __FreeBSD_version >= 500000 481128967Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 482128967Srik mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 483128967Srik#endif 484128967Srik#else /*NETGRAPH*/ 485128967Srik d->pp.pp_if.if_softc = d; 486128967Srik#if __FreeBSD_version > 501000 487128967Srik if_initname (&d->pp.pp_if, "cp", b->num * NCHAN + c->num); 488128967Srik#else 489128967Srik d->pp.pp_if.if_unit = b->num * NCHAN + c->num; 490128967Srik d->pp.pp_if.if_name = "cp"; 491128967Srik#endif 492128967Srik d->pp.pp_if.if_mtu = PP_MTU; 493128967Srik d->pp.pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 494128967Srik d->pp.pp_if.if_ioctl = cp_sioctl; 495128967Srik d->pp.pp_if.if_start = cp_ifstart; 496128967Srik d->pp.pp_if.if_watchdog = cp_ifwatchdog; 497128967Srik d->pp.pp_if.if_init = cp_initialize; 498128967Srik sppp_attach (&d->pp.pp_if); 499128967Srik if_attach (&d->pp.pp_if); 500128967Srik d->pp.pp_tlf = cp_tlf; 501128967Srik d->pp.pp_tls = cp_tls; 502128967Srik#if __FreeBSD_version >= 400000 || NBPFILTER > 0 503128967Srik /* If BPF is in the kernel, call the attach for it. 504128967Srik * The header size of PPP or Cisco/HDLC is 4 bytes. */ 505128967Srik bpfattach (&d->pp.pp_if, DLT_PPP, 4); 506128967Srik#endif 507128967Srik#endif /*NETGRAPH*/ 508128967Srik cp_start_e1 (c); 509128967Srik cp_start_chan (c, 1, 1, &d->buf, vtophys (&d->buf)); 510128967Srik 511128967Srik /* Register callback functions. */ 512128967Srik cp_register_transmit (c, &cp_transmit); 513128967Srik cp_register_receive (c, &cp_receive); 514128967Srik cp_register_error (c, &cp_error); 515128967Srik#if __FreeBSD_version >= 400000 516128967Srik d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 517128967Srik GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 518128967Srik#endif 519128967Srik } 520128967Srik splx (s); 521128967Srik#if __FreeBSD_version >= 400000 522128967Srik return 0; 523128967Srik#endif 524128967Srik} 525128967Srik 526128967Srik#if __FreeBSD_version >= 400000 527128967Srikstatic int cp_detach (device_t dev) 528128967Srik{ 529128967Srik bdrv_t *bd = device_get_softc (dev); 530128967Srik cp_board_t *b = bd->board; 531128967Srik cp_chan_t *c; 532128967Srik int s = splimp (); 533128967Srik 534128967Srik /* Check if the device is busy (open). */ 535128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 536128967Srik drv_t *d = (drv_t*) c->sys; 537128967Srik 538128967Srik if (! d || ! d->chan->type) 539128967Srik continue; 540128967Srik if (d->running) { 541128967Srik splx (s); 542128967Srik return EBUSY; 543128967Srik } 544128967Srik } 545128967Srik 546128967Srik /* Ok, we can unload driver */ 547128967Srik /* At first we should stop all channels */ 548128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 549128967Srik drv_t *d = (drv_t*) c->sys; 550128967Srik 551128967Srik if (! d || ! d->chan->type) 552128967Srik continue; 553128967Srik 554128967Srik cp_stop_chan (c); 555128967Srik cp_stop_e1 (c); 556128967Srik cp_set_dtr (d->chan, 0); 557128967Srik cp_set_rts (d->chan, 0); 558128967Srik } 559128967Srik 560128967Srik /* Reset the adapter. */ 561128967Srik cp_destroy = 1; 562128967Srik cp_interrupt_poll (b, 1); 563128967Srik cp_led_off (b); 564128967Srik cp_reset (b, 0 ,0); 565128967Srik if (led_timo[b->num].callout) 566128967Srik untimeout (cp_led_off, b, led_timo[b->num]); 567128967Srik 568128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 569128967Srik drv_t *d = (drv_t*) c->sys; 570128967Srik 571128967Srik if (! d || ! d->chan->type) 572128967Srik continue; 573128967Srik#ifndef NETGRAPH 574128967Srik#if __FreeBSD_version >= 410000 && NBPFILTER > 0 575128967Srik /* Detach from the packet filter list of interfaces. */ 576128967Srik bpfdetach (&d->pp.pp_if); 577128967Srik#endif 578128967Srik /* Detach from the sync PPP list. */ 579128967Srik sppp_detach (&d->pp.pp_if); 580128967Srik 581128967Srik /* Detach from the system list of interfaces. */ 582128967Srik if_detach (&d->pp.pp_if); 583128967Srik#else 584128967Srik#if __FreeBSD_version >= 500000 585128967Srik if (d->node) { 586128967Srik ng_rmnode_self (d->node); 587128967Srik NG_NODE_UNREF (d->node); 588128967Srik d->node = NULL; 589128967Srik } 590128967Srik mtx_destroy (&d->queue.ifq_mtx); 591128967Srik mtx_destroy (&d->hi_queue.ifq_mtx); 592128967Srik#else 593128967Srik ng_rmnode (d->node); 594128967Srik d->node = 0; 595128967Srik#endif 596128967Srik#endif 597128967Srik destroy_dev (d->devt); 598128967Srik } 599128967Srik 600128967Srik /* Disable the interrupt request. */ 601128967Srik bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 602128967Srik bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 603128967Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 604129673Sjhb bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 605128967Srik cp_led_off (b); 606128967Srik if (led_timo[b->num].callout) 607128967Srik untimeout (cp_led_off, b, led_timo[b->num]); 608128967Srik splx (s); 609128967Srik 610128967Srik s = splimp (); 611128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 612128967Srik drv_t *d = (drv_t*) c->sys; 613128967Srik 614128967Srik if (! d || ! d->chan->type) 615128967Srik continue; 616128967Srik channel [b->num*NCHAN + c->num] = 0; 617128967Srik /* Deallocate buffers. */ 618128967Srik#if __FreeBSD_version < 400000 619128967Srik free (d, M_DEVBUF); 620128967Srik#else 621128967Srik contigfree (d, sizeof (*d), M_DEVBUF); 622128967Srik#endif 623128967Srik } 624128967Srik adapter [b->num] = 0; 625128967Srik#if __FreeBSD_version < 400000 626128967Srik free (queue[b->num], M_DEVBUF); 627128967Srik#else 628128967Srik contigfree (queue[b->num], sizeof (cp_qbuf_t), M_DEVBUF); 629128967Srik#endif 630128967Srik free (b, M_DEVBUF); 631128967Srik splx (s); 632128967Srik return 0; 633128967Srik} 634128967Srik#endif 635128967Srik 636128967Srik#if __FreeBSD_version < 400000 637128967Srikstatic u_long cp_count; 638128967Srikstatic struct pci_device cp_driver = {"cp", cp_probe, cp_attach, &cp_count, 0}; 639128967SrikDATA_SET (pcidevice_set, cp_driver); 640128967Srik#endif 641128967Srik 642128967Srik#ifndef NETGRAPH 643128967Srikstatic void cp_ifstart (struct ifnet *ifp) 644128967Srik{ 645128967Srik drv_t *d = ifp->if_softc; 646128967Srik 647128967Srik cp_start (d); 648128967Srik} 649128967Srik 650128967Srikstatic void cp_ifwatchdog (struct ifnet *ifp) 651128967Srik{ 652128967Srik drv_t *d = ifp->if_softc; 653128967Srik 654128967Srik cp_watchdog (d); 655128967Srik} 656128967Srik 657128967Srikstatic void cp_tlf (struct sppp *sp) 658128967Srik{ 659128967Srik drv_t *d = sp->pp_if.if_softc; 660128967Srik 661128967Srik CP_DEBUG2 (d, ("cp_tlf\n")); 662128967Srik/* cp_set_dtr (d->chan, 0);*/ 663128967Srik/* cp_set_rts (d->chan, 0);*/ 664128967Srik sp->pp_down (sp); 665128967Srik} 666128967Srik 667128967Srikstatic void cp_tls (struct sppp *sp) 668128967Srik{ 669128967Srik drv_t *d = sp->pp_if.if_softc; 670128967Srik 671128967Srik CP_DEBUG2 (d, ("cp_tls\n")); 672128967Srik sp->pp_up (sp); 673128967Srik} 674128967Srik 675128967Srik/* 676128967Srik * Process an ioctl request. 677128967Srik */ 678128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 679128967Srik{ 680128967Srik drv_t *d = ifp->if_softc; 681128967Srik int error, s, was_up, should_be_up; 682128967Srik 683128967Srik was_up = (ifp->if_flags & IFF_RUNNING) != 0; 684128967Srik error = sppp_ioctl (ifp, cmd, data); 685128967Srik 686128967Srik if (error) 687128967Srik return error; 688128967Srik 689128967Srik if (! (ifp->if_flags & IFF_DEBUG)) 690128967Srik d->chan->debug = 0; 691128967Srik else if (! d->chan->debug) 692128967Srik d->chan->debug = 1; 693128967Srik 694128967Srik switch (cmd) { 695128967Srik default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 696128967Srik case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 697128967Srik case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 698128967Srik case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 699128967Srik case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 700128967Srik } 701128967Srik 702128967Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 703128967Srik s = splimp (); 704128967Srik should_be_up = (ifp->if_flags & IFF_RUNNING) != 0; 705128967Srik if (! was_up && should_be_up) { 706128967Srik /* Interface goes up -- start it. */ 707128967Srik cp_up (d); 708128967Srik cp_start (d); 709128967Srik } else if (was_up && ! should_be_up) { 710128967Srik /* Interface is going down -- stop it. */ 711128967Srik/* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 712128967Srik cp_down (d); 713128967Srik } 714128967Srik CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 715128967Srik splx (s); 716128967Srik return 0; 717128967Srik} 718128967Srik 719128967Srik/* 720128967Srik * Initialization of interface. 721128967Srik * It seems to be never called by upper level? 722128967Srik */ 723128967Srikstatic void cp_initialize (void *softc) 724128967Srik{ 725128967Srik drv_t *d = softc; 726128967Srik 727128967Srik CP_DEBUG (d, ("cp_initialize\n")); 728128967Srik} 729128967Srik#endif /*NETGRAPH*/ 730128967Srik 731128967Srik/* 732128967Srik * Stop the interface. Called on splimp(). 733128967Srik */ 734128967Srikstatic void cp_down (drv_t *d) 735128967Srik{ 736128967Srik CP_DEBUG (d, ("cp_down\n")); 737128967Srik /* Interface is going down -- stop it. */ 738128967Srik cp_set_dtr (d->chan, 0); 739128967Srik cp_set_rts (d->chan, 0); 740128967Srik 741128967Srik d->running = 0; 742128967Srik} 743128967Srik 744128967Srik/* 745128967Srik * Start the interface. Called on splimp(). 746128967Srik */ 747128967Srikstatic void cp_up (drv_t *d) 748128967Srik{ 749128967Srik CP_DEBUG (d, ("cp_up\n")); 750128967Srik cp_set_dtr (d->chan, 1); 751128967Srik cp_set_rts (d->chan, 1); 752128967Srik d->running = 1; 753128967Srik} 754128967Srik 755128967Srik/* 756128967Srik * Start output on the interface. Get another datagram to send 757128967Srik * off of the interface queue, and copy it to the interface 758128967Srik * before starting the output. 759128967Srik */ 760128967Srikstatic void cp_send (drv_t *d) 761128967Srik{ 762128967Srik struct mbuf *m; 763128967Srik u_short len; 764128967Srik 765128967Srik CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 766128967Srik 767128967Srik /* No output if the interface is down. */ 768128967Srik if (! d->running) 769128967Srik return; 770128967Srik 771128967Srik /* No output if the modem is off. */ 772128967Srik if (! (d->chan->lloop || d->chan->type != T_SERIAL || 773128967Srik cp_get_dsr (d->chan))) 774128967Srik return; 775128967Srik 776128967Srik while (cp_transmit_space (d->chan)) { 777128967Srik /* Get the packet to send. */ 778128967Srik#ifdef NETGRAPH 779128967Srik IF_DEQUEUE (&d->hi_queue, m); 780128967Srik if (! m) 781128967Srik IF_DEQUEUE (&d->queue, m); 782128967Srik#else 783128967Srik m = sppp_dequeue (&d->pp.pp_if); 784128967Srik#endif 785128967Srik if (! m) 786128967Srik return; 787128967Srik#if (__FreeBSD_version >= 400000 || NBPFILTER > 0) && !defined (NETGRAPH) 788128967Srik if (d->pp.pp_if.if_bpf) 789128967Srik#if __FreeBSD_version >= 500000 790128967Srik BPF_MTAP (&d->pp.pp_if, m); 791128967Srik#else 792128967Srik bpf_mtap (&d->pp.pp_if, m); 793128967Srik#endif 794128967Srik#endif 795128967Srik len = m->m_pkthdr.len; 796128967Srik if (len >= BUFSZ) 797128967Srik printf ("%s: too long packet: %d bytes: ", 798128967Srik d->name, len); 799128967Srik else if (! m->m_next) 800128967Srik cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 801128967Srik else { 802128967Srik u_char *buf = d->chan->tbuf[d->chan->te]; 803128967Srik m_copydata (m, 0, len, buf); 804128967Srik cp_send_packet (d->chan, buf, len, 0); 805128967Srik } 806128967Srik m_freem (m); 807128967Srik /* Set up transmit timeout, if the transmit ring is not empty.*/ 808128967Srik#ifdef NETGRAPH 809128967Srik d->timeout = 10; 810128967Srik#else 811128967Srik d->pp.pp_if.if_timer = 10; 812128967Srik#endif 813128967Srik } 814128967Srik#ifndef NETGRAPH 815128967Srik d->pp.pp_if.if_flags |= IFF_OACTIVE; 816128967Srik#endif 817128967Srik} 818128967Srik 819128967Srik/* 820128967Srik * Start output on the interface. 821128967Srik * Always called on splimp(). 822128967Srik */ 823128967Srikstatic void cp_start (drv_t *d) 824128967Srik{ 825128967Srik if (d->running) { 826128967Srik if (! d->chan->dtr) 827128967Srik cp_set_dtr (d->chan, 1); 828128967Srik if (! d->chan->rts) 829128967Srik cp_set_rts (d->chan, 1); 830128967Srik cp_send (d); 831128967Srik } 832128967Srik} 833128967Srik 834128967Srik/* 835128967Srik * Handle transmit timeouts. 836128967Srik * Recover after lost transmit interrupts. 837128967Srik * Always called on splimp(). 838128967Srik */ 839128967Srikstatic void cp_watchdog (drv_t *d) 840128967Srik{ 841128967Srik CP_DEBUG (d, ("device timeout\n")); 842128967Srik if (d->running) { 843128967Srik int s = splimp (); 844128967Srik 845128967Srik cp_stop_chan (d->chan); 846128967Srik cp_stop_e1 (d->chan); 847128967Srik cp_start_e1 (d->chan); 848128967Srik cp_start_chan (d->chan, 1, 1, 0, 0); 849128967Srik cp_set_dtr (d->chan, 1); 850128967Srik cp_set_rts (d->chan, 1); 851128967Srik cp_start (d); 852128967Srik splx (s); 853128967Srik } 854128967Srik} 855128967Srik 856128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len) 857128967Srik{ 858128967Srik drv_t *d = c->sys; 859128967Srik 860128967Srik#ifdef NETGRAPH 861128967Srik d->timeout = 0; 862128967Srik#else 863128967Srik ++d->pp.pp_if.if_opackets; 864128967Srik d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 865128967Srik d->pp.pp_if.if_timer = 0; 866128967Srik#endif 867128967Srik cp_start (d); 868128967Srik} 869128967Srik 870128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len) 871128967Srik{ 872128967Srik drv_t *d = c->sys; 873128967Srik struct mbuf *m; 874128967Srik#if __FreeBSD_version >= 500000 && defined NETGRAPH 875128967Srik int error; 876128967Srik#endif 877128967Srik 878128967Srik if (! d->running) 879128967Srik return; 880128967Srik 881128967Srik m = makembuf (data, len); 882128967Srik if (! m) { 883128967Srik CP_DEBUG (d, ("no memory for packet\n")); 884128967Srik#ifndef NETGRAPH 885128967Srik ++d->pp.pp_if.if_iqdrops; 886128967Srik#endif 887128967Srik return; 888128967Srik } 889128967Srik if (c->debug > 1) 890128967Srik printmbuf (m); 891128967Srik#ifdef NETGRAPH 892128967Srik m->m_pkthdr.rcvif = 0; 893128967Srik#if __FreeBSD_version >= 500000 894128967Srik NG_SEND_DATA_ONLY (error, d->hook, m); 895128967Srik#else 896128967Srik ng_queue_data (d->hook, m, 0); 897128967Srik#endif 898128967Srik#else 899128967Srik ++d->pp.pp_if.if_ipackets; 900128967Srik m->m_pkthdr.rcvif = &d->pp.pp_if; 901128967Srik#if __FreeBSD_version >= 400000 || NBPFILTER > 0 902128967Srik /* Check if there's a BPF listener on this interface. 903128967Srik * If so, hand off the raw packet to bpf. */ 904128967Srik if (d->pp.pp_if.if_bpf) 905128967Srik#if __FreeBSD_version >= 500000 906128967Srik BPF_TAP (&d->pp.pp_if, data, len); 907128967Srik#else 908128967Srik bpf_tap (&d->pp.pp_if, data, len); 909128967Srik#endif 910128967Srik#endif 911128967Srik sppp_input (&d->pp.pp_if, m); 912128967Srik#endif 913128967Srik} 914128967Srik 915128967Srikstatic void cp_error (cp_chan_t *c, int data) 916128967Srik{ 917128967Srik drv_t *d = c->sys; 918128967Srik 919128967Srik switch (data) { 920128967Srik case CP_FRAME: 921128967Srik CP_DEBUG (d, ("frame error\n")); 922128967Srik#ifndef NETGRAPH 923128967Srik ++d->pp.pp_if.if_ierrors; 924128967Srik#endif 925128967Srik break; 926128967Srik case CP_CRC: 927128967Srik CP_DEBUG (d, ("crc error\n")); 928128967Srik#ifndef NETGRAPH 929128967Srik ++d->pp.pp_if.if_ierrors; 930128967Srik#endif 931128967Srik break; 932128967Srik case CP_OVERRUN: 933128967Srik CP_DEBUG (d, ("overrun error\n")); 934128967Srik#ifndef NETGRAPH 935128967Srik ++d->pp.pp_if.if_collisions; 936128967Srik ++d->pp.pp_if.if_ierrors; 937128967Srik#endif 938128967Srik break; 939128967Srik case CP_OVERFLOW: 940128967Srik CP_DEBUG (d, ("overflow error\n")); 941128967Srik#ifndef NETGRAPH 942128967Srik ++d->pp.pp_if.if_ierrors; 943128967Srik#endif 944128967Srik break; 945128967Srik case CP_UNDERRUN: 946128967Srik CP_DEBUG (d, ("underrun error\n")); 947128967Srik#ifdef NETGRAPH 948128967Srik d->timeout = 0; 949128967Srik#else 950128967Srik ++d->pp.pp_if.if_oerrors; 951128967Srik d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 952128967Srik d->pp.pp_if.if_timer = 0; 953128967Srik#endif 954128967Srik cp_start (d); 955128967Srik break; 956128967Srik default: 957128967Srik CP_DEBUG (d, ("error #%d\n", data)); 958128967Srik break; 959128967Srik } 960128967Srik} 961128967Srik 962128967Srik/* 963128967Srik * You also need read, write, open, close routines. 964128967Srik * This should get you started 965128967Srik */ 966128967Srik#if __FreeBSD_version < 500000 967128967Srikstatic int cp_open (dev_t dev, int oflags, int devtype, struct proc *p) 968128967Srik#else 969128967Srikstatic int cp_open (dev_t dev, int oflags, int devtype, struct thread *td) 970128967Srik#endif 971128967Srik{ 972128967Srik int unit = minor (dev); 973128967Srik drv_t *d; 974128967Srik 975128967Srik if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 976128967Srik return ENXIO; 977128967Srik CP_DEBUG2 (d, ("cp_open\n")); 978128967Srik return 0; 979128967Srik} 980128967Srik 981128967Srik/* 982128967Srik * Only called on the LAST close. 983128967Srik */ 984128967Srik#if __FreeBSD_version < 500000 985128967Srikstatic int cp_close (dev_t dev, int fflag, int devtype, struct proc *p) 986128967Srik#else 987128967Srikstatic int cp_close (dev_t dev, int fflag, int devtype, struct thread *td) 988128967Srik#endif 989128967Srik{ 990128967Srik drv_t *d = channel [minor (dev)]; 991128967Srik 992128967Srik CP_DEBUG2 (d, ("cp_close\n")); 993128967Srik return 0; 994128967Srik} 995128967Srik 996128967Srikstatic int cp_modem_status (cp_chan_t *c) 997128967Srik{ 998128967Srik drv_t *d = c->sys; 999128967Srik int status, s; 1000128967Srik 1001128967Srik status = d->running ? TIOCM_LE : 0; 1002128967Srik s = splimp (); 1003128967Srik if (cp_get_cd (c)) status |= TIOCM_CD; 1004128967Srik if (cp_get_cts (c)) status |= TIOCM_CTS; 1005128967Srik if (cp_get_dsr (c)) status |= TIOCM_DSR; 1006128967Srik if (c->dtr) status |= TIOCM_DTR; 1007128967Srik if (c->rts) status |= TIOCM_RTS; 1008128967Srik splx (s); 1009128967Srik return status; 1010128967Srik} 1011128967Srik 1012128967Srik#if __FreeBSD_version < 500000 1013128967Srikstatic int cp_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1014128967Srik#else 1015128967Srikstatic int cp_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1016128967Srik#endif 1017128967Srik{ 1018128967Srik drv_t *d = channel [minor (dev)]; 1019128967Srik cp_chan_t *c = d->chan; 1020128967Srik struct serial_statistics *st; 1021128967Srik struct e1_statistics *opte1; 1022128967Srik struct e3_statistics *opte3; 1023128967Srik int error, s; 1024128967Srik char mask[16]; 1025128967Srik 1026128967Srik switch (cmd) { 1027128967Srik case SERIAL_GETREGISTERED: 1028128967Srik CP_DEBUG2 (d, ("ioctl: getregistered\n")); 1029128967Srik bzero (mask, sizeof(mask)); 1030128967Srik for (s=0; s<NBRD*NCHAN; ++s) 1031128967Srik if (channel [s]) 1032128967Srik mask [s/8] |= 1 << (s & 7); 1033128967Srik bcopy (mask, data, sizeof (mask)); 1034128967Srik return 0; 1035128967Srik 1036128967Srik#ifndef NETGRAPH 1037128967Srik case SERIAL_GETPROTO: 1038128967Srik CP_DEBUG2 (d, ("ioctl: getproto\n")); 1039128967Srik strcpy ((char*)data, (d->pp.pp_flags & PP_FR) ? "fr" : 1040128967Srik (d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp"); 1041128967Srik return 0; 1042128967Srik 1043128967Srik case SERIAL_SETPROTO: 1044128967Srik CP_DEBUG2 (d, ("ioctl: setproto\n")); 1045128967Srik /* Only for superuser! */ 1046128967Srik#if __FreeBSD_version < 400000 1047128967Srik error = suser (p->p_ucred, &p->p_acflag); 1048128967Srik#elif __FreeBSD_version < 500000 1049128967Srik error = suser (p); 1050128967Srik#else /* __FreeBSD_version >= 500000 */ 1051128967Srik error = suser (td); 1052128967Srik#endif /* __FreeBSD_version >= 500000 */ 1053128967Srik if (error) 1054128967Srik return error; 1055128967Srik if (d->pp.pp_if.if_flags & IFF_RUNNING) 1056128967Srik return EBUSY; 1057128967Srik if (! strcmp ("cisco", (char*)data)) { 1058128967Srik d->pp.pp_flags &= ~(PP_FR); 1059128967Srik d->pp.pp_flags |= PP_KEEPALIVE; 1060128967Srik d->pp.pp_if.if_flags |= PP_CISCO; 1061128967Srik } else if (! strcmp ("fr", (char*)data) && !PP_FR) { 1062128967Srik d->pp.pp_if.if_flags &= ~(PP_CISCO); 1063128967Srik d->pp.pp_flags |= PP_FR | PP_KEEPALIVE; 1064128967Srik } else if (! strcmp ("ppp", (char*)data)) { 1065128967Srik d->pp.pp_flags &= ~PP_FR; 1066128967Srik d->pp.pp_flags &= ~PP_KEEPALIVE; 1067128967Srik d->pp.pp_if.if_flags &= ~(PP_CISCO); 1068128967Srik } else 1069128967Srik return EINVAL; 1070128967Srik return 0; 1071128967Srik 1072128967Srik case SERIAL_GETKEEPALIVE: 1073128967Srik CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1074128967Srik if ((d->pp.pp_flags & PP_FR) || 1075128967Srik (d->pp.pp_if.if_flags & PP_CISCO)) 1076128967Srik return EINVAL; 1077128967Srik *(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0; 1078128967Srik return 0; 1079128967Srik 1080128967Srik case SERIAL_SETKEEPALIVE: 1081128967Srik CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1082128967Srik /* Only for superuser! */ 1083128967Srik#if __FreeBSD_version < 400000 1084128967Srik error = suser (p->p_ucred, &p->p_acflag); 1085128967Srik#elif __FreeBSD_version < 500000 1086128967Srik error = suser (p); 1087128967Srik#else 1088128967Srik error = suser (td); 1089128967Srik#endif 1090128967Srik if (error) 1091128967Srik return error; 1092128967Srik if ((d->pp.pp_flags & PP_FR) || 1093128967Srik (d->pp.pp_if.if_flags & PP_CISCO)) 1094128967Srik return EINVAL; 1095128967Srik s = splimp (); 1096128967Srik if (*(int*)data) 1097128967Srik d->pp.pp_flags |= PP_KEEPALIVE; 1098128967Srik else 1099128967Srik d->pp.pp_flags &= ~PP_KEEPALIVE; 1100128967Srik splx (s); 1101128967Srik return 0; 1102128967Srik#endif /*NETGRAPH*/ 1103128967Srik 1104128967Srik case SERIAL_GETMODE: 1105128967Srik CP_DEBUG2 (d, ("ioctl: getmode\n")); 1106128967Srik *(int*)data = SERIAL_HDLC; 1107128967Srik return 0; 1108128967Srik 1109128967Srik case SERIAL_SETMODE: 1110128967Srik /* Only for superuser! */ 1111128967Srik#if __FreeBSD_version < 400000 1112128967Srik error = suser (p->p_ucred, &p->p_acflag); 1113128967Srik#elif __FreeBSD_version < 500000 1114128967Srik error = suser (p); 1115128967Srik#else 1116128967Srik error = suser (td); 1117128967Srik#endif 1118128967Srik if (error) 1119128967Srik return error; 1120128967Srik if (*(int*)data != SERIAL_HDLC) 1121128967Srik return EINVAL; 1122128967Srik return 0; 1123128967Srik 1124128967Srik case SERIAL_GETCFG: 1125128967Srik CP_DEBUG2 (d, ("ioctl: getcfg\n")); 1126128967Srik if (c->type != T_E1 || c->unfram) 1127128967Srik return EINVAL; 1128128967Srik *(char*)data = c->board->mux ? 'c' : 'a'; 1129128967Srik return 0; 1130128967Srik 1131128967Srik case SERIAL_SETCFG: 1132128967Srik CP_DEBUG2 (d, ("ioctl: setcfg\n")); 1133128967Srik#if __FreeBSD_version < 400000 1134128967Srik error = suser (p->p_ucred, &p->p_acflag); 1135128967Srik#elif __FreeBSD_version < 500000 1136128967Srik error = suser (p); 1137128967Srik#else 1138128967Srik error = suser (td); 1139128967Srik#endif 1140128967Srik if (error) 1141128967Srik return error; 1142128967Srik if (c->type != T_E1) 1143128967Srik return EINVAL; 1144128967Srik s = splimp (); 1145128967Srik cp_set_mux (c->board, *((char*)data) == 'c'); 1146128967Srik splx (s); 1147128967Srik return 0; 1148128967Srik 1149128967Srik case SERIAL_GETSTAT: 1150128967Srik CP_DEBUG2 (d, ("ioctl: getstat\n")); 1151128967Srik st = (struct serial_statistics*) data; 1152128967Srik st->rintr = c->rintr; 1153128967Srik st->tintr = c->tintr; 1154128967Srik st->mintr = 0; 1155128967Srik st->ibytes = c->ibytes; 1156128967Srik st->ipkts = c->ipkts; 1157128967Srik st->obytes = c->obytes; 1158128967Srik st->opkts = c->opkts; 1159128967Srik st->ierrs = c->overrun + c->frame + c->crc; 1160128967Srik st->oerrs = c->underrun; 1161128967Srik return 0; 1162128967Srik 1163128967Srik case SERIAL_GETESTAT: 1164128967Srik CP_DEBUG2 (d, ("ioctl: getestat\n")); 1165128967Srik if (c->type != T_E1 && c->type != T_G703) 1166128967Srik return EINVAL; 1167128967Srik opte1 = (struct e1_statistics*) data; 1168128967Srik opte1->status = c->status; 1169128967Srik opte1->cursec = c->cursec; 1170128967Srik opte1->totsec = c->totsec + c->cursec; 1171128967Srik 1172128967Srik opte1->currnt.bpv = c->currnt.bpv; 1173128967Srik opte1->currnt.fse = c->currnt.fse; 1174128967Srik opte1->currnt.crce = c->currnt.crce; 1175128967Srik opte1->currnt.rcrce = c->currnt.rcrce; 1176128967Srik opte1->currnt.uas = c->currnt.uas; 1177128967Srik opte1->currnt.les = c->currnt.les; 1178128967Srik opte1->currnt.es = c->currnt.es; 1179128967Srik opte1->currnt.bes = c->currnt.bes; 1180128967Srik opte1->currnt.ses = c->currnt.ses; 1181128967Srik opte1->currnt.oofs = c->currnt.oofs; 1182128967Srik opte1->currnt.css = c->currnt.css; 1183128967Srik opte1->currnt.dm = c->currnt.dm; 1184128967Srik 1185128967Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1186128967Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1187128967Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1188128967Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1189128967Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1190128967Srik opte1->total.les = c->total.les + c->currnt.les; 1191128967Srik opte1->total.es = c->total.es + c->currnt.es; 1192128967Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1193128967Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1194128967Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1195128967Srik opte1->total.css = c->total.css + c->currnt.css; 1196128967Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1197128967Srik for (s=0; s<48; ++s) { 1198128967Srik opte1->interval[s].bpv = c->interval[s].bpv; 1199128967Srik opte1->interval[s].fse = c->interval[s].fse; 1200128967Srik opte1->interval[s].crce = c->interval[s].crce; 1201128967Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1202128967Srik opte1->interval[s].uas = c->interval[s].uas; 1203128967Srik opte1->interval[s].les = c->interval[s].les; 1204128967Srik opte1->interval[s].es = c->interval[s].es; 1205128967Srik opte1->interval[s].bes = c->interval[s].bes; 1206128967Srik opte1->interval[s].ses = c->interval[s].ses; 1207128967Srik opte1->interval[s].oofs = c->interval[s].oofs; 1208128967Srik opte1->interval[s].css = c->interval[s].css; 1209128967Srik opte1->interval[s].dm = c->interval[s].dm; 1210128967Srik } 1211128967Srik return 0; 1212128967Srik 1213128967Srik case SERIAL_GETE3STAT: 1214128967Srik CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 1215128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1216128967Srik return EINVAL; 1217128967Srik opte3 = (struct e3_statistics*) data; 1218128967Srik 1219128967Srik opte3->status = c->e3status; 1220128967Srik opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 1221128967Srik opte3->totsec = c->e3tsec + opte3->cursec; 1222128967Srik 1223128967Srik opte3->ccv = c->e3ccv; 1224128967Srik opte3->tcv = c->e3tcv + opte3->ccv; 1225128967Srik 1226128967Srik for (s = 0; s < 48; ++s) { 1227128967Srik opte3->icv[s] = c->e3icv[s]; 1228128967Srik } 1229128967Srik return 0; 1230128967Srik 1231128967Srik case SERIAL_CLRSTAT: 1232128967Srik CP_DEBUG2 (d, ("ioctl: clrstat\n")); 1233128967Srik /* Only for superuser! */ 1234128967Srik#if __FreeBSD_version < 400000 1235128967Srik error = suser (p->p_ucred, &p->p_acflag); 1236128967Srik#elif __FreeBSD_version < 500000 1237128967Srik error = suser (p); 1238128967Srik#else 1239128967Srik error = suser (td); 1240128967Srik#endif 1241128967Srik if (error) 1242128967Srik return error; 1243128967Srik c->rintr = 0; 1244128967Srik c->tintr = 0; 1245128967Srik c->ibytes = 0; 1246128967Srik c->obytes = 0; 1247128967Srik c->ipkts = 0; 1248128967Srik c->opkts = 0; 1249128967Srik c->overrun = 0; 1250128967Srik c->frame = 0; 1251128967Srik c->crc = 0; 1252128967Srik c->underrun = 0; 1253128967Srik bzero (&c->currnt, sizeof (c->currnt)); 1254128967Srik bzero (&c->total, sizeof (c->total)); 1255128967Srik bzero (c->interval, sizeof (c->interval)); 1256128967Srik c->e3ccv = 0; 1257128967Srik c->e3tcv = 0; 1258128967Srik bzero (c->e3icv, sizeof (c->e3icv)); 1259128967Srik return 0; 1260128967Srik 1261128967Srik case SERIAL_GETBAUD: 1262128967Srik CP_DEBUG2 (d, ("ioctl: getbaud\n")); 1263128967Srik *(long*)data = c->baud; 1264128967Srik return 0; 1265128967Srik 1266128967Srik case SERIAL_SETBAUD: 1267128967Srik CP_DEBUG2 (d, ("ioctl: setbaud\n")); 1268128967Srik /* Only for superuser! */ 1269128967Srik#if __FreeBSD_version < 400000 1270128967Srik error = suser (p->p_ucred, &p->p_acflag); 1271128967Srik#elif __FreeBSD_version < 500000 1272128967Srik error = suser (p); 1273128967Srik#else 1274128967Srik error = suser (td); 1275128967Srik#endif 1276128967Srik if (error) 1277128967Srik return error; 1278128967Srik s = splimp (); 1279128967Srik cp_set_baud (c, *(long*)data); 1280128967Srik splx (s); 1281128967Srik return 0; 1282128967Srik 1283128967Srik case SERIAL_GETLOOP: 1284128967Srik CP_DEBUG2 (d, ("ioctl: getloop\n")); 1285128967Srik *(int*)data = c->lloop; 1286128967Srik return 0; 1287128967Srik 1288128967Srik case SERIAL_SETLOOP: 1289128967Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1290128967Srik /* Only for superuser! */ 1291128967Srik#if __FreeBSD_version < 400000 1292128967Srik error = suser (p->p_ucred, &p->p_acflag); 1293128967Srik#elif __FreeBSD_version < 500000 1294128967Srik error = suser (p); 1295128967Srik#else 1296128967Srik error = suser (td); 1297128967Srik#endif 1298128967Srik if (error) 1299128967Srik return error; 1300128967Srik s = splimp (); 1301128967Srik cp_set_lloop (c, *(int*)data); 1302128967Srik splx (s); 1303128967Srik return 0; 1304128967Srik 1305128967Srik case SERIAL_GETDPLL: 1306128967Srik CP_DEBUG2 (d, ("ioctl: getdpll\n")); 1307128967Srik if (c->type != T_SERIAL) 1308128967Srik return EINVAL; 1309128967Srik *(int*)data = c->dpll; 1310128967Srik return 0; 1311128967Srik 1312128967Srik case SERIAL_SETDPLL: 1313128967Srik CP_DEBUG2 (d, ("ioctl: setdpll\n")); 1314128967Srik /* Only for superuser! */ 1315128967Srik#if __FreeBSD_version < 400000 1316128967Srik error = suser (p->p_ucred, &p->p_acflag); 1317128967Srik#elif __FreeBSD_version < 500000 1318128967Srik error = suser (p); 1319128967Srik#else 1320128967Srik error = suser (td); 1321128967Srik#endif 1322128967Srik if (error) 1323128967Srik return error; 1324128967Srik if (c->type != T_SERIAL) 1325128967Srik return EINVAL; 1326128967Srik s = splimp (); 1327128967Srik cp_set_dpll (c, *(int*)data); 1328128967Srik splx (s); 1329128967Srik return 0; 1330128967Srik 1331128967Srik case SERIAL_GETNRZI: 1332128967Srik CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 1333128967Srik if (c->type != T_SERIAL) 1334128967Srik return EINVAL; 1335128967Srik *(int*)data = c->nrzi; 1336128967Srik return 0; 1337128967Srik 1338128967Srik case SERIAL_SETNRZI: 1339128967Srik CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 1340128967Srik /* Only for superuser! */ 1341128967Srik#if __FreeBSD_version < 400000 1342128967Srik error = suser (p->p_ucred, &p->p_acflag); 1343128967Srik#elif __FreeBSD_version < 500000 1344128967Srik error = suser (p); 1345128967Srik#else 1346128967Srik error = suser (td); 1347128967Srik#endif 1348128967Srik if (error) 1349128967Srik return error; 1350128967Srik if (c->type != T_SERIAL) 1351128967Srik return EINVAL; 1352128967Srik s = splimp (); 1353128967Srik cp_set_nrzi (c, *(int*)data); 1354128967Srik splx (s); 1355128967Srik return 0; 1356128967Srik 1357128967Srik case SERIAL_GETDEBUG: 1358128967Srik CP_DEBUG2 (d, ("ioctl: getdebug\n")); 1359128967Srik *(int*)data = d->chan->debug; 1360128967Srik return 0; 1361128967Srik 1362128967Srik case SERIAL_SETDEBUG: 1363128967Srik CP_DEBUG2 (d, ("ioctl: setdebug\n")); 1364128967Srik /* Only for superuser! */ 1365128967Srik#if __FreeBSD_version < 400000 1366128967Srik error = suser (p->p_ucred, &p->p_acflag); 1367128967Srik#elif __FreeBSD_version < 500000 1368128967Srik error = suser (p); 1369128967Srik#else 1370128967Srik error = suser (td); 1371128967Srik#endif 1372128967Srik if (error) 1373128967Srik return error; 1374128967Srik d->chan->debug = *(int*)data; 1375128967Srik#ifndef NETGRAPH 1376128967Srik if (d->chan->debug) 1377128967Srik d->pp.pp_if.if_flags |= IFF_DEBUG; 1378128967Srik else 1379128967Srik d->pp.pp_if.if_flags &= ~IFF_DEBUG; 1380128967Srik#endif 1381128967Srik return 0; 1382128967Srik 1383128967Srik case SERIAL_GETHIGAIN: 1384128967Srik CP_DEBUG2 (d, ("ioctl: gethigain\n")); 1385128967Srik if (c->type != T_E1) 1386128967Srik return EINVAL; 1387128967Srik *(int*)data = c->higain; 1388128967Srik return 0; 1389128967Srik 1390128967Srik case SERIAL_SETHIGAIN: 1391128967Srik CP_DEBUG2 (d, ("ioctl: sethigain\n")); 1392128967Srik /* Only for superuser! */ 1393128967Srik#if __FreeBSD_version < 400000 1394128967Srik error = suser (p->p_ucred, &p->p_acflag); 1395128967Srik#elif __FreeBSD_version < 500000 1396128967Srik error = suser (p); 1397128967Srik#else 1398128967Srik error = suser (td); 1399128967Srik#endif 1400128967Srik if (error) 1401128967Srik return error; 1402128967Srik if (c->type != T_E1) 1403128967Srik return EINVAL; 1404128967Srik s = splimp (); 1405128967Srik cp_set_higain (c, *(int*)data); 1406128967Srik splx (s); 1407128967Srik return 0; 1408128967Srik 1409128967Srik case SERIAL_GETPHONY: 1410128967Srik CP_DEBUG2 (d, ("ioctl: getphony\n")); 1411128967Srik if (c->type != T_E1) 1412128967Srik return EINVAL; 1413128967Srik *(int*)data = c->phony; 1414128967Srik return 0; 1415128967Srik 1416128967Srik case SERIAL_SETPHONY: 1417128967Srik CP_DEBUG2 (d, ("ioctl: setphony\n")); 1418128967Srik /* Only for superuser! */ 1419128967Srik#if __FreeBSD_version < 400000 1420128967Srik error = suser (p->p_ucred, &p->p_acflag); 1421128967Srik#elif __FreeBSD_version < 500000 1422128967Srik error = suser (p); 1423128967Srik#else 1424128967Srik error = suser (td); 1425128967Srik#endif 1426128967Srik if (error) 1427128967Srik return error; 1428128967Srik if (c->type != T_E1) 1429128967Srik return EINVAL; 1430128967Srik s = splimp (); 1431128967Srik cp_set_phony (c, *(int*)data); 1432128967Srik splx (s); 1433128967Srik return 0; 1434128967Srik 1435128967Srik case SERIAL_GETUNFRAM: 1436128967Srik CP_DEBUG2 (d, ("ioctl: getunfram\n")); 1437128967Srik if (c->type != T_E1) 1438128967Srik return EINVAL; 1439128967Srik *(int*)data = c->unfram; 1440128967Srik return 0; 1441128967Srik 1442128967Srik case SERIAL_SETUNFRAM: 1443128967Srik CP_DEBUG2 (d, ("ioctl: setunfram\n")); 1444128967Srik /* Only for superuser! */ 1445128967Srik#if __FreeBSD_version < 400000 1446128967Srik error = suser (p->p_ucred, &p->p_acflag); 1447128967Srik#elif __FreeBSD_version < 500000 1448128967Srik error = suser (p); 1449128967Srik#else 1450128967Srik error = suser (td); 1451128967Srik#endif 1452128967Srik if (error) 1453128967Srik return error; 1454128967Srik if (c->type != T_E1) 1455128967Srik return EINVAL; 1456128967Srik s = splimp (); 1457128967Srik cp_set_unfram (c, *(int*)data); 1458128967Srik splx (s); 1459128967Srik return 0; 1460128967Srik 1461128967Srik case SERIAL_GETSCRAMBLER: 1462128967Srik CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 1463128967Srik if (c->type != T_G703 && !c->unfram) 1464128967Srik return EINVAL; 1465128967Srik *(int*)data = c->scrambler; 1466128967Srik return 0; 1467128967Srik 1468128967Srik case SERIAL_SETSCRAMBLER: 1469128967Srik CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 1470128967Srik /* Only for superuser! */ 1471128967Srik#if __FreeBSD_version < 400000 1472128967Srik error = suser (p->p_ucred, &p->p_acflag); 1473128967Srik#elif __FreeBSD_version < 500000 1474128967Srik error = suser (p); 1475128967Srik#else 1476128967Srik error = suser (td); 1477128967Srik#endif 1478128967Srik if (error) 1479128967Srik return error; 1480128967Srik if (c->type != T_G703 && !c->unfram) 1481128967Srik return EINVAL; 1482128967Srik s = splimp (); 1483128967Srik cp_set_scrambler (c, *(int*)data); 1484128967Srik splx (s); 1485128967Srik return 0; 1486128967Srik 1487128967Srik case SERIAL_GETMONITOR: 1488128967Srik CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 1489128967Srik if (c->type != T_E1 && 1490128967Srik c->type != T_E3 && 1491128967Srik c->type != T_T3 && 1492128967Srik c->type != T_STS1) 1493128967Srik return EINVAL; 1494128967Srik *(int*)data = c->monitor; 1495128967Srik return 0; 1496128967Srik 1497128967Srik case SERIAL_SETMONITOR: 1498128967Srik CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 1499128967Srik /* Only for superuser! */ 1500128967Srik#if __FreeBSD_version < 400000 1501128967Srik error = suser (p->p_ucred, &p->p_acflag); 1502128967Srik#elif __FreeBSD_version < 500000 1503128967Srik error = suser (p); 1504128967Srik#else 1505128967Srik error = suser (td); 1506128967Srik#endif 1507128967Srik if (error) 1508128967Srik return error; 1509128967Srik if (c->type != T_E1) 1510128967Srik return EINVAL; 1511128967Srik s = splimp (); 1512128967Srik cp_set_monitor (c, *(int*)data); 1513128967Srik splx (s); 1514128967Srik return 0; 1515128967Srik 1516128967Srik case SERIAL_GETUSE16: 1517128967Srik CP_DEBUG2 (d, ("ioctl: getuse16\n")); 1518128967Srik if (c->type != T_E1 || c->unfram) 1519128967Srik return EINVAL; 1520128967Srik *(int*)data = c->use16; 1521128967Srik return 0; 1522128967Srik 1523128967Srik case SERIAL_SETUSE16: 1524128967Srik CP_DEBUG2 (d, ("ioctl: setuse16\n")); 1525128967Srik /* Only for superuser! */ 1526128967Srik#if __FreeBSD_version < 400000 1527128967Srik error = suser (p->p_ucred, &p->p_acflag); 1528128967Srik#elif __FreeBSD_version < 500000 1529128967Srik error = suser (p); 1530128967Srik#else 1531128967Srik error = suser (td); 1532128967Srik#endif 1533128967Srik if (error) 1534128967Srik return error; 1535128967Srik if (c->type != T_E1) 1536128967Srik return EINVAL; 1537128967Srik s = splimp (); 1538128967Srik cp_set_use16 (c, *(int*)data); 1539128967Srik splx (s); 1540128967Srik return 0; 1541128967Srik 1542128967Srik case SERIAL_GETCRC4: 1543128967Srik CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 1544128967Srik if (c->type != T_E1 || c->unfram) 1545128967Srik return EINVAL; 1546128967Srik *(int*)data = c->crc4; 1547128967Srik return 0; 1548128967Srik 1549128967Srik case SERIAL_SETCRC4: 1550128967Srik CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 1551128967Srik /* Only for superuser! */ 1552128967Srik#if __FreeBSD_version < 400000 1553128967Srik error = suser (p->p_ucred, &p->p_acflag); 1554128967Srik#elif __FreeBSD_version < 500000 1555128967Srik error = suser (p); 1556128967Srik#else 1557128967Srik error = suser (td); 1558128967Srik#endif 1559128967Srik if (error) 1560128967Srik return error; 1561128967Srik if (c->type != T_E1) 1562128967Srik return EINVAL; 1563128967Srik s = splimp (); 1564128967Srik cp_set_crc4 (c, *(int*)data); 1565128967Srik splx (s); 1566128967Srik return 0; 1567128967Srik 1568128967Srik case SERIAL_GETCLK: 1569128967Srik CP_DEBUG2 (d, ("ioctl: getclk\n")); 1570128967Srik if (c->type != T_E1 && 1571128967Srik c->type != T_G703 && 1572128967Srik c->type != T_E3 && 1573128967Srik c->type != T_T3 && 1574128967Srik c->type != T_STS1) 1575128967Srik return EINVAL; 1576128967Srik switch (c->gsyn) { 1577128967Srik default: *(int*)data = E1CLK_INTERNAL; break; 1578128967Srik case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1579128967Srik case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1580128967Srik case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1581128967Srik case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 1582128967Srik case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 1583128967Srik } 1584128967Srik return 0; 1585128967Srik 1586128967Srik case SERIAL_SETCLK: 1587128967Srik CP_DEBUG2 (d, ("ioctl: setclk\n")); 1588128967Srik /* Only for superuser! */ 1589128967Srik#if __FreeBSD_version < 400000 1590128967Srik error = suser (p->p_ucred, &p->p_acflag); 1591128967Srik#elif __FreeBSD_version < 500000 1592128967Srik error = suser (p); 1593128967Srik#else 1594128967Srik error = suser (td); 1595128967Srik#endif 1596128967Srik if (error) 1597128967Srik return error; 1598128967Srik if (c->type != T_E1 && 1599128967Srik c->type != T_G703 && 1600128967Srik c->type != T_E3 && 1601128967Srik c->type != T_T3 && 1602128967Srik c->type != T_STS1) 1603128967Srik return EINVAL; 1604128967Srik s = splimp (); 1605128967Srik switch (*(int*)data) { 1606128967Srik default: cp_set_gsyn (c, GSYN_INT); break; 1607128967Srik case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 1608128967Srik case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 1609128967Srik case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 1610128967Srik case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 1611128967Srik case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 1612128967Srik } 1613128967Srik splx (s); 1614128967Srik return 0; 1615128967Srik 1616128967Srik case SERIAL_GETTIMESLOTS: 1617128967Srik CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1618128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1619128967Srik return EINVAL; 1620128967Srik *(u_long*)data = c->ts; 1621128967Srik return 0; 1622128967Srik 1623128967Srik case SERIAL_SETTIMESLOTS: 1624128967Srik CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 1625128967Srik /* Only for superuser! */ 1626128967Srik#if __FreeBSD_version < 400000 1627128967Srik error = suser (p->p_ucred, &p->p_acflag); 1628128967Srik#elif __FreeBSD_version < 500000 1629128967Srik error = suser (p); 1630128967Srik#else 1631128967Srik error = suser (td); 1632128967Srik#endif 1633128967Srik if (error) 1634128967Srik return error; 1635128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1636128967Srik return EINVAL; 1637128967Srik s = splimp (); 1638128967Srik cp_set_ts (c, *(u_long*)data); 1639128967Srik splx (s); 1640128967Srik return 0; 1641128967Srik 1642128967Srik case SERIAL_GETINVCLK: 1643128967Srik CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 1644128967Srik#if 1 1645128967Srik return EINVAL; 1646128967Srik#else 1647128967Srik if (c->type != T_SERIAL) 1648128967Srik return EINVAL; 1649128967Srik *(int*)data = c->invtxc; 1650128967Srik return 0; 1651128967Srik#endif 1652128967Srik 1653128967Srik case SERIAL_SETINVCLK: 1654128967Srik CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 1655128967Srik /* Only for superuser! */ 1656128967Srik#if __FreeBSD_version < 400000 1657128967Srik error = suser (p->p_ucred, &p->p_acflag); 1658128967Srik#elif __FreeBSD_version < 500000 1659128967Srik error = suser (p); 1660128967Srik#else 1661128967Srik error = suser (td); 1662128967Srik#endif 1663128967Srik if (error) 1664128967Srik return error; 1665128967Srik if (c->type != T_SERIAL) 1666128967Srik return EINVAL; 1667128967Srik s = splimp (); 1668128967Srik cp_set_invtxc (c, *(int*)data); 1669128967Srik cp_set_invrxc (c, *(int*)data); 1670128967Srik splx (s); 1671128967Srik return 0; 1672128967Srik 1673128967Srik case SERIAL_GETINVTCLK: 1674128967Srik CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 1675128967Srik if (c->type != T_SERIAL) 1676128967Srik return EINVAL; 1677128967Srik *(int*)data = c->invtxc; 1678128967Srik return 0; 1679128967Srik 1680128967Srik case SERIAL_SETINVTCLK: 1681128967Srik CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 1682128967Srik /* Only for superuser! */ 1683128967Srik#if __FreeBSD_version < 400000 1684128967Srik error = suser (p->p_ucred, &p->p_acflag); 1685128967Srik#elif __FreeBSD_version < 500000 1686128967Srik error = suser (p); 1687128967Srik#else 1688128967Srik error = suser (td); 1689128967Srik#endif 1690128967Srik if (error) 1691128967Srik return error; 1692128967Srik if (c->type != T_SERIAL) 1693128967Srik return EINVAL; 1694128967Srik s = splimp (); 1695128967Srik cp_set_invtxc (c, *(int*)data); 1696128967Srik splx (s); 1697128967Srik return 0; 1698128967Srik 1699128967Srik case SERIAL_GETINVRCLK: 1700128967Srik CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 1701128967Srik if (c->type != T_SERIAL) 1702128967Srik return EINVAL; 1703128967Srik *(int*)data = c->invrxc; 1704128967Srik return 0; 1705128967Srik 1706128967Srik case SERIAL_SETINVRCLK: 1707128967Srik CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 1708128967Srik /* Only for superuser! */ 1709128967Srik#if __FreeBSD_version < 400000 1710128967Srik error = suser (p->p_ucred, &p->p_acflag); 1711128967Srik#elif __FreeBSD_version < 500000 1712128967Srik error = suser (p); 1713128967Srik#else 1714128967Srik error = suser (td); 1715128967Srik#endif 1716128967Srik if (error) 1717128967Srik return error; 1718128967Srik if (c->type != T_SERIAL) 1719128967Srik return EINVAL; 1720128967Srik s = splimp (); 1721128967Srik cp_set_invrxc (c, *(int*)data); 1722128967Srik splx (s); 1723128967Srik return 0; 1724128967Srik 1725128967Srik case SERIAL_GETLEVEL: 1726128967Srik CP_DEBUG2 (d, ("ioctl: getlevel\n")); 1727128967Srik if (c->type != T_G703) 1728128967Srik return EINVAL; 1729128967Srik s = splimp (); 1730128967Srik *(int*)data = cp_get_lq (c); 1731128967Srik splx (s); 1732128967Srik return 0; 1733128967Srik 1734128967Srik#if 0 1735128967Srik case SERIAL_RESET: 1736128967Srik CP_DEBUG2 (d, ("ioctl: reset\n")); 1737128967Srik /* Only for superuser! */ 1738128967Srik#if __FreeBSD_version < 400000 1739128967Srik error = suser (p->p_ucred, &p->p_acflag); 1740128967Srik#elif __FreeBSD_version < 500000 1741128967Srik error = suser (p); 1742128967Srik#else 1743128967Srik error = suser (td); 1744128967Srik#endif 1745128967Srik if (error) 1746128967Srik return error; 1747128967Srik s = splimp (); 1748128967Srik cp_reset (c->board, 0, 0); 1749128967Srik splx (s); 1750128967Srik return 0; 1751128967Srik 1752128967Srik case SERIAL_HARDRESET: 1753128967Srik CP_DEBUG2 (d, ("ioctl: hardreset\n")); 1754128967Srik /* Only for superuser! */ 1755128967Srik#if __FreeBSD_version < 400000 1756128967Srik error = suser (p->p_ucred, &p->p_acflag); 1757128967Srik#elif __FreeBSD_version < 500000 1758128967Srik error = suser (p); 1759128967Srik#else 1760128967Srik error = suser (td); 1761128967Srik#endif 1762128967Srik if (error) 1763128967Srik return error; 1764128967Srik s = splimp (); 1765128967Srik /* hard_reset (c->board); */ 1766128967Srik splx (s); 1767128967Srik return 0; 1768128967Srik#endif 1769128967Srik 1770128967Srik case SERIAL_GETCABLE: 1771128967Srik CP_DEBUG2 (d, ("ioctl: getcable\n")); 1772128967Srik if (c->type != T_SERIAL) 1773128967Srik return EINVAL; 1774128967Srik s = splimp (); 1775128967Srik *(int*)data = cp_get_cable (c); 1776128967Srik splx (s); 1777128967Srik return 0; 1778128967Srik 1779128967Srik case SERIAL_GETDIR: 1780128967Srik CP_DEBUG2 (d, ("ioctl: getdir\n")); 1781128967Srik if (c->type != T_E1 && c->type != T_DATA) 1782128967Srik return EINVAL; 1783128967Srik *(int*)data = c->dir; 1784128967Srik return 0; 1785128967Srik 1786128967Srik case SERIAL_SETDIR: 1787128967Srik CP_DEBUG2 (d, ("ioctl: setdir\n")); 1788128967Srik /* Only for superuser! */ 1789128967Srik#if __FreeBSD_version < 400000 1790128967Srik error = suser (p->p_ucred, &p->p_acflag); 1791128967Srik#elif __FreeBSD_version < 500000 1792128967Srik error = suser (p); 1793128967Srik#else 1794128967Srik error = suser (td); 1795128967Srik#endif 1796128967Srik if (error) 1797128967Srik return error; 1798128967Srik s = splimp (); 1799128967Srik cp_set_dir (c, *(int*)data); 1800128967Srik splx (s); 1801128967Srik return 0; 1802128967Srik 1803128967Srik case SERIAL_GETRLOOP: 1804128967Srik CP_DEBUG2 (d, ("ioctl: getrloop\n")); 1805128967Srik if (c->type != T_G703 && 1806128967Srik c->type != T_E3 && 1807128967Srik c->type != T_T3 && 1808128967Srik c->type != T_STS1) 1809128967Srik return EINVAL; 1810128967Srik *(int*)data = cp_get_rloop (c); 1811128967Srik return 0; 1812128967Srik 1813128967Srik case SERIAL_SETRLOOP: 1814128967Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1815128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1816128967Srik return EINVAL; 1817128967Srik /* Only for superuser! */ 1818128967Srik#if __FreeBSD_version < 400000 1819128967Srik error = suser (p->p_ucred, &p->p_acflag); 1820128967Srik#elif __FreeBSD_version < 500000 1821128967Srik error = suser (p); 1822128967Srik#else 1823128967Srik error = suser (td); 1824128967Srik#endif 1825128967Srik if (error) 1826128967Srik return error; 1827128967Srik s = splimp (); 1828128967Srik cp_set_rloop (c, *(int*)data); 1829128967Srik splx (s); 1830128967Srik return 0; 1831128967Srik 1832128967Srik case SERIAL_GETCABLEN: 1833128967Srik CP_DEBUG2 (d, ("ioctl: getcablen\n")); 1834128967Srik if (c->type != T_T3 && c->type != T_STS1) 1835128967Srik return EINVAL; 1836128967Srik *(int*)data = c->cablen; 1837128967Srik return 0; 1838128967Srik 1839128967Srik case SERIAL_SETCABLEN: 1840128967Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1841128967Srik if (c->type != T_T3 && c->type != T_STS1) 1842128967Srik return EINVAL; 1843128967Srik /* Only for superuser! */ 1844128967Srik#if __FreeBSD_version < 400000 1845128967Srik error = suser (p->p_ucred, &p->p_acflag); 1846128967Srik#elif __FreeBSD_version < 500000 1847128967Srik error = suser (p); 1848128967Srik#else 1849128967Srik error = suser (td); 1850128967Srik#endif 1851128967Srik if (error) 1852128967Srik return error; 1853128967Srik s = splimp (); 1854128967Srik cp_set_cablen (c, *(int*)data); 1855128967Srik splx (s); 1856128967Srik return 0; 1857128967Srik 1858128967Srik case TIOCSDTR: /* Set DTR */ 1859128967Srik s = splimp (); 1860128967Srik cp_set_dtr (c, 1); 1861128967Srik splx (s); 1862128967Srik return 0; 1863128967Srik 1864128967Srik case TIOCCDTR: /* Clear DTR */ 1865128967Srik s = splimp (); 1866128967Srik cp_set_dtr (c, 0); 1867128967Srik splx (s); 1868128967Srik return 0; 1869128967Srik 1870128967Srik case TIOCMSET: /* Set DTR/RTS */ 1871128967Srik s = splimp (); 1872128967Srik cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1873128967Srik cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1874128967Srik splx (s); 1875128967Srik return 0; 1876128967Srik 1877128967Srik case TIOCMBIS: /* Add DTR/RTS */ 1878128967Srik s = splimp (); 1879128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 1880128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 1881128967Srik splx (s); 1882128967Srik return 0; 1883128967Srik 1884128967Srik case TIOCMBIC: /* Clear DTR/RTS */ 1885128967Srik s = splimp (); 1886128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1887128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1888128967Srik splx (s); 1889128967Srik return 0; 1890128967Srik 1891128967Srik case TIOCMGET: /* Get modem status */ 1892128967Srik *(int*)data = cp_modem_status (c); 1893128967Srik return 0; 1894128967Srik } 1895128967Srik return ENOTTY; 1896128967Srik} 1897128967Srik 1898128967Srik#if __FreeBSD_version < 400000 1899128967Srikstatic struct cdevsw cp_cdevsw = { 1900128967Srik cp_open, cp_close, noread, nowrite, 1901128967Srik cp_ioctl, nullstop, nullreset, nodevtotty, 1902128967Srik seltrue, nommap, NULL, "cp", 1903128967Srik NULL, -1 1904128967Srik }; 1905128967Srik#elif __FreeBSD_version < 500000 1906128967Srikstatic struct cdevsw cp_cdevsw = { 1907128967Srik cp_open, cp_close, noread, nowrite, 1908128967Srik cp_ioctl, nopoll, nommap, nostrategy, 1909128967Srik "cp", CDEV_MAJOR, nodump, nopsize, 1910128967Srik D_NAGGED, -1 1911128967Srik }; 1912128967Srik#elif __FreeBSD_version == 500000 1913128967Srikstatic struct cdevsw cp_cdevsw = { 1914128967Srik cp_open, cp_close, noread, nowrite, 1915128967Srik cp_ioctl, nopoll, nommap, nostrategy, 1916128967Srik "cp", CDEV_MAJOR, nodump, nopsize, 1917128967Srik D_NAGGED, 1918128967Srik }; 1919128967Srik#elif __FreeBSD_version <= 501000 1920128967Srikstatic struct cdevsw cp_cdevsw = { 1921128967Srik .d_open = cp_open, 1922128967Srik .d_close = cp_close, 1923128967Srik .d_read = noread, 1924128967Srik .d_write = nowrite, 1925128967Srik .d_ioctl = cp_ioctl, 1926128967Srik .d_poll = nopoll, 1927128967Srik .d_mmap = nommap, 1928128967Srik .d_strategy = nostrategy, 1929128967Srik .d_name = "cp", 1930128967Srik .d_maj = CDEV_MAJOR, 1931128967Srik .d_dump = nodump, 1932128967Srik .d_flags = D_NAGGED, 1933128967Srik}; 1934128967Srik#elif __FreeBSD_version < 502103 1935128967Srikstatic struct cdevsw cp_cdevsw = { 1936128967Srik .d_open = cp_open, 1937128967Srik .d_close = cp_close, 1938128967Srik .d_ioctl = cp_ioctl, 1939128967Srik .d_name = "cp", 1940128967Srik .d_maj = CDEV_MAJOR, 1941128967Srik .d_flags = D_NAGGED, 1942128967Srik}; 1943128967Srik#else /* __FreeBSD_version >= 502103 */ 1944128967Srikstatic struct cdevsw cp_cdevsw = { 1945128967Srik .d_version = D_VERSION, 1946128967Srik .d_open = cp_open, 1947128967Srik .d_close = cp_close, 1948128967Srik .d_ioctl = cp_ioctl, 1949128967Srik .d_name = "cp", 1950128967Srik .d_maj = CDEV_MAJOR, 1951128967Srik .d_flags = D_NEEDGIANT, 1952128967Srik}; 1953128967Srik#endif 1954128967Srik 1955128967Srik#ifdef NETGRAPH 1956128967Srik#if __FreeBSD_version >= 500000 1957128967Srikstatic int ng_cp_constructor (node_p node) 1958128967Srik{ 1959128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1960128967Srik#else 1961128967Srikstatic int ng_cp_constructor (node_p *node) 1962128967Srik{ 1963128967Srik drv_t *d = (*node)->private; 1964128967Srik#endif 1965128967Srik CP_DEBUG (d, ("Constructor\n")); 1966128967Srik return EINVAL; 1967128967Srik} 1968128967Srik 1969128967Srikstatic int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1970128967Srik{ 1971128967Srik int s; 1972128967Srik#if __FreeBSD_version >= 500000 1973128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1974128967Srik#else 1975128967Srik drv_t *d = node->private; 1976128967Srik#endif 1977128967Srik 1978128967Srik CP_DEBUG (d, ("Newhook\n")); 1979128967Srik /* Attach debug hook */ 1980128967Srik if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1981128967Srik#if __FreeBSD_version >= 500000 1982128967Srik NG_HOOK_SET_PRIVATE (hook, NULL); 1983128967Srik#else 1984128967Srik hook->private = 0; 1985128967Srik#endif 1986128967Srik d->debug_hook = hook; 1987128967Srik return 0; 1988128967Srik } 1989128967Srik 1990128967Srik /* Check for raw hook */ 1991128967Srik if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1992128967Srik return EINVAL; 1993128967Srik 1994128967Srik#if __FreeBSD_version >= 500000 1995128967Srik NG_HOOK_SET_PRIVATE (hook, d); 1996128967Srik#else 1997128967Srik hook->private = d; 1998128967Srik#endif 1999128967Srik d->hook = hook; 2000128967Srik s = splimp (); 2001128967Srik cp_up (d); 2002128967Srik splx (s); 2003128967Srik return 0; 2004128967Srik} 2005128967Srik 2006128967Srikstatic char *format_timeslots (u_long s) 2007128967Srik{ 2008128967Srik static char buf [100]; 2009128967Srik char *p = buf; 2010128967Srik int i; 2011128967Srik 2012128967Srik for (i=1; i<32; ++i) 2013128967Srik if ((s >> i) & 1) { 2014128967Srik int prev = (i > 1) & (s >> (i-1)); 2015128967Srik int next = (i < 31) & (s >> (i+1)); 2016128967Srik 2017128967Srik if (prev) { 2018128967Srik if (next) 2019128967Srik continue; 2020128967Srik *p++ = '-'; 2021128967Srik } else if (p > buf) 2022128967Srik *p++ = ','; 2023128967Srik 2024128967Srik if (i >= 10) 2025128967Srik *p++ = '0' + i / 10; 2026128967Srik *p++ = '0' + i % 10; 2027128967Srik } 2028128967Srik *p = 0; 2029128967Srik return buf; 2030128967Srik} 2031128967Srik 2032128967Srikstatic int print_modems (char *s, cp_chan_t *c, int need_header) 2033128967Srik{ 2034128967Srik int status = cp_modem_status (c); 2035128967Srik int length = 0; 2036128967Srik 2037128967Srik if (need_header) 2038128967Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 2039128967Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 2040128967Srik status & TIOCM_LE ? "On" : "-", 2041128967Srik status & TIOCM_DTR ? "On" : "-", 2042128967Srik status & TIOCM_DSR ? "On" : "-", 2043128967Srik status & TIOCM_RTS ? "On" : "-", 2044128967Srik status & TIOCM_CTS ? "On" : "-", 2045128967Srik status & TIOCM_CD ? "On" : "-"); 2046128967Srik return length; 2047128967Srik} 2048128967Srik 2049128967Srikstatic int print_stats (char *s, cp_chan_t *c, int need_header) 2050128967Srik{ 2051128967Srik int length = 0; 2052128967Srik 2053128967Srik if (need_header) 2054128967Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 2055128967Srik length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 2056128967Srik c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 2057128967Srik c->ipkts, c->overrun + c->frame + c->crc, 2058128967Srik (unsigned long) c->obytes, c->opkts, c->underrun); 2059128967Srik return length; 2060128967Srik} 2061128967Srik 2062128967Srikstatic char *format_e1_status (u_char status) 2063128967Srik{ 2064128967Srik static char buf [80]; 2065128967Srik 2066128967Srik if (status & E1_NOALARM) 2067128967Srik return "Ok"; 2068128967Srik buf[0] = 0; 2069128967Srik if (status & E1_LOS) strcat (buf, ",LOS"); 2070128967Srik if (status & E1_AIS) strcat (buf, ",AIS"); 2071128967Srik if (status & E1_LOF) strcat (buf, ",LOF"); 2072128967Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 2073128967Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 2074128967Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 2075128967Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 2076128967Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 2077128967Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 2078128967Srik if (buf[0] == ',') 2079128967Srik return buf+1; 2080128967Srik return "Unknown"; 2081128967Srik} 2082128967Srik 2083128967Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 2084128967Srik{ 2085128967Srik int n, length = 0; 2086128967Srik 2087128967Srik if (numerator < 1 || divider < 1) { 2088128967Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 2089128967Srik return length; 2090128967Srik } 2091128967Srik n = (int) (0.5 + 1000.0 * numerator / divider); 2092128967Srik if (n < 1000) { 2093128967Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 2094128967Srik return length; 2095128967Srik } 2096128967Srik *(s + length) = leftalign ? '/' : ' '; 2097128967Srik length ++; 2098128967Srik 2099128967Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 2100128967Srik else if (n >= 100000) n = (n+50) / 100 * 100; 2101128967Srik else if (n >= 10000) n = (n+5) / 10 * 10; 2102128967Srik 2103128967Srik switch (n) { 2104128967Srik case 1000: length += printf (s+length, ".999"); return length; 2105128967Srik case 10000: n = 9990; break; 2106128967Srik case 100000: n = 99900; break; 2107128967Srik case 1000000: n = 999000; break; 2108128967Srik } 2109128967Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 2110128967Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 2111128967Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 2112128967Srik else length += sprintf (s+length, "%d", n/1000); 2113128967Srik 2114128967Srik return length; 2115128967Srik} 2116128967Srik 2117128967Srikstatic int print_e1_stats (char *s, cp_chan_t *c) 2118128967Srik{ 2119128967Srik struct e1_counters total; 2120128967Srik u_long totsec; 2121128967Srik int length = 0; 2122128967Srik 2123128967Srik totsec = c->totsec + c->cursec; 2124128967Srik total.bpv = c->total.bpv + c->currnt.bpv; 2125128967Srik total.fse = c->total.fse + c->currnt.fse; 2126128967Srik total.crce = c->total.crce + c->currnt.crce; 2127128967Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 2128128967Srik total.uas = c->total.uas + c->currnt.uas; 2129128967Srik total.les = c->total.les + c->currnt.les; 2130128967Srik total.es = c->total.es + c->currnt.es; 2131128967Srik total.bes = c->total.bes + c->currnt.bes; 2132128967Srik total.ses = c->total.ses + c->currnt.ses; 2133128967Srik total.oofs = c->total.oofs + c->currnt.oofs; 2134128967Srik total.css = c->total.css + c->currnt.css; 2135128967Srik total.dm = c->total.dm + c->currnt.dm; 2136128967Srik 2137128967Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 2138128967Srik 2139128967Srik /* Unavailable seconds, degraded minutes */ 2140128967Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 2141128967Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 2142128967Srik 2143128967Srik /* Bipolar violations, frame sync errors */ 2144128967Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 2145128967Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 2146128967Srik 2147128967Srik /* CRC errors, remote CRC errors (E-bit) */ 2148128967Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 2149128967Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 2150128967Srik 2151128967Srik /* Errored seconds, line errored seconds */ 2152128967Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 2153128967Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 2154128967Srik 2155128967Srik /* Severely errored seconds, burst errored seconds */ 2156128967Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 2157128967Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 2158128967Srik 2159128967Srik /* Out of frame seconds, controlled slip seconds */ 2160128967Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 2161128967Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 2162128967Srik 2163128967Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 2164128967Srik 2165128967Srik /* Print total statistics. */ 2166128967Srik length += print_frac (s + length, 0, total.uas, totsec); 2167128967Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 2168128967Srik 2169128967Srik length += print_frac (s + length, 0, total.bpv, totsec); 2170128967Srik length += print_frac (s + length, 1, total.fse, totsec); 2171128967Srik 2172128967Srik length += print_frac (s + length, 0, total.crce, totsec); 2173128967Srik length += print_frac (s + length, 1, total.rcrce, totsec); 2174128967Srik 2175128967Srik length += print_frac (s + length, 0, total.es, totsec); 2176128967Srik length += print_frac (s + length, 1, total.les, totsec); 2177128967Srik 2178128967Srik length += print_frac (s + length, 0, total.ses, totsec); 2179128967Srik length += print_frac (s + length, 1, total.bes, totsec); 2180128967Srik 2181128967Srik length += print_frac (s + length, 0, total.oofs, totsec); 2182128967Srik length += print_frac (s + length, 1, total.css, totsec); 2183128967Srik 2184128967Srik length += sprintf (s + length, " -- Total\n"); 2185128967Srik return length; 2186128967Srik} 2187128967Srik 2188128967Srikstatic int print_chan (char *s, cp_chan_t *c) 2189128967Srik{ 2190128967Srik drv_t *d = c->sys; 2191128967Srik int length = 0; 2192128967Srik 2193128967Srik length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2194128967Srik if (d->chan->debug) 2195128967Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 2196128967Srik 2197128967Srik if (c->board->mux) { 2198128967Srik length += sprintf (s + length, " cfg=C"); 2199128967Srik } else { 2200128967Srik length += sprintf (s + length, " cfg=A"); 2201128967Srik } 2202128967Srik 2203128967Srik if (c->baud) 2204128967Srik length += sprintf (s + length, " %ld", c->baud); 2205128967Srik else 2206128967Srik length += sprintf (s + length, " extclock"); 2207128967Srik 2208128967Srik if (c->type == T_E1 || c->type == T_G703) 2209128967Srik switch (c->gsyn) { 2210128967Srik case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2211128967Srik case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2212128967Srik case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2213128967Srik case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2214128967Srik case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2215128967Srik case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2216128967Srik } 2217128967Srik if (c->type == T_SERIAL) { 2218128967Srik length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2219128967Srik length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2220128967Srik length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2221128967Srik } 2222128967Srik if (c->type == T_E1) 2223128967Srik length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2224128967Srik 2225128967Srik length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2226128967Srik 2227128967Srik if (c->type == T_E1) 2228128967Srik length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2229128967Srik if (c->type == T_G703) { 2230128967Srik int lq, x; 2231128967Srik 2232128967Srik x = splimp (); 2233128967Srik lq = cp_get_lq (c); 2234128967Srik splx (x); 2235128967Srik length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2236128967Srik } 2237128967Srik length += sprintf (s + length, "\n"); 2238128967Srik return length; 2239128967Srik} 2240128967Srik 2241128967Srik#if __FreeBSD_version >= 500000 2242128967Srikstatic int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2243128967Srik{ 2244128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2245128967Srik struct ng_mesg *msg; 2246128967Srik#else 2247128967Srikstatic int ng_cp_rcvmsg (node_p node, struct ng_mesg *msg, 2248128967Srik const char *retaddr, struct ng_mesg **rptr) 2249128967Srik{ 2250128967Srik drv_t *d = node->private; 2251128967Srik#endif 2252128967Srik struct ng_mesg *resp = NULL; 2253128967Srik int error = 0; 2254128967Srik 2255128967Srik CP_DEBUG (d, ("Rcvmsg\n")); 2256128967Srik#if __FreeBSD_version >= 500000 2257128967Srik NGI_GET_MSG (item, msg); 2258128967Srik#endif 2259128967Srik switch (msg->header.typecookie) { 2260128967Srik default: 2261128967Srik error = EINVAL; 2262128967Srik break; 2263128967Srik 2264128967Srik case NGM_CP_COOKIE: 2265128967Srik printf ("Not implemented yet\n"); 2266128967Srik error = EINVAL; 2267128967Srik break; 2268128967Srik 2269128967Srik case NGM_GENERIC_COOKIE: 2270128967Srik switch (msg->header.cmd) { 2271128967Srik default: 2272128967Srik error = EINVAL; 2273128967Srik break; 2274128967Srik 2275128967Srik case NGM_TEXT_STATUS: { 2276128967Srik char *s; 2277128967Srik int l = 0; 2278128967Srik int dl = sizeof (struct ng_mesg) + 730; 2279128967Srik 2280128967Srik#if __FreeBSD_version >= 500000 2281128967Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2282128967Srik if (! resp) { 2283128967Srik error = ENOMEM; 2284128967Srik break; 2285128967Srik } 2286128967Srik#else 2287128967Srik MALLOC (resp, struct ng_mesg *, dl, 2288128967Srik M_NETGRAPH, M_NOWAIT); 2289128967Srik if (! resp) { 2290128967Srik error = ENOMEM; 2291128967Srik break; 2292128967Srik } 2293128967Srik bzero (resp, dl); 2294128967Srik#endif 2295128967Srik s = (resp)->data; 2296128967Srik if (d) { 2297128967Srik l += print_chan (s + l, d->chan); 2298128967Srik l += print_stats (s + l, d->chan, 1); 2299128967Srik l += print_modems (s + l, d->chan, 1); 2300128967Srik l += print_e1_stats (s + l, d->chan); 2301128967Srik } else 2302128967Srik l += sprintf (s + l, "Error: node not connect to channel"); 2303128967Srik#if __FreeBSD_version < 500000 2304128967Srik (resp)->header.version = NG_VERSION; 2305128967Srik (resp)->header.arglen = strlen (s) + 1; 2306128967Srik (resp)->header.token = msg->header.token; 2307128967Srik (resp)->header.typecookie = NGM_CP_COOKIE; 2308128967Srik (resp)->header.cmd = msg->header.cmd; 2309128967Srik#endif 2310128967Srik strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 2311128967Srik } 2312128967Srik break; 2313128967Srik } 2314128967Srik break; 2315128967Srik } 2316128967Srik#if __FreeBSD_version >= 500000 2317128967Srik NG_RESPOND_MSG (error, node, item, resp); 2318128967Srik NG_FREE_MSG (msg); 2319128967Srik#else 2320128967Srik *rptr = resp; 2321128967Srik FREE (msg, M_NETGRAPH); 2322128967Srik#endif 2323128967Srik return error; 2324128967Srik} 2325128967Srik 2326128967Srik#if __FreeBSD_version >= 500000 2327128967Srikstatic int ng_cp_rcvdata (hook_p hook, item_p item) 2328128967Srik{ 2329128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2330128967Srik struct mbuf *m; 2331128967Srik meta_p meta; 2332128967Srik#else 2333128967Srikstatic int ng_cp_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) 2334128967Srik{ 2335128967Srik drv_t *d = hook->node->private; 2336128967Srik#endif 2337128967Srik struct ifqueue *q; 2338128967Srik int s; 2339128967Srik 2340128967Srik CP_DEBUG2 (d, ("Rcvdata\n")); 2341128967Srik#if __FreeBSD_version >= 500000 2342128967Srik NGI_GET_M (item, m); 2343128967Srik NGI_GET_META (item, meta); 2344128967Srik NG_FREE_ITEM (item); 2345128967Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 2346128967Srik NG_FREE_M (m); 2347128967Srik NG_FREE_META (meta); 2348128967Srik#else 2349128967Srik if (! hook->private || ! d) { 2350128967Srik NG_FREE_DATA (m,meta); 2351128967Srik#endif 2352128967Srik return ENETDOWN; 2353128967Srik } 2354128967Srik q = (meta && meta->priority > 0) ? &d->hi_queue : &d->queue; 2355128967Srik s = splimp (); 2356128967Srik#if __FreeBSD_version >= 500000 2357128967Srik IF_LOCK (q); 2358128967Srik if (_IF_QFULL (q)) { 2359128967Srik _IF_DROP (q); 2360128967Srik IF_UNLOCK (q); 2361128967Srik splx (s); 2362128967Srik NG_FREE_M (m); 2363128967Srik NG_FREE_META (meta); 2364128967Srik return ENOBUFS; 2365128967Srik } 2366128967Srik _IF_ENQUEUE (q, m); 2367128967Srik IF_UNLOCK (q); 2368128967Srik#else 2369128967Srik if (IF_QFULL (q)) { 2370128967Srik IF_DROP (q); 2371128967Srik splx (s); 2372128967Srik NG_FREE_DATA (m, meta); 2373128967Srik return ENOBUFS; 2374128967Srik } 2375128967Srik IF_ENQUEUE (q, m); 2376128967Srik#endif 2377128967Srik cp_start (d); 2378128967Srik splx (s); 2379128967Srik return 0; 2380128967Srik} 2381128967Srik 2382128967Srikstatic int ng_cp_rmnode (node_p node) 2383128967Srik{ 2384128967Srik#if __FreeBSD_version >= 500000 2385128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2386128967Srik 2387128967Srik CP_DEBUG (d, ("Rmnode\n")); 2388128967Srik if (d && d->running) { 2389128967Srik int s = splimp (); 2390128967Srik cp_down (d); 2391128967Srik splx (s); 2392128967Srik } 2393128967Srik#ifdef KLD_MODULE 2394128967Srik if (node->nd_flags & NG_REALLY_DIE) { 2395128967Srik NG_NODE_SET_PRIVATE (node, NULL); 2396128967Srik NG_NODE_UNREF (node); 2397128967Srik } 2398128967Srik node->nd_flags &= ~NG_INVALID; 2399128967Srik#endif 2400128967Srik#else /* __FreeBSD_version < 500000 */ 2401128967Srik drv_t *d = node->private; 2402128967Srik 2403128967Srik if (d && d->running) { 2404128967Srik int s = splimp (); 2405128967Srik cp_down (d); 2406128967Srik splx (s); 2407128967Srik } 2408128967Srik 2409128967Srik node->flags |= NG_INVALID; 2410128967Srik ng_cutlinks (node); 2411128967Srik#ifdef KLD_MODULE 2412128967Srik#if __FreeBSD_version >= 400000 2413128967Srik /* We do so because of pci module problem, see also comment in 2414128967Srik cp_unload. Not in 4.x. */ 2415128967Srik ng_unname (node); 2416128967Srik ng_unref (node); 2417128967Srik#else 2418128967Srik node->flags &= ~NG_INVALID; 2419128967Srik#endif 2420128967Srik#endif 2421128967Srik#endif 2422128967Srik return 0; 2423128967Srik} 2424128967Srik 2425128967Srikstatic void ng_cp_watchdog (void *arg) 2426128967Srik{ 2427128967Srik drv_t *d = arg; 2428128967Srik 2429128967Srik if (d) { 2430128967Srik if (d->timeout == 1) 2431128967Srik cp_watchdog (d); 2432128967Srik if (d->timeout) 2433128967Srik d->timeout--; 2434128967Srik d->timeout_handle = timeout (ng_cp_watchdog, d, hz); 2435128967Srik } 2436128967Srik} 2437128967Srik 2438128967Srikstatic int ng_cp_connect (hook_p hook) 2439128967Srik{ 2440128967Srik#if __FreeBSD_version >= 500000 2441128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2442128967Srik#else 2443128967Srik drv_t *d = hook->node->private; 2444128967Srik#endif 2445128967Srik 2446128967Srik if (d) { 2447128967Srik CP_DEBUG (d, ("Connect\n")); 2448128967Srik d->timeout_handle = timeout (ng_cp_watchdog, d, hz); 2449128967Srik } 2450128967Srik 2451128967Srik return 0; 2452128967Srik} 2453128967Srik 2454128967Srikstatic int ng_cp_disconnect (hook_p hook) 2455128967Srik{ 2456128967Srik#if __FreeBSD_version >= 500000 2457128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2458128967Srik#else 2459128967Srik drv_t *d = hook->node->private; 2460128967Srik#endif 2461128967Srik 2462128967Srik if (d) { 2463128967Srik CP_DEBUG (d, ("Disconnect\n")); 2464128967Srik#if __FreeBSD_version >= 500000 2465128967Srik if (NG_HOOK_PRIVATE (hook)) 2466128967Srik#else 2467128967Srik if (hook->private) 2468128967Srik#endif 2469128967Srik { 2470128967Srik int s = splimp (); 2471128967Srik cp_down (d); 2472128967Srik splx (s); 2473128967Srik } 2474128967Srik untimeout (ng_cp_watchdog, d, d->timeout_handle); 2475128967Srik } 2476128967Srik return 0; 2477128967Srik} 2478128967Srik#endif 2479128967Srik 2480128967Srik#if __FreeBSD_version < 400000 2481128967Srik 2482128967Srik#ifdef KLD_MODULE 2483128967Srikextern STAILQ_HEAD(devlist, pci_devinfo) pci_devq; 2484128967Srik 2485128967Srikstatic 2486128967Srikstruct pci_devinfo *pci_device_find (u_int16_t device, u_int16_t vendor, int unit) 2487128967Srik{ 2488128967Srik pcicfgregs *cfg; 2489128967Srik struct pci_devinfo *dinfo; 2490128967Srik int u=0,i; 2491128967Srik 2492128967Srik for (dinfo = STAILQ_FIRST (&pci_devq), i=0; 2493128967Srik dinfo && (i < pci_numdevs); 2494128967Srik dinfo = STAILQ_NEXT (dinfo, pci_links), i++) { 2495128967Srik cfg = &dinfo->cfg; 2496128967Srik if ((device == cfg->device) && (vendor == cfg->vendor)) { 2497128967Srik if (u == unit) 2498128967Srik return dinfo; 2499128967Srik u++; 2500128967Srik } 2501128967Srik } 2502128967Srik return 0; 2503128967Srik} 2504128967Srik 2505128967Srik/* 2506128967Srik * Function called when loading the driver. 2507128967Srik */ 2508128967Srikstatic int cp_load (void) 2509128967Srik{ 2510128967Srik int i, s; 2511128967Srik pcicfgregs *cfg; 2512128967Srik struct pci_devinfo *dinfo; 2513128967Srik 2514128967Srik s = splimp (); 2515128967Srik for (i=0; i<NBRD; ++i) { 2516128967Srik dinfo = pci_device_find (cp_device_id, cp_vendor_id, i); 2517128967Srik if (! dinfo) 2518128967Srik break; 2519128967Srik 2520128967Srik cfg = &dinfo->cfg; 2521128967Srik cp_attach (cfg, i); 2522128967Srik dinfo->device = &cp_driver; 2523128967Srik strncpy (dinfo->conf.pd_name, cp_driver.pd_name, 2524128967Srik sizeof(dinfo->conf.pd_name)); 2525128967Srik dinfo->conf.pd_name[sizeof(dinfo->conf.pd_name) - 1] = 0; 2526128967Srik dinfo->conf.pd_unit = i; 2527128967Srik } 2528128967Srik splx (s); 2529128967Srik if (! i) { 2530128967Srik /* Deactivate the timeout routine. */ 2531128967Srik untimeout (cp_timeout, 0, timeout_handle); 2532128967Srik return ENXIO; 2533128967Srik } 2534128967Srik return 0; 2535128967Srik} 2536128967Srik 2537128967Srik/* 2538128967Srik * Function called when unloading the driver. 2539128967Srik */ 2540128967Srikstatic int cp_unload (void) 2541128967Srik{ 2542128967Srik#if 1 2543128967Srik /* Currently pci loadable module not fully supported, so we just 2544128967Srik return EBUSY. Do not forget to correct ng_cp_rmnode then probelm 2545128967Srik would be solved. */ 2546128967Srik return EBUSY; 2547128967Srik#else 2548128967Srik int i, s; 2549128967Srik 2550128967Srik /* Check if the device is busy (open). */ 2551128967Srik for (i=0; i<NBRD*NCHAN; ++i) { 2552128967Srik drv_t *d = channel[i]; 2553128967Srik 2554128967Srik if (d && d->chan->type && d->running) 2555128967Srik return EBUSY; 2556128967Srik } 2557128967Srik 2558128967Srik s = splimp (); 2559128967Srik 2560128967Srik /* Deactivate the timeout routine. */ 2561128967Srik untimeout (cp_timeout, 0, timeout_handle); 2562128967Srik 2563128967Srik /* OK to unload the driver, unregister the interrupt first. */ 2564128967Srik for (i=0; i<NBRD; ++i) { 2565128967Srik cp_board_t *b = adapter [i]; 2566128967Srik 2567128967Srik if (!b || ! b->type) 2568128967Srik continue; 2569128967Srik 2570128967Srik cp_reset (b, 0 ,0); 2571128967Srik/* pci_unmap_int (tag, cp_intr, b, &net_imask);*/ 2572128967Srik /* Here should be something like pci_unmap_mem ()*/ 2573128967Srik } 2574128967Srik 2575128967Srik for (i=0; i<NBRD; i++) 2576128967Srik if (led_timo[i].callout) 2577128967Srik untimeout (cp_led_off, adapter + i, led_timo[i]); 2578128967Srik 2579128967Srik /* Detach the interfaces, free buffer memory. */ 2580128967Srik for (i=0; i<NBRD*NCHAN; ++i) { 2581128967Srik drv_t *d = channel[i]; 2582128967Srik 2583128967Srik if (! d) 2584128967Srik continue; 2585128967Srik#ifndef NETGRAPH 2586128967Srik#if __FreeBSD_version >= 400000 || NBPFILTER > 0 2587128967Srik /* Detach from the packet filter list of interfaces. */ 2588128967Srik { 2589128967Srik struct bpf_if *q, **b = &bpf_iflist; 2590128967Srik 2591128967Srik while ((q = *b)) { 2592128967Srik if (q->bif_ifp == d->pp.pp_if) { 2593128967Srik *b = q->bif_next; 2594128967Srik free (q, M_DEVBUF); 2595128967Srik } 2596128967Srik b = &(q->bif_next); 2597128967Srik } 2598128967Srik } 2599128967Srik#endif 2600128967Srik /* Detach from the sync PPP list. */ 2601128967Srik sppp_detach (&d->pp.pp_if); 2602128967Srik 2603128967Srik /* Detach from the system list of interfaces. */ 2604128967Srik { 2605128967Srik struct ifaddr *ifa; 2606128967Srik TAILQ_FOREACH (ifa, &d->pp.pp_if.if_addrhead, ifa_link) { 2607128967Srik TAILQ_REMOVE (&d->pp.pp_if.if_addrhead, ifa, ifa_link); 2608128967Srik free (ifa, M_IFADDR); 2609128967Srik } 2610128967Srik TAILQ_REMOVE (&ifnet, &d->pp.pp_if, if_link); 2611128967Srik } 2612128967Srik#endif 2613128967Srik /* Deallocate buffers. */ 2614128967Srik/* free (d, M_DEVBUF);*/ 2615128967Srik } 2616128967Srik 2617128967Srik for (i=0; i<NBRD; ++i) { 2618128967Srik cp_board_t *b = adapter + i; 2619128967Srik 2620128967Srik if (b && b->type) 2621128967Srik free (b, M_DEVBUF); 2622128967Srik } 2623128967Srik splx (s); 2624128967Srik return 0; 2625128967Srik#endif 2626128967Srik} 2627128967Srik#endif 2628128967Srik#endif 2629128967Srik 2630128967Srik#if __FreeBSD_version < 400000 2631128967Srik#ifdef KLD_MODULE 2632128967Srikstatic int cp_modevent (module_t mod, int type, void *unused) 2633128967Srik{ 2634128967Srik dev_t dev; 2635128967Srik 2636128967Srik switch (type) { 2637128967Srik case MOD_LOAD: 2638128967Srik dev = makedev (CDEV_MAJOR, 0); 2639128967Srik cdevsw_add (&dev, &cp_cdevsw, 0); 2640128967Srik timeout_handle = timeout (cp_timeout, 0, hz*5); 2641128967Srik return cp_load (); 2642128967Srik case MOD_UNLOAD: 2643128967Srik return cp_unload (); 2644128967Srik case MOD_SHUTDOWN: 2645128967Srik break; 2646128967Srik } 2647128967Srik return 0; 2648128967Srik} 2649128967Srik#endif /* KLD_MODULE */ 2650128967Srik 2651128967Srik#else /* __FreeBSD_version >= 400000 */ 2652128967Srikstatic int cp_modevent (module_t mod, int type, void *unused) 2653128967Srik{ 2654128967Srik dev_t dev; 2655128967Srik static int load_count = 0; 2656128967Srik struct cdevsw *cdsw; 2657128967Srik 2658128967Srik#if __FreeBSD_version >= 502103 2659128967Srik dev = udev2dev (makeudev(CDEV_MAJOR, 0)); 2660128967Srik#else 2661128967Srik dev = makedev (CDEV_MAJOR, 0); 2662128967Srik#endif 2663128967Srik switch (type) { 2664128967Srik case MOD_LOAD: 2665128967Srik if (dev != NODEV && 2666128967Srik (cdsw = devsw (dev)) && 2667128967Srik cdsw->d_maj == CDEV_MAJOR) { 2668128967Srik printf ("Tau-PCI driver is already in system\n"); 2669128967Srik return (ENXIO); 2670128967Srik } 2671128967Srik#if __FreeBSD_version >= 500000 && defined NETGRAPH 2672128967Srik if (ng_newtype (&typestruct)) 2673128967Srik printf ("Failed to register ng_cp\n"); 2674128967Srik#endif 2675128967Srik ++load_count; 2676128967Srik#if __FreeBSD_version <= 500000 2677128967Srik cdevsw_add (&cp_cdevsw); 2678128967Srik#endif 2679128967Srik timeout_handle = timeout (cp_timeout, 0, hz*5); 2680128967Srik break; 2681128967Srik case MOD_UNLOAD: 2682128967Srik if (load_count == 1) { 2683128967Srik printf ("Removing device entry for Tau-PCI\n"); 2684128967Srik#if __FreeBSD_version <= 500000 2685128967Srik cdevsw_remove (&cp_cdevsw); 2686128967Srik#endif 2687128967Srik#if __FreeBSD_version >= 500000 && defined NETGRAPH 2688128967Srik ng_rmtype (&typestruct); 2689128967Srik#endif 2690128967Srik } 2691128967Srik untimeout (cp_timeout, 0, timeout_handle); 2692128967Srik --load_count; 2693128967Srik break; 2694128967Srik case MOD_SHUTDOWN: 2695128967Srik break; 2696128967Srik } 2697128967Srik return 0; 2698128967Srik} 2699128967Srik#endif /* __FreeBSD_version < 400000 */ 2700128967Srik 2701128967Srik#ifdef NETGRAPH 2702128967Srikstatic struct ng_type typestruct = { 2703129837Srik .version = NG_ABI_VERSION, 2704129837Srik .name = NG_CP_NODE_TYPE, 2705129837Srik .constructor = ng_cp_constructor, 2706129837Srik .rcvmsg = ng_cp_rcvmsg, 2707129837Srik .shutdown = ng_cp_rmnode, 2708129837Srik .newhook = ng_cp_newhook, 2709129837Srik .connect = ng_cp_connect, 2710129837Srik .rcvdata = ng_cp_rcvdata, 2711129837Srik .disconnect = ng_cp_disconnect, 2712128967Srik}; 2713128967Srik#if __FreeBSD_version < 400000 2714128967SrikNETGRAPH_INIT_ORDERED (cp, &typestruct, SI_SUB_DRIVERS,\ 2715128967Srik SI_ORDER_MIDDLE + CDEV_MAJOR); 2716128967Srik#endif 2717128967Srik#endif /*NETGRAPH*/ 2718128967Srik 2719128967Srik#if __FreeBSD_version >= 500000 2720128967Srik#ifdef NETGRAPH 2721128967SrikMODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2722128967Srik#else 2723128967SrikMODULE_DEPEND (cp, sppp, 1, 1, 1); 2724128967Srik#endif 2725128967Srik#ifdef KLD_MODULE 2726128967SrikDRIVER_MODULE (cpmod, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2727128967Srik#else 2728128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2729128967Srik#endif 2730128967Srik#elif __FreeBSD_version >= 400000 2731128967Srik#ifdef NETGRAPH 2732128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, ng_mod_event, &typestruct); 2733128967Srik#else 2734128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2735128967Srik#endif 2736128967Srik#else /* __FreeBSD_version < 400000 */ 2737128967Srik#ifdef KLD_MODULE 2738128967Srik#ifndef NETGRAPH 2739128967Srikstatic moduledata_t cpmod = { "cp", cp_modevent, NULL}; 2740128967SrikDECLARE_MODULE (cp, cpmod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR); 2741128967Srik#endif 2742128967Srik#else /* KLD_MODULE */ 2743128967Srik 2744128967Srik/* 2745128967Srik * Now for some driver initialisation. 2746128967Srik * Occurs ONCE during boot (very early). 2747128967Srik * This is if we are NOT a loadable module. 2748128967Srik */ 2749128967Srikstatic void cp_drvinit (void *unused) 2750128967Srik{ 2751128967Srik dev_t dev; 2752128967Srik 2753128967Srik dev = makedev (CDEV_MAJOR, 0); 2754128967Srik cdevsw_add (&dev, &cp_cdevsw, 0); 2755128967Srik 2756128967Srik /* Activate the timeout routine. */ 2757128967Srik timeout_handle = timeout (cp_timeout, 0, hz); 2758128967Srik#ifdef NETGRAPH 2759128967Srik#if 0 2760128967Srik /* Register our node type in netgraph */ 2761128967Srik if (ng_newtype (&typestruct)) 2762128967Srik printf ("Failed to register ng_cp\n"); 2763128967Srik#endif 2764128967Srik#endif 2765128967Srik} 2766128967Srik 2767128967SrikSYSINIT (cpdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, cp_drvinit, 0) 2768128967Srik#endif /* KLD_MODULE */ 2769128967Srik#endif /* __FreeBSD_version < 400000 */ 2770128967Srik#endif /* NPCI */ 2771