if_cp.c revision 207554
1139749Simp/*- 2128967Srik * Cronyx-Tau-PCI adapter driver for FreeBSD. 3128967Srik * Supports PPP/HDLC, Cisco/HDLC and FrameRelay protocol in synchronous mode, 4128967Srik * and asyncronous channels with full modem control. 5128967Srik * Keepalive protocol implemented in both Cisco and PPP modes. 6128967Srik * 7128967Srik * Copyright (C) 1999-2004 Cronyx Engineering. 8128967Srik * Author: Kurakin Roman, <rik@cronyx.ru> 9128967Srik * 10128967Srik * Copyright (C) 1999-2002 Cronyx Engineering. 11128967Srik * Author: Serge Vakulenko, <vak@cronyx.ru> 12128967Srik * 13128967Srik * This software is distributed with NO WARRANTIES, not even the implied 14128967Srik * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15128967Srik * 16128967Srik * Authors grant any other persons or organisations a permission to use, 17128967Srik * modify and redistribute this software in source and binary forms, 18128967Srik * as long as this message is kept with the software, all derivative 19128967Srik * works or modified versions. 20128967Srik * 21130985Srik * Cronyx Id: if_cp.c,v 1.1.2.41 2004/06/23 17:09:13 rik Exp $ 22128967Srik */ 23128967Srik 24128967Srik#include <sys/cdefs.h> 25128967Srik__FBSDID("$FreeBSD: head/sys/dev/cp/if_cp.c 207554 2010-05-03 07:32:50Z sobomax $"); 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> 45138673Srik#include <dev/pci/pcivar.h> 46138673Srik#include <dev/pci/pcireg.h> 47128967Srik#include <machine/bus.h> 48128967Srik#include <sys/rman.h> 49128967Srik#include "opt_ng_cronyx.h" 50128967Srik#ifdef NETGRAPH_CRONYX 51128967Srik# include "opt_netgraph.h" 52128967Srik# ifndef NETGRAPH 53133646Srik# error #option NETGRAPH missed from configuration 54128967Srik# endif 55128967Srik# include <netgraph/ng_message.h> 56128967Srik# include <netgraph/netgraph.h> 57130985Srik# include <dev/cp/ng_cp.h> 58128967Srik#else 59128967Srik# include <net/if_sppp.h> 60147256Sbrooks# include <net/if_types.h> 61147256Sbrooks#include <dev/pci/pcivar.h> 62128967Srik# define PP_CISCO IFF_LINK2 63130971Srik# include <net/bpf.h> 64128967Srik#endif 65128967Srik#include <dev/cx/machdep.h> 66128967Srik#include <dev/cp/cpddk.h> 67128967Srik#include <machine/cserial.h> 68128967Srik#include <machine/resource.h> 69128967Srik#include <machine/pmap.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 96128967Srik {0, 0} 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 * Print the mbuf chain, for debug purposes only. 185150622Srik */ 186150622Srikstatic void printmbuf (struct mbuf *m) 187150622Srik{ 188150622Srik printf ("mbuf:"); 189150622Srik for (; m; m=m->m_next) { 190150622Srik if (m->m_flags & M_PKTHDR) 191150622Srik printf (" HDR %d:", m->m_pkthdr.len); 192150622Srik if (m->m_flags & M_EXT) 193150622Srik printf (" EXT:"); 194150622Srik printf (" %d", m->m_len); 195150622Srik } 196150622Srik printf ("\n"); 197150622Srik} 198150622Srik 199150622Srik/* 200150622Srik * Make an mbuf from data. 201150622Srik */ 202150622Srikstatic struct mbuf *makembuf (void *buf, unsigned len) 203150622Srik{ 204150622Srik struct mbuf *m; 205150622Srik 206150622Srik MGETHDR (m, M_DONTWAIT, MT_DATA); 207150622Srik if (! m) 208150622Srik return 0; 209150622Srik MCLGET (m, M_DONTWAIT); 210150622Srik if (! (m->m_flags & M_EXT)) { 211150622Srik m_freem (m); 212150622Srik return 0; 213150622Srik } 214150622Srik m->m_pkthdr.len = m->m_len = len; 215150622Srik bcopy (buf, mtod (m, caddr_t), len); 216150622Srik return m; 217150622Srik} 218150622Srik 219150622Srikstatic int cp_probe (device_t dev) 220150622Srik{ 221150622Srik if ((pci_get_vendor (dev) == cp_vendor_id) && 222150622Srik (pci_get_device (dev) == cp_device_id)) { 223150622Srik device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 224150622Srik return BUS_PROBE_DEFAULT; 225150622Srik } 226150622Srik return ENXIO; 227150622Srik} 228150622Srik 229150622Srikstatic void cp_timeout (void *arg) 230150622Srik{ 231150622Srik drv_t *d; 232150622Srik int s, i, k; 233150622Srik 234150622Srik for (i = 0; i < NBRD; ++i) { 235150622Srik if (adapter[i] == NULL) 236150622Srik continue; 237150622Srik for (k = 0; k < NCHAN; ++k) { 238150622Srik s = splimp (); 239150622Srik if (cp_destroy) { 240150622Srik splx (s); 241150622Srik return; 242150622Srik } 243150622Srik d = channel[i * NCHAN + k]; 244150622Srik if (!d) { 245150622Srik splx (s); 246150622Srik continue; 247150622Srik } 248150622Srik CP_LOCK ((bdrv_t *)d->board->sys); 249150622Srik switch (d->chan->type) { 250150622Srik case T_G703: 251150622Srik cp_g703_timer (d->chan); 252150622Srik break; 253150622Srik case T_E1: 254150622Srik cp_e1_timer (d->chan); 255150622Srik break; 256150622Srik case T_E3: 257150622Srik case T_T3: 258150622Srik case T_STS1: 259150622Srik cp_e3_timer (d->chan); 260150622Srik break; 261150622Srik default: 262150622Srik break; 263150622Srik } 264150622Srik CP_UNLOCK ((bdrv_t *)d->board->sys); 265150622Srik splx (s); 266150622Srik } 267150622Srik } 268150622Srik s = splimp (); 269150622Srik if (!cp_destroy) 270150622Srik callout_reset (&timeout_handle, hz, cp_timeout, 0); 271150622Srik splx (s); 272150622Srik} 273150622Srik 274150622Srikstatic void cp_led_off (void *arg) 275150622Srik{ 276150622Srik cp_board_t *b = arg; 277150622Srik bdrv_t *bd = (bdrv_t *) b->sys; 278150622Srik int s; 279150622Srik s = splimp (); 280150622Srik if (cp_destroy) { 281150622Srik splx (s); 282150622Srik return; 283150622Srik } 284150622Srik CP_LOCK (bd); 285150622Srik cp_led (b, 0); 286150622Srik CP_UNLOCK (bd); 287150622Srik splx (s); 288150622Srik} 289150622Srik 290150622Srikstatic void cp_intr (void *arg) 291150622Srik{ 292150622Srik bdrv_t *bd = arg; 293150622Srik cp_board_t *b = bd->board; 294150622Srik#ifndef NETGRAPH 295150622Srik int i; 296150622Srik#endif 297150622Srik int s = splimp (); 298150622Srik if (cp_destroy) { 299150622Srik splx (s); 300150622Srik return; 301150622Srik } 302150622Srik CP_LOCK (bd); 303150622Srik /* Check if we are ready */ 304150622Srik if (b->sys == NULL) { 305150622Srik /* Not we are not, just cleanup. */ 306150622Srik cp_interrupt_poll (b, 1); 307150622Srik CP_UNLOCK (bd); 308150622Srik return; 309150622Srik } 310150622Srik /* Turn LED on. */ 311150622Srik cp_led (b, 1); 312150622Srik 313150622Srik cp_interrupt (b); 314150622Srik 315150622Srik /* Turn LED off 50 msec later. */ 316150622Srik callout_reset (&led_timo[b->num], hz/20, cp_led_off, b); 317150622Srik CP_UNLOCK (bd); 318150622Srik splx (s); 319150622Srik 320150622Srik#ifndef NETGRAPH 321150622Srik /* Pass packets in a lock-free state */ 322150622Srik for (i = 0; i < NCHAN && b->chan[i].type; i++) { 323150622Srik drv_t *d = b->chan[i].sys; 324150622Srik struct mbuf *m; 325150622Srik if (!d || !d->running) 326150622Srik continue; 327150622Srik while (_IF_QLEN(&d->queue)) { 328150622Srik IF_DEQUEUE (&d->queue,m); 329150622Srik if (!m) 330150622Srik continue; 331150622Srik sppp_input (d->ifp, m); 332150622Srik } 333150622Srik } 334150622Srik#endif 335150622Srik} 336150622Srik 337150622Srikstatic void 338150622Srikcp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 339150622Srik{ 340150622Srik unsigned long *addr; 341150622Srik 342150622Srik if (error) 343150622Srik return; 344150622Srik 345150622Srik KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 346150622Srik addr = arg; 347150622Srik *addr = segs->ds_addr; 348150622Srik} 349150622Srik 350150622Srikstatic int 351150622Srikcp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 352150622Srik{ 353150622Srik int error; 354150622Srik 355150622Srik error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 356150622Srik BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 357150622Srik dmem->size, 0, NULL, NULL, &dmem->dmat); 358150622Srik if (error) { 359150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 360150622Srik else printf ("cp%d: ", bnum); 361150622Srik printf ("couldn't allocate tag for dma memory\n"); 362150622Srik return 0; 363150622Srik } 364150622Srik error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 365150622Srik BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 366150622Srik if (error) { 367150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 368150622Srik else printf ("cp%d: ", bnum); 369150622Srik printf ("couldn't allocate mem for dma memory\n"); 370150622Srik bus_dma_tag_destroy (dmem->dmat); 371150622Srik return 0; 372150622Srik } 373150622Srik error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 374150622Srik dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); 375150622Srik if (error) { 376150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 377150622Srik else printf ("cp%d: ", bnum); 378150622Srik printf ("couldn't load mem map for dma memory\n"); 379150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 380150622Srik bus_dma_tag_destroy (dmem->dmat); 381150622Srik return 0; 382150622Srik } 383150622Srik return 1; 384150622Srik} 385150622Srik 386150622Srikstatic void 387150622Srikcp_bus_dma_mem_free (cp_dma_mem_t *dmem) 388150622Srik{ 389150622Srik bus_dmamap_unload (dmem->dmat, dmem->mapp); 390150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 391150622Srik bus_dma_tag_destroy (dmem->dmat); 392150622Srik} 393150622Srik 394150622Srik/* 395150622Srik * Called if the probe succeeded. 396150622Srik */ 397150622Srikstatic int cp_attach (device_t dev) 398150622Srik{ 399150622Srik bdrv_t *bd = device_get_softc (dev); 400150622Srik int unit = device_get_unit (dev); 401150622Srik char *cp_ln = CP_LOCK_NAME; 402150622Srik unsigned short res; 403150622Srik vm_offset_t vbase; 404150622Srik int rid, error; 405150622Srik cp_board_t *b; 406150622Srik cp_chan_t *c; 407150622Srik drv_t *d; 408150622Srik int s = splimp (); 409150622Srik 410150622Srik b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 411150622Srik if (!b) { 412150622Srik printf ("cp%d: couldn't allocate memory\n", unit); 413150622Srik splx (s); 414150622Srik return (ENXIO); 415150622Srik } 416150622Srik bzero (b, sizeof(cp_board_t)); 417150622Srik 418150622Srik bd->board = b; 419150622Srik rid = PCIR_BAR(0); 420150622Srik bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 421150622Srik 0, ~0, 1, RF_ACTIVE); 422150622Srik if (! bd->cp_res) { 423150622Srik printf ("cp%d: cannot map memory\n", unit); 424150622Srik free (b, M_DEVBUF); 425150622Srik splx (s); 426150622Srik return (ENXIO); 427150622Srik } 428150622Srik vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 429150622Srik 430150622Srik cp_ln[2] = '0' + unit; 431150622Srik mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 432150622Srik res = cp_init (b, unit, (u_char*) vbase); 433150622Srik if (res) { 434150622Srik printf ("cp%d: can't init, error code:%x\n", unit, res); 435150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 436150622Srik free (b, M_DEVBUF); 437150622Srik splx (s); 438150622Srik return (ENXIO); 439150622Srik } 440150622Srik 441150622Srik bd->dmamem.size = sizeof(cp_qbuf_t); 442150622Srik if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 443150622Srik free (b, M_DEVBUF); 444150622Srik splx (s); 445150622Srik return (ENXIO); 446150622Srik } 447150622Srik CP_LOCK (bd); 448150622Srik cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); 449150622Srik CP_UNLOCK (bd); 450150622Srik 451150622Srik rid = 0; 452150622Srik bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 453150622Srik RF_SHAREABLE | RF_ACTIVE); 454150622Srik if (! bd->cp_irq) { 455150622Srik cp_destroy = 1; 456150622Srik printf ("cp%d: cannot map interrupt\n", unit); 457150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 458150622Srik PCIR_BAR(0), bd->cp_res); 459150622Srik mtx_destroy (&bd->cp_mtx); 460150622Srik free (b, M_DEVBUF); 461150622Srik splx (s); 462150622Srik return (ENXIO); 463150622Srik } 464188661Srwatson callout_init (&led_timo[unit], CALLOUT_MPSAFE); 465150622Srik error = bus_setup_intr (dev, bd->cp_irq, 466188661Srwatson INTR_TYPE_NET|INTR_MPSAFE, 467166901Spiso NULL, cp_intr, bd, &bd->cp_intrhand); 468150622Srik if (error) { 469150622Srik cp_destroy = 1; 470150622Srik printf ("cp%d: cannot set up irq\n", unit); 471150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 472150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 473150622Srik PCIR_BAR(0), bd->cp_res); 474150622Srik mtx_destroy (&bd->cp_mtx); 475150622Srik free (b, M_DEVBUF); 476150622Srik splx (s); 477150622Srik return (ENXIO); 478150622Srik } 479150622Srik printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 480150622Srik 481150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 482150622Srik if (! c->type) 483150622Srik continue; 484150622Srik d = &bd->channel[c->num]; 485150622Srik d->dmamem.size = sizeof(cp_buf_t); 486150622Srik if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 487150622Srik continue; 488150622Srik channel [b->num*NCHAN + c->num] = d; 489150622Srik sprintf (d->name, "cp%d.%d", b->num, c->num); 490150622Srik d->board = b; 491150622Srik d->chan = c; 492150622Srik c->sys = d; 493199407Sjhb callout_init (&d->timeout_handle, CALLOUT_MPSAFE); 494150622Srik#ifdef NETGRAPH 495150622Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 496150622Srik printf ("%s: cannot make common node\n", d->name); 497150622Srik d->node = NULL; 498150622Srik continue; 499150622Srik } 500150622Srik NG_NODE_SET_PRIVATE (d->node, d); 501150622Srik sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 502150622Srik c->board->num*NCHAN + c->num); 503150622Srik if (ng_name_node (d->node, d->nodename)) { 504150622Srik printf ("%s: cannot name node\n", d->nodename); 505150622Srik NG_NODE_UNREF (d->node); 506150622Srik continue; 507150622Srik } 508207554Ssobomax d->queue.ifq_maxlen = ifqmaxlen; 509207554Ssobomax d->hi_queue.ifq_maxlen = ifqmaxlen; 510150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 511150622Srik mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 512150622Srik#else /*NETGRAPH*/ 513150622Srik d->ifp = if_alloc(IFT_PPP); 514150622Srik if (d->ifp == NULL) { 515150622Srik printf ("%s: cannot if_alloc() interface\n", d->name); 516150622Srik continue; 517150622Srik } 518150622Srik d->ifp->if_softc = d; 519150622Srik if_initname (d->ifp, "cp", b->num * NCHAN + c->num); 520150622Srik d->ifp->if_mtu = PP_MTU; 521150622Srik d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 522150622Srik d->ifp->if_ioctl = cp_sioctl; 523150622Srik d->ifp->if_start = cp_ifstart; 524150622Srik d->ifp->if_init = cp_initialize; 525150622Srik d->queue.ifq_maxlen = NRBUF; 526150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 527150622Srik sppp_attach (d->ifp); 528150622Srik if_attach (d->ifp); 529150622Srik IFP2SP(d->ifp)->pp_tlf = cp_tlf; 530150622Srik IFP2SP(d->ifp)->pp_tls = cp_tls; 531150622Srik /* If BPF is in the kernel, call the attach for it. 532150622Srik * The header size of PPP or Cisco/HDLC is 4 bytes. */ 533150622Srik bpfattach (d->ifp, DLT_PPP, 4); 534150622Srik#endif /*NETGRAPH*/ 535150622Srik cp_start_e1 (c); 536150622Srik cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 537150622Srik 538150622Srik /* Register callback functions. */ 539150622Srik cp_register_transmit (c, &cp_transmit); 540150622Srik cp_register_receive (c, &cp_receive); 541150622Srik cp_register_error (c, &cp_error); 542150622Srik d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 543150622Srik GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 544150622Srik } 545150622Srik CP_LOCK (bd); 546150622Srik b->sys = bd; 547150622Srik adapter[unit] = b; 548150622Srik CP_UNLOCK (bd); 549150622Srik splx (s); 550150622Srik return 0; 551150622Srik} 552150622Srik 553150622Srikstatic int cp_detach (device_t dev) 554150622Srik{ 555150622Srik bdrv_t *bd = device_get_softc (dev); 556150622Srik cp_board_t *b = bd->board; 557150622Srik cp_chan_t *c; 558150622Srik int s; 559150622Srik 560150622Srik KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized")); 561150622Srik s = splimp (); 562150622Srik CP_LOCK (bd); 563150622Srik /* Check if the device is busy (open). */ 564150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 565150622Srik drv_t *d = (drv_t*) c->sys; 566150622Srik 567150622Srik if (! d || ! d->chan->type) 568150622Srik continue; 569150622Srik if (d->running) { 570150622Srik CP_UNLOCK (bd); 571150622Srik splx (s); 572150622Srik return EBUSY; 573150622Srik } 574150622Srik } 575150622Srik 576150622Srik /* Ok, we can unload driver */ 577150622Srik /* At first we should stop all channels */ 578150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 579150622Srik drv_t *d = (drv_t*) c->sys; 580150622Srik 581150622Srik if (! d || ! d->chan->type) 582150622Srik continue; 583150622Srik 584150622Srik cp_stop_chan (c); 585150622Srik cp_stop_e1 (c); 586150622Srik cp_set_dtr (d->chan, 0); 587150622Srik cp_set_rts (d->chan, 0); 588150622Srik } 589150622Srik 590150622Srik /* Reset the adapter. */ 591150622Srik cp_destroy = 1; 592150622Srik cp_interrupt_poll (b, 1); 593150622Srik cp_led_off (b); 594150622Srik cp_reset (b, 0 ,0); 595150622Srik callout_stop (&led_timo[b->num]); 596150622Srik 597150624Srik /* Disable the interrupt request. */ 598150624Srik bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 599150624Srik 600150622Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 601150622Srik drv_t *d = (drv_t*) c->sys; 602150622Srik 603150622Srik if (! d || ! d->chan->type) 604150622Srik continue; 605199407Sjhb callout_stop (&d->timeout_handle); 606150622Srik#ifndef NETGRAPH 607150622Srik /* Detach from the packet filter list of interfaces. */ 608150622Srik bpfdetach (d->ifp); 609150622Srik 610150622Srik /* Detach from the sync PPP list. */ 611150622Srik sppp_detach (d->ifp); 612150622Srik 613150622Srik /* Detach from the system list of interfaces. */ 614150622Srik if_detach (d->ifp); 615150622Srik if_free (d->ifp); 616150622Srik IF_DRAIN (&d->queue); 617150622Srik mtx_destroy (&d->queue.ifq_mtx); 618150622Srik#else 619150622Srik if (d->node) { 620150622Srik ng_rmnode_self (d->node); 621150622Srik NG_NODE_UNREF (d->node); 622150622Srik d->node = NULL; 623150622Srik } 624150622Srik mtx_destroy (&d->queue.ifq_mtx); 625150622Srik mtx_destroy (&d->hi_queue.ifq_mtx); 626150622Srik#endif 627150622Srik destroy_dev (d->devt); 628150622Srik } 629150622Srik 630150622Srik b->sys = NULL; 631150622Srik CP_UNLOCK (bd); 632150622Srik 633150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 634150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 635150622Srik 636150622Srik CP_LOCK (bd); 637150622Srik cp_led_off (b); 638150622Srik CP_UNLOCK (bd); 639150622Srik callout_drain (&led_timo[b->num]); 640150622Srik splx (s); 641150622Srik 642150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 643150622Srik drv_t *d = (drv_t*) c->sys; 644150622Srik 645150622Srik if (! d || ! d->chan->type) 646150622Srik continue; 647199407Sjhb callout_drain (&d->timeout_handle); 648150622Srik channel [b->num*NCHAN + c->num] = 0; 649150622Srik /* Deallocate buffers. */ 650150622Srik cp_bus_dma_mem_free (&d->dmamem); 651150622Srik } 652150622Srik adapter [b->num] = 0; 653150622Srik cp_bus_dma_mem_free (&bd->dmamem); 654150622Srik free (b, M_DEVBUF); 655150622Srik mtx_destroy (&bd->cp_mtx); 656150622Srik return 0; 657150622Srik} 658150622Srik 659150622Srik#ifndef NETGRAPH 660150622Srikstatic void cp_ifstart (struct ifnet *ifp) 661150622Srik{ 662150622Srik drv_t *d = ifp->if_softc; 663150622Srik bdrv_t *bd = d->board->sys; 664150622Srik 665150622Srik CP_LOCK (bd); 666150622Srik cp_start (d); 667150622Srik CP_UNLOCK (bd); 668150622Srik} 669150622Srik 670150622Srikstatic void cp_tlf (struct sppp *sp) 671150622Srik{ 672150622Srik drv_t *d = SP2IFP(sp)->if_softc; 673150622Srik 674150622Srik CP_DEBUG2 (d, ("cp_tlf\n")); 675150622Srik /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */ 676150622Srik/* cp_set_dtr (d->chan, 0);*/ 677150622Srik/* cp_set_rts (d->chan, 0);*/ 678150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 679150622Srik sp->pp_down (sp); 680150622Srik} 681150622Srik 682150622Srikstatic void cp_tls (struct sppp *sp) 683150622Srik{ 684150622Srik drv_t *d = SP2IFP(sp)->if_softc; 685150622Srik 686150622Srik CP_DEBUG2 (d, ("cp_tls\n")); 687150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 688150622Srik sp->pp_up (sp); 689150622Srik} 690150622Srik 691150622Srik/* 692150622Srik * Process an ioctl request. 693150622Srik */ 694150622Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 695150622Srik{ 696150622Srik drv_t *d = ifp->if_softc; 697150622Srik bdrv_t *bd = d->board->sys; 698150622Srik int error, s, was_up, should_be_up; 699150622Srik 700150622Srik was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 701150622Srik error = sppp_ioctl (ifp, cmd, data); 702150622Srik 703150622Srik if (error) 704150622Srik return error; 705150622Srik 706150622Srik if (! (ifp->if_flags & IFF_DEBUG)) 707150622Srik d->chan->debug = 0; 708180132Srik else 709180132Srik d->chan->debug = d->chan->debug_shadow; 710150622Srik 711150622Srik switch (cmd) { 712150622Srik default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 713150622Srik case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 714150622Srik case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 715150622Srik case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 716150622Srik case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 717150622Srik } 718150622Srik 719150622Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 720150622Srik s = splimp (); 721150622Srik CP_LOCK (bd); 722150622Srik should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 723150622Srik if (! was_up && should_be_up) { 724150622Srik /* Interface goes up -- start it. */ 725150622Srik cp_up (d); 726150622Srik cp_start (d); 727150622Srik } else if (was_up && ! should_be_up) { 728150622Srik /* Interface is going down -- stop it. */ 729150622Srik/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 730150622Srik cp_down (d); 731150622Srik } 732150622Srik CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 733150622Srik CP_UNLOCK (bd); 734150622Srik splx (s); 735150622Srik return 0; 736150622Srik} 737150622Srik 738150622Srik/* 739150622Srik * Initialization of interface. 740150622Srik * It seems to be never called by upper level? 741150622Srik */ 742150622Srikstatic void cp_initialize (void *softc) 743150622Srik{ 744150622Srik drv_t *d = softc; 745150622Srik 746150622Srik CP_DEBUG (d, ("cp_initialize\n")); 747150622Srik} 748150622Srik#endif /*NETGRAPH*/ 749150622Srik 750150622Srik/* 751150622Srik * Stop the interface. Called on splimp(). 752150622Srik */ 753150622Srikstatic void cp_down (drv_t *d) 754150622Srik{ 755150622Srik CP_DEBUG (d, ("cp_down\n")); 756150622Srik /* Interface is going down -- stop it. */ 757150622Srik cp_set_dtr (d->chan, 0); 758150622Srik cp_set_rts (d->chan, 0); 759150622Srik 760150622Srik d->running = 0; 761199407Sjhb callout_stop (&d->timeout_handle); 762150622Srik} 763150622Srik 764150622Srik/* 765150622Srik * Start the interface. Called on splimp(). 766150622Srik */ 767150622Srikstatic void cp_up (drv_t *d) 768150622Srik{ 769150622Srik CP_DEBUG (d, ("cp_up\n")); 770150622Srik cp_set_dtr (d->chan, 1); 771150622Srik cp_set_rts (d->chan, 1); 772150622Srik d->running = 1; 773150622Srik} 774150622Srik 775150622Srik/* 776150622Srik * Start output on the interface. Get another datagram to send 777150622Srik * off of the interface queue, and copy it to the interface 778150622Srik * before starting the output. 779150622Srik */ 780150622Srikstatic void cp_send (drv_t *d) 781150622Srik{ 782150622Srik struct mbuf *m; 783150622Srik u_short len; 784150622Srik 785150622Srik CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 786150622Srik 787150622Srik /* No output if the interface is down. */ 788150622Srik if (! d->running) 789150622Srik return; 790150622Srik 791150622Srik /* No output if the modem is off. */ 792150622Srik if (! (d->chan->lloop || d->chan->type != T_SERIAL || 793150622Srik cp_get_dsr (d->chan))) 794150622Srik return; 795150622Srik 796150622Srik while (cp_transmit_space (d->chan)) { 797150622Srik /* Get the packet to send. */ 798150622Srik#ifdef NETGRAPH 799150622Srik IF_DEQUEUE (&d->hi_queue, m); 800150622Srik if (! m) 801150622Srik IF_DEQUEUE (&d->queue, m); 802150622Srik#else 803150622Srik m = sppp_dequeue (d->ifp); 804150622Srik#endif 805150622Srik if (! m) 806150622Srik return; 807150622Srik#ifndef NETGRAPH 808165632Sjhb BPF_MTAP (d->ifp, m); 809150622Srik#endif 810150622Srik len = m_length (m, NULL); 811150622Srik if (len >= BUFSZ) 812150622Srik printf ("%s: too long packet: %d bytes: ", 813150622Srik d->name, len); 814150622Srik else if (! m->m_next) 815150622Srik cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 816150622Srik else { 817150622Srik u_char *buf = d->chan->tbuf[d->chan->te]; 818150622Srik m_copydata (m, 0, len, buf); 819150622Srik cp_send_packet (d->chan, buf, len, 0); 820150622Srik } 821150622Srik m_freem (m); 822150622Srik /* Set up transmit timeout, if the transmit ring is not empty.*/ 823150622Srik d->timeout = 10; 824150622Srik } 825150622Srik#ifndef NETGRAPH 826150622Srik d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 827150622Srik#endif 828150622Srik} 829150622Srik 830150622Srik/* 831150622Srik * Start output on the interface. 832150622Srik * Always called on splimp(). 833150622Srik */ 834150622Srikstatic void cp_start (drv_t *d) 835150622Srik{ 836150622Srik if (d->running) { 837150622Srik if (! d->chan->dtr) 838150622Srik cp_set_dtr (d->chan, 1); 839150622Srik if (! d->chan->rts) 840150622Srik cp_set_rts (d->chan, 1); 841150622Srik cp_send (d); 842199407Sjhb callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 843150622Srik } 844150622Srik} 845150622Srik 846150622Srik/* 847150622Srik * Handle transmit timeouts. 848150622Srik * Recover after lost transmit interrupts. 849150622Srik * Always called on splimp(). 850150622Srik */ 851150622Srikstatic void cp_watchdog (drv_t *d) 852150622Srik{ 853150622Srik CP_DEBUG (d, ("device timeout\n")); 854150622Srik if (d->running) { 855150622Srik cp_stop_chan (d->chan); 856150622Srik cp_stop_e1 (d->chan); 857150622Srik cp_start_e1 (d->chan); 858150622Srik cp_start_chan (d->chan, 1, 1, 0, 0); 859150622Srik cp_set_dtr (d->chan, 1); 860150622Srik cp_set_rts (d->chan, 1); 861150622Srik cp_start (d); 862150622Srik } 863150622Srik} 864150622Srik 865199407Sjhbstatic void cp_watchdog_timer (void *arg) 866199407Sjhb{ 867199407Sjhb drv_t *d = arg; 868199407Sjhb bdrv_t *bd = d->board->sys; 869199407Sjhb 870199407Sjhb CP_LOCK (bd); 871199407Sjhb if (d->timeout == 1) 872199407Sjhb cp_watchdog (d); 873199407Sjhb if (d->timeout) 874199407Sjhb d->timeout--; 875199407Sjhb callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 876199407Sjhb CP_UNLOCK (bd); 877199407Sjhb} 878199407Sjhb 879150622Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len) 880150622Srik{ 881150622Srik drv_t *d = c->sys; 882150622Srik 883150622Srik d->timeout = 0; 884199407Sjhb#ifndef NETGRAPH 885150622Srik ++d->ifp->if_opackets; 886150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 887150622Srik#endif 888150622Srik cp_start (d); 889150622Srik} 890150622Srik 891150622Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len) 892150622Srik{ 893150622Srik drv_t *d = c->sys; 894150622Srik struct mbuf *m; 895150622Srik#ifdef NETGRAPH 896150622Srik int error; 897150622Srik#endif 898150622Srik 899150622Srik if (! d->running) 900150622Srik return; 901150622Srik 902150622Srik m = makembuf (data, len); 903150622Srik if (! m) { 904150622Srik CP_DEBUG (d, ("no memory for packet\n")); 905150622Srik#ifndef NETGRAPH 906150622Srik ++d->ifp->if_iqdrops; 907150622Srik#endif 908150622Srik return; 909150622Srik } 910150622Srik if (c->debug > 1) 911150622Srik printmbuf (m); 912150622Srik#ifdef NETGRAPH 913150622Srik m->m_pkthdr.rcvif = 0; 914150622Srik NG_SEND_DATA_ONLY (error, d->hook, m); 915150622Srik#else 916150622Srik ++d->ifp->if_ipackets; 917150622Srik m->m_pkthdr.rcvif = d->ifp; 918150622Srik /* Check if there's a BPF listener on this interface. 919150622Srik * If so, hand off the raw packet to bpf. */ 920165632Sjhb BPF_TAP (d->ifp, data, len); 921150622Srik IF_ENQUEUE (&d->queue, m); 922150622Srik#endif 923150622Srik} 924150622Srik 925150622Srikstatic void cp_error (cp_chan_t *c, int data) 926150622Srik{ 927150622Srik drv_t *d = c->sys; 928150622Srik 929150622Srik switch (data) { 930150622Srik case CP_FRAME: 931150622Srik CP_DEBUG (d, ("frame error\n")); 932150622Srik#ifndef NETGRAPH 933150622Srik ++d->ifp->if_ierrors; 934150622Srik#endif 935150622Srik break; 936150622Srik case CP_CRC: 937150622Srik CP_DEBUG (d, ("crc error\n")); 938150622Srik#ifndef NETGRAPH 939150622Srik ++d->ifp->if_ierrors; 940150622Srik#endif 941150622Srik break; 942150622Srik case CP_OVERRUN: 943150622Srik CP_DEBUG (d, ("overrun error\n")); 944150622Srik#ifndef NETGRAPH 945150622Srik ++d->ifp->if_collisions; 946150622Srik ++d->ifp->if_ierrors; 947150622Srik#endif 948150622Srik break; 949150622Srik case CP_OVERFLOW: 950150622Srik CP_DEBUG (d, ("overflow error\n")); 951150622Srik#ifndef NETGRAPH 952150622Srik ++d->ifp->if_ierrors; 953150622Srik#endif 954150622Srik break; 955150622Srik case CP_UNDERRUN: 956150622Srik CP_DEBUG (d, ("underrun error\n")); 957150622Srik d->timeout = 0; 958199407Sjhb#ifndef NETGRAPH 959150622Srik ++d->ifp->if_oerrors; 960150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 961150622Srik#endif 962150622Srik cp_start (d); 963150622Srik break; 964150622Srik default: 965150622Srik CP_DEBUG (d, ("error #%d\n", data)); 966150622Srik break; 967150622Srik } 968150622Srik} 969150622Srik 970150622Srik/* 971128967Srik * You also need read, write, open, close routines. 972128967Srik * This should get you started 973128967Srik */ 974130585Sphkstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 975128967Srik{ 976183397Sed int unit = dev2unit (dev); 977128967Srik drv_t *d; 978128967Srik 979128967Srik if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 980128967Srik return ENXIO; 981128967Srik CP_DEBUG2 (d, ("cp_open\n")); 982128967Srik return 0; 983128967Srik} 984128967Srik 985128967Srik/* 986128967Srik * Only called on the LAST close. 987128967Srik */ 988130585Sphkstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 989128967Srik{ 990183397Sed drv_t *d = channel [dev2unit (dev)]; 991128967Srik 992128967Srik CP_DEBUG2 (d, ("cp_close\n")); 993128967Srik return 0; 994128967Srik} 995128967Srik 996128967Srikstatic int cp_modem_status (cp_chan_t *c) 997128967Srik{ 998128967Srik drv_t *d = c->sys; 999138823Srik bdrv_t *bd = d->board->sys; 1000128967Srik int status, s; 1001128967Srik 1002128967Srik status = d->running ? TIOCM_LE : 0; 1003128967Srik s = splimp (); 1004138823Srik CP_LOCK (bd); 1005128967Srik if (cp_get_cd (c)) status |= TIOCM_CD; 1006128967Srik if (cp_get_cts (c)) status |= TIOCM_CTS; 1007128967Srik if (cp_get_dsr (c)) status |= TIOCM_DSR; 1008128967Srik if (c->dtr) status |= TIOCM_DTR; 1009128967Srik if (c->rts) status |= TIOCM_RTS; 1010138823Srik CP_UNLOCK (bd); 1011128967Srik splx (s); 1012128967Srik return status; 1013128967Srik} 1014128967Srik 1015130585Sphkstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1016128967Srik{ 1017183397Sed drv_t *d = channel [dev2unit (dev)]; 1018138823Srik bdrv_t *bd = d->board->sys; 1019128967Srik cp_chan_t *c = d->chan; 1020128967Srik struct serial_statistics *st; 1021128967Srik struct e1_statistics *opte1; 1022128967Srik struct e3_statistics *opte3; 1023128967Srik int error, s; 1024128967Srik char mask[16]; 1025128967Srik 1026128967Srik switch (cmd) { 1027128967Srik case SERIAL_GETREGISTERED: 1028133646Srik CP_DEBUG2 (d, ("ioctl: getregistered\n")); 1029128967Srik bzero (mask, sizeof(mask)); 1030128967Srik for (s=0; s<NBRD*NCHAN; ++s) 1031128967Srik if (channel [s]) 1032128967Srik mask [s/8] |= 1 << (s & 7); 1033133646Srik bcopy (mask, data, sizeof (mask)); 1034128967Srik return 0; 1035128967Srik 1036128967Srik#ifndef NETGRAPH 1037128967Srik case SERIAL_GETPROTO: 1038133646Srik CP_DEBUG2 (d, ("ioctl: getproto\n")); 1039147256Sbrooks strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1040147256Sbrooks (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1041133646Srik return 0; 1042128967Srik 1043128967Srik case SERIAL_SETPROTO: 1044133646Srik CP_DEBUG2 (d, ("ioctl: setproto\n")); 1045133646Srik /* Only for superuser! */ 1046164033Srwatson error = priv_check (td, PRIV_DRIVER); 1047133646Srik if (error) 1048133646Srik return error; 1049148887Srwatson if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) 1050128967Srik return EBUSY; 1051133646Srik if (! strcmp ("cisco", (char*)data)) { 1052147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1053147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1054147256Sbrooks d->ifp->if_flags |= PP_CISCO; 1055138873Srik } else if (! strcmp ("fr", (char*)data) && PP_FR) { 1056147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1057147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1058133646Srik } else if (! strcmp ("ppp", (char*)data)) { 1059147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_FR; 1060147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1061147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1062133646Srik } else 1063128967Srik return EINVAL; 1064133646Srik return 0; 1065128967Srik 1066128967Srik case SERIAL_GETKEEPALIVE: 1067133646Srik CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1068147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1069147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1070128967Srik return EINVAL; 1071147256Sbrooks *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1072133646Srik return 0; 1073128967Srik 1074128967Srik case SERIAL_SETKEEPALIVE: 1075133646Srik CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1076133646Srik /* Only for superuser! */ 1077164033Srwatson error = priv_check (td, PRIV_DRIVER); 1078133646Srik if (error) 1079133646Srik return error; 1080147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1081147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1082128967Srik return EINVAL; 1083128967Srik s = splimp (); 1084138823Srik CP_LOCK (bd); 1085133646Srik if (*(int*)data) 1086147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1087128967Srik else 1088147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1089138823Srik CP_UNLOCK (bd); 1090128967Srik splx (s); 1091133646Srik return 0; 1092128967Srik#endif /*NETGRAPH*/ 1093128967Srik 1094128967Srik case SERIAL_GETMODE: 1095133646Srik CP_DEBUG2 (d, ("ioctl: getmode\n")); 1096128967Srik *(int*)data = SERIAL_HDLC; 1097133646Srik return 0; 1098128967Srik 1099128967Srik case SERIAL_SETMODE: 1100133646Srik /* Only for superuser! */ 1101164033Srwatson error = priv_check (td, PRIV_DRIVER); 1102133646Srik if (error) 1103133646Srik return error; 1104128967Srik if (*(int*)data != SERIAL_HDLC) 1105128967Srik return EINVAL; 1106133646Srik return 0; 1107128967Srik 1108128967Srik case SERIAL_GETCFG: 1109133646Srik CP_DEBUG2 (d, ("ioctl: getcfg\n")); 1110128967Srik if (c->type != T_E1 || c->unfram) 1111128967Srik return EINVAL; 1112128967Srik *(char*)data = c->board->mux ? 'c' : 'a'; 1113133646Srik return 0; 1114128967Srik 1115128967Srik case SERIAL_SETCFG: 1116133646Srik CP_DEBUG2 (d, ("ioctl: setcfg\n")); 1117164033Srwatson error = priv_check (td, PRIV_DRIVER); 1118133646Srik if (error) 1119133646Srik return error; 1120128967Srik if (c->type != T_E1) 1121128967Srik return EINVAL; 1122133646Srik s = splimp (); 1123138823Srik CP_LOCK (bd); 1124128967Srik cp_set_mux (c->board, *((char*)data) == 'c'); 1125138823Srik CP_UNLOCK (bd); 1126133646Srik splx (s); 1127133646Srik return 0; 1128128967Srik 1129128967Srik case SERIAL_GETSTAT: 1130133646Srik CP_DEBUG2 (d, ("ioctl: getstat\n")); 1131133646Srik st = (struct serial_statistics*) data; 1132133646Srik st->rintr = c->rintr; 1133133646Srik st->tintr = c->tintr; 1134133646Srik st->mintr = 0; 1135133646Srik st->ibytes = c->ibytes; 1136133646Srik st->ipkts = c->ipkts; 1137133646Srik st->obytes = c->obytes; 1138133646Srik st->opkts = c->opkts; 1139128967Srik st->ierrs = c->overrun + c->frame + c->crc; 1140128967Srik st->oerrs = c->underrun; 1141133646Srik return 0; 1142128967Srik 1143128967Srik case SERIAL_GETESTAT: 1144133646Srik CP_DEBUG2 (d, ("ioctl: getestat\n")); 1145128967Srik if (c->type != T_E1 && c->type != T_G703) 1146128967Srik return EINVAL; 1147128967Srik opte1 = (struct e1_statistics*) data; 1148128967Srik opte1->status = c->status; 1149128967Srik opte1->cursec = c->cursec; 1150128967Srik opte1->totsec = c->totsec + c->cursec; 1151128967Srik 1152128967Srik opte1->currnt.bpv = c->currnt.bpv; 1153128967Srik opte1->currnt.fse = c->currnt.fse; 1154128967Srik opte1->currnt.crce = c->currnt.crce; 1155128967Srik opte1->currnt.rcrce = c->currnt.rcrce; 1156128967Srik opte1->currnt.uas = c->currnt.uas; 1157128967Srik opte1->currnt.les = c->currnt.les; 1158128967Srik opte1->currnt.es = c->currnt.es; 1159128967Srik opte1->currnt.bes = c->currnt.bes; 1160128967Srik opte1->currnt.ses = c->currnt.ses; 1161128967Srik opte1->currnt.oofs = c->currnt.oofs; 1162128967Srik opte1->currnt.css = c->currnt.css; 1163128967Srik opte1->currnt.dm = c->currnt.dm; 1164128967Srik 1165128967Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1166128967Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1167128967Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1168128967Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1169128967Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1170128967Srik opte1->total.les = c->total.les + c->currnt.les; 1171128967Srik opte1->total.es = c->total.es + c->currnt.es; 1172128967Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1173128967Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1174128967Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1175128967Srik opte1->total.css = c->total.css + c->currnt.css; 1176128967Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1177128967Srik for (s=0; s<48; ++s) { 1178128967Srik opte1->interval[s].bpv = c->interval[s].bpv; 1179128967Srik opte1->interval[s].fse = c->interval[s].fse; 1180128967Srik opte1->interval[s].crce = c->interval[s].crce; 1181128967Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1182128967Srik opte1->interval[s].uas = c->interval[s].uas; 1183128967Srik opte1->interval[s].les = c->interval[s].les; 1184128967Srik opte1->interval[s].es = c->interval[s].es; 1185128967Srik opte1->interval[s].bes = c->interval[s].bes; 1186128967Srik opte1->interval[s].ses = c->interval[s].ses; 1187128967Srik opte1->interval[s].oofs = c->interval[s].oofs; 1188128967Srik opte1->interval[s].css = c->interval[s].css; 1189128967Srik opte1->interval[s].dm = c->interval[s].dm; 1190128967Srik } 1191128967Srik return 0; 1192128967Srik 1193128967Srik case SERIAL_GETE3STAT: 1194133646Srik CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 1195128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1196128967Srik return EINVAL; 1197133646Srik opte3 = (struct e3_statistics*) data; 1198128967Srik 1199128967Srik opte3->status = c->e3status; 1200128967Srik opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 1201128967Srik opte3->totsec = c->e3tsec + opte3->cursec; 1202128967Srik 1203128967Srik opte3->ccv = c->e3ccv; 1204128967Srik opte3->tcv = c->e3tcv + opte3->ccv; 1205128967Srik 1206128967Srik for (s = 0; s < 48; ++s) { 1207128967Srik opte3->icv[s] = c->e3icv[s]; 1208128967Srik } 1209133646Srik return 0; 1210128967Srik 1211128967Srik case SERIAL_CLRSTAT: 1212133646Srik CP_DEBUG2 (d, ("ioctl: clrstat\n")); 1213133646Srik /* Only for superuser! */ 1214164033Srwatson error = priv_check (td, PRIV_DRIVER); 1215133646Srik if (error) 1216133646Srik return error; 1217128967Srik c->rintr = 0; 1218128967Srik c->tintr = 0; 1219128967Srik c->ibytes = 0; 1220128967Srik c->obytes = 0; 1221128967Srik c->ipkts = 0; 1222128967Srik c->opkts = 0; 1223128967Srik c->overrun = 0; 1224128967Srik c->frame = 0; 1225133646Srik c->crc = 0; 1226128967Srik c->underrun = 0; 1227128967Srik bzero (&c->currnt, sizeof (c->currnt)); 1228128967Srik bzero (&c->total, sizeof (c->total)); 1229128967Srik bzero (c->interval, sizeof (c->interval)); 1230128967Srik c->e3ccv = 0; 1231128967Srik c->e3tcv = 0; 1232128967Srik bzero (c->e3icv, sizeof (c->e3icv)); 1233133646Srik return 0; 1234128967Srik 1235128967Srik case SERIAL_GETBAUD: 1236133646Srik CP_DEBUG2 (d, ("ioctl: getbaud\n")); 1237133646Srik *(long*)data = c->baud; 1238133646Srik return 0; 1239128967Srik 1240128967Srik case SERIAL_SETBAUD: 1241133646Srik CP_DEBUG2 (d, ("ioctl: setbaud\n")); 1242133646Srik /* Only for superuser! */ 1243164033Srwatson error = priv_check (td, PRIV_DRIVER); 1244133646Srik if (error) 1245133646Srik return error; 1246133646Srik s = splimp (); 1247138823Srik CP_LOCK (bd); 1248133646Srik cp_set_baud (c, *(long*)data); 1249138823Srik CP_UNLOCK (bd); 1250133646Srik splx (s); 1251133646Srik return 0; 1252128967Srik 1253128967Srik case SERIAL_GETLOOP: 1254133646Srik CP_DEBUG2 (d, ("ioctl: getloop\n")); 1255133646Srik *(int*)data = c->lloop; 1256133646Srik return 0; 1257128967Srik 1258128967Srik case SERIAL_SETLOOP: 1259133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1260133646Srik /* Only for superuser! */ 1261164033Srwatson error = priv_check (td, PRIV_DRIVER); 1262133646Srik if (error) 1263133646Srik return error; 1264133646Srik s = splimp (); 1265138823Srik CP_LOCK (bd); 1266128967Srik cp_set_lloop (c, *(int*)data); 1267138823Srik CP_UNLOCK (bd); 1268133646Srik splx (s); 1269133646Srik return 0; 1270128967Srik 1271128967Srik case SERIAL_GETDPLL: 1272133646Srik CP_DEBUG2 (d, ("ioctl: getdpll\n")); 1273133646Srik if (c->type != T_SERIAL) 1274133646Srik return EINVAL; 1275133646Srik *(int*)data = c->dpll; 1276133646Srik return 0; 1277128967Srik 1278128967Srik case SERIAL_SETDPLL: 1279133646Srik CP_DEBUG2 (d, ("ioctl: setdpll\n")); 1280133646Srik /* Only for superuser! */ 1281164033Srwatson error = priv_check (td, PRIV_DRIVER); 1282133646Srik if (error) 1283133646Srik return error; 1284133646Srik if (c->type != T_SERIAL) 1285133646Srik return EINVAL; 1286133646Srik s = splimp (); 1287138823Srik CP_LOCK (bd); 1288133646Srik cp_set_dpll (c, *(int*)data); 1289138823Srik CP_UNLOCK (bd); 1290133646Srik splx (s); 1291133646Srik return 0; 1292128967Srik 1293128967Srik case SERIAL_GETNRZI: 1294133646Srik CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 1295133646Srik if (c->type != T_SERIAL) 1296133646Srik return EINVAL; 1297133646Srik *(int*)data = c->nrzi; 1298133646Srik return 0; 1299128967Srik 1300128967Srik case SERIAL_SETNRZI: 1301133646Srik CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 1302133646Srik /* Only for superuser! */ 1303164033Srwatson error = priv_check (td, PRIV_DRIVER); 1304133646Srik if (error) 1305133646Srik return error; 1306133646Srik if (c->type != T_SERIAL) 1307133646Srik return EINVAL; 1308133646Srik s = splimp (); 1309138823Srik CP_LOCK (bd); 1310133646Srik cp_set_nrzi (c, *(int*)data); 1311138823Srik CP_UNLOCK (bd); 1312133646Srik splx (s); 1313133646Srik return 0; 1314128967Srik 1315128967Srik case SERIAL_GETDEBUG: 1316133646Srik CP_DEBUG2 (d, ("ioctl: getdebug\n")); 1317133646Srik *(int*)data = d->chan->debug; 1318133646Srik return 0; 1319128967Srik 1320128967Srik case SERIAL_SETDEBUG: 1321133646Srik CP_DEBUG2 (d, ("ioctl: setdebug\n")); 1322133646Srik /* Only for superuser! */ 1323164033Srwatson error = priv_check (td, PRIV_DRIVER); 1324133646Srik if (error) 1325133646Srik return error; 1326180132Srik#ifndef NETGRAPH 1327180132Srik /* 1328180132Srik * The debug_shadow is always greater than zero for logic 1329180132Srik * simplicity. For switching debug off the IFF_DEBUG is 1330180132Srik * responsible. 1331180132Srik */ 1332180132Srik d->chan->debug_shadow = (*(int*)data) ? (*(int*)data) : 1; 1333180132Srik if (d->ifp->if_flags & IFF_DEBUG) 1334180132Srik d->chan->debug = d->chan->debug_shadow; 1335180132Srik#else 1336133646Srik d->chan->debug = *(int*)data; 1337128967Srik#endif 1338133646Srik return 0; 1339128967Srik 1340128967Srik case SERIAL_GETHIGAIN: 1341133646Srik CP_DEBUG2 (d, ("ioctl: gethigain\n")); 1342133646Srik if (c->type != T_E1) 1343133646Srik return EINVAL; 1344133646Srik *(int*)data = c->higain; 1345128967Srik return 0; 1346128967Srik 1347128967Srik case SERIAL_SETHIGAIN: 1348133646Srik CP_DEBUG2 (d, ("ioctl: sethigain\n")); 1349133646Srik /* Only for superuser! */ 1350164033Srwatson error = priv_check (td, PRIV_DRIVER); 1351133646Srik if (error) 1352133646Srik return error; 1353133646Srik if (c->type != T_E1) 1354133646Srik return EINVAL; 1355128967Srik s = splimp (); 1356138823Srik CP_LOCK (bd); 1357128967Srik cp_set_higain (c, *(int*)data); 1358138823Srik CP_UNLOCK (bd); 1359128967Srik splx (s); 1360128967Srik return 0; 1361128967Srik 1362128967Srik case SERIAL_GETPHONY: 1363128967Srik CP_DEBUG2 (d, ("ioctl: getphony\n")); 1364133646Srik if (c->type != T_E1) 1365133646Srik return EINVAL; 1366133646Srik *(int*)data = c->phony; 1367128967Srik return 0; 1368128967Srik 1369128967Srik case SERIAL_SETPHONY: 1370128967Srik CP_DEBUG2 (d, ("ioctl: setphony\n")); 1371133646Srik /* Only for superuser! */ 1372164033Srwatson error = priv_check (td, PRIV_DRIVER); 1373133646Srik if (error) 1374133646Srik return error; 1375133646Srik if (c->type != T_E1) 1376133646Srik return EINVAL; 1377128967Srik s = splimp (); 1378138823Srik CP_LOCK (bd); 1379128967Srik cp_set_phony (c, *(int*)data); 1380138823Srik CP_UNLOCK (bd); 1381128967Srik splx (s); 1382128967Srik return 0; 1383128967Srik 1384128967Srik case SERIAL_GETUNFRAM: 1385128967Srik CP_DEBUG2 (d, ("ioctl: getunfram\n")); 1386133646Srik if (c->type != T_E1) 1387133646Srik return EINVAL; 1388133646Srik *(int*)data = c->unfram; 1389128967Srik return 0; 1390128967Srik 1391128967Srik case SERIAL_SETUNFRAM: 1392128967Srik CP_DEBUG2 (d, ("ioctl: setunfram\n")); 1393133646Srik /* Only for superuser! */ 1394164033Srwatson error = priv_check (td, PRIV_DRIVER); 1395133646Srik if (error) 1396133646Srik return error; 1397133646Srik if (c->type != T_E1) 1398133646Srik return EINVAL; 1399128967Srik s = splimp (); 1400138823Srik CP_LOCK (bd); 1401128967Srik cp_set_unfram (c, *(int*)data); 1402138823Srik CP_UNLOCK (bd); 1403128967Srik splx (s); 1404128967Srik return 0; 1405128967Srik 1406128967Srik case SERIAL_GETSCRAMBLER: 1407128967Srik CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 1408133646Srik if (c->type != T_G703 && !c->unfram) 1409133646Srik return EINVAL; 1410133646Srik *(int*)data = c->scrambler; 1411128967Srik return 0; 1412128967Srik 1413128967Srik case SERIAL_SETSCRAMBLER: 1414128967Srik CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 1415133646Srik /* Only for superuser! */ 1416164033Srwatson error = priv_check (td, PRIV_DRIVER); 1417133646Srik if (error) 1418133646Srik return error; 1419133646Srik if (c->type != T_G703 && !c->unfram) 1420133646Srik return EINVAL; 1421128967Srik s = splimp (); 1422138823Srik CP_LOCK (bd); 1423128967Srik cp_set_scrambler (c, *(int*)data); 1424138823Srik CP_UNLOCK (bd); 1425128967Srik splx (s); 1426128967Srik return 0; 1427128967Srik 1428128967Srik case SERIAL_GETMONITOR: 1429128967Srik CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 1430133646Srik if (c->type != T_E1 && 1431128967Srik c->type != T_E3 && 1432128967Srik c->type != T_T3 && 1433128967Srik c->type != T_STS1) 1434133646Srik return EINVAL; 1435133646Srik *(int*)data = c->monitor; 1436128967Srik return 0; 1437128967Srik 1438128967Srik case SERIAL_SETMONITOR: 1439128967Srik CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 1440133646Srik /* Only for superuser! */ 1441164033Srwatson error = priv_check (td, PRIV_DRIVER); 1442133646Srik if (error) 1443133646Srik return error; 1444133646Srik if (c->type != T_E1) 1445133646Srik return EINVAL; 1446128967Srik s = splimp (); 1447138823Srik CP_LOCK (bd); 1448128967Srik cp_set_monitor (c, *(int*)data); 1449138823Srik CP_UNLOCK (bd); 1450128967Srik splx (s); 1451128967Srik return 0; 1452128967Srik 1453128967Srik case SERIAL_GETUSE16: 1454133646Srik CP_DEBUG2 (d, ("ioctl: getuse16\n")); 1455133646Srik if (c->type != T_E1 || c->unfram) 1456133646Srik return EINVAL; 1457133646Srik *(int*)data = c->use16; 1458128967Srik return 0; 1459128967Srik 1460128967Srik case SERIAL_SETUSE16: 1461133646Srik CP_DEBUG2 (d, ("ioctl: setuse16\n")); 1462133646Srik /* Only for superuser! */ 1463164033Srwatson error = priv_check (td, PRIV_DRIVER); 1464133646Srik if (error) 1465133646Srik return error; 1466133646Srik if (c->type != T_E1) 1467133646Srik return EINVAL; 1468128967Srik s = splimp (); 1469138823Srik CP_LOCK (bd); 1470128967Srik cp_set_use16 (c, *(int*)data); 1471138823Srik CP_UNLOCK (bd); 1472128967Srik splx (s); 1473128967Srik return 0; 1474128967Srik 1475128967Srik case SERIAL_GETCRC4: 1476133646Srik CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 1477133646Srik if (c->type != T_E1 || c->unfram) 1478133646Srik return EINVAL; 1479133646Srik *(int*)data = c->crc4; 1480128967Srik return 0; 1481128967Srik 1482128967Srik case SERIAL_SETCRC4: 1483133646Srik CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 1484133646Srik /* Only for superuser! */ 1485164033Srwatson error = priv_check (td, PRIV_DRIVER); 1486133646Srik if (error) 1487133646Srik return error; 1488133646Srik if (c->type != T_E1) 1489133646Srik return EINVAL; 1490128967Srik s = splimp (); 1491138823Srik CP_LOCK (bd); 1492128967Srik cp_set_crc4 (c, *(int*)data); 1493138823Srik CP_UNLOCK (bd); 1494128967Srik splx (s); 1495128967Srik return 0; 1496128967Srik 1497128967Srik case SERIAL_GETCLK: 1498133646Srik CP_DEBUG2 (d, ("ioctl: getclk\n")); 1499133646Srik if (c->type != T_E1 && 1500128967Srik c->type != T_G703 && 1501128967Srik c->type != T_E3 && 1502128967Srik c->type != T_T3 && 1503128967Srik c->type != T_STS1) 1504133646Srik return EINVAL; 1505128967Srik switch (c->gsyn) { 1506128967Srik default: *(int*)data = E1CLK_INTERNAL; break; 1507128967Srik case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1508128967Srik case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1509128967Srik case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1510128967Srik case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 1511128967Srik case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 1512128967Srik } 1513128967Srik return 0; 1514128967Srik 1515128967Srik case SERIAL_SETCLK: 1516133646Srik CP_DEBUG2 (d, ("ioctl: setclk\n")); 1517133646Srik /* Only for superuser! */ 1518164033Srwatson error = priv_check (td, PRIV_DRIVER); 1519133646Srik if (error) 1520133646Srik return error; 1521128967Srik if (c->type != T_E1 && 1522128967Srik c->type != T_G703 && 1523128967Srik c->type != T_E3 && 1524128967Srik c->type != T_T3 && 1525128967Srik c->type != T_STS1) 1526133646Srik return EINVAL; 1527128967Srik s = splimp (); 1528138823Srik CP_LOCK (bd); 1529128967Srik switch (*(int*)data) { 1530128967Srik default: cp_set_gsyn (c, GSYN_INT); break; 1531128967Srik case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 1532128967Srik case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 1533128967Srik case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 1534128967Srik case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 1535128967Srik case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 1536128967Srik } 1537138823Srik CP_UNLOCK (bd); 1538128967Srik splx (s); 1539128967Srik return 0; 1540128967Srik 1541128967Srik case SERIAL_GETTIMESLOTS: 1542133646Srik CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1543133646Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1544133646Srik return EINVAL; 1545133646Srik *(u_long*)data = c->ts; 1546128967Srik return 0; 1547128967Srik 1548128967Srik case SERIAL_SETTIMESLOTS: 1549133646Srik CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 1550133646Srik /* Only for superuser! */ 1551164033Srwatson error = priv_check (td, PRIV_DRIVER); 1552133646Srik if (error) 1553133646Srik return error; 1554128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1555133646Srik return EINVAL; 1556128967Srik s = splimp (); 1557138823Srik CP_LOCK (bd); 1558128967Srik cp_set_ts (c, *(u_long*)data); 1559138823Srik CP_UNLOCK (bd); 1560128967Srik splx (s); 1561128967Srik return 0; 1562128967Srik 1563128967Srik case SERIAL_GETINVCLK: 1564133646Srik CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 1565128967Srik#if 1 1566128967Srik return EINVAL; 1567128967Srik#else 1568133646Srik if (c->type != T_SERIAL) 1569133646Srik return EINVAL; 1570133646Srik *(int*)data = c->invtxc; 1571128967Srik return 0; 1572128967Srik#endif 1573128967Srik 1574128967Srik case SERIAL_SETINVCLK: 1575133646Srik CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 1576133646Srik /* Only for superuser! */ 1577164033Srwatson error = priv_check (td, PRIV_DRIVER); 1578133646Srik if (error) 1579133646Srik return error; 1580133646Srik if (c->type != T_SERIAL) 1581133646Srik return EINVAL; 1582128967Srik s = splimp (); 1583138823Srik CP_LOCK (bd); 1584128967Srik cp_set_invtxc (c, *(int*)data); 1585128967Srik cp_set_invrxc (c, *(int*)data); 1586138823Srik CP_UNLOCK (bd); 1587128967Srik splx (s); 1588128967Srik return 0; 1589128967Srik 1590128967Srik case SERIAL_GETINVTCLK: 1591133646Srik CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 1592133646Srik if (c->type != T_SERIAL) 1593133646Srik return EINVAL; 1594133646Srik *(int*)data = c->invtxc; 1595128967Srik return 0; 1596128967Srik 1597128967Srik case SERIAL_SETINVTCLK: 1598133646Srik CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 1599133646Srik /* Only for superuser! */ 1600164033Srwatson error = priv_check (td, PRIV_DRIVER); 1601133646Srik if (error) 1602133646Srik return error; 1603133646Srik if (c->type != T_SERIAL) 1604133646Srik return EINVAL; 1605128967Srik s = splimp (); 1606138823Srik CP_LOCK (bd); 1607128967Srik cp_set_invtxc (c, *(int*)data); 1608138823Srik CP_UNLOCK (bd); 1609128967Srik splx (s); 1610128967Srik return 0; 1611128967Srik 1612128967Srik case SERIAL_GETINVRCLK: 1613133646Srik CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 1614133646Srik if (c->type != T_SERIAL) 1615133646Srik return EINVAL; 1616133646Srik *(int*)data = c->invrxc; 1617128967Srik return 0; 1618128967Srik 1619128967Srik case SERIAL_SETINVRCLK: 1620133646Srik CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 1621133646Srik /* Only for superuser! */ 1622164033Srwatson error = priv_check (td, PRIV_DRIVER); 1623133646Srik if (error) 1624133646Srik return error; 1625133646Srik if (c->type != T_SERIAL) 1626133646Srik return EINVAL; 1627128967Srik s = splimp (); 1628138823Srik CP_LOCK (bd); 1629128967Srik cp_set_invrxc (c, *(int*)data); 1630138823Srik CP_UNLOCK (bd); 1631128967Srik splx (s); 1632128967Srik return 0; 1633128967Srik 1634128967Srik case SERIAL_GETLEVEL: 1635133646Srik CP_DEBUG2 (d, ("ioctl: getlevel\n")); 1636133646Srik if (c->type != T_G703) 1637133646Srik return EINVAL; 1638128967Srik s = splimp (); 1639138823Srik CP_LOCK (bd); 1640133646Srik *(int*)data = cp_get_lq (c); 1641138823Srik CP_UNLOCK (bd); 1642128967Srik splx (s); 1643128967Srik return 0; 1644128967Srik 1645128967Srik#if 0 1646128967Srik case SERIAL_RESET: 1647133646Srik CP_DEBUG2 (d, ("ioctl: reset\n")); 1648133646Srik /* Only for superuser! */ 1649164033Srwatson error = priv_check (td, PRIV_DRIVER); 1650133646Srik if (error) 1651133646Srik return error; 1652128967Srik s = splimp (); 1653138823Srik CP_LOCK (bd); 1654128967Srik cp_reset (c->board, 0, 0); 1655138823Srik CP_UNLOCK (bd); 1656128967Srik splx (s); 1657128967Srik return 0; 1658128967Srik 1659128967Srik case SERIAL_HARDRESET: 1660133646Srik CP_DEBUG2 (d, ("ioctl: hardreset\n")); 1661133646Srik /* Only for superuser! */ 1662164033Srwatson error = priv_check (td, PRIV_DRIVER); 1663133646Srik if (error) 1664133646Srik return error; 1665128967Srik s = splimp (); 1666138823Srik CP_LOCK (bd); 1667128967Srik /* hard_reset (c->board); */ 1668138823Srik CP_UNLOCK (bd); 1669128967Srik splx (s); 1670128967Srik return 0; 1671128967Srik#endif 1672128967Srik 1673128967Srik case SERIAL_GETCABLE: 1674133646Srik CP_DEBUG2 (d, ("ioctl: getcable\n")); 1675133646Srik if (c->type != T_SERIAL) 1676133646Srik return EINVAL; 1677128967Srik s = splimp (); 1678138823Srik CP_LOCK (bd); 1679128967Srik *(int*)data = cp_get_cable (c); 1680138823Srik CP_UNLOCK (bd); 1681128967Srik splx (s); 1682128967Srik return 0; 1683128967Srik 1684128967Srik case SERIAL_GETDIR: 1685133646Srik CP_DEBUG2 (d, ("ioctl: getdir\n")); 1686133646Srik if (c->type != T_E1 && c->type != T_DATA) 1687133646Srik return EINVAL; 1688128967Srik *(int*)data = c->dir; 1689128967Srik return 0; 1690128967Srik 1691128967Srik case SERIAL_SETDIR: 1692133646Srik CP_DEBUG2 (d, ("ioctl: setdir\n")); 1693133646Srik /* Only for superuser! */ 1694164033Srwatson error = priv_check (td, PRIV_DRIVER); 1695133646Srik if (error) 1696133646Srik return error; 1697128967Srik s = splimp (); 1698138823Srik CP_LOCK (bd); 1699128967Srik cp_set_dir (c, *(int*)data); 1700138823Srik CP_UNLOCK (bd); 1701128967Srik splx (s); 1702128967Srik return 0; 1703128967Srik 1704128967Srik case SERIAL_GETRLOOP: 1705133646Srik CP_DEBUG2 (d, ("ioctl: getrloop\n")); 1706133646Srik if (c->type != T_G703 && 1707128967Srik c->type != T_E3 && 1708128967Srik c->type != T_T3 && 1709128967Srik c->type != T_STS1) 1710133646Srik return EINVAL; 1711133646Srik *(int*)data = cp_get_rloop (c); 1712133646Srik return 0; 1713128967Srik 1714128967Srik case SERIAL_SETRLOOP: 1715133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1716133646Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1717133646Srik return EINVAL; 1718133646Srik /* Only for superuser! */ 1719164033Srwatson error = priv_check (td, PRIV_DRIVER); 1720133646Srik if (error) 1721133646Srik return error; 1722133646Srik s = splimp (); 1723138823Srik CP_LOCK (bd); 1724128967Srik cp_set_rloop (c, *(int*)data); 1725138823Srik CP_UNLOCK (bd); 1726133646Srik splx (s); 1727133646Srik return 0; 1728128967Srik 1729128967Srik case SERIAL_GETCABLEN: 1730133646Srik CP_DEBUG2 (d, ("ioctl: getcablen\n")); 1731133646Srik if (c->type != T_T3 && c->type != T_STS1) 1732133646Srik return EINVAL; 1733133646Srik *(int*)data = c->cablen; 1734133646Srik return 0; 1735128967Srik 1736128967Srik case SERIAL_SETCABLEN: 1737133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1738133646Srik if (c->type != T_T3 && c->type != T_STS1) 1739133646Srik return EINVAL; 1740133646Srik /* Only for superuser! */ 1741164033Srwatson error = priv_check (td, PRIV_DRIVER); 1742133646Srik if (error) 1743133646Srik return error; 1744133646Srik s = splimp (); 1745138823Srik CP_LOCK (bd); 1746128967Srik cp_set_cablen (c, *(int*)data); 1747138823Srik CP_UNLOCK (bd); 1748133646Srik splx (s); 1749133646Srik return 0; 1750128967Srik 1751133646Srik case TIOCSDTR: /* Set DTR */ 1752128967Srik s = splimp (); 1753138823Srik CP_LOCK (bd); 1754128967Srik cp_set_dtr (c, 1); 1755138823Srik CP_UNLOCK (bd); 1756128967Srik splx (s); 1757128967Srik return 0; 1758128967Srik 1759133646Srik case TIOCCDTR: /* Clear DTR */ 1760128967Srik s = splimp (); 1761138823Srik CP_LOCK (bd); 1762128967Srik cp_set_dtr (c, 0); 1763138823Srik CP_UNLOCK (bd); 1764128967Srik splx (s); 1765128967Srik return 0; 1766128967Srik 1767133646Srik case TIOCMSET: /* Set DTR/RTS */ 1768128967Srik s = splimp (); 1769138823Srik CP_LOCK (bd); 1770128967Srik cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1771128967Srik cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1772138823Srik CP_UNLOCK (bd); 1773128967Srik splx (s); 1774128967Srik return 0; 1775128967Srik 1776133646Srik case TIOCMBIS: /* Add DTR/RTS */ 1777128967Srik s = splimp (); 1778138823Srik CP_LOCK (bd); 1779128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 1780128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 1781138823Srik CP_UNLOCK (bd); 1782128967Srik splx (s); 1783128967Srik return 0; 1784128967Srik 1785133646Srik case TIOCMBIC: /* Clear DTR/RTS */ 1786128967Srik s = splimp (); 1787138823Srik CP_LOCK (bd); 1788128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1789128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1790138823Srik CP_UNLOCK (bd); 1791128967Srik splx (s); 1792128967Srik return 0; 1793128967Srik 1794133646Srik case TIOCMGET: /* Get modem status */ 1795128967Srik *(int*)data = cp_modem_status (c); 1796128967Srik return 0; 1797128967Srik } 1798128967Srik return ENOTTY; 1799128967Srik} 1800128967Srik 1801128967Srik#ifdef NETGRAPH 1802128967Srikstatic int ng_cp_constructor (node_p node) 1803128967Srik{ 1804128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1805128967Srik CP_DEBUG (d, ("Constructor\n")); 1806128967Srik return EINVAL; 1807128967Srik} 1808128967Srik 1809128967Srikstatic int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1810128967Srik{ 1811128967Srik int s; 1812128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1813138823Srik bdrv_t *bd = d->board->sys; 1814128967Srik 1815128967Srik CP_DEBUG (d, ("Newhook\n")); 1816128967Srik /* Attach debug hook */ 1817128967Srik if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1818128967Srik NG_HOOK_SET_PRIVATE (hook, NULL); 1819128967Srik d->debug_hook = hook; 1820128967Srik return 0; 1821128967Srik } 1822128967Srik 1823128967Srik /* Check for raw hook */ 1824128967Srik if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1825128967Srik return EINVAL; 1826128967Srik 1827128967Srik NG_HOOK_SET_PRIVATE (hook, d); 1828128967Srik d->hook = hook; 1829128967Srik s = splimp (); 1830138823Srik CP_LOCK (bd); 1831128967Srik cp_up (d); 1832138823Srik CP_UNLOCK (bd); 1833128967Srik splx (s); 1834128967Srik return 0; 1835128967Srik} 1836128967Srik 1837128967Srikstatic char *format_timeslots (u_long s) 1838128967Srik{ 1839128967Srik static char buf [100]; 1840128967Srik char *p = buf; 1841128967Srik int i; 1842128967Srik 1843128967Srik for (i=1; i<32; ++i) 1844128967Srik if ((s >> i) & 1) { 1845128967Srik int prev = (i > 1) & (s >> (i-1)); 1846128967Srik int next = (i < 31) & (s >> (i+1)); 1847128967Srik 1848128967Srik if (prev) { 1849128967Srik if (next) 1850128967Srik continue; 1851128967Srik *p++ = '-'; 1852128967Srik } else if (p > buf) 1853128967Srik *p++ = ','; 1854128967Srik 1855128967Srik if (i >= 10) 1856128967Srik *p++ = '0' + i / 10; 1857128967Srik *p++ = '0' + i % 10; 1858128967Srik } 1859128967Srik *p = 0; 1860128967Srik return buf; 1861128967Srik} 1862128967Srik 1863128967Srikstatic int print_modems (char *s, cp_chan_t *c, int need_header) 1864128967Srik{ 1865128967Srik int status = cp_modem_status (c); 1866128967Srik int length = 0; 1867128967Srik 1868128967Srik if (need_header) 1869128967Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1870128967Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1871128967Srik status & TIOCM_LE ? "On" : "-", 1872128967Srik status & TIOCM_DTR ? "On" : "-", 1873128967Srik status & TIOCM_DSR ? "On" : "-", 1874128967Srik status & TIOCM_RTS ? "On" : "-", 1875128967Srik status & TIOCM_CTS ? "On" : "-", 1876128967Srik status & TIOCM_CD ? "On" : "-"); 1877128967Srik return length; 1878128967Srik} 1879128967Srik 1880128967Srikstatic int print_stats (char *s, cp_chan_t *c, int need_header) 1881128967Srik{ 1882128967Srik int length = 0; 1883128967Srik 1884128967Srik if (need_header) 1885128967Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1886128967Srik length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1887128967Srik c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1888128967Srik c->ipkts, c->overrun + c->frame + c->crc, 1889128967Srik (unsigned long) c->obytes, c->opkts, c->underrun); 1890128967Srik return length; 1891128967Srik} 1892128967Srik 1893128967Srikstatic char *format_e1_status (u_char status) 1894128967Srik{ 1895128967Srik static char buf [80]; 1896128967Srik 1897128967Srik if (status & E1_NOALARM) 1898128967Srik return "Ok"; 1899128967Srik buf[0] = 0; 1900128967Srik if (status & E1_LOS) strcat (buf, ",LOS"); 1901128967Srik if (status & E1_AIS) strcat (buf, ",AIS"); 1902128967Srik if (status & E1_LOF) strcat (buf, ",LOF"); 1903128967Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 1904128967Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1905128967Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 1906128967Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1907128967Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1908128967Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1909128967Srik if (buf[0] == ',') 1910128967Srik return buf+1; 1911128967Srik return "Unknown"; 1912128967Srik} 1913128967Srik 1914128967Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1915128967Srik{ 1916128967Srik int n, length = 0; 1917128967Srik 1918128967Srik if (numerator < 1 || divider < 1) { 1919128967Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 1920128967Srik return length; 1921128967Srik } 1922128967Srik n = (int) (0.5 + 1000.0 * numerator / divider); 1923128967Srik if (n < 1000) { 1924128967Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1925128967Srik return length; 1926128967Srik } 1927128967Srik *(s + length) = leftalign ? '/' : ' '; 1928128967Srik length ++; 1929128967Srik 1930128967Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 1931128967Srik else if (n >= 100000) n = (n+50) / 100 * 100; 1932128967Srik else if (n >= 10000) n = (n+5) / 10 * 10; 1933128967Srik 1934128967Srik switch (n) { 1935128967Srik case 1000: length += printf (s+length, ".999"); return length; 1936128967Srik case 10000: n = 9990; break; 1937128967Srik case 100000: n = 99900; break; 1938128967Srik case 1000000: n = 999000; break; 1939128967Srik } 1940133646Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1941128967Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1942128967Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1943133646Srik else length += sprintf (s+length, "%d", n/1000); 1944128967Srik 1945128967Srik return length; 1946128967Srik} 1947128967Srik 1948128967Srikstatic int print_e1_stats (char *s, cp_chan_t *c) 1949128967Srik{ 1950128967Srik struct e1_counters total; 1951128967Srik u_long totsec; 1952128967Srik int length = 0; 1953128967Srik 1954128967Srik totsec = c->totsec + c->cursec; 1955128967Srik total.bpv = c->total.bpv + c->currnt.bpv; 1956128967Srik total.fse = c->total.fse + c->currnt.fse; 1957128967Srik total.crce = c->total.crce + c->currnt.crce; 1958128967Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 1959128967Srik total.uas = c->total.uas + c->currnt.uas; 1960128967Srik total.les = c->total.les + c->currnt.les; 1961128967Srik total.es = c->total.es + c->currnt.es; 1962128967Srik total.bes = c->total.bes + c->currnt.bes; 1963128967Srik total.ses = c->total.ses + c->currnt.ses; 1964128967Srik total.oofs = c->total.oofs + c->currnt.oofs; 1965128967Srik total.css = c->total.css + c->currnt.css; 1966128967Srik total.dm = c->total.dm + c->currnt.dm; 1967128967Srik 1968128967Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1969128967Srik 1970128967Srik /* Unavailable seconds, degraded minutes */ 1971128967Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1972128967Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1973128967Srik 1974128967Srik /* Bipolar violations, frame sync errors */ 1975128967Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1976128967Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1977128967Srik 1978128967Srik /* CRC errors, remote CRC errors (E-bit) */ 1979128967Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 1980128967Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 1981128967Srik 1982128967Srik /* Errored seconds, line errored seconds */ 1983128967Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 1984128967Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 1985128967Srik 1986128967Srik /* Severely errored seconds, burst errored seconds */ 1987128967Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 1988128967Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 1989128967Srik 1990128967Srik /* Out of frame seconds, controlled slip seconds */ 1991128967Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 1992128967Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 1993128967Srik 1994128967Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 1995128967Srik 1996128967Srik /* Print total statistics. */ 1997128967Srik length += print_frac (s + length, 0, total.uas, totsec); 1998128967Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 1999128967Srik 2000128967Srik length += print_frac (s + length, 0, total.bpv, totsec); 2001128967Srik length += print_frac (s + length, 1, total.fse, totsec); 2002128967Srik 2003128967Srik length += print_frac (s + length, 0, total.crce, totsec); 2004128967Srik length += print_frac (s + length, 1, total.rcrce, totsec); 2005128967Srik 2006128967Srik length += print_frac (s + length, 0, total.es, totsec); 2007128967Srik length += print_frac (s + length, 1, total.les, totsec); 2008128967Srik 2009128967Srik length += print_frac (s + length, 0, total.ses, totsec); 2010128967Srik length += print_frac (s + length, 1, total.bes, totsec); 2011128967Srik 2012128967Srik length += print_frac (s + length, 0, total.oofs, totsec); 2013128967Srik length += print_frac (s + length, 1, total.css, totsec); 2014128967Srik 2015128967Srik length += sprintf (s + length, " -- Total\n"); 2016128967Srik return length; 2017128967Srik} 2018128967Srik 2019128967Srikstatic int print_chan (char *s, cp_chan_t *c) 2020128967Srik{ 2021128967Srik drv_t *d = c->sys; 2022138823Srik bdrv_t *bd = d->board->sys; 2023128967Srik int length = 0; 2024128967Srik 2025128967Srik length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2026128967Srik if (d->chan->debug) 2027128967Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 2028128967Srik 2029128967Srik if (c->board->mux) { 2030128967Srik length += sprintf (s + length, " cfg=C"); 2031128967Srik } else { 2032128967Srik length += sprintf (s + length, " cfg=A"); 2033128967Srik } 2034128967Srik 2035128967Srik if (c->baud) 2036128967Srik length += sprintf (s + length, " %ld", c->baud); 2037128967Srik else 2038128967Srik length += sprintf (s + length, " extclock"); 2039128967Srik 2040128967Srik if (c->type == T_E1 || c->type == T_G703) 2041128967Srik switch (c->gsyn) { 2042128967Srik case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2043128967Srik case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2044128967Srik case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2045128967Srik case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2046128967Srik case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2047128967Srik case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2048128967Srik } 2049128967Srik if (c->type == T_SERIAL) { 2050128967Srik length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2051128967Srik length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2052128967Srik length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2053128967Srik } 2054128967Srik if (c->type == T_E1) 2055128967Srik length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2056128967Srik 2057128967Srik length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2058128967Srik 2059128967Srik if (c->type == T_E1) 2060128967Srik length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2061128967Srik if (c->type == T_G703) { 2062128967Srik int lq, x; 2063128967Srik 2064128967Srik x = splimp (); 2065138823Srik CP_LOCK (bd); 2066128967Srik lq = cp_get_lq (c); 2067138823Srik CP_UNLOCK (bd); 2068128967Srik splx (x); 2069128967Srik length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2070128967Srik } 2071128967Srik length += sprintf (s + length, "\n"); 2072128967Srik return length; 2073128967Srik} 2074128967Srik 2075128967Srikstatic int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2076128967Srik{ 2077128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2078128967Srik struct ng_mesg *msg; 2079128967Srik struct ng_mesg *resp = NULL; 2080128967Srik int error = 0; 2081128967Srik 2082128967Srik CP_DEBUG (d, ("Rcvmsg\n")); 2083128967Srik NGI_GET_MSG (item, msg); 2084128967Srik switch (msg->header.typecookie) { 2085128967Srik default: 2086128967Srik error = EINVAL; 2087128967Srik break; 2088128967Srik 2089128967Srik case NGM_CP_COOKIE: 2090128967Srik printf ("Not implemented yet\n"); 2091128967Srik error = EINVAL; 2092128967Srik break; 2093128967Srik 2094128967Srik case NGM_GENERIC_COOKIE: 2095128967Srik switch (msg->header.cmd) { 2096128967Srik default: 2097128967Srik error = EINVAL; 2098128967Srik break; 2099128967Srik 2100128967Srik case NGM_TEXT_STATUS: { 2101128967Srik char *s; 2102128967Srik int l = 0; 2103128967Srik int dl = sizeof (struct ng_mesg) + 730; 2104128967Srik 2105128967Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2106128967Srik if (! resp) { 2107128967Srik error = ENOMEM; 2108128967Srik break; 2109128967Srik } 2110128967Srik s = (resp)->data; 2111128967Srik if (d) { 2112128967Srik l += print_chan (s + l, d->chan); 2113128967Srik l += print_stats (s + l, d->chan, 1); 2114128967Srik l += print_modems (s + l, d->chan, 1); 2115128967Srik l += print_e1_stats (s + l, d->chan); 2116128967Srik } else 2117128967Srik l += sprintf (s + l, "Error: node not connect to channel"); 2118193813Simp strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRSIZ); 2119128967Srik } 2120128967Srik break; 2121128967Srik } 2122128967Srik break; 2123128967Srik } 2124128967Srik NG_RESPOND_MSG (error, node, item, resp); 2125128967Srik NG_FREE_MSG (msg); 2126128967Srik return error; 2127128967Srik} 2128128967Srik 2129128967Srikstatic int ng_cp_rcvdata (hook_p hook, item_p item) 2130128967Srik{ 2131128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2132128967Srik struct mbuf *m; 2133131108Sjulian struct ng_tag_prio *ptag; 2134138823Srik bdrv_t *bd = d->board->sys; 2135128967Srik struct ifqueue *q; 2136128967Srik int s; 2137128967Srik 2138128967Srik CP_DEBUG2 (d, ("Rcvdata\n")); 2139128967Srik NGI_GET_M (item, m); 2140128967Srik NG_FREE_ITEM (item); 2141128967Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 2142128967Srik NG_FREE_M (m); 2143128967Srik return ENETDOWN; 2144128967Srik } 2145131108Sjulian 2146131108Sjulian /* Check for high priority data */ 2147131108Sjulian if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2148131108Sjulian NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2149131108Sjulian q = &d->hi_queue; 2150131108Sjulian else 2151131108Sjulian q = &d->queue; 2152131108Sjulian 2153128967Srik s = splimp (); 2154138823Srik CP_LOCK (bd); 2155128967Srik IF_LOCK (q); 2156128967Srik if (_IF_QFULL (q)) { 2157128967Srik _IF_DROP (q); 2158128967Srik IF_UNLOCK (q); 2159138823Srik CP_UNLOCK (bd); 2160128967Srik splx (s); 2161128967Srik NG_FREE_M (m); 2162128967Srik return ENOBUFS; 2163128967Srik } 2164128967Srik _IF_ENQUEUE (q, m); 2165128967Srik IF_UNLOCK (q); 2166128967Srik cp_start (d); 2167138823Srik CP_UNLOCK (bd); 2168128967Srik splx (s); 2169128967Srik return 0; 2170128967Srik} 2171128967Srik 2172128967Srikstatic int ng_cp_rmnode (node_p node) 2173128967Srik{ 2174128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2175128967Srik 2176128967Srik CP_DEBUG (d, ("Rmnode\n")); 2177128967Srik if (d && d->running) { 2178138823Srik bdrv_t *bd = d->board->sys; 2179128967Srik int s = splimp (); 2180138823Srik CP_LOCK (bd); 2181128967Srik cp_down (d); 2182138823Srik CP_UNLOCK (bd); 2183128967Srik splx (s); 2184128967Srik } 2185128967Srik#ifdef KLD_MODULE 2186132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 2187128967Srik NG_NODE_SET_PRIVATE (node, NULL); 2188128967Srik NG_NODE_UNREF (node); 2189128967Srik } 2190132464Sjulian NG_NODE_REVIVE(node); /* Persistant node */ 2191128967Srik#endif 2192128967Srik return 0; 2193128967Srik} 2194128967Srik 2195128967Srikstatic int ng_cp_connect (hook_p hook) 2196128967Srik{ 2197128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2198128967Srik 2199128967Srik if (d) { 2200128967Srik CP_DEBUG (d, ("Connect\n")); 2201199407Sjhb callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 2202128967Srik } 2203128967Srik 2204128967Srik return 0; 2205128967Srik} 2206128967Srik 2207128967Srikstatic int ng_cp_disconnect (hook_p hook) 2208128967Srik{ 2209128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2210128967Srik 2211128967Srik if (d) { 2212128967Srik CP_DEBUG (d, ("Disconnect\n")); 2213128967Srik if (NG_HOOK_PRIVATE (hook)) 2214128967Srik { 2215138823Srik bdrv_t *bd = d->board->sys; 2216128967Srik int s = splimp (); 2217138823Srik CP_LOCK (bd); 2218128967Srik cp_down (d); 2219138823Srik CP_UNLOCK (bd); 2220128967Srik splx (s); 2221128967Srik } 2222138823Srik /* If we were wait it than it reasserted now, just stop it. */ 2223138823Srik if (!callout_drain (&d->timeout_handle)) 2224138823Srik callout_stop (&d->timeout_handle); 2225128967Srik } 2226128967Srik return 0; 2227128967Srik} 2228128967Srik#endif 2229128967Srik 2230128967Srikstatic int cp_modevent (module_t mod, int type, void *unused) 2231128967Srik{ 2232128967Srik static int load_count = 0; 2233128967Srik 2234128967Srik switch (type) { 2235128967Srik case MOD_LOAD: 2236138673Srik#ifdef NETGRAPH 2237128967Srik if (ng_newtype (&typestruct)) 2238128967Srik printf ("Failed to register ng_cp\n"); 2239128967Srik#endif 2240128967Srik ++load_count; 2241188661Srwatson callout_init (&timeout_handle, CALLOUT_MPSAFE); 2242138823Srik callout_reset (&timeout_handle, hz*5, cp_timeout, 0); 2243128967Srik break; 2244128967Srik case MOD_UNLOAD: 2245128967Srik if (load_count == 1) { 2246128967Srik printf ("Removing device entry for Tau-PCI\n"); 2247138673Srik#ifdef NETGRAPH 2248128967Srik ng_rmtype (&typestruct); 2249128967Srik#endif 2250128967Srik } 2251138823Srik /* If we were wait it than it reasserted now, just stop it. 2252138823Srik * Actually we shouldn't get this condition. But code could be 2253138823Srik * changed in the future, so just be a litle paranoid. 2254138823Srik */ 2255138823Srik if (!callout_drain (&timeout_handle)) 2256138823Srik callout_stop (&timeout_handle); 2257128967Srik --load_count; 2258128967Srik break; 2259128967Srik case MOD_SHUTDOWN: 2260128967Srik break; 2261128967Srik } 2262128967Srik return 0; 2263128967Srik} 2264128967Srik 2265128967Srik#ifdef NETGRAPH 2266128967Srikstatic struct ng_type typestruct = { 2267129837Srik .version = NG_ABI_VERSION, 2268129837Srik .name = NG_CP_NODE_TYPE, 2269129837Srik .constructor = ng_cp_constructor, 2270129837Srik .rcvmsg = ng_cp_rcvmsg, 2271129837Srik .shutdown = ng_cp_rmnode, 2272129837Srik .newhook = ng_cp_newhook, 2273129837Srik .connect = ng_cp_connect, 2274129837Srik .rcvdata = ng_cp_rcvdata, 2275129837Srik .disconnect = ng_cp_disconnect, 2276128967Srik}; 2277128967Srik#endif /*NETGRAPH*/ 2278128967Srik 2279128967Srik#ifdef NETGRAPH 2280128967SrikMODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2281128967Srik#else 2282128967SrikMODULE_DEPEND (cp, sppp, 1, 1, 1); 2283128967Srik#endif 2284128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2285138823SrikMODULE_VERSION (cp, 1); 2286