if_cp.c revision 276750
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: head/sys/dev/cp/if_cp.c 276750 2015-01-06 12:59:37Z rwatson $"); 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#include <machine/pmap.h> 71128967Srik 72128967Srik/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 73128967Srik#ifndef PP_FR 74128967Srik#define PP_FR 0 75128967Srik#endif 76128967Srik 77128967Srik#define CP_DEBUG(d,s) ({if (d->chan->debug) {\ 78128967Srik printf ("%s: ", d->name); printf s;}}) 79128967Srik#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 80128967Srik printf ("%s: ", d->name); printf s;}}) 81138823Srik#define CP_LOCK_NAME "cpX" 82128967Srik 83188661Srwatson#define CP_LOCK(_bd) mtx_lock (&(_bd)->cp_mtx) 84188661Srwatson#define CP_UNLOCK(_bd) mtx_unlock (&(_bd)->cp_mtx) 85188661Srwatson#define CP_LOCK_ASSERT(_bd) mtx_assert (&(_bd)->cp_mtx, MA_OWNED) 86138823Srik 87128967Srikstatic int cp_probe __P((device_t)); 88128967Srikstatic int cp_attach __P((device_t)); 89128967Srikstatic int cp_detach __P((device_t)); 90128967Srik 91128967Srikstatic device_method_t cp_methods[] = { 92128967Srik /* Device interface */ 93128967Srik DEVMETHOD(device_probe, cp_probe), 94128967Srik DEVMETHOD(device_attach, cp_attach), 95128967Srik DEVMETHOD(device_detach, cp_detach), 96128967Srik 97246128Ssbz DEVMETHOD_END 98128967Srik}; 99128967Srik 100130985Sriktypedef struct _cp_dma_mem_t { 101130985Srik unsigned long phys; 102130985Srik void *virt; 103130985Srik size_t size; 104130985Srik bus_dma_tag_t dmat; 105130985Srik bus_dmamap_t mapp; 106130985Srik} cp_dma_mem_t; 107128967Srik 108128967Sriktypedef struct _drv_t { 109138823Srik char name [8]; 110138823Srik int running; 111138823Srik cp_chan_t *chan; 112138823Srik cp_board_t *board; 113138823Srik cp_dma_mem_t dmamem; 114128967Srik#ifdef NETGRAPH 115193813Simp char nodename [NG_NODESIZE]; 116128967Srik hook_p hook; 117128967Srik hook_p debug_hook; 118128967Srik node_p node; 119128967Srik struct ifqueue queue; 120128967Srik struct ifqueue hi_queue; 121128967Srik#else 122138823Srik struct ifqueue queue; 123147256Sbrooks struct ifnet *ifp; 124128967Srik#endif 125199407Sjhb short timeout; 126199407Sjhb struct callout timeout_handle; 127138823Srik struct cdev *devt; 128128967Srik} drv_t; 129128967Srik 130130985Sriktypedef struct _bdrv_t { 131130985Srik cp_board_t *board; 132130985Srik struct resource *cp_res; 133130985Srik struct resource *cp_irq; 134130985Srik void *cp_intrhand; 135130985Srik cp_dma_mem_t dmamem; 136130985Srik drv_t channel [NCHAN]; 137138823Srik struct mtx cp_mtx; 138130985Srik} bdrv_t; 139130985Srik 140130985Srikstatic driver_t cp_driver = { 141130985Srik "cp", 142130985Srik cp_methods, 143130985Srik sizeof(bdrv_t), 144130985Srik}; 145130985Srik 146130985Srikstatic devclass_t cp_devclass; 147130985Srik 148128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len); 149128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len); 150128967Srikstatic void cp_error (cp_chan_t *c, int data); 151128967Srikstatic void cp_up (drv_t *d); 152128967Srikstatic void cp_start (drv_t *d); 153128967Srikstatic void cp_down (drv_t *d); 154128967Srikstatic void cp_watchdog (drv_t *d); 155199407Sjhbstatic void cp_watchdog_timer (void *arg); 156128967Srik#ifdef NETGRAPH 157128967Srikextern struct ng_type typestruct; 158128967Srik#else 159128967Srikstatic void cp_ifstart (struct ifnet *ifp); 160128967Srikstatic void cp_tlf (struct sppp *sp); 161128967Srikstatic void cp_tls (struct sppp *sp); 162128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 163128967Srikstatic void cp_initialize (void *softc); 164128967Srik#endif 165128967Srik 166128967Srikstatic cp_board_t *adapter [NBRD]; 167128967Srikstatic drv_t *channel [NBRD*NCHAN]; 168138823Srikstatic struct callout led_timo [NBRD]; 169138823Srikstatic struct callout timeout_handle; 170128967Srik 171128967Srikstatic int cp_destroy = 0; 172128967Srik 173150622Srikstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td); 174150622Srikstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td); 175150622Srikstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); 176150622Srikstatic struct cdevsw cp_cdevsw = { 177150622Srik .d_version = D_VERSION, 178150622Srik .d_open = cp_open, 179150622Srik .d_close = cp_close, 180150622Srik .d_ioctl = cp_ioctl, 181150622Srik .d_name = "cp", 182150622Srik}; 183150622Srik 184128967Srik/* 185150622Srik * Make an mbuf from data. 186150622Srik */ 187150622Srikstatic struct mbuf *makembuf (void *buf, unsigned len) 188150622Srik{ 189150622Srik struct mbuf *m; 190150622Srik 191243857Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 192150622Srik if (! m) 193150622Srik return 0; 194276750Srwatson if (!(MCLGET (m, M_NOWAIT))) { 195150622Srik m_freem (m); 196150622Srik return 0; 197150622Srik } 198150622Srik m->m_pkthdr.len = m->m_len = len; 199150622Srik bcopy (buf, mtod (m, caddr_t), len); 200150622Srik return m; 201150622Srik} 202150622Srik 203150622Srikstatic int cp_probe (device_t dev) 204150622Srik{ 205150622Srik if ((pci_get_vendor (dev) == cp_vendor_id) && 206150622Srik (pci_get_device (dev) == cp_device_id)) { 207150622Srik device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 208150622Srik return BUS_PROBE_DEFAULT; 209150622Srik } 210150622Srik return ENXIO; 211150622Srik} 212150622Srik 213150622Srikstatic void cp_timeout (void *arg) 214150622Srik{ 215150622Srik drv_t *d; 216150622Srik int s, i, k; 217150622Srik 218150622Srik for (i = 0; i < NBRD; ++i) { 219150622Srik if (adapter[i] == NULL) 220150622Srik continue; 221150622Srik for (k = 0; k < NCHAN; ++k) { 222150622Srik s = splimp (); 223150622Srik if (cp_destroy) { 224150622Srik splx (s); 225150622Srik return; 226150622Srik } 227150622Srik d = channel[i * NCHAN + k]; 228150622Srik if (!d) { 229150622Srik splx (s); 230150622Srik continue; 231150622Srik } 232150622Srik CP_LOCK ((bdrv_t *)d->board->sys); 233150622Srik switch (d->chan->type) { 234150622Srik case T_G703: 235150622Srik cp_g703_timer (d->chan); 236150622Srik break; 237150622Srik case T_E1: 238150622Srik cp_e1_timer (d->chan); 239150622Srik break; 240150622Srik case T_E3: 241150622Srik case T_T3: 242150622Srik case T_STS1: 243150622Srik cp_e3_timer (d->chan); 244150622Srik break; 245150622Srik default: 246150622Srik break; 247150622Srik } 248150622Srik CP_UNLOCK ((bdrv_t *)d->board->sys); 249150622Srik splx (s); 250150622Srik } 251150622Srik } 252150622Srik s = splimp (); 253150622Srik if (!cp_destroy) 254150622Srik callout_reset (&timeout_handle, hz, cp_timeout, 0); 255150622Srik splx (s); 256150622Srik} 257150622Srik 258150622Srikstatic void cp_led_off (void *arg) 259150622Srik{ 260150622Srik cp_board_t *b = arg; 261150622Srik bdrv_t *bd = (bdrv_t *) b->sys; 262150622Srik int s; 263150622Srik s = splimp (); 264150622Srik if (cp_destroy) { 265150622Srik splx (s); 266150622Srik return; 267150622Srik } 268150622Srik CP_LOCK (bd); 269150622Srik cp_led (b, 0); 270150622Srik CP_UNLOCK (bd); 271150622Srik splx (s); 272150622Srik} 273150622Srik 274150622Srikstatic void cp_intr (void *arg) 275150622Srik{ 276150622Srik bdrv_t *bd = arg; 277150622Srik cp_board_t *b = bd->board; 278150622Srik#ifndef NETGRAPH 279150622Srik int i; 280150622Srik#endif 281150622Srik int s = splimp (); 282150622Srik if (cp_destroy) { 283150622Srik splx (s); 284150622Srik return; 285150622Srik } 286150622Srik CP_LOCK (bd); 287150622Srik /* Check if we are ready */ 288150622Srik if (b->sys == NULL) { 289150622Srik /* Not we are not, just cleanup. */ 290150622Srik cp_interrupt_poll (b, 1); 291150622Srik CP_UNLOCK (bd); 292150622Srik return; 293150622Srik } 294150622Srik /* Turn LED on. */ 295150622Srik cp_led (b, 1); 296150622Srik 297150622Srik cp_interrupt (b); 298150622Srik 299150622Srik /* Turn LED off 50 msec later. */ 300150622Srik callout_reset (&led_timo[b->num], hz/20, cp_led_off, b); 301150622Srik CP_UNLOCK (bd); 302150622Srik splx (s); 303150622Srik 304150622Srik#ifndef NETGRAPH 305150622Srik /* Pass packets in a lock-free state */ 306150622Srik for (i = 0; i < NCHAN && b->chan[i].type; i++) { 307150622Srik drv_t *d = b->chan[i].sys; 308150622Srik struct mbuf *m; 309150622Srik if (!d || !d->running) 310150622Srik continue; 311150622Srik while (_IF_QLEN(&d->queue)) { 312150622Srik IF_DEQUEUE (&d->queue,m); 313150622Srik if (!m) 314150622Srik continue; 315150622Srik sppp_input (d->ifp, m); 316150622Srik } 317150622Srik } 318150622Srik#endif 319150622Srik} 320150622Srik 321150622Srikstatic void 322150622Srikcp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 323150622Srik{ 324150622Srik unsigned long *addr; 325150622Srik 326150622Srik if (error) 327150622Srik return; 328150622Srik 329150622Srik KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 330150622Srik addr = arg; 331150622Srik *addr = segs->ds_addr; 332150622Srik} 333150622Srik 334150622Srikstatic int 335150622Srikcp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 336150622Srik{ 337150622Srik int error; 338150622Srik 339150622Srik error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 340150622Srik BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 341150622Srik dmem->size, 0, NULL, NULL, &dmem->dmat); 342150622Srik if (error) { 343150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 344150622Srik else printf ("cp%d: ", bnum); 345150622Srik printf ("couldn't allocate tag for dma memory\n"); 346150622Srik return 0; 347150622Srik } 348150622Srik error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 349150622Srik BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 350150622Srik if (error) { 351150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 352150622Srik else printf ("cp%d: ", bnum); 353150622Srik printf ("couldn't allocate mem for dma memory\n"); 354150622Srik bus_dma_tag_destroy (dmem->dmat); 355150622Srik return 0; 356150622Srik } 357150622Srik error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 358150622Srik dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); 359150622Srik if (error) { 360150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 361150622Srik else printf ("cp%d: ", bnum); 362150622Srik printf ("couldn't load mem map for dma memory\n"); 363150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 364150622Srik bus_dma_tag_destroy (dmem->dmat); 365150622Srik return 0; 366150622Srik } 367150622Srik return 1; 368150622Srik} 369150622Srik 370150622Srikstatic void 371150622Srikcp_bus_dma_mem_free (cp_dma_mem_t *dmem) 372150622Srik{ 373150622Srik bus_dmamap_unload (dmem->dmat, dmem->mapp); 374150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 375150622Srik bus_dma_tag_destroy (dmem->dmat); 376150622Srik} 377150622Srik 378150622Srik/* 379150622Srik * Called if the probe succeeded. 380150622Srik */ 381150622Srikstatic int cp_attach (device_t dev) 382150622Srik{ 383150622Srik bdrv_t *bd = device_get_softc (dev); 384150622Srik int unit = device_get_unit (dev); 385150622Srik char *cp_ln = CP_LOCK_NAME; 386150622Srik unsigned short res; 387150622Srik vm_offset_t vbase; 388150622Srik int rid, error; 389150622Srik cp_board_t *b; 390150622Srik cp_chan_t *c; 391150622Srik drv_t *d; 392150622Srik int s = splimp (); 393150622Srik 394150622Srik b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 395150622Srik if (!b) { 396150622Srik printf ("cp%d: couldn't allocate memory\n", unit); 397150622Srik splx (s); 398150622Srik return (ENXIO); 399150622Srik } 400150622Srik bzero (b, sizeof(cp_board_t)); 401150622Srik 402150622Srik bd->board = b; 403150622Srik rid = PCIR_BAR(0); 404150622Srik bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 405150622Srik 0, ~0, 1, RF_ACTIVE); 406150622Srik if (! bd->cp_res) { 407150622Srik printf ("cp%d: cannot map memory\n", unit); 408150622Srik free (b, M_DEVBUF); 409150622Srik splx (s); 410150622Srik return (ENXIO); 411150622Srik } 412150622Srik vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 413150622Srik 414150622Srik cp_ln[2] = '0' + unit; 415150622Srik mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 416150622Srik res = cp_init (b, unit, (u_char*) vbase); 417150622Srik if (res) { 418150622Srik printf ("cp%d: can't init, error code:%x\n", unit, res); 419150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 420150622Srik free (b, M_DEVBUF); 421150622Srik splx (s); 422150622Srik return (ENXIO); 423150622Srik } 424150622Srik 425150622Srik bd->dmamem.size = sizeof(cp_qbuf_t); 426150622Srik if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 427150622Srik free (b, M_DEVBUF); 428150622Srik splx (s); 429150622Srik return (ENXIO); 430150622Srik } 431150622Srik CP_LOCK (bd); 432150622Srik cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); 433150622Srik CP_UNLOCK (bd); 434150622Srik 435150622Srik rid = 0; 436150622Srik bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 437150622Srik RF_SHAREABLE | RF_ACTIVE); 438150622Srik if (! bd->cp_irq) { 439150622Srik cp_destroy = 1; 440150622Srik printf ("cp%d: cannot map interrupt\n", unit); 441150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 442150622Srik PCIR_BAR(0), bd->cp_res); 443150622Srik mtx_destroy (&bd->cp_mtx); 444150622Srik free (b, M_DEVBUF); 445150622Srik splx (s); 446150622Srik return (ENXIO); 447150622Srik } 448188661Srwatson callout_init (&led_timo[unit], CALLOUT_MPSAFE); 449150622Srik error = bus_setup_intr (dev, bd->cp_irq, 450188661Srwatson INTR_TYPE_NET|INTR_MPSAFE, 451166901Spiso NULL, cp_intr, bd, &bd->cp_intrhand); 452150622Srik if (error) { 453150622Srik cp_destroy = 1; 454150622Srik printf ("cp%d: cannot set up irq\n", unit); 455150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 456150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 457150622Srik PCIR_BAR(0), bd->cp_res); 458150622Srik mtx_destroy (&bd->cp_mtx); 459150622Srik free (b, M_DEVBUF); 460150622Srik splx (s); 461150622Srik return (ENXIO); 462150622Srik } 463150622Srik printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 464150622Srik 465150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 466150622Srik if (! c->type) 467150622Srik continue; 468150622Srik d = &bd->channel[c->num]; 469150622Srik d->dmamem.size = sizeof(cp_buf_t); 470150622Srik if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 471150622Srik continue; 472150622Srik channel [b->num*NCHAN + c->num] = d; 473150622Srik sprintf (d->name, "cp%d.%d", b->num, c->num); 474150622Srik d->board = b; 475150622Srik d->chan = c; 476150622Srik c->sys = d; 477199407Sjhb callout_init (&d->timeout_handle, CALLOUT_MPSAFE); 478150622Srik#ifdef NETGRAPH 479150622Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 480150622Srik printf ("%s: cannot make common node\n", d->name); 481150622Srik d->node = NULL; 482150622Srik continue; 483150622Srik } 484150622Srik NG_NODE_SET_PRIVATE (d->node, d); 485150622Srik sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 486150622Srik c->board->num*NCHAN + c->num); 487150622Srik if (ng_name_node (d->node, d->nodename)) { 488150622Srik printf ("%s: cannot name node\n", d->nodename); 489150622Srik NG_NODE_UNREF (d->node); 490150622Srik continue; 491150622Srik } 492207554Ssobomax d->queue.ifq_maxlen = ifqmaxlen; 493207554Ssobomax d->hi_queue.ifq_maxlen = ifqmaxlen; 494150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 495150622Srik mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 496150622Srik#else /*NETGRAPH*/ 497150622Srik d->ifp = if_alloc(IFT_PPP); 498150622Srik if (d->ifp == NULL) { 499150622Srik printf ("%s: cannot if_alloc() interface\n", d->name); 500150622Srik continue; 501150622Srik } 502150622Srik d->ifp->if_softc = d; 503150622Srik if_initname (d->ifp, "cp", b->num * NCHAN + c->num); 504150622Srik d->ifp->if_mtu = PP_MTU; 505150622Srik d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 506150622Srik d->ifp->if_ioctl = cp_sioctl; 507150622Srik d->ifp->if_start = cp_ifstart; 508150622Srik d->ifp->if_init = cp_initialize; 509150622Srik d->queue.ifq_maxlen = NRBUF; 510150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 511150622Srik sppp_attach (d->ifp); 512150622Srik if_attach (d->ifp); 513150622Srik IFP2SP(d->ifp)->pp_tlf = cp_tlf; 514150622Srik IFP2SP(d->ifp)->pp_tls = cp_tls; 515150622Srik /* If BPF is in the kernel, call the attach for it. 516150622Srik * The header size of PPP or Cisco/HDLC is 4 bytes. */ 517150622Srik bpfattach (d->ifp, DLT_PPP, 4); 518150622Srik#endif /*NETGRAPH*/ 519150622Srik cp_start_e1 (c); 520150622Srik cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 521150622Srik 522150622Srik /* Register callback functions. */ 523150622Srik cp_register_transmit (c, &cp_transmit); 524150622Srik cp_register_receive (c, &cp_receive); 525150622Srik cp_register_error (c, &cp_error); 526150622Srik d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 527150622Srik GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 528150622Srik } 529150622Srik CP_LOCK (bd); 530150622Srik b->sys = bd; 531150622Srik adapter[unit] = b; 532150622Srik CP_UNLOCK (bd); 533150622Srik splx (s); 534150622Srik return 0; 535150622Srik} 536150622Srik 537150622Srikstatic int cp_detach (device_t dev) 538150622Srik{ 539150622Srik bdrv_t *bd = device_get_softc (dev); 540150622Srik cp_board_t *b = bd->board; 541150622Srik cp_chan_t *c; 542150622Srik int s; 543150622Srik 544150622Srik KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized")); 545150622Srik s = splimp (); 546150622Srik CP_LOCK (bd); 547150622Srik /* Check if the device is busy (open). */ 548150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 549150622Srik drv_t *d = (drv_t*) c->sys; 550150622Srik 551150622Srik if (! d || ! d->chan->type) 552150622Srik continue; 553150622Srik if (d->running) { 554150622Srik CP_UNLOCK (bd); 555150622Srik splx (s); 556150622Srik return EBUSY; 557150622Srik } 558150622Srik } 559150622Srik 560150622Srik /* Ok, we can unload driver */ 561150622Srik /* At first we should stop all channels */ 562150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 563150622Srik drv_t *d = (drv_t*) c->sys; 564150622Srik 565150622Srik if (! d || ! d->chan->type) 566150622Srik continue; 567150622Srik 568150622Srik cp_stop_chan (c); 569150622Srik cp_stop_e1 (c); 570150622Srik cp_set_dtr (d->chan, 0); 571150622Srik cp_set_rts (d->chan, 0); 572150622Srik } 573150622Srik 574150622Srik /* Reset the adapter. */ 575150622Srik cp_destroy = 1; 576150622Srik cp_interrupt_poll (b, 1); 577150622Srik cp_led_off (b); 578150622Srik cp_reset (b, 0 ,0); 579150622Srik callout_stop (&led_timo[b->num]); 580150622Srik 581150624Srik /* Disable the interrupt request. */ 582150624Srik bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 583150624Srik 584150622Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 585150622Srik drv_t *d = (drv_t*) c->sys; 586150622Srik 587150622Srik if (! d || ! d->chan->type) 588150622Srik continue; 589199407Sjhb callout_stop (&d->timeout_handle); 590150622Srik#ifndef NETGRAPH 591150622Srik /* Detach from the packet filter list of interfaces. */ 592150622Srik bpfdetach (d->ifp); 593150622Srik 594150622Srik /* Detach from the sync PPP list. */ 595150622Srik sppp_detach (d->ifp); 596150622Srik 597150622Srik /* Detach from the system list of interfaces. */ 598150622Srik if_detach (d->ifp); 599150622Srik if_free (d->ifp); 600150622Srik IF_DRAIN (&d->queue); 601150622Srik mtx_destroy (&d->queue.ifq_mtx); 602150622Srik#else 603150622Srik if (d->node) { 604150622Srik ng_rmnode_self (d->node); 605150622Srik NG_NODE_UNREF (d->node); 606150622Srik d->node = NULL; 607150622Srik } 608150622Srik mtx_destroy (&d->queue.ifq_mtx); 609150622Srik mtx_destroy (&d->hi_queue.ifq_mtx); 610150622Srik#endif 611150622Srik destroy_dev (d->devt); 612150622Srik } 613150622Srik 614150622Srik b->sys = NULL; 615150622Srik CP_UNLOCK (bd); 616150622Srik 617150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 618150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 619150622Srik 620150622Srik CP_LOCK (bd); 621150622Srik cp_led_off (b); 622150622Srik CP_UNLOCK (bd); 623150622Srik callout_drain (&led_timo[b->num]); 624150622Srik splx (s); 625150622Srik 626150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 627150622Srik drv_t *d = (drv_t*) c->sys; 628150622Srik 629150622Srik if (! d || ! d->chan->type) 630150622Srik continue; 631199407Sjhb callout_drain (&d->timeout_handle); 632150622Srik channel [b->num*NCHAN + c->num] = 0; 633150622Srik /* Deallocate buffers. */ 634150622Srik cp_bus_dma_mem_free (&d->dmamem); 635150622Srik } 636150622Srik adapter [b->num] = 0; 637150622Srik cp_bus_dma_mem_free (&bd->dmamem); 638150622Srik free (b, M_DEVBUF); 639150622Srik mtx_destroy (&bd->cp_mtx); 640150622Srik return 0; 641150622Srik} 642150622Srik 643150622Srik#ifndef NETGRAPH 644150622Srikstatic void cp_ifstart (struct ifnet *ifp) 645150622Srik{ 646150622Srik drv_t *d = ifp->if_softc; 647150622Srik bdrv_t *bd = d->board->sys; 648150622Srik 649150622Srik CP_LOCK (bd); 650150622Srik cp_start (d); 651150622Srik CP_UNLOCK (bd); 652150622Srik} 653150622Srik 654150622Srikstatic void cp_tlf (struct sppp *sp) 655150622Srik{ 656150622Srik drv_t *d = SP2IFP(sp)->if_softc; 657150622Srik 658150622Srik CP_DEBUG2 (d, ("cp_tlf\n")); 659150622Srik /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */ 660150622Srik/* cp_set_dtr (d->chan, 0);*/ 661150622Srik/* cp_set_rts (d->chan, 0);*/ 662150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 663150622Srik sp->pp_down (sp); 664150622Srik} 665150622Srik 666150622Srikstatic void cp_tls (struct sppp *sp) 667150622Srik{ 668150622Srik drv_t *d = SP2IFP(sp)->if_softc; 669150622Srik 670150622Srik CP_DEBUG2 (d, ("cp_tls\n")); 671150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 672150622Srik sp->pp_up (sp); 673150622Srik} 674150622Srik 675150622Srik/* 676150622Srik * Process an ioctl request. 677150622Srik */ 678150622Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 679150622Srik{ 680150622Srik drv_t *d = ifp->if_softc; 681150622Srik bdrv_t *bd = d->board->sys; 682150622Srik int error, s, was_up, should_be_up; 683150622Srik 684150622Srik was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 685150622Srik error = sppp_ioctl (ifp, cmd, data); 686150622Srik 687150622Srik if (error) 688150622Srik return error; 689150622Srik 690150622Srik if (! (ifp->if_flags & IFF_DEBUG)) 691150622Srik d->chan->debug = 0; 692180132Srik else 693180132Srik d->chan->debug = d->chan->debug_shadow; 694150622Srik 695150622Srik switch (cmd) { 696150622Srik default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 697150622Srik case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 698150622Srik case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 699150622Srik case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 700150622Srik case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 701150622Srik } 702150622Srik 703150622Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 704150622Srik s = splimp (); 705150622Srik CP_LOCK (bd); 706150622Srik should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 707150622Srik if (! was_up && should_be_up) { 708150622Srik /* Interface goes up -- start it. */ 709150622Srik cp_up (d); 710150622Srik cp_start (d); 711150622Srik } else if (was_up && ! should_be_up) { 712150622Srik /* Interface is going down -- stop it. */ 713150622Srik/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 714150622Srik cp_down (d); 715150622Srik } 716150622Srik CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 717150622Srik CP_UNLOCK (bd); 718150622Srik splx (s); 719150622Srik return 0; 720150622Srik} 721150622Srik 722150622Srik/* 723150622Srik * Initialization of interface. 724150622Srik * It seems to be never called by upper level? 725150622Srik */ 726150622Srikstatic void cp_initialize (void *softc) 727150622Srik{ 728150622Srik drv_t *d = softc; 729150622Srik 730150622Srik CP_DEBUG (d, ("cp_initialize\n")); 731150622Srik} 732150622Srik#endif /*NETGRAPH*/ 733150622Srik 734150622Srik/* 735150622Srik * Stop the interface. Called on splimp(). 736150622Srik */ 737150622Srikstatic void cp_down (drv_t *d) 738150622Srik{ 739150622Srik CP_DEBUG (d, ("cp_down\n")); 740150622Srik /* Interface is going down -- stop it. */ 741150622Srik cp_set_dtr (d->chan, 0); 742150622Srik cp_set_rts (d->chan, 0); 743150622Srik 744150622Srik d->running = 0; 745199407Sjhb callout_stop (&d->timeout_handle); 746150622Srik} 747150622Srik 748150622Srik/* 749150622Srik * Start the interface. Called on splimp(). 750150622Srik */ 751150622Srikstatic void cp_up (drv_t *d) 752150622Srik{ 753150622Srik CP_DEBUG (d, ("cp_up\n")); 754150622Srik cp_set_dtr (d->chan, 1); 755150622Srik cp_set_rts (d->chan, 1); 756150622Srik d->running = 1; 757150622Srik} 758150622Srik 759150622Srik/* 760150622Srik * Start output on the interface. Get another datagram to send 761150622Srik * off of the interface queue, and copy it to the interface 762150622Srik * before starting the output. 763150622Srik */ 764150622Srikstatic void cp_send (drv_t *d) 765150622Srik{ 766150622Srik struct mbuf *m; 767150622Srik u_short len; 768150622Srik 769150622Srik CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 770150622Srik 771150622Srik /* No output if the interface is down. */ 772150622Srik if (! d->running) 773150622Srik return; 774150622Srik 775150622Srik /* No output if the modem is off. */ 776150622Srik if (! (d->chan->lloop || d->chan->type != T_SERIAL || 777150622Srik cp_get_dsr (d->chan))) 778150622Srik return; 779150622Srik 780150622Srik while (cp_transmit_space (d->chan)) { 781150622Srik /* Get the packet to send. */ 782150622Srik#ifdef NETGRAPH 783150622Srik IF_DEQUEUE (&d->hi_queue, m); 784150622Srik if (! m) 785150622Srik IF_DEQUEUE (&d->queue, m); 786150622Srik#else 787150622Srik m = sppp_dequeue (d->ifp); 788150622Srik#endif 789150622Srik if (! m) 790150622Srik return; 791150622Srik#ifndef NETGRAPH 792165632Sjhb BPF_MTAP (d->ifp, m); 793150622Srik#endif 794150622Srik len = m_length (m, NULL); 795150622Srik if (len >= BUFSZ) 796150622Srik printf ("%s: too long packet: %d bytes: ", 797150622Srik d->name, len); 798150622Srik else if (! m->m_next) 799150622Srik cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 800150622Srik else { 801150622Srik u_char *buf = d->chan->tbuf[d->chan->te]; 802150622Srik m_copydata (m, 0, len, buf); 803150622Srik cp_send_packet (d->chan, buf, len, 0); 804150622Srik } 805150622Srik m_freem (m); 806150622Srik /* Set up transmit timeout, if the transmit ring is not empty.*/ 807150622Srik d->timeout = 10; 808150622Srik } 809150622Srik#ifndef NETGRAPH 810150622Srik d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 811150622Srik#endif 812150622Srik} 813150622Srik 814150622Srik/* 815150622Srik * Start output on the interface. 816150622Srik * Always called on splimp(). 817150622Srik */ 818150622Srikstatic void cp_start (drv_t *d) 819150622Srik{ 820150622Srik if (d->running) { 821150622Srik if (! d->chan->dtr) 822150622Srik cp_set_dtr (d->chan, 1); 823150622Srik if (! d->chan->rts) 824150622Srik cp_set_rts (d->chan, 1); 825150622Srik cp_send (d); 826199407Sjhb callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 827150622Srik } 828150622Srik} 829150622Srik 830150622Srik/* 831150622Srik * Handle transmit timeouts. 832150622Srik * Recover after lost transmit interrupts. 833150622Srik * Always called on splimp(). 834150622Srik */ 835150622Srikstatic void cp_watchdog (drv_t *d) 836150622Srik{ 837150622Srik CP_DEBUG (d, ("device timeout\n")); 838150622Srik if (d->running) { 839150622Srik cp_stop_chan (d->chan); 840150622Srik cp_stop_e1 (d->chan); 841150622Srik cp_start_e1 (d->chan); 842150622Srik cp_start_chan (d->chan, 1, 1, 0, 0); 843150622Srik cp_set_dtr (d->chan, 1); 844150622Srik cp_set_rts (d->chan, 1); 845150622Srik cp_start (d); 846150622Srik } 847150622Srik} 848150622Srik 849199407Sjhbstatic void cp_watchdog_timer (void *arg) 850199407Sjhb{ 851199407Sjhb drv_t *d = arg; 852199407Sjhb bdrv_t *bd = d->board->sys; 853199407Sjhb 854199407Sjhb CP_LOCK (bd); 855199407Sjhb if (d->timeout == 1) 856199407Sjhb cp_watchdog (d); 857199407Sjhb if (d->timeout) 858199407Sjhb d->timeout--; 859199407Sjhb callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 860199407Sjhb CP_UNLOCK (bd); 861199407Sjhb} 862199407Sjhb 863150622Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len) 864150622Srik{ 865150622Srik drv_t *d = c->sys; 866150622Srik 867150622Srik d->timeout = 0; 868199407Sjhb#ifndef NETGRAPH 869271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_OPACKETS, 1); 870150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 871150622Srik#endif 872150622Srik cp_start (d); 873150622Srik} 874150622Srik 875150622Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len) 876150622Srik{ 877150622Srik drv_t *d = c->sys; 878150622Srik struct mbuf *m; 879150622Srik#ifdef NETGRAPH 880150622Srik int error; 881150622Srik#endif 882150622Srik 883150622Srik if (! d->running) 884150622Srik return; 885150622Srik 886150622Srik m = makembuf (data, len); 887150622Srik if (! m) { 888150622Srik CP_DEBUG (d, ("no memory for packet\n")); 889150622Srik#ifndef NETGRAPH 890271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IQDROPS, 1); 891150622Srik#endif 892150622Srik return; 893150622Srik } 894150622Srik if (c->debug > 1) 895271373Srwatson m_print (m, 0); 896150622Srik#ifdef NETGRAPH 897150622Srik m->m_pkthdr.rcvif = 0; 898150622Srik NG_SEND_DATA_ONLY (error, d->hook, m); 899150622Srik#else 900271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IPACKETS, 1); 901150622Srik m->m_pkthdr.rcvif = d->ifp; 902150622Srik /* Check if there's a BPF listener on this interface. 903150622Srik * If so, hand off the raw packet to bpf. */ 904272266Smelifaro BPF_MTAP(d->ifp, m); 905150622Srik IF_ENQUEUE (&d->queue, m); 906150622Srik#endif 907150622Srik} 908150622Srik 909150622Srikstatic void cp_error (cp_chan_t *c, int data) 910150622Srik{ 911150622Srik drv_t *d = c->sys; 912150622Srik 913150622Srik switch (data) { 914150622Srik case CP_FRAME: 915150622Srik CP_DEBUG (d, ("frame error\n")); 916150622Srik#ifndef NETGRAPH 917271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 918150622Srik#endif 919150622Srik break; 920150622Srik case CP_CRC: 921150622Srik CP_DEBUG (d, ("crc error\n")); 922150622Srik#ifndef NETGRAPH 923271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 924150622Srik#endif 925150622Srik break; 926150622Srik case CP_OVERRUN: 927150622Srik CP_DEBUG (d, ("overrun error\n")); 928150622Srik#ifndef NETGRAPH 929271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_COLLISIONS, 1); 930271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 931150622Srik#endif 932150622Srik break; 933150622Srik case CP_OVERFLOW: 934150622Srik CP_DEBUG (d, ("overflow error\n")); 935150622Srik#ifndef NETGRAPH 936271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 937150622Srik#endif 938150622Srik break; 939150622Srik case CP_UNDERRUN: 940150622Srik CP_DEBUG (d, ("underrun error\n")); 941150622Srik d->timeout = 0; 942199407Sjhb#ifndef NETGRAPH 943271849Sglebius if_inc_counter(d->ifp, IFCOUNTER_OERRORS, 1); 944150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 945150622Srik#endif 946150622Srik cp_start (d); 947150622Srik break; 948150622Srik default: 949150622Srik CP_DEBUG (d, ("error #%d\n", data)); 950150622Srik break; 951150622Srik } 952150622Srik} 953150622Srik 954150622Srik/* 955128967Srik * You also need read, write, open, close routines. 956128967Srik * This should get you started 957128967Srik */ 958130585Sphkstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 959128967Srik{ 960183397Sed int unit = dev2unit (dev); 961128967Srik drv_t *d; 962128967Srik 963128967Srik if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 964128967Srik return ENXIO; 965128967Srik CP_DEBUG2 (d, ("cp_open\n")); 966128967Srik return 0; 967128967Srik} 968128967Srik 969128967Srik/* 970128967Srik * Only called on the LAST close. 971128967Srik */ 972130585Sphkstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 973128967Srik{ 974183397Sed drv_t *d = channel [dev2unit (dev)]; 975128967Srik 976128967Srik CP_DEBUG2 (d, ("cp_close\n")); 977128967Srik return 0; 978128967Srik} 979128967Srik 980128967Srikstatic int cp_modem_status (cp_chan_t *c) 981128967Srik{ 982128967Srik drv_t *d = c->sys; 983138823Srik bdrv_t *bd = d->board->sys; 984128967Srik int status, s; 985128967Srik 986128967Srik status = d->running ? TIOCM_LE : 0; 987128967Srik s = splimp (); 988138823Srik CP_LOCK (bd); 989128967Srik if (cp_get_cd (c)) status |= TIOCM_CD; 990128967Srik if (cp_get_cts (c)) status |= TIOCM_CTS; 991128967Srik if (cp_get_dsr (c)) status |= TIOCM_DSR; 992128967Srik if (c->dtr) status |= TIOCM_DTR; 993128967Srik if (c->rts) status |= TIOCM_RTS; 994138823Srik CP_UNLOCK (bd); 995128967Srik splx (s); 996128967Srik return status; 997128967Srik} 998128967Srik 999130585Sphkstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1000128967Srik{ 1001183397Sed drv_t *d = channel [dev2unit (dev)]; 1002138823Srik bdrv_t *bd = d->board->sys; 1003128967Srik cp_chan_t *c = d->chan; 1004128967Srik struct serial_statistics *st; 1005128967Srik struct e1_statistics *opte1; 1006128967Srik struct e3_statistics *opte3; 1007128967Srik int error, s; 1008128967Srik char mask[16]; 1009128967Srik 1010128967Srik switch (cmd) { 1011128967Srik case SERIAL_GETREGISTERED: 1012133646Srik CP_DEBUG2 (d, ("ioctl: getregistered\n")); 1013128967Srik bzero (mask, sizeof(mask)); 1014128967Srik for (s=0; s<NBRD*NCHAN; ++s) 1015128967Srik if (channel [s]) 1016128967Srik mask [s/8] |= 1 << (s & 7); 1017133646Srik bcopy (mask, data, sizeof (mask)); 1018128967Srik return 0; 1019128967Srik 1020128967Srik#ifndef NETGRAPH 1021128967Srik case SERIAL_GETPROTO: 1022133646Srik CP_DEBUG2 (d, ("ioctl: getproto\n")); 1023147256Sbrooks strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1024147256Sbrooks (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1025133646Srik return 0; 1026128967Srik 1027128967Srik case SERIAL_SETPROTO: 1028133646Srik CP_DEBUG2 (d, ("ioctl: setproto\n")); 1029133646Srik /* Only for superuser! */ 1030164033Srwatson error = priv_check (td, PRIV_DRIVER); 1031133646Srik if (error) 1032133646Srik return error; 1033148887Srwatson if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) 1034128967Srik return EBUSY; 1035133646Srik if (! strcmp ("cisco", (char*)data)) { 1036147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1037147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1038147256Sbrooks d->ifp->if_flags |= PP_CISCO; 1039228963Sdim#if PP_FR != 0 1040228963Sdim } else if (! strcmp ("fr", (char*)data)) { 1041147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1042147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1043228963Sdim#endif 1044133646Srik } else if (! strcmp ("ppp", (char*)data)) { 1045147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_FR; 1046147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1047147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1048133646Srik } else 1049128967Srik return EINVAL; 1050133646Srik return 0; 1051128967Srik 1052128967Srik case SERIAL_GETKEEPALIVE: 1053133646Srik CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1054147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1055147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1056128967Srik return EINVAL; 1057147256Sbrooks *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1058133646Srik return 0; 1059128967Srik 1060128967Srik case SERIAL_SETKEEPALIVE: 1061133646Srik CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1062133646Srik /* Only for superuser! */ 1063164033Srwatson error = priv_check (td, PRIV_DRIVER); 1064133646Srik if (error) 1065133646Srik return error; 1066147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1067147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1068128967Srik return EINVAL; 1069128967Srik s = splimp (); 1070138823Srik CP_LOCK (bd); 1071133646Srik if (*(int*)data) 1072147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1073128967Srik else 1074147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1075138823Srik CP_UNLOCK (bd); 1076128967Srik splx (s); 1077133646Srik return 0; 1078128967Srik#endif /*NETGRAPH*/ 1079128967Srik 1080128967Srik case SERIAL_GETMODE: 1081133646Srik CP_DEBUG2 (d, ("ioctl: getmode\n")); 1082128967Srik *(int*)data = SERIAL_HDLC; 1083133646Srik return 0; 1084128967Srik 1085128967Srik case SERIAL_SETMODE: 1086133646Srik /* Only for superuser! */ 1087164033Srwatson error = priv_check (td, PRIV_DRIVER); 1088133646Srik if (error) 1089133646Srik return error; 1090128967Srik if (*(int*)data != SERIAL_HDLC) 1091128967Srik return EINVAL; 1092133646Srik return 0; 1093128967Srik 1094128967Srik case SERIAL_GETCFG: 1095133646Srik CP_DEBUG2 (d, ("ioctl: getcfg\n")); 1096128967Srik if (c->type != T_E1 || c->unfram) 1097128967Srik return EINVAL; 1098128967Srik *(char*)data = c->board->mux ? 'c' : 'a'; 1099133646Srik return 0; 1100128967Srik 1101128967Srik case SERIAL_SETCFG: 1102133646Srik CP_DEBUG2 (d, ("ioctl: setcfg\n")); 1103164033Srwatson error = priv_check (td, PRIV_DRIVER); 1104133646Srik if (error) 1105133646Srik return error; 1106128967Srik if (c->type != T_E1) 1107128967Srik return EINVAL; 1108133646Srik s = splimp (); 1109138823Srik CP_LOCK (bd); 1110128967Srik cp_set_mux (c->board, *((char*)data) == 'c'); 1111138823Srik CP_UNLOCK (bd); 1112133646Srik splx (s); 1113133646Srik return 0; 1114128967Srik 1115128967Srik case SERIAL_GETSTAT: 1116133646Srik CP_DEBUG2 (d, ("ioctl: getstat\n")); 1117133646Srik st = (struct serial_statistics*) data; 1118133646Srik st->rintr = c->rintr; 1119133646Srik st->tintr = c->tintr; 1120133646Srik st->mintr = 0; 1121133646Srik st->ibytes = c->ibytes; 1122133646Srik st->ipkts = c->ipkts; 1123133646Srik st->obytes = c->obytes; 1124133646Srik st->opkts = c->opkts; 1125128967Srik st->ierrs = c->overrun + c->frame + c->crc; 1126128967Srik st->oerrs = c->underrun; 1127133646Srik return 0; 1128128967Srik 1129128967Srik case SERIAL_GETESTAT: 1130133646Srik CP_DEBUG2 (d, ("ioctl: getestat\n")); 1131128967Srik if (c->type != T_E1 && c->type != T_G703) 1132128967Srik return EINVAL; 1133128967Srik opte1 = (struct e1_statistics*) data; 1134128967Srik opte1->status = c->status; 1135128967Srik opte1->cursec = c->cursec; 1136128967Srik opte1->totsec = c->totsec + c->cursec; 1137128967Srik 1138128967Srik opte1->currnt.bpv = c->currnt.bpv; 1139128967Srik opte1->currnt.fse = c->currnt.fse; 1140128967Srik opte1->currnt.crce = c->currnt.crce; 1141128967Srik opte1->currnt.rcrce = c->currnt.rcrce; 1142128967Srik opte1->currnt.uas = c->currnt.uas; 1143128967Srik opte1->currnt.les = c->currnt.les; 1144128967Srik opte1->currnt.es = c->currnt.es; 1145128967Srik opte1->currnt.bes = c->currnt.bes; 1146128967Srik opte1->currnt.ses = c->currnt.ses; 1147128967Srik opte1->currnt.oofs = c->currnt.oofs; 1148128967Srik opte1->currnt.css = c->currnt.css; 1149128967Srik opte1->currnt.dm = c->currnt.dm; 1150128967Srik 1151128967Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1152128967Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1153128967Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1154128967Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1155128967Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1156128967Srik opte1->total.les = c->total.les + c->currnt.les; 1157128967Srik opte1->total.es = c->total.es + c->currnt.es; 1158128967Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1159128967Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1160128967Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1161128967Srik opte1->total.css = c->total.css + c->currnt.css; 1162128967Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1163128967Srik for (s=0; s<48; ++s) { 1164128967Srik opte1->interval[s].bpv = c->interval[s].bpv; 1165128967Srik opte1->interval[s].fse = c->interval[s].fse; 1166128967Srik opte1->interval[s].crce = c->interval[s].crce; 1167128967Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1168128967Srik opte1->interval[s].uas = c->interval[s].uas; 1169128967Srik opte1->interval[s].les = c->interval[s].les; 1170128967Srik opte1->interval[s].es = c->interval[s].es; 1171128967Srik opte1->interval[s].bes = c->interval[s].bes; 1172128967Srik opte1->interval[s].ses = c->interval[s].ses; 1173128967Srik opte1->interval[s].oofs = c->interval[s].oofs; 1174128967Srik opte1->interval[s].css = c->interval[s].css; 1175128967Srik opte1->interval[s].dm = c->interval[s].dm; 1176128967Srik } 1177128967Srik return 0; 1178128967Srik 1179128967Srik case SERIAL_GETE3STAT: 1180133646Srik CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 1181128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1182128967Srik return EINVAL; 1183133646Srik opte3 = (struct e3_statistics*) data; 1184128967Srik 1185128967Srik opte3->status = c->e3status; 1186128967Srik opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 1187128967Srik opte3->totsec = c->e3tsec + opte3->cursec; 1188128967Srik 1189128967Srik opte3->ccv = c->e3ccv; 1190128967Srik opte3->tcv = c->e3tcv + opte3->ccv; 1191128967Srik 1192128967Srik for (s = 0; s < 48; ++s) { 1193128967Srik opte3->icv[s] = c->e3icv[s]; 1194128967Srik } 1195133646Srik return 0; 1196128967Srik 1197128967Srik case SERIAL_CLRSTAT: 1198133646Srik CP_DEBUG2 (d, ("ioctl: clrstat\n")); 1199133646Srik /* Only for superuser! */ 1200164033Srwatson error = priv_check (td, PRIV_DRIVER); 1201133646Srik if (error) 1202133646Srik return error; 1203128967Srik c->rintr = 0; 1204128967Srik c->tintr = 0; 1205128967Srik c->ibytes = 0; 1206128967Srik c->obytes = 0; 1207128967Srik c->ipkts = 0; 1208128967Srik c->opkts = 0; 1209128967Srik c->overrun = 0; 1210128967Srik c->frame = 0; 1211133646Srik c->crc = 0; 1212128967Srik c->underrun = 0; 1213128967Srik bzero (&c->currnt, sizeof (c->currnt)); 1214128967Srik bzero (&c->total, sizeof (c->total)); 1215128967Srik bzero (c->interval, sizeof (c->interval)); 1216128967Srik c->e3ccv = 0; 1217128967Srik c->e3tcv = 0; 1218128967Srik bzero (c->e3icv, sizeof (c->e3icv)); 1219133646Srik return 0; 1220128967Srik 1221128967Srik case SERIAL_GETBAUD: 1222133646Srik CP_DEBUG2 (d, ("ioctl: getbaud\n")); 1223133646Srik *(long*)data = c->baud; 1224133646Srik return 0; 1225128967Srik 1226128967Srik case SERIAL_SETBAUD: 1227133646Srik CP_DEBUG2 (d, ("ioctl: setbaud\n")); 1228133646Srik /* Only for superuser! */ 1229164033Srwatson error = priv_check (td, PRIV_DRIVER); 1230133646Srik if (error) 1231133646Srik return error; 1232133646Srik s = splimp (); 1233138823Srik CP_LOCK (bd); 1234133646Srik cp_set_baud (c, *(long*)data); 1235138823Srik CP_UNLOCK (bd); 1236133646Srik splx (s); 1237133646Srik return 0; 1238128967Srik 1239128967Srik case SERIAL_GETLOOP: 1240133646Srik CP_DEBUG2 (d, ("ioctl: getloop\n")); 1241133646Srik *(int*)data = c->lloop; 1242133646Srik return 0; 1243128967Srik 1244128967Srik case SERIAL_SETLOOP: 1245133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1246133646Srik /* Only for superuser! */ 1247164033Srwatson error = priv_check (td, PRIV_DRIVER); 1248133646Srik if (error) 1249133646Srik return error; 1250133646Srik s = splimp (); 1251138823Srik CP_LOCK (bd); 1252128967Srik cp_set_lloop (c, *(int*)data); 1253138823Srik CP_UNLOCK (bd); 1254133646Srik splx (s); 1255133646Srik return 0; 1256128967Srik 1257128967Srik case SERIAL_GETDPLL: 1258133646Srik CP_DEBUG2 (d, ("ioctl: getdpll\n")); 1259133646Srik if (c->type != T_SERIAL) 1260133646Srik return EINVAL; 1261133646Srik *(int*)data = c->dpll; 1262133646Srik return 0; 1263128967Srik 1264128967Srik case SERIAL_SETDPLL: 1265133646Srik CP_DEBUG2 (d, ("ioctl: setdpll\n")); 1266133646Srik /* Only for superuser! */ 1267164033Srwatson error = priv_check (td, PRIV_DRIVER); 1268133646Srik if (error) 1269133646Srik return error; 1270133646Srik if (c->type != T_SERIAL) 1271133646Srik return EINVAL; 1272133646Srik s = splimp (); 1273138823Srik CP_LOCK (bd); 1274133646Srik cp_set_dpll (c, *(int*)data); 1275138823Srik CP_UNLOCK (bd); 1276133646Srik splx (s); 1277133646Srik return 0; 1278128967Srik 1279128967Srik case SERIAL_GETNRZI: 1280133646Srik CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 1281133646Srik if (c->type != T_SERIAL) 1282133646Srik return EINVAL; 1283133646Srik *(int*)data = c->nrzi; 1284133646Srik return 0; 1285128967Srik 1286128967Srik case SERIAL_SETNRZI: 1287133646Srik CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 1288133646Srik /* Only for superuser! */ 1289164033Srwatson error = priv_check (td, PRIV_DRIVER); 1290133646Srik if (error) 1291133646Srik return error; 1292133646Srik if (c->type != T_SERIAL) 1293133646Srik return EINVAL; 1294133646Srik s = splimp (); 1295138823Srik CP_LOCK (bd); 1296133646Srik cp_set_nrzi (c, *(int*)data); 1297138823Srik CP_UNLOCK (bd); 1298133646Srik splx (s); 1299133646Srik return 0; 1300128967Srik 1301128967Srik case SERIAL_GETDEBUG: 1302133646Srik CP_DEBUG2 (d, ("ioctl: getdebug\n")); 1303133646Srik *(int*)data = d->chan->debug; 1304133646Srik return 0; 1305128967Srik 1306128967Srik case SERIAL_SETDEBUG: 1307133646Srik CP_DEBUG2 (d, ("ioctl: setdebug\n")); 1308133646Srik /* Only for superuser! */ 1309164033Srwatson error = priv_check (td, PRIV_DRIVER); 1310133646Srik if (error) 1311133646Srik return error; 1312180132Srik#ifndef NETGRAPH 1313180132Srik /* 1314180132Srik * The debug_shadow is always greater than zero for logic 1315180132Srik * simplicity. For switching debug off the IFF_DEBUG is 1316180132Srik * responsible. 1317180132Srik */ 1318180132Srik d->chan->debug_shadow = (*(int*)data) ? (*(int*)data) : 1; 1319180132Srik if (d->ifp->if_flags & IFF_DEBUG) 1320180132Srik d->chan->debug = d->chan->debug_shadow; 1321180132Srik#else 1322133646Srik d->chan->debug = *(int*)data; 1323128967Srik#endif 1324133646Srik return 0; 1325128967Srik 1326128967Srik case SERIAL_GETHIGAIN: 1327133646Srik CP_DEBUG2 (d, ("ioctl: gethigain\n")); 1328133646Srik if (c->type != T_E1) 1329133646Srik return EINVAL; 1330133646Srik *(int*)data = c->higain; 1331128967Srik return 0; 1332128967Srik 1333128967Srik case SERIAL_SETHIGAIN: 1334133646Srik CP_DEBUG2 (d, ("ioctl: sethigain\n")); 1335133646Srik /* Only for superuser! */ 1336164033Srwatson error = priv_check (td, PRIV_DRIVER); 1337133646Srik if (error) 1338133646Srik return error; 1339133646Srik if (c->type != T_E1) 1340133646Srik return EINVAL; 1341128967Srik s = splimp (); 1342138823Srik CP_LOCK (bd); 1343128967Srik cp_set_higain (c, *(int*)data); 1344138823Srik CP_UNLOCK (bd); 1345128967Srik splx (s); 1346128967Srik return 0; 1347128967Srik 1348128967Srik case SERIAL_GETPHONY: 1349128967Srik CP_DEBUG2 (d, ("ioctl: getphony\n")); 1350133646Srik if (c->type != T_E1) 1351133646Srik return EINVAL; 1352133646Srik *(int*)data = c->phony; 1353128967Srik return 0; 1354128967Srik 1355128967Srik case SERIAL_SETPHONY: 1356128967Srik CP_DEBUG2 (d, ("ioctl: setphony\n")); 1357133646Srik /* Only for superuser! */ 1358164033Srwatson error = priv_check (td, PRIV_DRIVER); 1359133646Srik if (error) 1360133646Srik return error; 1361133646Srik if (c->type != T_E1) 1362133646Srik return EINVAL; 1363128967Srik s = splimp (); 1364138823Srik CP_LOCK (bd); 1365128967Srik cp_set_phony (c, *(int*)data); 1366138823Srik CP_UNLOCK (bd); 1367128967Srik splx (s); 1368128967Srik return 0; 1369128967Srik 1370128967Srik case SERIAL_GETUNFRAM: 1371128967Srik CP_DEBUG2 (d, ("ioctl: getunfram\n")); 1372133646Srik if (c->type != T_E1) 1373133646Srik return EINVAL; 1374133646Srik *(int*)data = c->unfram; 1375128967Srik return 0; 1376128967Srik 1377128967Srik case SERIAL_SETUNFRAM: 1378128967Srik CP_DEBUG2 (d, ("ioctl: setunfram\n")); 1379133646Srik /* Only for superuser! */ 1380164033Srwatson error = priv_check (td, PRIV_DRIVER); 1381133646Srik if (error) 1382133646Srik return error; 1383133646Srik if (c->type != T_E1) 1384133646Srik return EINVAL; 1385128967Srik s = splimp (); 1386138823Srik CP_LOCK (bd); 1387128967Srik cp_set_unfram (c, *(int*)data); 1388138823Srik CP_UNLOCK (bd); 1389128967Srik splx (s); 1390128967Srik return 0; 1391128967Srik 1392128967Srik case SERIAL_GETSCRAMBLER: 1393128967Srik CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 1394133646Srik if (c->type != T_G703 && !c->unfram) 1395133646Srik return EINVAL; 1396133646Srik *(int*)data = c->scrambler; 1397128967Srik return 0; 1398128967Srik 1399128967Srik case SERIAL_SETSCRAMBLER: 1400128967Srik CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 1401133646Srik /* Only for superuser! */ 1402164033Srwatson error = priv_check (td, PRIV_DRIVER); 1403133646Srik if (error) 1404133646Srik return error; 1405133646Srik if (c->type != T_G703 && !c->unfram) 1406133646Srik return EINVAL; 1407128967Srik s = splimp (); 1408138823Srik CP_LOCK (bd); 1409128967Srik cp_set_scrambler (c, *(int*)data); 1410138823Srik CP_UNLOCK (bd); 1411128967Srik splx (s); 1412128967Srik return 0; 1413128967Srik 1414128967Srik case SERIAL_GETMONITOR: 1415128967Srik CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 1416133646Srik if (c->type != T_E1 && 1417128967Srik c->type != T_E3 && 1418128967Srik c->type != T_T3 && 1419128967Srik c->type != T_STS1) 1420133646Srik return EINVAL; 1421133646Srik *(int*)data = c->monitor; 1422128967Srik return 0; 1423128967Srik 1424128967Srik case SERIAL_SETMONITOR: 1425128967Srik CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 1426133646Srik /* Only for superuser! */ 1427164033Srwatson error = priv_check (td, PRIV_DRIVER); 1428133646Srik if (error) 1429133646Srik return error; 1430133646Srik if (c->type != T_E1) 1431133646Srik return EINVAL; 1432128967Srik s = splimp (); 1433138823Srik CP_LOCK (bd); 1434128967Srik cp_set_monitor (c, *(int*)data); 1435138823Srik CP_UNLOCK (bd); 1436128967Srik splx (s); 1437128967Srik return 0; 1438128967Srik 1439128967Srik case SERIAL_GETUSE16: 1440133646Srik CP_DEBUG2 (d, ("ioctl: getuse16\n")); 1441133646Srik if (c->type != T_E1 || c->unfram) 1442133646Srik return EINVAL; 1443133646Srik *(int*)data = c->use16; 1444128967Srik return 0; 1445128967Srik 1446128967Srik case SERIAL_SETUSE16: 1447133646Srik CP_DEBUG2 (d, ("ioctl: setuse16\n")); 1448133646Srik /* Only for superuser! */ 1449164033Srwatson error = priv_check (td, PRIV_DRIVER); 1450133646Srik if (error) 1451133646Srik return error; 1452133646Srik if (c->type != T_E1) 1453133646Srik return EINVAL; 1454128967Srik s = splimp (); 1455138823Srik CP_LOCK (bd); 1456128967Srik cp_set_use16 (c, *(int*)data); 1457138823Srik CP_UNLOCK (bd); 1458128967Srik splx (s); 1459128967Srik return 0; 1460128967Srik 1461128967Srik case SERIAL_GETCRC4: 1462133646Srik CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 1463133646Srik if (c->type != T_E1 || c->unfram) 1464133646Srik return EINVAL; 1465133646Srik *(int*)data = c->crc4; 1466128967Srik return 0; 1467128967Srik 1468128967Srik case SERIAL_SETCRC4: 1469133646Srik CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 1470133646Srik /* Only for superuser! */ 1471164033Srwatson error = priv_check (td, PRIV_DRIVER); 1472133646Srik if (error) 1473133646Srik return error; 1474133646Srik if (c->type != T_E1) 1475133646Srik return EINVAL; 1476128967Srik s = splimp (); 1477138823Srik CP_LOCK (bd); 1478128967Srik cp_set_crc4 (c, *(int*)data); 1479138823Srik CP_UNLOCK (bd); 1480128967Srik splx (s); 1481128967Srik return 0; 1482128967Srik 1483128967Srik case SERIAL_GETCLK: 1484133646Srik CP_DEBUG2 (d, ("ioctl: getclk\n")); 1485133646Srik if (c->type != T_E1 && 1486128967Srik c->type != T_G703 && 1487128967Srik c->type != T_E3 && 1488128967Srik c->type != T_T3 && 1489128967Srik c->type != T_STS1) 1490133646Srik return EINVAL; 1491128967Srik switch (c->gsyn) { 1492128967Srik default: *(int*)data = E1CLK_INTERNAL; break; 1493128967Srik case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1494128967Srik case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1495128967Srik case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1496128967Srik case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 1497128967Srik case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 1498128967Srik } 1499128967Srik return 0; 1500128967Srik 1501128967Srik case SERIAL_SETCLK: 1502133646Srik CP_DEBUG2 (d, ("ioctl: setclk\n")); 1503133646Srik /* Only for superuser! */ 1504164033Srwatson error = priv_check (td, PRIV_DRIVER); 1505133646Srik if (error) 1506133646Srik return error; 1507128967Srik if (c->type != T_E1 && 1508128967Srik c->type != T_G703 && 1509128967Srik c->type != T_E3 && 1510128967Srik c->type != T_T3 && 1511128967Srik c->type != T_STS1) 1512133646Srik return EINVAL; 1513128967Srik s = splimp (); 1514138823Srik CP_LOCK (bd); 1515128967Srik switch (*(int*)data) { 1516128967Srik default: cp_set_gsyn (c, GSYN_INT); break; 1517128967Srik case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 1518128967Srik case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 1519128967Srik case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 1520128967Srik case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 1521128967Srik case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 1522128967Srik } 1523138823Srik CP_UNLOCK (bd); 1524128967Srik splx (s); 1525128967Srik return 0; 1526128967Srik 1527128967Srik case SERIAL_GETTIMESLOTS: 1528133646Srik CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1529133646Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1530133646Srik return EINVAL; 1531133646Srik *(u_long*)data = c->ts; 1532128967Srik return 0; 1533128967Srik 1534128967Srik case SERIAL_SETTIMESLOTS: 1535133646Srik CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 1536133646Srik /* Only for superuser! */ 1537164033Srwatson error = priv_check (td, PRIV_DRIVER); 1538133646Srik if (error) 1539133646Srik return error; 1540128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1541133646Srik return EINVAL; 1542128967Srik s = splimp (); 1543138823Srik CP_LOCK (bd); 1544128967Srik cp_set_ts (c, *(u_long*)data); 1545138823Srik CP_UNLOCK (bd); 1546128967Srik splx (s); 1547128967Srik return 0; 1548128967Srik 1549128967Srik case SERIAL_GETINVCLK: 1550133646Srik CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 1551128967Srik#if 1 1552128967Srik return EINVAL; 1553128967Srik#else 1554133646Srik if (c->type != T_SERIAL) 1555133646Srik return EINVAL; 1556133646Srik *(int*)data = c->invtxc; 1557128967Srik return 0; 1558128967Srik#endif 1559128967Srik 1560128967Srik case SERIAL_SETINVCLK: 1561133646Srik CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 1562133646Srik /* Only for superuser! */ 1563164033Srwatson error = priv_check (td, PRIV_DRIVER); 1564133646Srik if (error) 1565133646Srik return error; 1566133646Srik if (c->type != T_SERIAL) 1567133646Srik return EINVAL; 1568128967Srik s = splimp (); 1569138823Srik CP_LOCK (bd); 1570128967Srik cp_set_invtxc (c, *(int*)data); 1571128967Srik cp_set_invrxc (c, *(int*)data); 1572138823Srik CP_UNLOCK (bd); 1573128967Srik splx (s); 1574128967Srik return 0; 1575128967Srik 1576128967Srik case SERIAL_GETINVTCLK: 1577133646Srik CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 1578133646Srik if (c->type != T_SERIAL) 1579133646Srik return EINVAL; 1580133646Srik *(int*)data = c->invtxc; 1581128967Srik return 0; 1582128967Srik 1583128967Srik case SERIAL_SETINVTCLK: 1584133646Srik CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 1585133646Srik /* Only for superuser! */ 1586164033Srwatson error = priv_check (td, PRIV_DRIVER); 1587133646Srik if (error) 1588133646Srik return error; 1589133646Srik if (c->type != T_SERIAL) 1590133646Srik return EINVAL; 1591128967Srik s = splimp (); 1592138823Srik CP_LOCK (bd); 1593128967Srik cp_set_invtxc (c, *(int*)data); 1594138823Srik CP_UNLOCK (bd); 1595128967Srik splx (s); 1596128967Srik return 0; 1597128967Srik 1598128967Srik case SERIAL_GETINVRCLK: 1599133646Srik CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 1600133646Srik if (c->type != T_SERIAL) 1601133646Srik return EINVAL; 1602133646Srik *(int*)data = c->invrxc; 1603128967Srik return 0; 1604128967Srik 1605128967Srik case SERIAL_SETINVRCLK: 1606133646Srik CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 1607133646Srik /* Only for superuser! */ 1608164033Srwatson error = priv_check (td, PRIV_DRIVER); 1609133646Srik if (error) 1610133646Srik return error; 1611133646Srik if (c->type != T_SERIAL) 1612133646Srik return EINVAL; 1613128967Srik s = splimp (); 1614138823Srik CP_LOCK (bd); 1615128967Srik cp_set_invrxc (c, *(int*)data); 1616138823Srik CP_UNLOCK (bd); 1617128967Srik splx (s); 1618128967Srik return 0; 1619128967Srik 1620128967Srik case SERIAL_GETLEVEL: 1621133646Srik CP_DEBUG2 (d, ("ioctl: getlevel\n")); 1622133646Srik if (c->type != T_G703) 1623133646Srik return EINVAL; 1624128967Srik s = splimp (); 1625138823Srik CP_LOCK (bd); 1626133646Srik *(int*)data = cp_get_lq (c); 1627138823Srik CP_UNLOCK (bd); 1628128967Srik splx (s); 1629128967Srik return 0; 1630128967Srik 1631128967Srik#if 0 1632128967Srik case SERIAL_RESET: 1633133646Srik CP_DEBUG2 (d, ("ioctl: reset\n")); 1634133646Srik /* Only for superuser! */ 1635164033Srwatson error = priv_check (td, PRIV_DRIVER); 1636133646Srik if (error) 1637133646Srik return error; 1638128967Srik s = splimp (); 1639138823Srik CP_LOCK (bd); 1640128967Srik cp_reset (c->board, 0, 0); 1641138823Srik CP_UNLOCK (bd); 1642128967Srik splx (s); 1643128967Srik return 0; 1644128967Srik 1645128967Srik case SERIAL_HARDRESET: 1646133646Srik CP_DEBUG2 (d, ("ioctl: hardreset\n")); 1647133646Srik /* Only for superuser! */ 1648164033Srwatson error = priv_check (td, PRIV_DRIVER); 1649133646Srik if (error) 1650133646Srik return error; 1651128967Srik s = splimp (); 1652138823Srik CP_LOCK (bd); 1653128967Srik /* hard_reset (c->board); */ 1654138823Srik CP_UNLOCK (bd); 1655128967Srik splx (s); 1656128967Srik return 0; 1657128967Srik#endif 1658128967Srik 1659128967Srik case SERIAL_GETCABLE: 1660133646Srik CP_DEBUG2 (d, ("ioctl: getcable\n")); 1661133646Srik if (c->type != T_SERIAL) 1662133646Srik return EINVAL; 1663128967Srik s = splimp (); 1664138823Srik CP_LOCK (bd); 1665128967Srik *(int*)data = cp_get_cable (c); 1666138823Srik CP_UNLOCK (bd); 1667128967Srik splx (s); 1668128967Srik return 0; 1669128967Srik 1670128967Srik case SERIAL_GETDIR: 1671133646Srik CP_DEBUG2 (d, ("ioctl: getdir\n")); 1672133646Srik if (c->type != T_E1 && c->type != T_DATA) 1673133646Srik return EINVAL; 1674128967Srik *(int*)data = c->dir; 1675128967Srik return 0; 1676128967Srik 1677128967Srik case SERIAL_SETDIR: 1678133646Srik CP_DEBUG2 (d, ("ioctl: setdir\n")); 1679133646Srik /* Only for superuser! */ 1680164033Srwatson error = priv_check (td, PRIV_DRIVER); 1681133646Srik if (error) 1682133646Srik return error; 1683128967Srik s = splimp (); 1684138823Srik CP_LOCK (bd); 1685128967Srik cp_set_dir (c, *(int*)data); 1686138823Srik CP_UNLOCK (bd); 1687128967Srik splx (s); 1688128967Srik return 0; 1689128967Srik 1690128967Srik case SERIAL_GETRLOOP: 1691133646Srik CP_DEBUG2 (d, ("ioctl: getrloop\n")); 1692133646Srik if (c->type != T_G703 && 1693128967Srik c->type != T_E3 && 1694128967Srik c->type != T_T3 && 1695128967Srik c->type != T_STS1) 1696133646Srik return EINVAL; 1697133646Srik *(int*)data = cp_get_rloop (c); 1698133646Srik return 0; 1699128967Srik 1700128967Srik case SERIAL_SETRLOOP: 1701133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1702133646Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1703133646Srik return EINVAL; 1704133646Srik /* Only for superuser! */ 1705164033Srwatson error = priv_check (td, PRIV_DRIVER); 1706133646Srik if (error) 1707133646Srik return error; 1708133646Srik s = splimp (); 1709138823Srik CP_LOCK (bd); 1710128967Srik cp_set_rloop (c, *(int*)data); 1711138823Srik CP_UNLOCK (bd); 1712133646Srik splx (s); 1713133646Srik return 0; 1714128967Srik 1715128967Srik case SERIAL_GETCABLEN: 1716133646Srik CP_DEBUG2 (d, ("ioctl: getcablen\n")); 1717133646Srik if (c->type != T_T3 && c->type != T_STS1) 1718133646Srik return EINVAL; 1719133646Srik *(int*)data = c->cablen; 1720133646Srik return 0; 1721128967Srik 1722128967Srik case SERIAL_SETCABLEN: 1723133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1724133646Srik if (c->type != T_T3 && c->type != T_STS1) 1725133646Srik return EINVAL; 1726133646Srik /* Only for superuser! */ 1727164033Srwatson error = priv_check (td, PRIV_DRIVER); 1728133646Srik if (error) 1729133646Srik return error; 1730133646Srik s = splimp (); 1731138823Srik CP_LOCK (bd); 1732128967Srik cp_set_cablen (c, *(int*)data); 1733138823Srik CP_UNLOCK (bd); 1734133646Srik splx (s); 1735133646Srik return 0; 1736128967Srik 1737133646Srik case TIOCSDTR: /* Set DTR */ 1738128967Srik s = splimp (); 1739138823Srik CP_LOCK (bd); 1740128967Srik cp_set_dtr (c, 1); 1741138823Srik CP_UNLOCK (bd); 1742128967Srik splx (s); 1743128967Srik return 0; 1744128967Srik 1745133646Srik case TIOCCDTR: /* Clear DTR */ 1746128967Srik s = splimp (); 1747138823Srik CP_LOCK (bd); 1748128967Srik cp_set_dtr (c, 0); 1749138823Srik CP_UNLOCK (bd); 1750128967Srik splx (s); 1751128967Srik return 0; 1752128967Srik 1753133646Srik case TIOCMSET: /* Set DTR/RTS */ 1754128967Srik s = splimp (); 1755138823Srik CP_LOCK (bd); 1756128967Srik cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1757128967Srik cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1758138823Srik CP_UNLOCK (bd); 1759128967Srik splx (s); 1760128967Srik return 0; 1761128967Srik 1762133646Srik case TIOCMBIS: /* Add DTR/RTS */ 1763128967Srik s = splimp (); 1764138823Srik CP_LOCK (bd); 1765128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 1766128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 1767138823Srik CP_UNLOCK (bd); 1768128967Srik splx (s); 1769128967Srik return 0; 1770128967Srik 1771133646Srik case TIOCMBIC: /* Clear DTR/RTS */ 1772128967Srik s = splimp (); 1773138823Srik CP_LOCK (bd); 1774128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1775128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1776138823Srik CP_UNLOCK (bd); 1777128967Srik splx (s); 1778128967Srik return 0; 1779128967Srik 1780133646Srik case TIOCMGET: /* Get modem status */ 1781128967Srik *(int*)data = cp_modem_status (c); 1782128967Srik return 0; 1783128967Srik } 1784128967Srik return ENOTTY; 1785128967Srik} 1786128967Srik 1787128967Srik#ifdef NETGRAPH 1788128967Srikstatic int ng_cp_constructor (node_p node) 1789128967Srik{ 1790128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1791128967Srik CP_DEBUG (d, ("Constructor\n")); 1792128967Srik return EINVAL; 1793128967Srik} 1794128967Srik 1795128967Srikstatic int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1796128967Srik{ 1797128967Srik int s; 1798128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1799138823Srik bdrv_t *bd = d->board->sys; 1800128967Srik 1801128967Srik CP_DEBUG (d, ("Newhook\n")); 1802128967Srik /* Attach debug hook */ 1803128967Srik if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1804128967Srik NG_HOOK_SET_PRIVATE (hook, NULL); 1805128967Srik d->debug_hook = hook; 1806128967Srik return 0; 1807128967Srik } 1808128967Srik 1809128967Srik /* Check for raw hook */ 1810128967Srik if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1811128967Srik return EINVAL; 1812128967Srik 1813128967Srik NG_HOOK_SET_PRIVATE (hook, d); 1814128967Srik d->hook = hook; 1815128967Srik s = splimp (); 1816138823Srik CP_LOCK (bd); 1817128967Srik cp_up (d); 1818138823Srik CP_UNLOCK (bd); 1819128967Srik splx (s); 1820128967Srik return 0; 1821128967Srik} 1822128967Srik 1823128967Srikstatic char *format_timeslots (u_long s) 1824128967Srik{ 1825128967Srik static char buf [100]; 1826128967Srik char *p = buf; 1827128967Srik int i; 1828128967Srik 1829128967Srik for (i=1; i<32; ++i) 1830128967Srik if ((s >> i) & 1) { 1831128967Srik int prev = (i > 1) & (s >> (i-1)); 1832128967Srik int next = (i < 31) & (s >> (i+1)); 1833128967Srik 1834128967Srik if (prev) { 1835128967Srik if (next) 1836128967Srik continue; 1837128967Srik *p++ = '-'; 1838128967Srik } else if (p > buf) 1839128967Srik *p++ = ','; 1840128967Srik 1841128967Srik if (i >= 10) 1842128967Srik *p++ = '0' + i / 10; 1843128967Srik *p++ = '0' + i % 10; 1844128967Srik } 1845128967Srik *p = 0; 1846128967Srik return buf; 1847128967Srik} 1848128967Srik 1849128967Srikstatic int print_modems (char *s, cp_chan_t *c, int need_header) 1850128967Srik{ 1851128967Srik int status = cp_modem_status (c); 1852128967Srik int length = 0; 1853128967Srik 1854128967Srik if (need_header) 1855128967Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1856128967Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1857128967Srik status & TIOCM_LE ? "On" : "-", 1858128967Srik status & TIOCM_DTR ? "On" : "-", 1859128967Srik status & TIOCM_DSR ? "On" : "-", 1860128967Srik status & TIOCM_RTS ? "On" : "-", 1861128967Srik status & TIOCM_CTS ? "On" : "-", 1862128967Srik status & TIOCM_CD ? "On" : "-"); 1863128967Srik return length; 1864128967Srik} 1865128967Srik 1866128967Srikstatic int print_stats (char *s, cp_chan_t *c, int need_header) 1867128967Srik{ 1868128967Srik int length = 0; 1869128967Srik 1870128967Srik if (need_header) 1871128967Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1872128967Srik length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1873128967Srik c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1874128967Srik c->ipkts, c->overrun + c->frame + c->crc, 1875128967Srik (unsigned long) c->obytes, c->opkts, c->underrun); 1876128967Srik return length; 1877128967Srik} 1878128967Srik 1879128967Srikstatic char *format_e1_status (u_char status) 1880128967Srik{ 1881128967Srik static char buf [80]; 1882128967Srik 1883128967Srik if (status & E1_NOALARM) 1884128967Srik return "Ok"; 1885128967Srik buf[0] = 0; 1886128967Srik if (status & E1_LOS) strcat (buf, ",LOS"); 1887128967Srik if (status & E1_AIS) strcat (buf, ",AIS"); 1888128967Srik if (status & E1_LOF) strcat (buf, ",LOF"); 1889128967Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 1890128967Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1891128967Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 1892128967Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1893128967Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1894128967Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1895128967Srik if (buf[0] == ',') 1896128967Srik return buf+1; 1897128967Srik return "Unknown"; 1898128967Srik} 1899128967Srik 1900128967Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1901128967Srik{ 1902128967Srik int n, length = 0; 1903128967Srik 1904128967Srik if (numerator < 1 || divider < 1) { 1905128967Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 1906128967Srik return length; 1907128967Srik } 1908128967Srik n = (int) (0.5 + 1000.0 * numerator / divider); 1909128967Srik if (n < 1000) { 1910128967Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1911128967Srik return length; 1912128967Srik } 1913128967Srik *(s + length) = leftalign ? '/' : ' '; 1914128967Srik length ++; 1915128967Srik 1916128967Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 1917128967Srik else if (n >= 100000) n = (n+50) / 100 * 100; 1918128967Srik else if (n >= 10000) n = (n+5) / 10 * 10; 1919128967Srik 1920128967Srik switch (n) { 1921128967Srik case 1000: length += printf (s+length, ".999"); return length; 1922128967Srik case 10000: n = 9990; break; 1923128967Srik case 100000: n = 99900; break; 1924128967Srik case 1000000: n = 999000; break; 1925128967Srik } 1926133646Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1927128967Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1928128967Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1929133646Srik else length += sprintf (s+length, "%d", n/1000); 1930128967Srik 1931128967Srik return length; 1932128967Srik} 1933128967Srik 1934128967Srikstatic int print_e1_stats (char *s, cp_chan_t *c) 1935128967Srik{ 1936128967Srik struct e1_counters total; 1937128967Srik u_long totsec; 1938128967Srik int length = 0; 1939128967Srik 1940128967Srik totsec = c->totsec + c->cursec; 1941128967Srik total.bpv = c->total.bpv + c->currnt.bpv; 1942128967Srik total.fse = c->total.fse + c->currnt.fse; 1943128967Srik total.crce = c->total.crce + c->currnt.crce; 1944128967Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 1945128967Srik total.uas = c->total.uas + c->currnt.uas; 1946128967Srik total.les = c->total.les + c->currnt.les; 1947128967Srik total.es = c->total.es + c->currnt.es; 1948128967Srik total.bes = c->total.bes + c->currnt.bes; 1949128967Srik total.ses = c->total.ses + c->currnt.ses; 1950128967Srik total.oofs = c->total.oofs + c->currnt.oofs; 1951128967Srik total.css = c->total.css + c->currnt.css; 1952128967Srik total.dm = c->total.dm + c->currnt.dm; 1953128967Srik 1954128967Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1955128967Srik 1956128967Srik /* Unavailable seconds, degraded minutes */ 1957128967Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1958128967Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1959128967Srik 1960128967Srik /* Bipolar violations, frame sync errors */ 1961128967Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1962128967Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1963128967Srik 1964128967Srik /* CRC errors, remote CRC errors (E-bit) */ 1965128967Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 1966128967Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 1967128967Srik 1968128967Srik /* Errored seconds, line errored seconds */ 1969128967Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 1970128967Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 1971128967Srik 1972128967Srik /* Severely errored seconds, burst errored seconds */ 1973128967Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 1974128967Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 1975128967Srik 1976128967Srik /* Out of frame seconds, controlled slip seconds */ 1977128967Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 1978128967Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 1979128967Srik 1980128967Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 1981128967Srik 1982128967Srik /* Print total statistics. */ 1983128967Srik length += print_frac (s + length, 0, total.uas, totsec); 1984128967Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 1985128967Srik 1986128967Srik length += print_frac (s + length, 0, total.bpv, totsec); 1987128967Srik length += print_frac (s + length, 1, total.fse, totsec); 1988128967Srik 1989128967Srik length += print_frac (s + length, 0, total.crce, totsec); 1990128967Srik length += print_frac (s + length, 1, total.rcrce, totsec); 1991128967Srik 1992128967Srik length += print_frac (s + length, 0, total.es, totsec); 1993128967Srik length += print_frac (s + length, 1, total.les, totsec); 1994128967Srik 1995128967Srik length += print_frac (s + length, 0, total.ses, totsec); 1996128967Srik length += print_frac (s + length, 1, total.bes, totsec); 1997128967Srik 1998128967Srik length += print_frac (s + length, 0, total.oofs, totsec); 1999128967Srik length += print_frac (s + length, 1, total.css, totsec); 2000128967Srik 2001128967Srik length += sprintf (s + length, " -- Total\n"); 2002128967Srik return length; 2003128967Srik} 2004128967Srik 2005128967Srikstatic int print_chan (char *s, cp_chan_t *c) 2006128967Srik{ 2007128967Srik drv_t *d = c->sys; 2008138823Srik bdrv_t *bd = d->board->sys; 2009128967Srik int length = 0; 2010128967Srik 2011128967Srik length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2012128967Srik if (d->chan->debug) 2013128967Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 2014128967Srik 2015128967Srik if (c->board->mux) { 2016128967Srik length += sprintf (s + length, " cfg=C"); 2017128967Srik } else { 2018128967Srik length += sprintf (s + length, " cfg=A"); 2019128967Srik } 2020128967Srik 2021128967Srik if (c->baud) 2022128967Srik length += sprintf (s + length, " %ld", c->baud); 2023128967Srik else 2024128967Srik length += sprintf (s + length, " extclock"); 2025128967Srik 2026128967Srik if (c->type == T_E1 || c->type == T_G703) 2027128967Srik switch (c->gsyn) { 2028128967Srik case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2029128967Srik case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2030128967Srik case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2031128967Srik case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2032128967Srik case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2033128967Srik case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2034128967Srik } 2035128967Srik if (c->type == T_SERIAL) { 2036128967Srik length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2037128967Srik length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2038128967Srik length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2039128967Srik } 2040128967Srik if (c->type == T_E1) 2041128967Srik length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2042128967Srik 2043128967Srik length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2044128967Srik 2045128967Srik if (c->type == T_E1) 2046128967Srik length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2047128967Srik if (c->type == T_G703) { 2048128967Srik int lq, x; 2049128967Srik 2050128967Srik x = splimp (); 2051138823Srik CP_LOCK (bd); 2052128967Srik lq = cp_get_lq (c); 2053138823Srik CP_UNLOCK (bd); 2054128967Srik splx (x); 2055128967Srik length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2056128967Srik } 2057128967Srik length += sprintf (s + length, "\n"); 2058128967Srik return length; 2059128967Srik} 2060128967Srik 2061128967Srikstatic int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2062128967Srik{ 2063128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2064128967Srik struct ng_mesg *msg; 2065128967Srik struct ng_mesg *resp = NULL; 2066128967Srik int error = 0; 2067128967Srik 2068128967Srik CP_DEBUG (d, ("Rcvmsg\n")); 2069128967Srik NGI_GET_MSG (item, msg); 2070128967Srik switch (msg->header.typecookie) { 2071128967Srik default: 2072128967Srik error = EINVAL; 2073128967Srik break; 2074128967Srik 2075128967Srik case NGM_CP_COOKIE: 2076128967Srik printf ("Not implemented yet\n"); 2077128967Srik error = EINVAL; 2078128967Srik break; 2079128967Srik 2080128967Srik case NGM_GENERIC_COOKIE: 2081128967Srik switch (msg->header.cmd) { 2082128967Srik default: 2083128967Srik error = EINVAL; 2084128967Srik break; 2085128967Srik 2086128967Srik case NGM_TEXT_STATUS: { 2087128967Srik char *s; 2088128967Srik int l = 0; 2089128967Srik int dl = sizeof (struct ng_mesg) + 730; 2090128967Srik 2091128967Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2092128967Srik if (! resp) { 2093128967Srik error = ENOMEM; 2094128967Srik break; 2095128967Srik } 2096128967Srik s = (resp)->data; 2097128967Srik if (d) { 2098128967Srik l += print_chan (s + l, d->chan); 2099128967Srik l += print_stats (s + l, d->chan, 1); 2100128967Srik l += print_modems (s + l, d->chan, 1); 2101128967Srik l += print_e1_stats (s + l, d->chan); 2102128967Srik } else 2103128967Srik l += sprintf (s + l, "Error: node not connect to channel"); 2104193813Simp strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRSIZ); 2105128967Srik } 2106128967Srik break; 2107128967Srik } 2108128967Srik break; 2109128967Srik } 2110128967Srik NG_RESPOND_MSG (error, node, item, resp); 2111128967Srik NG_FREE_MSG (msg); 2112128967Srik return error; 2113128967Srik} 2114128967Srik 2115128967Srikstatic int ng_cp_rcvdata (hook_p hook, item_p item) 2116128967Srik{ 2117128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2118128967Srik struct mbuf *m; 2119131108Sjulian struct ng_tag_prio *ptag; 2120138823Srik bdrv_t *bd = d->board->sys; 2121128967Srik struct ifqueue *q; 2122128967Srik int s; 2123128967Srik 2124128967Srik CP_DEBUG2 (d, ("Rcvdata\n")); 2125128967Srik NGI_GET_M (item, m); 2126128967Srik NG_FREE_ITEM (item); 2127128967Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 2128128967Srik NG_FREE_M (m); 2129128967Srik return ENETDOWN; 2130128967Srik } 2131131108Sjulian 2132131108Sjulian /* Check for high priority data */ 2133131108Sjulian if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2134131108Sjulian NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2135131108Sjulian q = &d->hi_queue; 2136131108Sjulian else 2137131108Sjulian q = &d->queue; 2138131108Sjulian 2139128967Srik s = splimp (); 2140138823Srik CP_LOCK (bd); 2141128967Srik IF_LOCK (q); 2142128967Srik if (_IF_QFULL (q)) { 2143128967Srik IF_UNLOCK (q); 2144138823Srik CP_UNLOCK (bd); 2145128967Srik splx (s); 2146128967Srik NG_FREE_M (m); 2147128967Srik return ENOBUFS; 2148128967Srik } 2149128967Srik _IF_ENQUEUE (q, m); 2150128967Srik IF_UNLOCK (q); 2151128967Srik cp_start (d); 2152138823Srik CP_UNLOCK (bd); 2153128967Srik splx (s); 2154128967Srik return 0; 2155128967Srik} 2156128967Srik 2157128967Srikstatic int ng_cp_rmnode (node_p node) 2158128967Srik{ 2159128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2160128967Srik 2161128967Srik CP_DEBUG (d, ("Rmnode\n")); 2162128967Srik if (d && d->running) { 2163138823Srik bdrv_t *bd = d->board->sys; 2164128967Srik int s = splimp (); 2165138823Srik CP_LOCK (bd); 2166128967Srik cp_down (d); 2167138823Srik CP_UNLOCK (bd); 2168128967Srik splx (s); 2169128967Srik } 2170128967Srik#ifdef KLD_MODULE 2171132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 2172128967Srik NG_NODE_SET_PRIVATE (node, NULL); 2173128967Srik NG_NODE_UNREF (node); 2174128967Srik } 2175132464Sjulian NG_NODE_REVIVE(node); /* Persistant node */ 2176128967Srik#endif 2177128967Srik return 0; 2178128967Srik} 2179128967Srik 2180128967Srikstatic int ng_cp_connect (hook_p hook) 2181128967Srik{ 2182128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2183128967Srik 2184128967Srik if (d) { 2185128967Srik CP_DEBUG (d, ("Connect\n")); 2186199407Sjhb callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 2187128967Srik } 2188128967Srik 2189128967Srik return 0; 2190128967Srik} 2191128967Srik 2192128967Srikstatic int ng_cp_disconnect (hook_p hook) 2193128967Srik{ 2194128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2195128967Srik 2196128967Srik if (d) { 2197128967Srik CP_DEBUG (d, ("Disconnect\n")); 2198128967Srik if (NG_HOOK_PRIVATE (hook)) 2199128967Srik { 2200138823Srik bdrv_t *bd = d->board->sys; 2201128967Srik int s = splimp (); 2202138823Srik CP_LOCK (bd); 2203128967Srik cp_down (d); 2204138823Srik CP_UNLOCK (bd); 2205128967Srik splx (s); 2206128967Srik } 2207138823Srik /* If we were wait it than it reasserted now, just stop it. */ 2208138823Srik if (!callout_drain (&d->timeout_handle)) 2209138823Srik callout_stop (&d->timeout_handle); 2210128967Srik } 2211128967Srik return 0; 2212128967Srik} 2213128967Srik#endif 2214128967Srik 2215128967Srikstatic int cp_modevent (module_t mod, int type, void *unused) 2216128967Srik{ 2217128967Srik static int load_count = 0; 2218128967Srik 2219128967Srik switch (type) { 2220128967Srik case MOD_LOAD: 2221138673Srik#ifdef NETGRAPH 2222128967Srik if (ng_newtype (&typestruct)) 2223128967Srik printf ("Failed to register ng_cp\n"); 2224128967Srik#endif 2225128967Srik ++load_count; 2226188661Srwatson callout_init (&timeout_handle, CALLOUT_MPSAFE); 2227138823Srik callout_reset (&timeout_handle, hz*5, cp_timeout, 0); 2228128967Srik break; 2229128967Srik case MOD_UNLOAD: 2230128967Srik if (load_count == 1) { 2231128967Srik printf ("Removing device entry for Tau-PCI\n"); 2232138673Srik#ifdef NETGRAPH 2233128967Srik ng_rmtype (&typestruct); 2234128967Srik#endif 2235128967Srik } 2236138823Srik /* If we were wait it than it reasserted now, just stop it. 2237138823Srik * Actually we shouldn't get this condition. But code could be 2238138823Srik * changed in the future, so just be a litle paranoid. 2239138823Srik */ 2240138823Srik if (!callout_drain (&timeout_handle)) 2241138823Srik callout_stop (&timeout_handle); 2242128967Srik --load_count; 2243128967Srik break; 2244128967Srik case MOD_SHUTDOWN: 2245128967Srik break; 2246128967Srik } 2247128967Srik return 0; 2248128967Srik} 2249128967Srik 2250128967Srik#ifdef NETGRAPH 2251128967Srikstatic struct ng_type typestruct = { 2252129837Srik .version = NG_ABI_VERSION, 2253129837Srik .name = NG_CP_NODE_TYPE, 2254129837Srik .constructor = ng_cp_constructor, 2255129837Srik .rcvmsg = ng_cp_rcvmsg, 2256129837Srik .shutdown = ng_cp_rmnode, 2257129837Srik .newhook = ng_cp_newhook, 2258129837Srik .connect = ng_cp_connect, 2259129837Srik .rcvdata = ng_cp_rcvdata, 2260129837Srik .disconnect = ng_cp_disconnect, 2261128967Srik}; 2262128967Srik#endif /*NETGRAPH*/ 2263128967Srik 2264128967Srik#ifdef NETGRAPH 2265128967SrikMODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2266128967Srik#else 2267128967SrikMODULE_DEPEND (cp, sppp, 1, 1, 1); 2268128967Srik#endif 2269128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2270138823SrikMODULE_VERSION (cp, 1); 2271