1139749Simp/*- 2128967Srik * Cronyx-Tau-PCI adapter driver for FreeBSD. 3128967Srik * Supports PPP/HDLC, Cisco/HDLC and FrameRelay protocol in synchronous mode, 4250460Seadler * and asynchronous channels with full modem control. 5128967Srik * Keepalive protocol implemented in both Cisco and PPP modes. 6128967Srik * 7128967Srik * Copyright (C) 1999-2004 Cronyx Engineering. 8128967Srik * Author: Kurakin Roman, <rik@cronyx.ru> 9128967Srik * 10128967Srik * Copyright (C) 1999-2002 Cronyx Engineering. 11128967Srik * Author: Serge Vakulenko, <vak@cronyx.ru> 12128967Srik * 13128967Srik * This software is distributed with NO WARRANTIES, not even the implied 14128967Srik * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15128967Srik * 16128967Srik * Authors grant any other persons or organisations a permission to use, 17128967Srik * modify and redistribute this software in source and binary forms, 18128967Srik * as long as this message is kept with the software, all derivative 19128967Srik * works or modified versions. 20128967Srik * 21130985Srik * Cronyx Id: if_cp.c,v 1.1.2.41 2004/06/23 17:09:13 rik Exp $ 22128967Srik */ 23128967Srik 24128967Srik#include <sys/cdefs.h> 25128967Srik__FBSDID("$FreeBSD: stable/11/sys/dev/cp/if_cp.c 315221 2017-03-14 02:06:03Z pfg $"); 26128967Srik 27128967Srik#include <sys/param.h> 28128967Srik#include <sys/ucred.h> 29128967Srik#include <sys/proc.h> 30128967Srik#include <sys/systm.h> 31128967Srik#include <sys/mbuf.h> 32128967Srik#include <sys/kernel.h> 33129879Sphk#include <sys/module.h> 34128967Srik#include <sys/conf.h> 35128967Srik#include <sys/malloc.h> 36164033Srwatson#include <sys/priv.h> 37128967Srik#include <sys/socket.h> 38128967Srik#include <sys/sockio.h> 39138823Srik#include <sys/sysctl.h> 40128967Srik#include <sys/tty.h> 41130971Srik#include <sys/bus.h> 42128967Srik#include <vm/vm.h> 43128967Srik#include <vm/pmap.h> 44128967Srik#include <net/if.h> 45257176Sglebius#include <net/if_var.h> 46138673Srik#include <dev/pci/pcivar.h> 47138673Srik#include <dev/pci/pcireg.h> 48128967Srik#include <machine/bus.h> 49128967Srik#include <sys/rman.h> 50128967Srik#include "opt_ng_cronyx.h" 51128967Srik#ifdef NETGRAPH_CRONYX 52128967Srik# include "opt_netgraph.h" 53128967Srik# ifndef NETGRAPH 54133646Srik# error #option NETGRAPH missed from configuration 55128967Srik# endif 56128967Srik# include <netgraph/ng_message.h> 57128967Srik# include <netgraph/netgraph.h> 58130985Srik# include <dev/cp/ng_cp.h> 59128967Srik#else 60128967Srik# include <net/if_sppp.h> 61147256Sbrooks# include <net/if_types.h> 62147256Sbrooks#include <dev/pci/pcivar.h> 63128967Srik# define PP_CISCO IFF_LINK2 64130971Srik# include <net/bpf.h> 65128967Srik#endif 66128967Srik#include <dev/cx/machdep.h> 67128967Srik#include <dev/cp/cpddk.h> 68128967Srik#include <machine/cserial.h> 69128967Srik#include <machine/resource.h> 70128967Srik 71128967Srik/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 72128967Srik#ifndef PP_FR 73128967Srik#define PP_FR 0 74128967Srik#endif 75128967Srik 76128967Srik#define CP_DEBUG(d,s) ({if (d->chan->debug) {\ 77128967Srik printf ("%s: ", d->name); printf s;}}) 78128967Srik#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 79128967Srik printf ("%s: ", d->name); printf s;}}) 80138823Srik#define CP_LOCK_NAME "cpX" 81128967Srik 82188661Srwatson#define CP_LOCK(_bd) mtx_lock (&(_bd)->cp_mtx) 83188661Srwatson#define CP_UNLOCK(_bd) mtx_unlock (&(_bd)->cp_mtx) 84188661Srwatson#define CP_LOCK_ASSERT(_bd) mtx_assert (&(_bd)->cp_mtx, MA_OWNED) 85138823Srik 86128967Srikstatic int cp_probe __P((device_t)); 87128967Srikstatic int cp_attach __P((device_t)); 88128967Srikstatic int cp_detach __P((device_t)); 89128967Srik 90128967Srikstatic device_method_t cp_methods[] = { 91128967Srik /* Device interface */ 92128967Srik DEVMETHOD(device_probe, cp_probe), 93128967Srik DEVMETHOD(device_attach, cp_attach), 94128967Srik DEVMETHOD(device_detach, cp_detach), 95128967Srik 96246128Ssbz DEVMETHOD_END 97128967Srik}; 98128967Srik 99130985Sriktypedef struct _cp_dma_mem_t { 100130985Srik unsigned long phys; 101130985Srik void *virt; 102130985Srik size_t size; 103130985Srik bus_dma_tag_t dmat; 104130985Srik bus_dmamap_t mapp; 105130985Srik} cp_dma_mem_t; 106128967Srik 107128967Sriktypedef struct _drv_t { 108138823Srik char name [8]; 109138823Srik int running; 110138823Srik cp_chan_t *chan; 111138823Srik cp_board_t *board; 112138823Srik cp_dma_mem_t dmamem; 113128967Srik#ifdef NETGRAPH 114193813Simp char nodename [NG_NODESIZE]; 115128967Srik hook_p hook; 116128967Srik hook_p debug_hook; 117128967Srik node_p node; 118128967Srik struct ifqueue queue; 119128967Srik struct ifqueue hi_queue; 120128967Srik#else 121138823Srik struct ifqueue queue; 122147256Sbrooks struct ifnet *ifp; 123128967Srik#endif 124199407Sjhb short timeout; 125199407Sjhb struct callout timeout_handle; 126138823Srik struct cdev *devt; 127128967Srik} drv_t; 128128967Srik 129130985Sriktypedef struct _bdrv_t { 130130985Srik cp_board_t *board; 131130985Srik struct resource *cp_res; 132130985Srik struct resource *cp_irq; 133130985Srik void *cp_intrhand; 134130985Srik cp_dma_mem_t dmamem; 135130985Srik drv_t channel [NCHAN]; 136138823Srik struct mtx cp_mtx; 137130985Srik} bdrv_t; 138130985Srik 139130985Srikstatic driver_t cp_driver = { 140130985Srik "cp", 141130985Srik cp_methods, 142130985Srik sizeof(bdrv_t), 143130985Srik}; 144130985Srik 145130985Srikstatic devclass_t cp_devclass; 146130985Srik 147128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len); 148128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len); 149128967Srikstatic void cp_error (cp_chan_t *c, int data); 150128967Srikstatic void cp_up (drv_t *d); 151128967Srikstatic void cp_start (drv_t *d); 152128967Srikstatic void cp_down (drv_t *d); 153128967Srikstatic void cp_watchdog (drv_t *d); 154199407Sjhbstatic void cp_watchdog_timer (void *arg); 155128967Srik#ifdef NETGRAPH 156128967Srikextern struct ng_type typestruct; 157128967Srik#else 158128967Srikstatic void cp_ifstart (struct ifnet *ifp); 159128967Srikstatic void cp_tlf (struct sppp *sp); 160128967Srikstatic void cp_tls (struct sppp *sp); 161128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 162128967Srikstatic void cp_initialize (void *softc); 163128967Srik#endif 164128967Srik 165128967Srikstatic cp_board_t *adapter [NBRD]; 166128967Srikstatic drv_t *channel [NBRD*NCHAN]; 167138823Srikstatic struct callout led_timo [NBRD]; 168138823Srikstatic struct callout timeout_handle; 169128967Srik 170128967Srikstatic int cp_destroy = 0; 171128967Srik 172150622Srikstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td); 173150622Srikstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td); 174150622Srikstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); 175150622Srikstatic struct cdevsw cp_cdevsw = { 176150622Srik .d_version = D_VERSION, 177150622Srik .d_open = cp_open, 178150622Srik .d_close = cp_close, 179150622Srik .d_ioctl = cp_ioctl, 180150622Srik .d_name = "cp", 181150622Srik}; 182150622Srik 183128967Srik/* 184150622Srik * Make an mbuf from data. 185150622Srik */ 186150622Srikstatic struct mbuf *makembuf (void *buf, unsigned len) 187150622Srik{ 188150622Srik struct mbuf *m; 189150622Srik 190243857Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 191150622Srik if (! m) 192150622Srik return 0; 193276750Srwatson if (!(MCLGET (m, M_NOWAIT))) { 194150622Srik m_freem (m); 195150622Srik return 0; 196150622Srik } 197150622Srik m->m_pkthdr.len = m->m_len = len; 198150622Srik bcopy (buf, mtod (m, caddr_t), len); 199150622Srik return m; 200150622Srik} 201150622Srik 202150622Srikstatic int cp_probe (device_t dev) 203150622Srik{ 204150622Srik if ((pci_get_vendor (dev) == cp_vendor_id) && 205150622Srik (pci_get_device (dev) == cp_device_id)) { 206150622Srik device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 207150622Srik return BUS_PROBE_DEFAULT; 208150622Srik } 209150622Srik return ENXIO; 210150622Srik} 211150622Srik 212150622Srikstatic void cp_timeout (void *arg) 213150622Srik{ 214150622Srik drv_t *d; 215150622Srik int s, i, k; 216150622Srik 217150622Srik for (i = 0; i < NBRD; ++i) { 218150622Srik if (adapter[i] == NULL) 219150622Srik continue; 220150622Srik for (k = 0; k < NCHAN; ++k) { 221150622Srik s = splimp (); 222150622Srik if (cp_destroy) { 223150622Srik splx (s); 224150622Srik return; 225150622Srik } 226150622Srik d = channel[i * NCHAN + k]; 227150622Srik if (!d) { 228150622Srik splx (s); 229150622Srik continue; 230150622Srik } 231150622Srik CP_LOCK ((bdrv_t *)d->board->sys); 232150622Srik switch (d->chan->type) { 233150622Srik case T_G703: 234150622Srik cp_g703_timer (d->chan); 235150622Srik break; 236150622Srik case T_E1: 237150622Srik cp_e1_timer (d->chan); 238150622Srik break; 239150622Srik case T_E3: 240150622Srik case T_T3: 241150622Srik case T_STS1: 242150622Srik cp_e3_timer (d->chan); 243150622Srik break; 244150622Srik default: 245150622Srik break; 246150622Srik } 247150622Srik CP_UNLOCK ((bdrv_t *)d->board->sys); 248150622Srik splx (s); 249150622Srik } 250150622Srik } 251150622Srik s = splimp (); 252150622Srik if (!cp_destroy) 253150622Srik callout_reset (&timeout_handle, hz, cp_timeout, 0); 254150622Srik splx (s); 255150622Srik} 256150622Srik 257150622Srikstatic void cp_led_off (void *arg) 258150622Srik{ 259150622Srik cp_board_t *b = arg; 260150622Srik bdrv_t *bd = (bdrv_t *) b->sys; 261150622Srik int s; 262150622Srik s = splimp (); 263150622Srik if (cp_destroy) { 264150622Srik splx (s); 265150622Srik return; 266150622Srik } 267150622Srik CP_LOCK (bd); 268150622Srik cp_led (b, 0); 269150622Srik CP_UNLOCK (bd); 270150622Srik splx (s); 271150622Srik} 272150622Srik 273150622Srikstatic void cp_intr (void *arg) 274150622Srik{ 275150622Srik bdrv_t *bd = arg; 276150622Srik cp_board_t *b = bd->board; 277150622Srik#ifndef NETGRAPH 278150622Srik int i; 279150622Srik#endif 280150622Srik int s = splimp (); 281150622Srik if (cp_destroy) { 282150622Srik splx (s); 283150622Srik return; 284150622Srik } 285150622Srik CP_LOCK (bd); 286150622Srik /* Check if we are ready */ 287150622Srik if (b->sys == NULL) { 288150622Srik /* Not we are not, just cleanup. */ 289150622Srik cp_interrupt_poll (b, 1); 290150622Srik CP_UNLOCK (bd); 291150622Srik return; 292150622Srik } 293150622Srik /* Turn LED on. */ 294150622Srik cp_led (b, 1); 295150622Srik 296150622Srik cp_interrupt (b); 297150622Srik 298150622Srik /* Turn LED off 50 msec later. */ 299150622Srik callout_reset (&led_timo[b->num], hz/20, cp_led_off, b); 300150622Srik CP_UNLOCK (bd); 301150622Srik splx (s); 302150622Srik 303150622Srik#ifndef NETGRAPH 304150622Srik /* Pass packets in a lock-free state */ 305150622Srik for (i = 0; i < NCHAN && b->chan[i].type; i++) { 306150622Srik drv_t *d = b->chan[i].sys; 307150622Srik struct mbuf *m; 308150622Srik if (!d || !d->running) 309150622Srik continue; 310150622Srik while (_IF_QLEN(&d->queue)) { 311150622Srik IF_DEQUEUE (&d->queue,m); 312150622Srik if (!m) 313150622Srik continue; 314150622Srik sppp_input (d->ifp, m); 315150622Srik } 316150622Srik } 317150622Srik#endif 318150622Srik} 319150622Srik 320150622Srikstatic void 321150622Srikcp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 322150622Srik{ 323150622Srik unsigned long *addr; 324150622Srik 325150622Srik if (error) 326150622Srik return; 327150622Srik 328150622Srik KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 329150622Srik addr = arg; 330150622Srik *addr = segs->ds_addr; 331150622Srik} 332150622Srik 333150622Srikstatic int 334150622Srikcp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 335150622Srik{ 336150622Srik int error; 337150622Srik 338150622Srik error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 339150622Srik BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 340150622Srik dmem->size, 0, NULL, NULL, &dmem->dmat); 341150622Srik if (error) { 342150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 343150622Srik else printf ("cp%d: ", bnum); 344150622Srik printf ("couldn't allocate tag for dma memory\n"); 345150622Srik return 0; 346150622Srik } 347150622Srik error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 348150622Srik BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 349150622Srik if (error) { 350150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 351150622Srik else printf ("cp%d: ", bnum); 352150622Srik printf ("couldn't allocate mem for dma memory\n"); 353150622Srik bus_dma_tag_destroy (dmem->dmat); 354150622Srik return 0; 355150622Srik } 356150622Srik error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 357150622Srik dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); 358150622Srik if (error) { 359150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 360150622Srik else printf ("cp%d: ", bnum); 361150622Srik printf ("couldn't load mem map for dma memory\n"); 362150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 363150622Srik bus_dma_tag_destroy (dmem->dmat); 364150622Srik return 0; 365150622Srik } 366150622Srik return 1; 367150622Srik} 368150622Srik 369150622Srikstatic void 370150622Srikcp_bus_dma_mem_free (cp_dma_mem_t *dmem) 371150622Srik{ 372150622Srik bus_dmamap_unload (dmem->dmat, dmem->mapp); 373150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 374150622Srik bus_dma_tag_destroy (dmem->dmat); 375150622Srik} 376150622Srik 377150622Srik/* 378150622Srik * Called if the probe succeeded. 379150622Srik */ 380150622Srikstatic int cp_attach (device_t dev) 381150622Srik{ 382150622Srik bdrv_t *bd = device_get_softc (dev); 383150622Srik int unit = device_get_unit (dev); 384150622Srik char *cp_ln = CP_LOCK_NAME; 385150622Srik unsigned short res; 386150622Srik vm_offset_t vbase; 387150622Srik int rid, error; 388150622Srik cp_board_t *b; 389150622Srik cp_chan_t *c; 390150622Srik drv_t *d; 391150622Srik int s = splimp (); 392150622Srik 393150622Srik b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 394150622Srik if (!b) { 395150622Srik printf ("cp%d: couldn't allocate memory\n", unit); 396150622Srik splx (s); 397150622Srik return (ENXIO); 398150622Srik } 399150622Srik bzero (b, sizeof(cp_board_t)); 400150622Srik 401150622Srik bd->board = b; 402150622Srik rid = PCIR_BAR(0); 403150622Srik bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 404150622Srik 0, ~0, 1, RF_ACTIVE); 405150622Srik if (! bd->cp_res) { 406150622Srik printf ("cp%d: cannot map memory\n", unit); 407150622Srik free (b, M_DEVBUF); 408150622Srik splx (s); 409150622Srik return (ENXIO); 410150622Srik } 411150622Srik vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 412150622Srik 413150622Srik cp_ln[2] = '0' + unit; 414150622Srik mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 415150622Srik res = cp_init (b, unit, (u_char*) vbase); 416150622Srik if (res) { 417150622Srik printf ("cp%d: can't init, error code:%x\n", unit, res); 418150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 419150622Srik free (b, M_DEVBUF); 420150622Srik splx (s); 421150622Srik return (ENXIO); 422150622Srik } 423150622Srik 424150622Srik bd->dmamem.size = sizeof(cp_qbuf_t); 425150622Srik if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 426150622Srik free (b, M_DEVBUF); 427150622Srik splx (s); 428150622Srik return (ENXIO); 429150622Srik } 430150622Srik CP_LOCK (bd); 431150622Srik cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); 432150622Srik CP_UNLOCK (bd); 433150622Srik 434150622Srik rid = 0; 435150622Srik bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 436150622Srik RF_SHAREABLE | RF_ACTIVE); 437150622Srik if (! bd->cp_irq) { 438150622Srik cp_destroy = 1; 439150622Srik printf ("cp%d: cannot map interrupt\n", unit); 440150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 441150622Srik PCIR_BAR(0), bd->cp_res); 442150622Srik mtx_destroy (&bd->cp_mtx); 443150622Srik free (b, M_DEVBUF); 444150622Srik splx (s); 445150622Srik return (ENXIO); 446150622Srik } 447283291Sjkim callout_init (&led_timo[unit], 1); 448150622Srik error = bus_setup_intr (dev, bd->cp_irq, 449188661Srwatson INTR_TYPE_NET|INTR_MPSAFE, 450166901Spiso NULL, cp_intr, bd, &bd->cp_intrhand); 451150622Srik if (error) { 452150622Srik cp_destroy = 1; 453150622Srik printf ("cp%d: cannot set up irq\n", unit); 454150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 455150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 456150622Srik PCIR_BAR(0), bd->cp_res); 457150622Srik mtx_destroy (&bd->cp_mtx); 458150622Srik free (b, M_DEVBUF); 459150622Srik splx (s); 460150622Srik return (ENXIO); 461150622Srik } 462150622Srik printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 463150622Srik 464150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 465150622Srik if (! c->type) 466150622Srik continue; 467150622Srik d = &bd->channel[c->num]; 468150622Srik d->dmamem.size = sizeof(cp_buf_t); 469150622Srik if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 470150622Srik continue; 471150622Srik channel [b->num*NCHAN + c->num] = d; 472150622Srik sprintf (d->name, "cp%d.%d", b->num, c->num); 473150622Srik d->board = b; 474150622Srik d->chan = c; 475150622Srik c->sys = d; 476283291Sjkim callout_init (&d->timeout_handle, 1); 477150622Srik#ifdef NETGRAPH 478150622Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 479150622Srik printf ("%s: cannot make common node\n", d->name); 480150622Srik d->node = NULL; 481150622Srik continue; 482150622Srik } 483150622Srik NG_NODE_SET_PRIVATE (d->node, d); 484150622Srik sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 485150622Srik c->board->num*NCHAN + c->num); 486150622Srik if (ng_name_node (d->node, d->nodename)) { 487150622Srik printf ("%s: cannot name node\n", d->nodename); 488150622Srik NG_NODE_UNREF (d->node); 489150622Srik continue; 490150622Srik } 491207554Ssobomax d->queue.ifq_maxlen = ifqmaxlen; 492207554Ssobomax d->hi_queue.ifq_maxlen = ifqmaxlen; 493150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 494150622Srik mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 495150622Srik#else /*NETGRAPH*/ 496150622Srik d->ifp = if_alloc(IFT_PPP); 497150622Srik if (d->ifp == NULL) { 498150622Srik printf ("%s: cannot if_alloc() interface\n", d->name); 499150622Srik continue; 500150622Srik } 501150622Srik d->ifp->if_softc = d; 502150622Srik if_initname (d->ifp, "cp", b->num * NCHAN + c->num); 503150622Srik d->ifp->if_mtu = PP_MTU; 504150622Srik d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 505150622Srik d->ifp->if_ioctl = cp_sioctl; 506150622Srik d->ifp->if_start = cp_ifstart; 507150622Srik d->ifp->if_init = cp_initialize; 508150622Srik d->queue.ifq_maxlen = NRBUF; 509150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 510150622Srik sppp_attach (d->ifp); 511150622Srik if_attach (d->ifp); 512150622Srik IFP2SP(d->ifp)->pp_tlf = cp_tlf; 513150622Srik IFP2SP(d->ifp)->pp_tls = cp_tls; 514150622Srik /* If BPF is in the kernel, call the attach for it. 515150622Srik * The header size of PPP or Cisco/HDLC is 4 bytes. */ 516150622Srik bpfattach (d->ifp, DLT_PPP, 4); 517150622Srik#endif /*NETGRAPH*/ 518150622Srik cp_start_e1 (c); 519150622Srik cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 520150622Srik 521150622Srik /* Register callback functions. */ 522150622Srik cp_register_transmit (c, &cp_transmit); 523150622Srik cp_register_receive (c, &cp_receive); 524150622Srik cp_register_error (c, &cp_error); 525150622Srik d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 526150622Srik GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 527150622Srik } 528150622Srik CP_LOCK (bd); 529150622Srik b->sys = bd; 530150622Srik adapter[unit] = b; 531150622Srik CP_UNLOCK (bd); 532150622Srik splx (s); 533150622Srik return 0; 534150622Srik} 535150622Srik 536150622Srikstatic int cp_detach (device_t dev) 537150622Srik{ 538150622Srik bdrv_t *bd = device_get_softc (dev); 539150622Srik cp_board_t *b = bd->board; 540150622Srik cp_chan_t *c; 541150622Srik int s; 542150622Srik 543150622Srik KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized")); 544150622Srik s = splimp (); 545150622Srik CP_LOCK (bd); 546150622Srik /* Check if the device is busy (open). */ 547150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 548150622Srik drv_t *d = (drv_t*) c->sys; 549150622Srik 550150622Srik if (! d || ! d->chan->type) 551150622Srik continue; 552150622Srik if (d->running) { 553150622Srik CP_UNLOCK (bd); 554150622Srik splx (s); 555150622Srik return EBUSY; 556150622Srik } 557150622Srik } 558150622Srik 559150622Srik /* Ok, we can unload driver */ 560150622Srik /* At first we should stop all channels */ 561150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 562150622Srik drv_t *d = (drv_t*) c->sys; 563150622Srik 564150622Srik if (! d || ! d->chan->type) 565150622Srik continue; 566150622Srik 567150622Srik cp_stop_chan (c); 568150622Srik cp_stop_e1 (c); 569150622Srik cp_set_dtr (d->chan, 0); 570150622Srik cp_set_rts (d->chan, 0); 571150622Srik } 572150622Srik 573150622Srik /* Reset the adapter. */ 574150622Srik cp_destroy = 1; 575150622Srik cp_interrupt_poll (b, 1); 576150622Srik cp_led_off (b); 577150622Srik cp_reset (b, 0 ,0); 578150622Srik callout_stop (&led_timo[b->num]); 579150622Srik 580150624Srik /* Disable the interrupt request. */ 581150624Srik bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 582150624Srik 583150622Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 584150622Srik drv_t *d = (drv_t*) c->sys; 585150622Srik 586150622Srik if (! d || ! d->chan->type) 587150622Srik continue; 588199407Sjhb callout_stop (&d->timeout_handle); 589150622Srik#ifndef NETGRAPH 590150622Srik /* Detach from the packet filter list of interfaces. */ 591150622Srik bpfdetach (d->ifp); 592150622Srik 593150622Srik /* Detach from the sync PPP list. */ 594150622Srik sppp_detach (d->ifp); 595150622Srik 596150622Srik /* Detach from the system list of interfaces. */ 597150622Srik if_detach (d->ifp); 598150622Srik if_free (d->ifp); 599150622Srik IF_DRAIN (&d->queue); 600150622Srik mtx_destroy (&d->queue.ifq_mtx); 601150622Srik#else 602150622Srik if (d->node) { 603150622Srik ng_rmnode_self (d->node); 604150622Srik NG_NODE_UNREF (d->node); 605150622Srik d->node = NULL; 606150622Srik } 607150622Srik mtx_destroy (&d->queue.ifq_mtx); 608150622Srik mtx_destroy (&d->hi_queue.ifq_mtx); 609150622Srik#endif 610150622Srik destroy_dev (d->devt); 611150622Srik } 612150622Srik 613150622Srik b->sys = NULL; 614150622Srik CP_UNLOCK (bd); 615150622Srik 616150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 617150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 618150622Srik 619150622Srik CP_LOCK (bd); 620150622Srik cp_led_off (b); 621150622Srik CP_UNLOCK (bd); 622150622Srik callout_drain (&led_timo[b->num]); 623150622Srik splx (s); 624150622Srik 625150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 626150622Srik drv_t *d = (drv_t*) c->sys; 627150622Srik 628150622Srik if (! d || ! d->chan->type) 629150622Srik continue; 630199407Sjhb callout_drain (&d->timeout_handle); 631315221Spfg channel [b->num*NCHAN + c->num] = NULL; 632150622Srik /* Deallocate buffers. */ 633150622Srik cp_bus_dma_mem_free (&d->dmamem); 634150622Srik } 635315221Spfg adapter [b->num] = NULL; 636150622Srik cp_bus_dma_mem_free (&bd->dmamem); 637150622Srik free (b, M_DEVBUF); 638150622Srik mtx_destroy (&bd->cp_mtx); 639150622Srik return 0; 640150622Srik} 641150622Srik 642150622Srik#ifndef NETGRAPH 643150622Srikstatic void cp_ifstart (struct ifnet *ifp) 644150622Srik{ 645150622Srik drv_t *d = ifp->if_softc; 646150622Srik bdrv_t *bd = d->board->sys; 647150622Srik 648150622Srik CP_LOCK (bd); 649150622Srik cp_start (d); 650150622Srik CP_UNLOCK (bd); 651150622Srik} 652150622Srik 653150622Srikstatic void cp_tlf (struct sppp *sp) 654150622Srik{ 655150622Srik drv_t *d = SP2IFP(sp)->if_softc; 656150622Srik 657150622Srik CP_DEBUG2 (d, ("cp_tlf\n")); 658150622Srik /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */ 659150622Srik/* cp_set_dtr (d->chan, 0);*/ 660150622Srik/* cp_set_rts (d->chan, 0);*/ 661150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 662150622Srik sp->pp_down (sp); 663150622Srik} 664150622Srik 665150622Srikstatic void cp_tls (struct sppp *sp) 666150622Srik{ 667150622Srik drv_t *d = SP2IFP(sp)->if_softc; 668150622Srik 669150622Srik CP_DEBUG2 (d, ("cp_tls\n")); 670150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 671150622Srik sp->pp_up (sp); 672150622Srik} 673150622Srik 674150622Srik/* 675150622Srik * Process an ioctl request. 676150622Srik */ 677150622Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 678150622Srik{ 679150622Srik drv_t *d = ifp->if_softc; 680150622Srik bdrv_t *bd = d->board->sys; 681150622Srik int error, s, was_up, should_be_up; 682150622Srik 683150622Srik was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 684150622Srik error = sppp_ioctl (ifp, cmd, data); 685150622Srik 686150622Srik if (error) 687150622Srik return error; 688150622Srik 689150622Srik if (! (ifp->if_flags & IFF_DEBUG)) 690150622Srik d->chan->debug = 0; 691180132Srik else 692180132Srik d->chan->debug = d->chan->debug_shadow; 693150622Srik 694150622Srik switch (cmd) { 695150622Srik default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 696150622Srik case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 697150622Srik case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 698150622Srik case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 699150622Srik case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 700150622Srik } 701150622Srik 702150622Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 703150622Srik s = splimp (); 704150622Srik CP_LOCK (bd); 705150622Srik should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 706150622Srik if (! was_up && should_be_up) { 707150622Srik /* Interface goes up -- start it. */ 708150622Srik cp_up (d); 709150622Srik cp_start (d); 710150622Srik } else if (was_up && ! should_be_up) { 711150622Srik /* Interface is going down -- stop it. */ 712150622Srik/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 713150622Srik cp_down (d); 714150622Srik } 715150622Srik CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 716150622Srik CP_UNLOCK (bd); 717150622Srik splx (s); 718150622Srik return 0; 719150622Srik} 720150622Srik 721150622Srik/* 722150622Srik * Initialization of interface. 723150622Srik * It seems to be never called by upper level? 724150622Srik */ 725150622Srikstatic void cp_initialize (void *softc) 726150622Srik{ 727150622Srik drv_t *d = softc; 728150622Srik 729150622Srik CP_DEBUG (d, ("cp_initialize\n")); 730150622Srik} 731150622Srik#endif /*NETGRAPH*/ 732150622Srik 733150622Srik/* 734150622Srik * Stop the interface. Called on splimp(). 735150622Srik */ 736150622Srikstatic void cp_down (drv_t *d) 737150622Srik{ 738150622Srik CP_DEBUG (d, ("cp_down\n")); 739150622Srik /* Interface is going down -- stop it. */ 740150622Srik cp_set_dtr (d->chan, 0); 741150622Srik cp_set_rts (d->chan, 0); 742150622Srik 743150622Srik d->running = 0; 744199407Sjhb callout_stop (&d->timeout_handle); 745150622Srik} 746150622Srik 747150622Srik/* 748150622Srik * Start the interface. Called on splimp(). 749150622Srik */ 750150622Srikstatic void cp_up (drv_t *d) 751150622Srik{ 752150622Srik CP_DEBUG (d, ("cp_up\n")); 753150622Srik cp_set_dtr (d->chan, 1); 754150622Srik cp_set_rts (d->chan, 1); 755150622Srik d->running = 1; 756150622Srik} 757150622Srik 758150622Srik/* 759150622Srik * Start output on the interface. Get another datagram to send 760150622Srik * off of the interface queue, and copy it to the interface 761150622Srik * before starting the output. 762150622Srik */ 763150622Srikstatic void cp_send (drv_t *d) 764150622Srik{ 765150622Srik struct mbuf *m; 766150622Srik u_short len; 767150622Srik 768150622Srik CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 769150622Srik 770150622Srik /* No output if the interface is down. */ 771150622Srik if (! d->running) 772150622Srik return; 773150622Srik 774150622Srik /* No output if the modem is off. */ 775150622Srik if (! (d->chan->lloop || d->chan->type != T_SERIAL || 776150622Srik cp_get_dsr (d->chan))) 777150622Srik return; 778150622Srik 779150622Srik while (cp_transmit_space (d->chan)) { 780150622Srik /* Get the packet to send. */ 781150622Srik#ifdef NETGRAPH 782150622Srik IF_DEQUEUE (&d->hi_queue, m); 783150622Srik if (! m) 784150622Srik IF_DEQUEUE (&d->queue, m); 785150622Srik#else 786150622Srik m = sppp_dequeue (d->ifp); 787150622Srik#endif 788150622Srik if (! m) 789150622Srik return; 790150622Srik#ifndef NETGRAPH 791165632Sjhb BPF_MTAP (d->ifp, m); 792150622Srik#endif 793150622Srik len = m_length (m, NULL); 794150622Srik if (len >= BUFSZ) 795150622Srik printf ("%s: too long packet: %d bytes: ", 796150622Srik d->name, len); 797150622Srik else if (! m->m_next) 798150622Srik cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 799150622Srik else { 800150622Srik u_char *buf = d->chan->tbuf[d->chan->te]; 801150622Srik m_copydata (m, 0, len, buf); 802150622Srik cp_send_packet (d->chan, buf, len, 0); 803150622Srik } 804150622Srik m_freem (m); 805150622Srik /* Set up transmit timeout, if the transmit ring is not empty.*/ 806150622Srik d->timeout = 10; 807150622Srik } 808150622Srik#ifndef NETGRAPH 809150622Srik d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 810150622Srik#endif 811150622Srik} 812150622Srik 813150622Srik/* 814150622Srik * Start output on the interface. 815150622Srik * Always called on splimp(). 816150622Srik */ 817150622Srikstatic void cp_start (drv_t *d) 818150622Srik{ 819150622Srik if (d->running) { 820150622Srik if (! d->chan->dtr) 821150622Srik cp_set_dtr (d->chan, 1); 822150622Srik if (! d->chan->rts) 823150622Srik cp_set_rts (d->chan, 1); 824150622Srik cp_send (d); 825199407Sjhb callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 826150622Srik } 827150622Srik} 828150622Srik 829150622Srik/* 830150622Srik * Handle transmit timeouts. 831150622Srik * Recover after lost transmit interrupts. 832150622Srik * Always called on splimp(). 833150622Srik */ 834150622Srikstatic void cp_watchdog (drv_t *d) 835150622Srik{ 836150622Srik CP_DEBUG (d, ("device timeout\n")); 837150622Srik if (d->running) { 838150622Srik cp_stop_chan (d->chan); 839150622Srik cp_stop_e1 (d->chan); 840150622Srik cp_start_e1 (d->chan); 841150622Srik cp_start_chan (d->chan, 1, 1, 0, 0); 842150622Srik cp_set_dtr (d->chan, 1); 843150622Srik cp_set_rts (d->chan, 1); 844150622Srik cp_start (d); 845150622Srik } 846150622Srik} 847150622Srik 848199407Sjhbstatic void cp_watchdog_timer (void *arg) 849199407Sjhb{ 850199407Sjhb drv_t *d = arg; 851199407Sjhb bdrv_t *bd = d->board->sys; 852199407Sjhb 853199407Sjhb CP_LOCK (bd); 854199407Sjhb if (d->timeout == 1) 855199407Sjhb cp_watchdog (d); 856199407Sjhb if (d->timeout) 857199407Sjhb d->timeout--; 858199407Sjhb callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 859199407Sjhb CP_UNLOCK (bd); 860199407Sjhb} 861199407Sjhb 862150622Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len) 863150622Srik{ 864150622Srik drv_t *d = c->sys; 865150622Srik 866150622Srik d->timeout = 0; 867199407Sjhb#ifndef NETGRAPH 868271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_OPACKETS, 1); 869150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 870150622Srik#endif 871150622Srik cp_start (d); 872150622Srik} 873150622Srik 874150622Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len) 875150622Srik{ 876150622Srik drv_t *d = c->sys; 877150622Srik struct mbuf *m; 878150622Srik#ifdef NETGRAPH 879150622Srik int error; 880150622Srik#endif 881150622Srik 882150622Srik if (! d->running) 883150622Srik return; 884150622Srik 885150622Srik m = makembuf (data, len); 886150622Srik if (! m) { 887150622Srik CP_DEBUG (d, ("no memory for packet\n")); 888150622Srik#ifndef NETGRAPH 889271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IQDROPS, 1); 890150622Srik#endif 891150622Srik return; 892150622Srik } 893150622Srik if (c->debug > 1) 894271373Srwatson m_print (m, 0); 895150622Srik#ifdef NETGRAPH 896150622Srik m->m_pkthdr.rcvif = 0; 897150622Srik NG_SEND_DATA_ONLY (error, d->hook, m); 898150622Srik#else 899271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IPACKETS, 1); 900150622Srik m->m_pkthdr.rcvif = d->ifp; 901150622Srik /* Check if there's a BPF listener on this interface. 902150622Srik * If so, hand off the raw packet to bpf. */ 903272266Smelifaro BPF_MTAP(d->ifp, m); 904150622Srik IF_ENQUEUE (&d->queue, m); 905150622Srik#endif 906150622Srik} 907150622Srik 908150622Srikstatic void cp_error (cp_chan_t *c, int data) 909150622Srik{ 910150622Srik drv_t *d = c->sys; 911150622Srik 912150622Srik switch (data) { 913150622Srik case CP_FRAME: 914150622Srik CP_DEBUG (d, ("frame error\n")); 915150622Srik#ifndef NETGRAPH 916271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 917150622Srik#endif 918150622Srik break; 919150622Srik case CP_CRC: 920150622Srik CP_DEBUG (d, ("crc error\n")); 921150622Srik#ifndef NETGRAPH 922271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 923150622Srik#endif 924150622Srik break; 925150622Srik case CP_OVERRUN: 926150622Srik CP_DEBUG (d, ("overrun error\n")); 927150622Srik#ifndef NETGRAPH 928271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_COLLISIONS, 1); 929271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 930150622Srik#endif 931150622Srik break; 932150622Srik case CP_OVERFLOW: 933150622Srik CP_DEBUG (d, ("overflow error\n")); 934150622Srik#ifndef NETGRAPH 935271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 936150622Srik#endif 937150622Srik break; 938150622Srik case CP_UNDERRUN: 939150622Srik CP_DEBUG (d, ("underrun error\n")); 940150622Srik d->timeout = 0; 941199407Sjhb#ifndef NETGRAPH 942271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_OERRORS, 1); 943150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 944150622Srik#endif 945150622Srik cp_start (d); 946150622Srik break; 947150622Srik default: 948150622Srik CP_DEBUG (d, ("error #%d\n", data)); 949150622Srik break; 950150622Srik } 951150622Srik} 952150622Srik 953150622Srik/* 954128967Srik * You also need read, write, open, close routines. 955128967Srik * This should get you started 956128967Srik */ 957130585Sphkstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 958128967Srik{ 959183397Sed int unit = dev2unit (dev); 960128967Srik drv_t *d; 961128967Srik 962128967Srik if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 963128967Srik return ENXIO; 964128967Srik CP_DEBUG2 (d, ("cp_open\n")); 965128967Srik return 0; 966128967Srik} 967128967Srik 968128967Srik/* 969128967Srik * Only called on the LAST close. 970128967Srik */ 971130585Sphkstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 972128967Srik{ 973183397Sed drv_t *d = channel [dev2unit (dev)]; 974128967Srik 975128967Srik CP_DEBUG2 (d, ("cp_close\n")); 976128967Srik return 0; 977128967Srik} 978128967Srik 979128967Srikstatic int cp_modem_status (cp_chan_t *c) 980128967Srik{ 981128967Srik drv_t *d = c->sys; 982138823Srik bdrv_t *bd = d->board->sys; 983128967Srik int status, s; 984128967Srik 985128967Srik status = d->running ? TIOCM_LE : 0; 986128967Srik s = splimp (); 987138823Srik CP_LOCK (bd); 988128967Srik if (cp_get_cd (c)) status |= TIOCM_CD; 989128967Srik if (cp_get_cts (c)) status |= TIOCM_CTS; 990128967Srik if (cp_get_dsr (c)) status |= TIOCM_DSR; 991128967Srik if (c->dtr) status |= TIOCM_DTR; 992128967Srik if (c->rts) status |= TIOCM_RTS; 993138823Srik CP_UNLOCK (bd); 994128967Srik splx (s); 995128967Srik return status; 996128967Srik} 997128967Srik 998130585Sphkstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 999128967Srik{ 1000183397Sed drv_t *d = channel [dev2unit (dev)]; 1001138823Srik bdrv_t *bd = d->board->sys; 1002128967Srik cp_chan_t *c = d->chan; 1003128967Srik struct serial_statistics *st; 1004128967Srik struct e1_statistics *opte1; 1005128967Srik struct e3_statistics *opte3; 1006128967Srik int error, s; 1007128967Srik char mask[16]; 1008128967Srik 1009128967Srik switch (cmd) { 1010128967Srik case SERIAL_GETREGISTERED: 1011133646Srik CP_DEBUG2 (d, ("ioctl: getregistered\n")); 1012128967Srik bzero (mask, sizeof(mask)); 1013128967Srik for (s=0; s<NBRD*NCHAN; ++s) 1014128967Srik if (channel [s]) 1015128967Srik mask [s/8] |= 1 << (s & 7); 1016133646Srik bcopy (mask, data, sizeof (mask)); 1017128967Srik return 0; 1018128967Srik 1019128967Srik#ifndef NETGRAPH 1020128967Srik case SERIAL_GETPROTO: 1021133646Srik CP_DEBUG2 (d, ("ioctl: getproto\n")); 1022147256Sbrooks strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1023147256Sbrooks (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1024133646Srik return 0; 1025128967Srik 1026128967Srik case SERIAL_SETPROTO: 1027133646Srik CP_DEBUG2 (d, ("ioctl: setproto\n")); 1028133646Srik /* Only for superuser! */ 1029164033Srwatson error = priv_check (td, PRIV_DRIVER); 1030133646Srik if (error) 1031133646Srik return error; 1032148887Srwatson if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) 1033128967Srik return EBUSY; 1034133646Srik if (! strcmp ("cisco", (char*)data)) { 1035147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1036147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1037147256Sbrooks d->ifp->if_flags |= PP_CISCO; 1038228963Sdim#if PP_FR != 0 1039228963Sdim } else if (! strcmp ("fr", (char*)data)) { 1040147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1041147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1042228963Sdim#endif 1043133646Srik } else if (! strcmp ("ppp", (char*)data)) { 1044147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_FR; 1045147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1046147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1047133646Srik } else 1048128967Srik return EINVAL; 1049133646Srik return 0; 1050128967Srik 1051128967Srik case SERIAL_GETKEEPALIVE: 1052133646Srik CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1053147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1054147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1055128967Srik return EINVAL; 1056147256Sbrooks *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1057133646Srik return 0; 1058128967Srik 1059128967Srik case SERIAL_SETKEEPALIVE: 1060133646Srik CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1061133646Srik /* Only for superuser! */ 1062164033Srwatson error = priv_check (td, PRIV_DRIVER); 1063133646Srik if (error) 1064133646Srik return error; 1065147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1066147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1067128967Srik return EINVAL; 1068128967Srik s = splimp (); 1069138823Srik CP_LOCK (bd); 1070133646Srik if (*(int*)data) 1071147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1072128967Srik else 1073147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1074138823Srik CP_UNLOCK (bd); 1075128967Srik splx (s); 1076133646Srik return 0; 1077128967Srik#endif /*NETGRAPH*/ 1078128967Srik 1079128967Srik case SERIAL_GETMODE: 1080133646Srik CP_DEBUG2 (d, ("ioctl: getmode\n")); 1081128967Srik *(int*)data = SERIAL_HDLC; 1082133646Srik return 0; 1083128967Srik 1084128967Srik case SERIAL_SETMODE: 1085133646Srik /* Only for superuser! */ 1086164033Srwatson error = priv_check (td, PRIV_DRIVER); 1087133646Srik if (error) 1088133646Srik return error; 1089128967Srik if (*(int*)data != SERIAL_HDLC) 1090128967Srik return EINVAL; 1091133646Srik return 0; 1092128967Srik 1093128967Srik case SERIAL_GETCFG: 1094133646Srik CP_DEBUG2 (d, ("ioctl: getcfg\n")); 1095128967Srik if (c->type != T_E1 || c->unfram) 1096128967Srik return EINVAL; 1097128967Srik *(char*)data = c->board->mux ? 'c' : 'a'; 1098133646Srik return 0; 1099128967Srik 1100128967Srik case SERIAL_SETCFG: 1101133646Srik CP_DEBUG2 (d, ("ioctl: setcfg\n")); 1102164033Srwatson error = priv_check (td, PRIV_DRIVER); 1103133646Srik if (error) 1104133646Srik return error; 1105128967Srik if (c->type != T_E1) 1106128967Srik return EINVAL; 1107133646Srik s = splimp (); 1108138823Srik CP_LOCK (bd); 1109128967Srik cp_set_mux (c->board, *((char*)data) == 'c'); 1110138823Srik CP_UNLOCK (bd); 1111133646Srik splx (s); 1112133646Srik return 0; 1113128967Srik 1114128967Srik case SERIAL_GETSTAT: 1115133646Srik CP_DEBUG2 (d, ("ioctl: getstat\n")); 1116133646Srik st = (struct serial_statistics*) data; 1117133646Srik st->rintr = c->rintr; 1118133646Srik st->tintr = c->tintr; 1119133646Srik st->mintr = 0; 1120133646Srik st->ibytes = c->ibytes; 1121133646Srik st->ipkts = c->ipkts; 1122133646Srik st->obytes = c->obytes; 1123133646Srik st->opkts = c->opkts; 1124128967Srik st->ierrs = c->overrun + c->frame + c->crc; 1125128967Srik st->oerrs = c->underrun; 1126133646Srik return 0; 1127128967Srik 1128128967Srik case SERIAL_GETESTAT: 1129133646Srik CP_DEBUG2 (d, ("ioctl: getestat\n")); 1130128967Srik if (c->type != T_E1 && c->type != T_G703) 1131128967Srik return EINVAL; 1132128967Srik opte1 = (struct e1_statistics*) data; 1133128967Srik opte1->status = c->status; 1134128967Srik opte1->cursec = c->cursec; 1135128967Srik opte1->totsec = c->totsec + c->cursec; 1136128967Srik 1137128967Srik opte1->currnt.bpv = c->currnt.bpv; 1138128967Srik opte1->currnt.fse = c->currnt.fse; 1139128967Srik opte1->currnt.crce = c->currnt.crce; 1140128967Srik opte1->currnt.rcrce = c->currnt.rcrce; 1141128967Srik opte1->currnt.uas = c->currnt.uas; 1142128967Srik opte1->currnt.les = c->currnt.les; 1143128967Srik opte1->currnt.es = c->currnt.es; 1144128967Srik opte1->currnt.bes = c->currnt.bes; 1145128967Srik opte1->currnt.ses = c->currnt.ses; 1146128967Srik opte1->currnt.oofs = c->currnt.oofs; 1147128967Srik opte1->currnt.css = c->currnt.css; 1148128967Srik opte1->currnt.dm = c->currnt.dm; 1149128967Srik 1150128967Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1151128967Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1152128967Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1153128967Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1154128967Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1155128967Srik opte1->total.les = c->total.les + c->currnt.les; 1156128967Srik opte1->total.es = c->total.es + c->currnt.es; 1157128967Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1158128967Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1159128967Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1160128967Srik opte1->total.css = c->total.css + c->currnt.css; 1161128967Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1162128967Srik for (s=0; s<48; ++s) { 1163128967Srik opte1->interval[s].bpv = c->interval[s].bpv; 1164128967Srik opte1->interval[s].fse = c->interval[s].fse; 1165128967Srik opte1->interval[s].crce = c->interval[s].crce; 1166128967Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1167128967Srik opte1->interval[s].uas = c->interval[s].uas; 1168128967Srik opte1->interval[s].les = c->interval[s].les; 1169128967Srik opte1->interval[s].es = c->interval[s].es; 1170128967Srik opte1->interval[s].bes = c->interval[s].bes; 1171128967Srik opte1->interval[s].ses = c->interval[s].ses; 1172128967Srik opte1->interval[s].oofs = c->interval[s].oofs; 1173128967Srik opte1->interval[s].css = c->interval[s].css; 1174128967Srik opte1->interval[s].dm = c->interval[s].dm; 1175128967Srik } 1176128967Srik return 0; 1177128967Srik 1178128967Srik case SERIAL_GETE3STAT: 1179133646Srik CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 1180128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1181128967Srik return EINVAL; 1182133646Srik opte3 = (struct e3_statistics*) data; 1183128967Srik 1184128967Srik opte3->status = c->e3status; 1185128967Srik opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 1186128967Srik opte3->totsec = c->e3tsec + opte3->cursec; 1187128967Srik 1188128967Srik opte3->ccv = c->e3ccv; 1189128967Srik opte3->tcv = c->e3tcv + opte3->ccv; 1190128967Srik 1191128967Srik for (s = 0; s < 48; ++s) { 1192128967Srik opte3->icv[s] = c->e3icv[s]; 1193128967Srik } 1194133646Srik return 0; 1195128967Srik 1196128967Srik case SERIAL_CLRSTAT: 1197133646Srik CP_DEBUG2 (d, ("ioctl: clrstat\n")); 1198133646Srik /* Only for superuser! */ 1199164033Srwatson error = priv_check (td, PRIV_DRIVER); 1200133646Srik if (error) 1201133646Srik return error; 1202128967Srik c->rintr = 0; 1203128967Srik c->tintr = 0; 1204128967Srik c->ibytes = 0; 1205128967Srik c->obytes = 0; 1206128967Srik c->ipkts = 0; 1207128967Srik c->opkts = 0; 1208128967Srik c->overrun = 0; 1209128967Srik c->frame = 0; 1210133646Srik c->crc = 0; 1211128967Srik c->underrun = 0; 1212128967Srik bzero (&c->currnt, sizeof (c->currnt)); 1213128967Srik bzero (&c->total, sizeof (c->total)); 1214128967Srik bzero (c->interval, sizeof (c->interval)); 1215128967Srik c->e3ccv = 0; 1216128967Srik c->e3tcv = 0; 1217128967Srik bzero (c->e3icv, sizeof (c->e3icv)); 1218133646Srik return 0; 1219128967Srik 1220128967Srik case SERIAL_GETBAUD: 1221133646Srik CP_DEBUG2 (d, ("ioctl: getbaud\n")); 1222133646Srik *(long*)data = c->baud; 1223133646Srik return 0; 1224128967Srik 1225128967Srik case SERIAL_SETBAUD: 1226133646Srik CP_DEBUG2 (d, ("ioctl: setbaud\n")); 1227133646Srik /* Only for superuser! */ 1228164033Srwatson error = priv_check (td, PRIV_DRIVER); 1229133646Srik if (error) 1230133646Srik return error; 1231133646Srik s = splimp (); 1232138823Srik CP_LOCK (bd); 1233133646Srik cp_set_baud (c, *(long*)data); 1234138823Srik CP_UNLOCK (bd); 1235133646Srik splx (s); 1236133646Srik return 0; 1237128967Srik 1238128967Srik case SERIAL_GETLOOP: 1239133646Srik CP_DEBUG2 (d, ("ioctl: getloop\n")); 1240133646Srik *(int*)data = c->lloop; 1241133646Srik return 0; 1242128967Srik 1243128967Srik case SERIAL_SETLOOP: 1244133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1245133646Srik /* Only for superuser! */ 1246164033Srwatson error = priv_check (td, PRIV_DRIVER); 1247133646Srik if (error) 1248133646Srik return error; 1249133646Srik s = splimp (); 1250138823Srik CP_LOCK (bd); 1251128967Srik cp_set_lloop (c, *(int*)data); 1252138823Srik CP_UNLOCK (bd); 1253133646Srik splx (s); 1254133646Srik return 0; 1255128967Srik 1256128967Srik case SERIAL_GETDPLL: 1257133646Srik CP_DEBUG2 (d, ("ioctl: getdpll\n")); 1258133646Srik if (c->type != T_SERIAL) 1259133646Srik return EINVAL; 1260133646Srik *(int*)data = c->dpll; 1261133646Srik return 0; 1262128967Srik 1263128967Srik case SERIAL_SETDPLL: 1264133646Srik CP_DEBUG2 (d, ("ioctl: setdpll\n")); 1265133646Srik /* Only for superuser! */ 1266164033Srwatson error = priv_check (td, PRIV_DRIVER); 1267133646Srik if (error) 1268133646Srik return error; 1269133646Srik if (c->type != T_SERIAL) 1270133646Srik return EINVAL; 1271133646Srik s = splimp (); 1272138823Srik CP_LOCK (bd); 1273133646Srik cp_set_dpll (c, *(int*)data); 1274138823Srik CP_UNLOCK (bd); 1275133646Srik splx (s); 1276133646Srik return 0; 1277128967Srik 1278128967Srik case SERIAL_GETNRZI: 1279133646Srik CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 1280133646Srik if (c->type != T_SERIAL) 1281133646Srik return EINVAL; 1282133646Srik *(int*)data = c->nrzi; 1283133646Srik return 0; 1284128967Srik 1285128967Srik case SERIAL_SETNRZI: 1286133646Srik CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 1287133646Srik /* Only for superuser! */ 1288164033Srwatson error = priv_check (td, PRIV_DRIVER); 1289133646Srik if (error) 1290133646Srik return error; 1291133646Srik if (c->type != T_SERIAL) 1292133646Srik return EINVAL; 1293133646Srik s = splimp (); 1294138823Srik CP_LOCK (bd); 1295133646Srik cp_set_nrzi (c, *(int*)data); 1296138823Srik CP_UNLOCK (bd); 1297133646Srik splx (s); 1298133646Srik return 0; 1299128967Srik 1300128967Srik case SERIAL_GETDEBUG: 1301133646Srik CP_DEBUG2 (d, ("ioctl: getdebug\n")); 1302133646Srik *(int*)data = d->chan->debug; 1303133646Srik return 0; 1304128967Srik 1305128967Srik case SERIAL_SETDEBUG: 1306133646Srik CP_DEBUG2 (d, ("ioctl: setdebug\n")); 1307133646Srik /* Only for superuser! */ 1308164033Srwatson error = priv_check (td, PRIV_DRIVER); 1309133646Srik if (error) 1310133646Srik return error; 1311180132Srik#ifndef NETGRAPH 1312180132Srik /* 1313180132Srik * The debug_shadow is always greater than zero for logic 1314180132Srik * simplicity. For switching debug off the IFF_DEBUG is 1315180132Srik * responsible. 1316180132Srik */ 1317180132Srik d->chan->debug_shadow = (*(int*)data) ? (*(int*)data) : 1; 1318180132Srik if (d->ifp->if_flags & IFF_DEBUG) 1319180132Srik d->chan->debug = d->chan->debug_shadow; 1320180132Srik#else 1321133646Srik d->chan->debug = *(int*)data; 1322128967Srik#endif 1323133646Srik return 0; 1324128967Srik 1325128967Srik case SERIAL_GETHIGAIN: 1326133646Srik CP_DEBUG2 (d, ("ioctl: gethigain\n")); 1327133646Srik if (c->type != T_E1) 1328133646Srik return EINVAL; 1329133646Srik *(int*)data = c->higain; 1330128967Srik return 0; 1331128967Srik 1332128967Srik case SERIAL_SETHIGAIN: 1333133646Srik CP_DEBUG2 (d, ("ioctl: sethigain\n")); 1334133646Srik /* Only for superuser! */ 1335164033Srwatson error = priv_check (td, PRIV_DRIVER); 1336133646Srik if (error) 1337133646Srik return error; 1338133646Srik if (c->type != T_E1) 1339133646Srik return EINVAL; 1340128967Srik s = splimp (); 1341138823Srik CP_LOCK (bd); 1342128967Srik cp_set_higain (c, *(int*)data); 1343138823Srik CP_UNLOCK (bd); 1344128967Srik splx (s); 1345128967Srik return 0; 1346128967Srik 1347128967Srik case SERIAL_GETPHONY: 1348128967Srik CP_DEBUG2 (d, ("ioctl: getphony\n")); 1349133646Srik if (c->type != T_E1) 1350133646Srik return EINVAL; 1351133646Srik *(int*)data = c->phony; 1352128967Srik return 0; 1353128967Srik 1354128967Srik case SERIAL_SETPHONY: 1355128967Srik CP_DEBUG2 (d, ("ioctl: setphony\n")); 1356133646Srik /* Only for superuser! */ 1357164033Srwatson error = priv_check (td, PRIV_DRIVER); 1358133646Srik if (error) 1359133646Srik return error; 1360133646Srik if (c->type != T_E1) 1361133646Srik return EINVAL; 1362128967Srik s = splimp (); 1363138823Srik CP_LOCK (bd); 1364128967Srik cp_set_phony (c, *(int*)data); 1365138823Srik CP_UNLOCK (bd); 1366128967Srik splx (s); 1367128967Srik return 0; 1368128967Srik 1369128967Srik case SERIAL_GETUNFRAM: 1370128967Srik CP_DEBUG2 (d, ("ioctl: getunfram\n")); 1371133646Srik if (c->type != T_E1) 1372133646Srik return EINVAL; 1373133646Srik *(int*)data = c->unfram; 1374128967Srik return 0; 1375128967Srik 1376128967Srik case SERIAL_SETUNFRAM: 1377128967Srik CP_DEBUG2 (d, ("ioctl: setunfram\n")); 1378133646Srik /* Only for superuser! */ 1379164033Srwatson error = priv_check (td, PRIV_DRIVER); 1380133646Srik if (error) 1381133646Srik return error; 1382133646Srik if (c->type != T_E1) 1383133646Srik return EINVAL; 1384128967Srik s = splimp (); 1385138823Srik CP_LOCK (bd); 1386128967Srik cp_set_unfram (c, *(int*)data); 1387138823Srik CP_UNLOCK (bd); 1388128967Srik splx (s); 1389128967Srik return 0; 1390128967Srik 1391128967Srik case SERIAL_GETSCRAMBLER: 1392128967Srik CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 1393133646Srik if (c->type != T_G703 && !c->unfram) 1394133646Srik return EINVAL; 1395133646Srik *(int*)data = c->scrambler; 1396128967Srik return 0; 1397128967Srik 1398128967Srik case SERIAL_SETSCRAMBLER: 1399128967Srik CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 1400133646Srik /* Only for superuser! */ 1401164033Srwatson error = priv_check (td, PRIV_DRIVER); 1402133646Srik if (error) 1403133646Srik return error; 1404133646Srik if (c->type != T_G703 && !c->unfram) 1405133646Srik return EINVAL; 1406128967Srik s = splimp (); 1407138823Srik CP_LOCK (bd); 1408128967Srik cp_set_scrambler (c, *(int*)data); 1409138823Srik CP_UNLOCK (bd); 1410128967Srik splx (s); 1411128967Srik return 0; 1412128967Srik 1413128967Srik case SERIAL_GETMONITOR: 1414128967Srik CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 1415133646Srik if (c->type != T_E1 && 1416128967Srik c->type != T_E3 && 1417128967Srik c->type != T_T3 && 1418128967Srik c->type != T_STS1) 1419133646Srik return EINVAL; 1420133646Srik *(int*)data = c->monitor; 1421128967Srik return 0; 1422128967Srik 1423128967Srik case SERIAL_SETMONITOR: 1424128967Srik CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 1425133646Srik /* Only for superuser! */ 1426164033Srwatson error = priv_check (td, PRIV_DRIVER); 1427133646Srik if (error) 1428133646Srik return error; 1429133646Srik if (c->type != T_E1) 1430133646Srik return EINVAL; 1431128967Srik s = splimp (); 1432138823Srik CP_LOCK (bd); 1433128967Srik cp_set_monitor (c, *(int*)data); 1434138823Srik CP_UNLOCK (bd); 1435128967Srik splx (s); 1436128967Srik return 0; 1437128967Srik 1438128967Srik case SERIAL_GETUSE16: 1439133646Srik CP_DEBUG2 (d, ("ioctl: getuse16\n")); 1440133646Srik if (c->type != T_E1 || c->unfram) 1441133646Srik return EINVAL; 1442133646Srik *(int*)data = c->use16; 1443128967Srik return 0; 1444128967Srik 1445128967Srik case SERIAL_SETUSE16: 1446133646Srik CP_DEBUG2 (d, ("ioctl: setuse16\n")); 1447133646Srik /* Only for superuser! */ 1448164033Srwatson error = priv_check (td, PRIV_DRIVER); 1449133646Srik if (error) 1450133646Srik return error; 1451133646Srik if (c->type != T_E1) 1452133646Srik return EINVAL; 1453128967Srik s = splimp (); 1454138823Srik CP_LOCK (bd); 1455128967Srik cp_set_use16 (c, *(int*)data); 1456138823Srik CP_UNLOCK (bd); 1457128967Srik splx (s); 1458128967Srik return 0; 1459128967Srik 1460128967Srik case SERIAL_GETCRC4: 1461133646Srik CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 1462133646Srik if (c->type != T_E1 || c->unfram) 1463133646Srik return EINVAL; 1464133646Srik *(int*)data = c->crc4; 1465128967Srik return 0; 1466128967Srik 1467128967Srik case SERIAL_SETCRC4: 1468133646Srik CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 1469133646Srik /* Only for superuser! */ 1470164033Srwatson error = priv_check (td, PRIV_DRIVER); 1471133646Srik if (error) 1472133646Srik return error; 1473133646Srik if (c->type != T_E1) 1474133646Srik return EINVAL; 1475128967Srik s = splimp (); 1476138823Srik CP_LOCK (bd); 1477128967Srik cp_set_crc4 (c, *(int*)data); 1478138823Srik CP_UNLOCK (bd); 1479128967Srik splx (s); 1480128967Srik return 0; 1481128967Srik 1482128967Srik case SERIAL_GETCLK: 1483133646Srik CP_DEBUG2 (d, ("ioctl: getclk\n")); 1484133646Srik if (c->type != T_E1 && 1485128967Srik c->type != T_G703 && 1486128967Srik c->type != T_E3 && 1487128967Srik c->type != T_T3 && 1488128967Srik c->type != T_STS1) 1489133646Srik return EINVAL; 1490128967Srik switch (c->gsyn) { 1491128967Srik default: *(int*)data = E1CLK_INTERNAL; break; 1492128967Srik case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1493128967Srik case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1494128967Srik case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1495128967Srik case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 1496128967Srik case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 1497128967Srik } 1498128967Srik return 0; 1499128967Srik 1500128967Srik case SERIAL_SETCLK: 1501133646Srik CP_DEBUG2 (d, ("ioctl: setclk\n")); 1502133646Srik /* Only for superuser! */ 1503164033Srwatson error = priv_check (td, PRIV_DRIVER); 1504133646Srik if (error) 1505133646Srik return error; 1506128967Srik if (c->type != T_E1 && 1507128967Srik c->type != T_G703 && 1508128967Srik c->type != T_E3 && 1509128967Srik c->type != T_T3 && 1510128967Srik c->type != T_STS1) 1511133646Srik return EINVAL; 1512128967Srik s = splimp (); 1513138823Srik CP_LOCK (bd); 1514128967Srik switch (*(int*)data) { 1515128967Srik default: cp_set_gsyn (c, GSYN_INT); break; 1516128967Srik case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 1517128967Srik case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 1518128967Srik case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 1519128967Srik case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 1520128967Srik case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 1521128967Srik } 1522138823Srik CP_UNLOCK (bd); 1523128967Srik splx (s); 1524128967Srik return 0; 1525128967Srik 1526128967Srik case SERIAL_GETTIMESLOTS: 1527133646Srik CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1528133646Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1529133646Srik return EINVAL; 1530133646Srik *(u_long*)data = c->ts; 1531128967Srik return 0; 1532128967Srik 1533128967Srik case SERIAL_SETTIMESLOTS: 1534133646Srik CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 1535133646Srik /* Only for superuser! */ 1536164033Srwatson error = priv_check (td, PRIV_DRIVER); 1537133646Srik if (error) 1538133646Srik return error; 1539128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1540133646Srik return EINVAL; 1541128967Srik s = splimp (); 1542138823Srik CP_LOCK (bd); 1543128967Srik cp_set_ts (c, *(u_long*)data); 1544138823Srik CP_UNLOCK (bd); 1545128967Srik splx (s); 1546128967Srik return 0; 1547128967Srik 1548128967Srik case SERIAL_GETINVCLK: 1549133646Srik CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 1550128967Srik#if 1 1551128967Srik return EINVAL; 1552128967Srik#else 1553133646Srik if (c->type != T_SERIAL) 1554133646Srik return EINVAL; 1555133646Srik *(int*)data = c->invtxc; 1556128967Srik return 0; 1557128967Srik#endif 1558128967Srik 1559128967Srik case SERIAL_SETINVCLK: 1560133646Srik CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 1561133646Srik /* Only for superuser! */ 1562164033Srwatson error = priv_check (td, PRIV_DRIVER); 1563133646Srik if (error) 1564133646Srik return error; 1565133646Srik if (c->type != T_SERIAL) 1566133646Srik return EINVAL; 1567128967Srik s = splimp (); 1568138823Srik CP_LOCK (bd); 1569128967Srik cp_set_invtxc (c, *(int*)data); 1570128967Srik cp_set_invrxc (c, *(int*)data); 1571138823Srik CP_UNLOCK (bd); 1572128967Srik splx (s); 1573128967Srik return 0; 1574128967Srik 1575128967Srik case SERIAL_GETINVTCLK: 1576133646Srik CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 1577133646Srik if (c->type != T_SERIAL) 1578133646Srik return EINVAL; 1579133646Srik *(int*)data = c->invtxc; 1580128967Srik return 0; 1581128967Srik 1582128967Srik case SERIAL_SETINVTCLK: 1583133646Srik CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 1584133646Srik /* Only for superuser! */ 1585164033Srwatson error = priv_check (td, PRIV_DRIVER); 1586133646Srik if (error) 1587133646Srik return error; 1588133646Srik if (c->type != T_SERIAL) 1589133646Srik return EINVAL; 1590128967Srik s = splimp (); 1591138823Srik CP_LOCK (bd); 1592128967Srik cp_set_invtxc (c, *(int*)data); 1593138823Srik CP_UNLOCK (bd); 1594128967Srik splx (s); 1595128967Srik return 0; 1596128967Srik 1597128967Srik case SERIAL_GETINVRCLK: 1598133646Srik CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 1599133646Srik if (c->type != T_SERIAL) 1600133646Srik return EINVAL; 1601133646Srik *(int*)data = c->invrxc; 1602128967Srik return 0; 1603128967Srik 1604128967Srik case SERIAL_SETINVRCLK: 1605133646Srik CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 1606133646Srik /* Only for superuser! */ 1607164033Srwatson error = priv_check (td, PRIV_DRIVER); 1608133646Srik if (error) 1609133646Srik return error; 1610133646Srik if (c->type != T_SERIAL) 1611133646Srik return EINVAL; 1612128967Srik s = splimp (); 1613138823Srik CP_LOCK (bd); 1614128967Srik cp_set_invrxc (c, *(int*)data); 1615138823Srik CP_UNLOCK (bd); 1616128967Srik splx (s); 1617128967Srik return 0; 1618128967Srik 1619128967Srik case SERIAL_GETLEVEL: 1620133646Srik CP_DEBUG2 (d, ("ioctl: getlevel\n")); 1621133646Srik if (c->type != T_G703) 1622133646Srik return EINVAL; 1623128967Srik s = splimp (); 1624138823Srik CP_LOCK (bd); 1625133646Srik *(int*)data = cp_get_lq (c); 1626138823Srik CP_UNLOCK (bd); 1627128967Srik splx (s); 1628128967Srik return 0; 1629128967Srik 1630128967Srik#if 0 1631128967Srik case SERIAL_RESET: 1632133646Srik CP_DEBUG2 (d, ("ioctl: reset\n")); 1633133646Srik /* Only for superuser! */ 1634164033Srwatson error = priv_check (td, PRIV_DRIVER); 1635133646Srik if (error) 1636133646Srik return error; 1637128967Srik s = splimp (); 1638138823Srik CP_LOCK (bd); 1639128967Srik cp_reset (c->board, 0, 0); 1640138823Srik CP_UNLOCK (bd); 1641128967Srik splx (s); 1642128967Srik return 0; 1643128967Srik 1644128967Srik case SERIAL_HARDRESET: 1645133646Srik CP_DEBUG2 (d, ("ioctl: hardreset\n")); 1646133646Srik /* Only for superuser! */ 1647164033Srwatson error = priv_check (td, PRIV_DRIVER); 1648133646Srik if (error) 1649133646Srik return error; 1650128967Srik s = splimp (); 1651138823Srik CP_LOCK (bd); 1652128967Srik /* hard_reset (c->board); */ 1653138823Srik CP_UNLOCK (bd); 1654128967Srik splx (s); 1655128967Srik return 0; 1656128967Srik#endif 1657128967Srik 1658128967Srik case SERIAL_GETCABLE: 1659133646Srik CP_DEBUG2 (d, ("ioctl: getcable\n")); 1660133646Srik if (c->type != T_SERIAL) 1661133646Srik return EINVAL; 1662128967Srik s = splimp (); 1663138823Srik CP_LOCK (bd); 1664128967Srik *(int*)data = cp_get_cable (c); 1665138823Srik CP_UNLOCK (bd); 1666128967Srik splx (s); 1667128967Srik return 0; 1668128967Srik 1669128967Srik case SERIAL_GETDIR: 1670133646Srik CP_DEBUG2 (d, ("ioctl: getdir\n")); 1671133646Srik if (c->type != T_E1 && c->type != T_DATA) 1672133646Srik return EINVAL; 1673128967Srik *(int*)data = c->dir; 1674128967Srik return 0; 1675128967Srik 1676128967Srik case SERIAL_SETDIR: 1677133646Srik CP_DEBUG2 (d, ("ioctl: setdir\n")); 1678133646Srik /* Only for superuser! */ 1679164033Srwatson error = priv_check (td, PRIV_DRIVER); 1680133646Srik if (error) 1681133646Srik return error; 1682128967Srik s = splimp (); 1683138823Srik CP_LOCK (bd); 1684128967Srik cp_set_dir (c, *(int*)data); 1685138823Srik CP_UNLOCK (bd); 1686128967Srik splx (s); 1687128967Srik return 0; 1688128967Srik 1689128967Srik case SERIAL_GETRLOOP: 1690133646Srik CP_DEBUG2 (d, ("ioctl: getrloop\n")); 1691133646Srik if (c->type != T_G703 && 1692128967Srik c->type != T_E3 && 1693128967Srik c->type != T_T3 && 1694128967Srik c->type != T_STS1) 1695133646Srik return EINVAL; 1696133646Srik *(int*)data = cp_get_rloop (c); 1697133646Srik return 0; 1698128967Srik 1699128967Srik case SERIAL_SETRLOOP: 1700133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1701133646Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1702133646Srik return EINVAL; 1703133646Srik /* Only for superuser! */ 1704164033Srwatson error = priv_check (td, PRIV_DRIVER); 1705133646Srik if (error) 1706133646Srik return error; 1707133646Srik s = splimp (); 1708138823Srik CP_LOCK (bd); 1709128967Srik cp_set_rloop (c, *(int*)data); 1710138823Srik CP_UNLOCK (bd); 1711133646Srik splx (s); 1712133646Srik return 0; 1713128967Srik 1714128967Srik case SERIAL_GETCABLEN: 1715133646Srik CP_DEBUG2 (d, ("ioctl: getcablen\n")); 1716133646Srik if (c->type != T_T3 && c->type != T_STS1) 1717133646Srik return EINVAL; 1718133646Srik *(int*)data = c->cablen; 1719133646Srik return 0; 1720128967Srik 1721128967Srik case SERIAL_SETCABLEN: 1722133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1723133646Srik if (c->type != T_T3 && c->type != T_STS1) 1724133646Srik return EINVAL; 1725133646Srik /* Only for superuser! */ 1726164033Srwatson error = priv_check (td, PRIV_DRIVER); 1727133646Srik if (error) 1728133646Srik return error; 1729133646Srik s = splimp (); 1730138823Srik CP_LOCK (bd); 1731128967Srik cp_set_cablen (c, *(int*)data); 1732138823Srik CP_UNLOCK (bd); 1733133646Srik splx (s); 1734133646Srik return 0; 1735128967Srik 1736133646Srik case TIOCSDTR: /* Set DTR */ 1737128967Srik s = splimp (); 1738138823Srik CP_LOCK (bd); 1739128967Srik cp_set_dtr (c, 1); 1740138823Srik CP_UNLOCK (bd); 1741128967Srik splx (s); 1742128967Srik return 0; 1743128967Srik 1744133646Srik case TIOCCDTR: /* Clear DTR */ 1745128967Srik s = splimp (); 1746138823Srik CP_LOCK (bd); 1747128967Srik cp_set_dtr (c, 0); 1748138823Srik CP_UNLOCK (bd); 1749128967Srik splx (s); 1750128967Srik return 0; 1751128967Srik 1752133646Srik case TIOCMSET: /* Set DTR/RTS */ 1753128967Srik s = splimp (); 1754138823Srik CP_LOCK (bd); 1755128967Srik cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1756128967Srik cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1757138823Srik CP_UNLOCK (bd); 1758128967Srik splx (s); 1759128967Srik return 0; 1760128967Srik 1761133646Srik case TIOCMBIS: /* Add DTR/RTS */ 1762128967Srik s = splimp (); 1763138823Srik CP_LOCK (bd); 1764128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 1765128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 1766138823Srik CP_UNLOCK (bd); 1767128967Srik splx (s); 1768128967Srik return 0; 1769128967Srik 1770133646Srik case TIOCMBIC: /* Clear DTR/RTS */ 1771128967Srik s = splimp (); 1772138823Srik CP_LOCK (bd); 1773128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1774128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1775138823Srik CP_UNLOCK (bd); 1776128967Srik splx (s); 1777128967Srik return 0; 1778128967Srik 1779133646Srik case TIOCMGET: /* Get modem status */ 1780128967Srik *(int*)data = cp_modem_status (c); 1781128967Srik return 0; 1782128967Srik } 1783128967Srik return ENOTTY; 1784128967Srik} 1785128967Srik 1786128967Srik#ifdef NETGRAPH 1787128967Srikstatic int ng_cp_constructor (node_p node) 1788128967Srik{ 1789128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1790128967Srik CP_DEBUG (d, ("Constructor\n")); 1791128967Srik return EINVAL; 1792128967Srik} 1793128967Srik 1794128967Srikstatic int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1795128967Srik{ 1796128967Srik int s; 1797128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1798138823Srik bdrv_t *bd = d->board->sys; 1799128967Srik 1800128967Srik CP_DEBUG (d, ("Newhook\n")); 1801128967Srik /* Attach debug hook */ 1802128967Srik if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1803128967Srik NG_HOOK_SET_PRIVATE (hook, NULL); 1804128967Srik d->debug_hook = hook; 1805128967Srik return 0; 1806128967Srik } 1807128967Srik 1808128967Srik /* Check for raw hook */ 1809128967Srik if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1810128967Srik return EINVAL; 1811128967Srik 1812128967Srik NG_HOOK_SET_PRIVATE (hook, d); 1813128967Srik d->hook = hook; 1814128967Srik s = splimp (); 1815138823Srik CP_LOCK (bd); 1816128967Srik cp_up (d); 1817138823Srik CP_UNLOCK (bd); 1818128967Srik splx (s); 1819128967Srik return 0; 1820128967Srik} 1821128967Srik 1822128967Srikstatic char *format_timeslots (u_long s) 1823128967Srik{ 1824128967Srik static char buf [100]; 1825128967Srik char *p = buf; 1826128967Srik int i; 1827128967Srik 1828128967Srik for (i=1; i<32; ++i) 1829128967Srik if ((s >> i) & 1) { 1830128967Srik int prev = (i > 1) & (s >> (i-1)); 1831128967Srik int next = (i < 31) & (s >> (i+1)); 1832128967Srik 1833128967Srik if (prev) { 1834128967Srik if (next) 1835128967Srik continue; 1836128967Srik *p++ = '-'; 1837128967Srik } else if (p > buf) 1838128967Srik *p++ = ','; 1839128967Srik 1840128967Srik if (i >= 10) 1841128967Srik *p++ = '0' + i / 10; 1842128967Srik *p++ = '0' + i % 10; 1843128967Srik } 1844128967Srik *p = 0; 1845128967Srik return buf; 1846128967Srik} 1847128967Srik 1848128967Srikstatic int print_modems (char *s, cp_chan_t *c, int need_header) 1849128967Srik{ 1850128967Srik int status = cp_modem_status (c); 1851128967Srik int length = 0; 1852128967Srik 1853128967Srik if (need_header) 1854128967Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1855128967Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1856128967Srik status & TIOCM_LE ? "On" : "-", 1857128967Srik status & TIOCM_DTR ? "On" : "-", 1858128967Srik status & TIOCM_DSR ? "On" : "-", 1859128967Srik status & TIOCM_RTS ? "On" : "-", 1860128967Srik status & TIOCM_CTS ? "On" : "-", 1861128967Srik status & TIOCM_CD ? "On" : "-"); 1862128967Srik return length; 1863128967Srik} 1864128967Srik 1865128967Srikstatic int print_stats (char *s, cp_chan_t *c, int need_header) 1866128967Srik{ 1867128967Srik int length = 0; 1868128967Srik 1869128967Srik if (need_header) 1870128967Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1871128967Srik length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1872128967Srik c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1873128967Srik c->ipkts, c->overrun + c->frame + c->crc, 1874128967Srik (unsigned long) c->obytes, c->opkts, c->underrun); 1875128967Srik return length; 1876128967Srik} 1877128967Srik 1878128967Srikstatic char *format_e1_status (u_char status) 1879128967Srik{ 1880128967Srik static char buf [80]; 1881128967Srik 1882128967Srik if (status & E1_NOALARM) 1883128967Srik return "Ok"; 1884128967Srik buf[0] = 0; 1885128967Srik if (status & E1_LOS) strcat (buf, ",LOS"); 1886128967Srik if (status & E1_AIS) strcat (buf, ",AIS"); 1887128967Srik if (status & E1_LOF) strcat (buf, ",LOF"); 1888128967Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 1889128967Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1890128967Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 1891128967Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1892128967Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1893128967Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1894128967Srik if (buf[0] == ',') 1895128967Srik return buf+1; 1896128967Srik return "Unknown"; 1897128967Srik} 1898128967Srik 1899128967Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1900128967Srik{ 1901128967Srik int n, length = 0; 1902128967Srik 1903128967Srik if (numerator < 1 || divider < 1) { 1904128967Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 1905128967Srik return length; 1906128967Srik } 1907128967Srik n = (int) (0.5 + 1000.0 * numerator / divider); 1908128967Srik if (n < 1000) { 1909128967Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1910128967Srik return length; 1911128967Srik } 1912128967Srik *(s + length) = leftalign ? '/' : ' '; 1913128967Srik length ++; 1914128967Srik 1915128967Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 1916128967Srik else if (n >= 100000) n = (n+50) / 100 * 100; 1917128967Srik else if (n >= 10000) n = (n+5) / 10 * 10; 1918128967Srik 1919128967Srik switch (n) { 1920128967Srik case 1000: length += printf (s+length, ".999"); return length; 1921128967Srik case 10000: n = 9990; break; 1922128967Srik case 100000: n = 99900; break; 1923128967Srik case 1000000: n = 999000; break; 1924128967Srik } 1925133646Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1926128967Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1927128967Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1928133646Srik else length += sprintf (s+length, "%d", n/1000); 1929128967Srik 1930128967Srik return length; 1931128967Srik} 1932128967Srik 1933128967Srikstatic int print_e1_stats (char *s, cp_chan_t *c) 1934128967Srik{ 1935128967Srik struct e1_counters total; 1936128967Srik u_long totsec; 1937128967Srik int length = 0; 1938128967Srik 1939128967Srik totsec = c->totsec + c->cursec; 1940128967Srik total.bpv = c->total.bpv + c->currnt.bpv; 1941128967Srik total.fse = c->total.fse + c->currnt.fse; 1942128967Srik total.crce = c->total.crce + c->currnt.crce; 1943128967Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 1944128967Srik total.uas = c->total.uas + c->currnt.uas; 1945128967Srik total.les = c->total.les + c->currnt.les; 1946128967Srik total.es = c->total.es + c->currnt.es; 1947128967Srik total.bes = c->total.bes + c->currnt.bes; 1948128967Srik total.ses = c->total.ses + c->currnt.ses; 1949128967Srik total.oofs = c->total.oofs + c->currnt.oofs; 1950128967Srik total.css = c->total.css + c->currnt.css; 1951128967Srik total.dm = c->total.dm + c->currnt.dm; 1952128967Srik 1953128967Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1954128967Srik 1955128967Srik /* Unavailable seconds, degraded minutes */ 1956128967Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1957128967Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1958128967Srik 1959128967Srik /* Bipolar violations, frame sync errors */ 1960128967Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1961128967Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1962128967Srik 1963128967Srik /* CRC errors, remote CRC errors (E-bit) */ 1964128967Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 1965128967Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 1966128967Srik 1967128967Srik /* Errored seconds, line errored seconds */ 1968128967Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 1969128967Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 1970128967Srik 1971128967Srik /* Severely errored seconds, burst errored seconds */ 1972128967Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 1973128967Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 1974128967Srik 1975128967Srik /* Out of frame seconds, controlled slip seconds */ 1976128967Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 1977128967Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 1978128967Srik 1979128967Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 1980128967Srik 1981128967Srik /* Print total statistics. */ 1982128967Srik length += print_frac (s + length, 0, total.uas, totsec); 1983128967Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 1984128967Srik 1985128967Srik length += print_frac (s + length, 0, total.bpv, totsec); 1986128967Srik length += print_frac (s + length, 1, total.fse, totsec); 1987128967Srik 1988128967Srik length += print_frac (s + length, 0, total.crce, totsec); 1989128967Srik length += print_frac (s + length, 1, total.rcrce, totsec); 1990128967Srik 1991128967Srik length += print_frac (s + length, 0, total.es, totsec); 1992128967Srik length += print_frac (s + length, 1, total.les, totsec); 1993128967Srik 1994128967Srik length += print_frac (s + length, 0, total.ses, totsec); 1995128967Srik length += print_frac (s + length, 1, total.bes, totsec); 1996128967Srik 1997128967Srik length += print_frac (s + length, 0, total.oofs, totsec); 1998128967Srik length += print_frac (s + length, 1, total.css, totsec); 1999128967Srik 2000128967Srik length += sprintf (s + length, " -- Total\n"); 2001128967Srik return length; 2002128967Srik} 2003128967Srik 2004128967Srikstatic int print_chan (char *s, cp_chan_t *c) 2005128967Srik{ 2006128967Srik drv_t *d = c->sys; 2007138823Srik bdrv_t *bd = d->board->sys; 2008128967Srik int length = 0; 2009128967Srik 2010128967Srik length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2011128967Srik if (d->chan->debug) 2012128967Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 2013128967Srik 2014128967Srik if (c->board->mux) { 2015128967Srik length += sprintf (s + length, " cfg=C"); 2016128967Srik } else { 2017128967Srik length += sprintf (s + length, " cfg=A"); 2018128967Srik } 2019128967Srik 2020128967Srik if (c->baud) 2021128967Srik length += sprintf (s + length, " %ld", c->baud); 2022128967Srik else 2023128967Srik length += sprintf (s + length, " extclock"); 2024128967Srik 2025128967Srik if (c->type == T_E1 || c->type == T_G703) 2026128967Srik switch (c->gsyn) { 2027128967Srik case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2028128967Srik case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2029128967Srik case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2030128967Srik case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2031128967Srik case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2032128967Srik case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2033128967Srik } 2034128967Srik if (c->type == T_SERIAL) { 2035128967Srik length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2036128967Srik length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2037128967Srik length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2038128967Srik } 2039128967Srik if (c->type == T_E1) 2040128967Srik length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2041128967Srik 2042128967Srik length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2043128967Srik 2044128967Srik if (c->type == T_E1) 2045128967Srik length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2046128967Srik if (c->type == T_G703) { 2047128967Srik int lq, x; 2048128967Srik 2049128967Srik x = splimp (); 2050138823Srik CP_LOCK (bd); 2051128967Srik lq = cp_get_lq (c); 2052138823Srik CP_UNLOCK (bd); 2053128967Srik splx (x); 2054128967Srik length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2055128967Srik } 2056128967Srik length += sprintf (s + length, "\n"); 2057128967Srik return length; 2058128967Srik} 2059128967Srik 2060128967Srikstatic int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2061128967Srik{ 2062128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2063128967Srik struct ng_mesg *msg; 2064128967Srik struct ng_mesg *resp = NULL; 2065128967Srik int error = 0; 2066128967Srik 2067128967Srik CP_DEBUG (d, ("Rcvmsg\n")); 2068128967Srik NGI_GET_MSG (item, msg); 2069128967Srik switch (msg->header.typecookie) { 2070128967Srik default: 2071128967Srik error = EINVAL; 2072128967Srik break; 2073128967Srik 2074128967Srik case NGM_CP_COOKIE: 2075128967Srik printf ("Not implemented yet\n"); 2076128967Srik error = EINVAL; 2077128967Srik break; 2078128967Srik 2079128967Srik case NGM_GENERIC_COOKIE: 2080128967Srik switch (msg->header.cmd) { 2081128967Srik default: 2082128967Srik error = EINVAL; 2083128967Srik break; 2084128967Srik 2085128967Srik case NGM_TEXT_STATUS: { 2086128967Srik char *s; 2087128967Srik int l = 0; 2088128967Srik int dl = sizeof (struct ng_mesg) + 730; 2089128967Srik 2090128967Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2091128967Srik if (! resp) { 2092128967Srik error = ENOMEM; 2093128967Srik break; 2094128967Srik } 2095128967Srik s = (resp)->data; 2096128967Srik if (d) { 2097128967Srik l += print_chan (s + l, d->chan); 2098128967Srik l += print_stats (s + l, d->chan, 1); 2099128967Srik l += print_modems (s + l, d->chan, 1); 2100128967Srik l += print_e1_stats (s + l, d->chan); 2101128967Srik } else 2102128967Srik l += sprintf (s + l, "Error: node not connect to channel"); 2103193813Simp strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRSIZ); 2104128967Srik } 2105128967Srik break; 2106128967Srik } 2107128967Srik break; 2108128967Srik } 2109128967Srik NG_RESPOND_MSG (error, node, item, resp); 2110128967Srik NG_FREE_MSG (msg); 2111128967Srik return error; 2112128967Srik} 2113128967Srik 2114128967Srikstatic int ng_cp_rcvdata (hook_p hook, item_p item) 2115128967Srik{ 2116128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2117128967Srik struct mbuf *m; 2118131108Sjulian struct ng_tag_prio *ptag; 2119138823Srik bdrv_t *bd = d->board->sys; 2120128967Srik struct ifqueue *q; 2121128967Srik int s; 2122128967Srik 2123128967Srik CP_DEBUG2 (d, ("Rcvdata\n")); 2124128967Srik NGI_GET_M (item, m); 2125128967Srik NG_FREE_ITEM (item); 2126128967Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 2127128967Srik NG_FREE_M (m); 2128128967Srik return ENETDOWN; 2129128967Srik } 2130131108Sjulian 2131131108Sjulian /* Check for high priority data */ 2132131108Sjulian if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2133131108Sjulian NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2134131108Sjulian q = &d->hi_queue; 2135131108Sjulian else 2136131108Sjulian q = &d->queue; 2137131108Sjulian 2138128967Srik s = splimp (); 2139138823Srik CP_LOCK (bd); 2140128967Srik IF_LOCK (q); 2141128967Srik if (_IF_QFULL (q)) { 2142128967Srik IF_UNLOCK (q); 2143138823Srik CP_UNLOCK (bd); 2144128967Srik splx (s); 2145128967Srik NG_FREE_M (m); 2146128967Srik return ENOBUFS; 2147128967Srik } 2148128967Srik _IF_ENQUEUE (q, m); 2149128967Srik IF_UNLOCK (q); 2150128967Srik cp_start (d); 2151138823Srik CP_UNLOCK (bd); 2152128967Srik splx (s); 2153128967Srik return 0; 2154128967Srik} 2155128967Srik 2156128967Srikstatic int ng_cp_rmnode (node_p node) 2157128967Srik{ 2158128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2159128967Srik 2160128967Srik CP_DEBUG (d, ("Rmnode\n")); 2161128967Srik if (d && d->running) { 2162138823Srik bdrv_t *bd = d->board->sys; 2163128967Srik int s = splimp (); 2164138823Srik CP_LOCK (bd); 2165128967Srik cp_down (d); 2166138823Srik CP_UNLOCK (bd); 2167128967Srik splx (s); 2168128967Srik } 2169128967Srik#ifdef KLD_MODULE 2170132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 2171128967Srik NG_NODE_SET_PRIVATE (node, NULL); 2172128967Srik NG_NODE_UNREF (node); 2173128967Srik } 2174298955Spfg NG_NODE_REVIVE(node); /* Persistent node */ 2175128967Srik#endif 2176128967Srik return 0; 2177128967Srik} 2178128967Srik 2179128967Srikstatic int ng_cp_connect (hook_p hook) 2180128967Srik{ 2181128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2182128967Srik 2183128967Srik if (d) { 2184128967Srik CP_DEBUG (d, ("Connect\n")); 2185199407Sjhb callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 2186128967Srik } 2187128967Srik 2188128967Srik return 0; 2189128967Srik} 2190128967Srik 2191128967Srikstatic int ng_cp_disconnect (hook_p hook) 2192128967Srik{ 2193128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2194128967Srik 2195128967Srik if (d) { 2196128967Srik CP_DEBUG (d, ("Disconnect\n")); 2197128967Srik if (NG_HOOK_PRIVATE (hook)) 2198128967Srik { 2199138823Srik bdrv_t *bd = d->board->sys; 2200128967Srik int s = splimp (); 2201138823Srik CP_LOCK (bd); 2202128967Srik cp_down (d); 2203138823Srik CP_UNLOCK (bd); 2204128967Srik splx (s); 2205128967Srik } 2206138823Srik /* If we were wait it than it reasserted now, just stop it. */ 2207138823Srik if (!callout_drain (&d->timeout_handle)) 2208138823Srik callout_stop (&d->timeout_handle); 2209128967Srik } 2210128967Srik return 0; 2211128967Srik} 2212128967Srik#endif 2213128967Srik 2214128967Srikstatic int cp_modevent (module_t mod, int type, void *unused) 2215128967Srik{ 2216128967Srik static int load_count = 0; 2217128967Srik 2218128967Srik switch (type) { 2219128967Srik case MOD_LOAD: 2220138673Srik#ifdef NETGRAPH 2221128967Srik if (ng_newtype (&typestruct)) 2222128967Srik printf ("Failed to register ng_cp\n"); 2223128967Srik#endif 2224128967Srik ++load_count; 2225283291Sjkim callout_init (&timeout_handle, 1); 2226138823Srik callout_reset (&timeout_handle, hz*5, cp_timeout, 0); 2227128967Srik break; 2228128967Srik case MOD_UNLOAD: 2229128967Srik if (load_count == 1) { 2230128967Srik printf ("Removing device entry for Tau-PCI\n"); 2231138673Srik#ifdef NETGRAPH 2232128967Srik ng_rmtype (&typestruct); 2233128967Srik#endif 2234128967Srik } 2235138823Srik /* If we were wait it than it reasserted now, just stop it. 2236138823Srik * Actually we shouldn't get this condition. But code could be 2237138823Srik * changed in the future, so just be a litle paranoid. 2238138823Srik */ 2239138823Srik if (!callout_drain (&timeout_handle)) 2240138823Srik callout_stop (&timeout_handle); 2241128967Srik --load_count; 2242128967Srik break; 2243128967Srik case MOD_SHUTDOWN: 2244128967Srik break; 2245128967Srik } 2246128967Srik return 0; 2247128967Srik} 2248128967Srik 2249128967Srik#ifdef NETGRAPH 2250128967Srikstatic struct ng_type typestruct = { 2251129837Srik .version = NG_ABI_VERSION, 2252129837Srik .name = NG_CP_NODE_TYPE, 2253129837Srik .constructor = ng_cp_constructor, 2254129837Srik .rcvmsg = ng_cp_rcvmsg, 2255129837Srik .shutdown = ng_cp_rmnode, 2256129837Srik .newhook = ng_cp_newhook, 2257129837Srik .connect = ng_cp_connect, 2258129837Srik .rcvdata = ng_cp_rcvdata, 2259129837Srik .disconnect = ng_cp_disconnect, 2260128967Srik}; 2261128967Srik#endif /*NETGRAPH*/ 2262128967Srik 2263128967Srik#ifdef NETGRAPH 2264128967SrikMODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2265128967Srik#else 2266128967SrikMODULE_DEPEND (cp, sppp, 1, 1, 1); 2267128967Srik#endif 2268128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2269138823SrikMODULE_VERSION (cp, 1); 2270