if_cp.c revision 150622
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 150622 2005-09-27 16:12:49Z rik $"); 26128967Srik 27128967Srik#include <sys/param.h> 28128967Srik#include <sys/ucred.h> 29128967Srik#include <sys/proc.h> 30128967Srik#include <sys/systm.h> 31128967Srik#include <sys/mbuf.h> 32128967Srik#include <sys/kernel.h> 33129879Sphk#include <sys/module.h> 34128967Srik#include <sys/conf.h> 35128967Srik#include <sys/malloc.h> 36128967Srik#include <sys/socket.h> 37128967Srik#include <sys/sockio.h> 38138823Srik#include <sys/sysctl.h> 39128967Srik#include <sys/tty.h> 40130971Srik#include <sys/bus.h> 41128967Srik#include <vm/vm.h> 42128967Srik#include <vm/pmap.h> 43128967Srik#include <net/if.h> 44138673Srik#include <dev/pci/pcivar.h> 45138673Srik#include <dev/pci/pcireg.h> 46128967Srik#include <machine/bus.h> 47128967Srik#include <sys/rman.h> 48128967Srik#include "opt_ng_cronyx.h" 49128967Srik#ifdef NETGRAPH_CRONYX 50128967Srik# include "opt_netgraph.h" 51128967Srik# ifndef NETGRAPH 52133646Srik# error #option NETGRAPH missed from configuration 53128967Srik# endif 54128967Srik# include <netgraph/ng_message.h> 55128967Srik# include <netgraph/netgraph.h> 56130985Srik# include <dev/cp/ng_cp.h> 57128967Srik#else 58128967Srik# include <net/if_sppp.h> 59147256Sbrooks# include <net/if_types.h> 60147256Sbrooks#include <dev/pci/pcivar.h> 61128967Srik# define PP_CISCO IFF_LINK2 62130971Srik# include <net/bpf.h> 63128967Srik#endif 64128967Srik#include <dev/cx/machdep.h> 65128967Srik#include <dev/cp/cpddk.h> 66128967Srik#include <machine/cserial.h> 67128967Srik#include <machine/resource.h> 68128967Srik#include <machine/pmap.h> 69128967Srik 70128967Srik/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 71128967Srik#ifndef PP_FR 72128967Srik#define PP_FR 0 73128967Srik#endif 74128967Srik 75128967Srik#define CP_DEBUG(d,s) ({if (d->chan->debug) {\ 76128967Srik printf ("%s: ", d->name); printf s;}}) 77128967Srik#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 78128967Srik printf ("%s: ", d->name); printf s;}}) 79138823Srik#define CP_LOCK_NAME "cpX" 80128967Srik 81138823Srikstatic int cp_mpsafenet = 1; 82138823SrikTUNABLE_INT("debug.cp.mpsafenet", &cp_mpsafenet); 83138823SrikSYSCTL_NODE(_debug, OID_AUTO, cp, CTLFLAG_RD, 0, "Cronyx Tau-PCI Adapters"); 84138823SrikSYSCTL_INT(_debug_cp, OID_AUTO, mpsafenet, CTLFLAG_RD, &cp_mpsafenet, 0, 85138823Srik "Enable/disable MPSAFE network support for Cronyx Tau-PCI Adapters"); 86138823Srik 87138823Srik#define CP_LOCK(_bd) do { \ 88138823Srik if (cp_mpsafenet) \ 89138823Srik mtx_lock (&(_bd)->cp_mtx); \ 90138823Srik } while (0) 91138823Srik#define CP_UNLOCK(_bd) do { \ 92138823Srik if (cp_mpsafenet) \ 93138823Srik mtx_unlock (&(_bd)->cp_mtx); \ 94138823Srik } while (0) 95138823Srik 96138823Srik#define CP_LOCK_ASSERT(_bd) do { \ 97138823Srik if (cp_mpsafenet) \ 98138823Srik mtx_assert (&(_bd)->cp_mtx, MA_OWNED); \ 99138823Srik } while (0) 100138823Srik 101128967Srikstatic int cp_probe __P((device_t)); 102128967Srikstatic int cp_attach __P((device_t)); 103128967Srikstatic int cp_detach __P((device_t)); 104128967Srik 105128967Srikstatic device_method_t cp_methods[] = { 106128967Srik /* Device interface */ 107128967Srik DEVMETHOD(device_probe, cp_probe), 108128967Srik DEVMETHOD(device_attach, cp_attach), 109128967Srik DEVMETHOD(device_detach, cp_detach), 110128967Srik 111128967Srik {0, 0} 112128967Srik}; 113128967Srik 114130985Sriktypedef struct _cp_dma_mem_t { 115130985Srik unsigned long phys; 116130985Srik void *virt; 117130985Srik size_t size; 118130985Srik bus_dma_tag_t dmat; 119130985Srik bus_dmamap_t mapp; 120130985Srik} cp_dma_mem_t; 121128967Srik 122128967Sriktypedef struct _drv_t { 123138823Srik char name [8]; 124138823Srik int running; 125138823Srik cp_chan_t *chan; 126138823Srik cp_board_t *board; 127138823Srik cp_dma_mem_t dmamem; 128128967Srik#ifdef NETGRAPH 129128967Srik char nodename [NG_NODELEN+1]; 130128967Srik hook_p hook; 131128967Srik hook_p debug_hook; 132128967Srik node_p node; 133128967Srik struct ifqueue queue; 134128967Srik struct ifqueue hi_queue; 135128967Srik short timeout; 136138823Srik struct callout timeout_handle; 137128967Srik#else 138138823Srik struct ifqueue queue; 139147256Sbrooks struct ifnet *ifp; 140128967Srik#endif 141138823Srik struct cdev *devt; 142128967Srik} drv_t; 143128967Srik 144130985Sriktypedef struct _bdrv_t { 145130985Srik cp_board_t *board; 146130985Srik struct resource *cp_res; 147130985Srik struct resource *cp_irq; 148130985Srik void *cp_intrhand; 149130985Srik cp_dma_mem_t dmamem; 150130985Srik drv_t channel [NCHAN]; 151138823Srik struct mtx cp_mtx; 152130985Srik} bdrv_t; 153130985Srik 154130985Srikstatic driver_t cp_driver = { 155130985Srik "cp", 156130985Srik cp_methods, 157130985Srik sizeof(bdrv_t), 158130985Srik}; 159130985Srik 160130985Srikstatic devclass_t cp_devclass; 161130985Srik 162128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len); 163128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len); 164128967Srikstatic void cp_error (cp_chan_t *c, int data); 165128967Srikstatic void cp_up (drv_t *d); 166128967Srikstatic void cp_start (drv_t *d); 167128967Srikstatic void cp_down (drv_t *d); 168128967Srikstatic void cp_watchdog (drv_t *d); 169128967Srik#ifdef NETGRAPH 170128967Srikextern struct ng_type typestruct; 171128967Srik#else 172128967Srikstatic void cp_ifstart (struct ifnet *ifp); 173128967Srikstatic void cp_tlf (struct sppp *sp); 174128967Srikstatic void cp_tls (struct sppp *sp); 175128967Srikstatic void cp_ifwatchdog (struct ifnet *ifp); 176128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 177128967Srikstatic void cp_initialize (void *softc); 178128967Srik#endif 179128967Srik 180128967Srikstatic cp_board_t *adapter [NBRD]; 181128967Srikstatic drv_t *channel [NBRD*NCHAN]; 182138823Srikstatic struct callout led_timo [NBRD]; 183138823Srikstatic struct callout timeout_handle; 184128967Srik 185128967Srikstatic int cp_destroy = 0; 186128967Srik 187150622Srikstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td); 188150622Srikstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td); 189150622Srikstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); 190150622Srikstatic struct cdevsw cp_cdevsw = { 191150622Srik .d_version = D_VERSION, 192150622Srik .d_open = cp_open, 193150622Srik .d_close = cp_close, 194150622Srik .d_ioctl = cp_ioctl, 195150622Srik .d_name = "cp", 196150622Srik .d_flags = D_NEEDGIANT, 197150622Srik}; 198150622Srik 199128967Srik/* 200150622Srik * Print the mbuf chain, for debug purposes only. 201150622Srik */ 202150622Srikstatic void printmbuf (struct mbuf *m) 203150622Srik{ 204150622Srik printf ("mbuf:"); 205150622Srik for (; m; m=m->m_next) { 206150622Srik if (m->m_flags & M_PKTHDR) 207150622Srik printf (" HDR %d:", m->m_pkthdr.len); 208150622Srik if (m->m_flags & M_EXT) 209150622Srik printf (" EXT:"); 210150622Srik printf (" %d", m->m_len); 211150622Srik } 212150622Srik printf ("\n"); 213150622Srik} 214150622Srik 215150622Srik/* 216150622Srik * Make an mbuf from data. 217150622Srik */ 218150622Srikstatic struct mbuf *makembuf (void *buf, unsigned len) 219150622Srik{ 220150622Srik struct mbuf *m; 221150622Srik 222150622Srik MGETHDR (m, M_DONTWAIT, MT_DATA); 223150622Srik if (! m) 224150622Srik return 0; 225150622Srik MCLGET (m, M_DONTWAIT); 226150622Srik if (! (m->m_flags & M_EXT)) { 227150622Srik m_freem (m); 228150622Srik return 0; 229150622Srik } 230150622Srik m->m_pkthdr.len = m->m_len = len; 231150622Srik bcopy (buf, mtod (m, caddr_t), len); 232150622Srik return m; 233150622Srik} 234150622Srik 235150622Srikstatic int cp_probe (device_t dev) 236150622Srik{ 237150622Srik if ((pci_get_vendor (dev) == cp_vendor_id) && 238150622Srik (pci_get_device (dev) == cp_device_id)) { 239150622Srik device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 240150622Srik return BUS_PROBE_DEFAULT; 241150622Srik } 242150622Srik return ENXIO; 243150622Srik} 244150622Srik 245150622Srikstatic void cp_timeout (void *arg) 246150622Srik{ 247150622Srik drv_t *d; 248150622Srik int s, i, k; 249150622Srik 250150622Srik for (i = 0; i < NBRD; ++i) { 251150622Srik if (adapter[i] == NULL) 252150622Srik continue; 253150622Srik for (k = 0; k < NCHAN; ++k) { 254150622Srik s = splimp (); 255150622Srik if (cp_destroy) { 256150622Srik splx (s); 257150622Srik return; 258150622Srik } 259150622Srik d = channel[i * NCHAN + k]; 260150622Srik if (!d) { 261150622Srik splx (s); 262150622Srik continue; 263150622Srik } 264150622Srik CP_LOCK ((bdrv_t *)d->board->sys); 265150622Srik switch (d->chan->type) { 266150622Srik case T_G703: 267150622Srik cp_g703_timer (d->chan); 268150622Srik break; 269150622Srik case T_E1: 270150622Srik cp_e1_timer (d->chan); 271150622Srik break; 272150622Srik case T_E3: 273150622Srik case T_T3: 274150622Srik case T_STS1: 275150622Srik cp_e3_timer (d->chan); 276150622Srik break; 277150622Srik default: 278150622Srik break; 279150622Srik } 280150622Srik CP_UNLOCK ((bdrv_t *)d->board->sys); 281150622Srik splx (s); 282150622Srik } 283150622Srik } 284150622Srik s = splimp (); 285150622Srik if (!cp_destroy) 286150622Srik callout_reset (&timeout_handle, hz, cp_timeout, 0); 287150622Srik splx (s); 288150622Srik} 289150622Srik 290150622Srikstatic void cp_led_off (void *arg) 291150622Srik{ 292150622Srik cp_board_t *b = arg; 293150622Srik bdrv_t *bd = (bdrv_t *) b->sys; 294150622Srik int s; 295150622Srik s = splimp (); 296150622Srik if (cp_destroy) { 297150622Srik splx (s); 298150622Srik return; 299150622Srik } 300150622Srik CP_LOCK (bd); 301150622Srik cp_led (b, 0); 302150622Srik CP_UNLOCK (bd); 303150622Srik splx (s); 304150622Srik} 305150622Srik 306150622Srikstatic void cp_intr (void *arg) 307150622Srik{ 308150622Srik bdrv_t *bd = arg; 309150622Srik cp_board_t *b = bd->board; 310150622Srik#ifndef NETGRAPH 311150622Srik int i; 312150622Srik#endif 313150622Srik int s = splimp (); 314150622Srik if (cp_destroy) { 315150622Srik splx (s); 316150622Srik return; 317150622Srik } 318150622Srik CP_LOCK (bd); 319150622Srik /* Check if we are ready */ 320150622Srik if (b->sys == NULL) { 321150622Srik /* Not we are not, just cleanup. */ 322150622Srik cp_interrupt_poll (b, 1); 323150622Srik CP_UNLOCK (bd); 324150622Srik return; 325150622Srik } 326150622Srik /* Turn LED on. */ 327150622Srik cp_led (b, 1); 328150622Srik 329150622Srik cp_interrupt (b); 330150622Srik 331150622Srik /* Turn LED off 50 msec later. */ 332150622Srik callout_reset (&led_timo[b->num], hz/20, cp_led_off, b); 333150622Srik CP_UNLOCK (bd); 334150622Srik splx (s); 335150622Srik 336150622Srik#ifndef NETGRAPH 337150622Srik /* Pass packets in a lock-free state */ 338150622Srik for (i = 0; i < NCHAN && b->chan[i].type; i++) { 339150622Srik drv_t *d = b->chan[i].sys; 340150622Srik struct mbuf *m; 341150622Srik if (!d || !d->running) 342150622Srik continue; 343150622Srik while (_IF_QLEN(&d->queue)) { 344150622Srik IF_DEQUEUE (&d->queue,m); 345150622Srik if (!m) 346150622Srik continue; 347150622Srik sppp_input (d->ifp, m); 348150622Srik } 349150622Srik } 350150622Srik#endif 351150622Srik} 352150622Srik 353150622Srikstatic void 354150622Srikcp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 355150622Srik{ 356150622Srik unsigned long *addr; 357150622Srik 358150622Srik if (error) 359150622Srik return; 360150622Srik 361150622Srik KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 362150622Srik addr = arg; 363150622Srik *addr = segs->ds_addr; 364150622Srik} 365150622Srik 366150622Srikstatic int 367150622Srikcp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 368150622Srik{ 369150622Srik int error; 370150622Srik 371150622Srik error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 372150622Srik BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 373150622Srik dmem->size, 0, NULL, NULL, &dmem->dmat); 374150622Srik if (error) { 375150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 376150622Srik else printf ("cp%d: ", bnum); 377150622Srik printf ("couldn't allocate tag for dma memory\n"); 378150622Srik return 0; 379150622Srik } 380150622Srik error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 381150622Srik BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 382150622Srik if (error) { 383150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 384150622Srik else printf ("cp%d: ", bnum); 385150622Srik printf ("couldn't allocate mem for dma memory\n"); 386150622Srik bus_dma_tag_destroy (dmem->dmat); 387150622Srik return 0; 388150622Srik } 389150622Srik error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 390150622Srik dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); 391150622Srik if (error) { 392150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 393150622Srik else printf ("cp%d: ", bnum); 394150622Srik printf ("couldn't load mem map for dma memory\n"); 395150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 396150622Srik bus_dma_tag_destroy (dmem->dmat); 397150622Srik return 0; 398150622Srik } 399150622Srik return 1; 400150622Srik} 401150622Srik 402150622Srikstatic void 403150622Srikcp_bus_dma_mem_free (cp_dma_mem_t *dmem) 404150622Srik{ 405150622Srik bus_dmamap_unload (dmem->dmat, dmem->mapp); 406150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 407150622Srik bus_dma_tag_destroy (dmem->dmat); 408150622Srik} 409150622Srik 410150622Srik/* 411150622Srik * Called if the probe succeeded. 412150622Srik */ 413150622Srikstatic int cp_attach (device_t dev) 414150622Srik{ 415150622Srik bdrv_t *bd = device_get_softc (dev); 416150622Srik int unit = device_get_unit (dev); 417150622Srik char *cp_ln = CP_LOCK_NAME; 418150622Srik unsigned short res; 419150622Srik vm_offset_t vbase; 420150622Srik int rid, error; 421150622Srik cp_board_t *b; 422150622Srik cp_chan_t *c; 423150622Srik drv_t *d; 424150622Srik int s = splimp (); 425150622Srik 426150622Srik b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 427150622Srik if (!b) { 428150622Srik printf ("cp%d: couldn't allocate memory\n", unit); 429150622Srik splx (s); 430150622Srik return (ENXIO); 431150622Srik } 432150622Srik bzero (b, sizeof(cp_board_t)); 433150622Srik 434150622Srik bd->board = b; 435150622Srik rid = PCIR_BAR(0); 436150622Srik bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 437150622Srik 0, ~0, 1, RF_ACTIVE); 438150622Srik if (! bd->cp_res) { 439150622Srik printf ("cp%d: cannot map memory\n", unit); 440150622Srik free (b, M_DEVBUF); 441150622Srik splx (s); 442150622Srik return (ENXIO); 443150622Srik } 444150622Srik vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 445150622Srik 446150622Srik cp_ln[2] = '0' + unit; 447150622Srik mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 448150622Srik res = cp_init (b, unit, (u_char*) vbase); 449150622Srik if (res) { 450150622Srik printf ("cp%d: can't init, error code:%x\n", unit, res); 451150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 452150622Srik free (b, M_DEVBUF); 453150622Srik splx (s); 454150622Srik return (ENXIO); 455150622Srik } 456150622Srik 457150622Srik bd->dmamem.size = sizeof(cp_qbuf_t); 458150622Srik if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 459150622Srik free (b, M_DEVBUF); 460150622Srik splx (s); 461150622Srik return (ENXIO); 462150622Srik } 463150622Srik CP_LOCK (bd); 464150622Srik cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); 465150622Srik CP_UNLOCK (bd); 466150622Srik 467150622Srik rid = 0; 468150622Srik bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 469150622Srik RF_SHAREABLE | RF_ACTIVE); 470150622Srik if (! bd->cp_irq) { 471150622Srik cp_destroy = 1; 472150622Srik printf ("cp%d: cannot map interrupt\n", unit); 473150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 474150622Srik PCIR_BAR(0), bd->cp_res); 475150622Srik mtx_destroy (&bd->cp_mtx); 476150622Srik free (b, M_DEVBUF); 477150622Srik splx (s); 478150622Srik return (ENXIO); 479150622Srik } 480150622Srik callout_init (&led_timo[unit], cp_mpsafenet ? CALLOUT_MPSAFE : 0); 481150622Srik error = bus_setup_intr (dev, bd->cp_irq, 482150622Srik INTR_TYPE_NET|(cp_mpsafenet?INTR_MPSAFE:0), 483150622Srik cp_intr, bd, &bd->cp_intrhand); 484150622Srik if (error) { 485150622Srik cp_destroy = 1; 486150622Srik printf ("cp%d: cannot set up irq\n", unit); 487150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 488150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 489150622Srik PCIR_BAR(0), bd->cp_res); 490150622Srik mtx_destroy (&bd->cp_mtx); 491150622Srik free (b, M_DEVBUF); 492150622Srik splx (s); 493150622Srik return (ENXIO); 494150622Srik } 495150622Srik printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 496150622Srik 497150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 498150622Srik if (! c->type) 499150622Srik continue; 500150622Srik d = &bd->channel[c->num]; 501150622Srik d->dmamem.size = sizeof(cp_buf_t); 502150622Srik if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 503150622Srik continue; 504150622Srik channel [b->num*NCHAN + c->num] = d; 505150622Srik sprintf (d->name, "cp%d.%d", b->num, c->num); 506150622Srik d->board = b; 507150622Srik d->chan = c; 508150622Srik c->sys = d; 509150622Srik#ifdef NETGRAPH 510150622Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 511150622Srik printf ("%s: cannot make common node\n", d->name); 512150622Srik d->node = NULL; 513150622Srik continue; 514150622Srik } 515150622Srik NG_NODE_SET_PRIVATE (d->node, d); 516150622Srik sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 517150622Srik c->board->num*NCHAN + c->num); 518150622Srik if (ng_name_node (d->node, d->nodename)) { 519150622Srik printf ("%s: cannot name node\n", d->nodename); 520150622Srik NG_NODE_UNREF (d->node); 521150622Srik continue; 522150622Srik } 523150622Srik d->queue.ifq_maxlen = IFQ_MAXLEN; 524150622Srik d->hi_queue.ifq_maxlen = IFQ_MAXLEN; 525150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 526150622Srik mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 527150622Srik callout_init (&d->timeout_handle, 528150622Srik cp_mpsafenet ? CALLOUT_MPSAFE : 0); 529150622Srik#else /*NETGRAPH*/ 530150622Srik d->ifp = if_alloc(IFT_PPP); 531150622Srik if (d->ifp == NULL) { 532150622Srik printf ("%s: cannot if_alloc() interface\n", d->name); 533150622Srik continue; 534150622Srik } 535150622Srik d->ifp->if_softc = d; 536150622Srik if_initname (d->ifp, "cp", b->num * NCHAN + c->num); 537150622Srik d->ifp->if_mtu = PP_MTU; 538150622Srik d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 539150622Srik if (!cp_mpsafenet) 540150622Srik d->ifp->if_flags |= IFF_NEEDSGIANT; 541150622Srik d->ifp->if_ioctl = cp_sioctl; 542150622Srik d->ifp->if_start = cp_ifstart; 543150622Srik d->ifp->if_watchdog = cp_ifwatchdog; 544150622Srik d->ifp->if_init = cp_initialize; 545150622Srik d->queue.ifq_maxlen = NRBUF; 546150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 547150622Srik sppp_attach (d->ifp); 548150622Srik if_attach (d->ifp); 549150622Srik IFP2SP(d->ifp)->pp_tlf = cp_tlf; 550150622Srik IFP2SP(d->ifp)->pp_tls = cp_tls; 551150622Srik /* If BPF is in the kernel, call the attach for it. 552150622Srik * The header size of PPP or Cisco/HDLC is 4 bytes. */ 553150622Srik bpfattach (d->ifp, DLT_PPP, 4); 554150622Srik#endif /*NETGRAPH*/ 555150622Srik cp_start_e1 (c); 556150622Srik cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 557150622Srik 558150622Srik /* Register callback functions. */ 559150622Srik cp_register_transmit (c, &cp_transmit); 560150622Srik cp_register_receive (c, &cp_receive); 561150622Srik cp_register_error (c, &cp_error); 562150622Srik d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 563150622Srik GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 564150622Srik } 565150622Srik CP_LOCK (bd); 566150622Srik b->sys = bd; 567150622Srik adapter[unit] = b; 568150622Srik CP_UNLOCK (bd); 569150622Srik splx (s); 570150622Srik return 0; 571150622Srik} 572150622Srik 573150622Srikstatic int cp_detach (device_t dev) 574150622Srik{ 575150622Srik bdrv_t *bd = device_get_softc (dev); 576150622Srik cp_board_t *b = bd->board; 577150622Srik cp_chan_t *c; 578150622Srik int s; 579150622Srik 580150622Srik KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized")); 581150622Srik s = splimp (); 582150622Srik CP_LOCK (bd); 583150622Srik /* Check if the device is busy (open). */ 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; 589150622Srik if (d->running) { 590150622Srik CP_UNLOCK (bd); 591150622Srik splx (s); 592150622Srik return EBUSY; 593150622Srik } 594150622Srik } 595150622Srik 596150622Srik /* Ok, we can unload driver */ 597150622Srik /* At first we should stop all channels */ 598150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 599150622Srik drv_t *d = (drv_t*) c->sys; 600150622Srik 601150622Srik if (! d || ! d->chan->type) 602150622Srik continue; 603150622Srik 604150622Srik cp_stop_chan (c); 605150622Srik cp_stop_e1 (c); 606150622Srik cp_set_dtr (d->chan, 0); 607150622Srik cp_set_rts (d->chan, 0); 608150622Srik } 609150622Srik 610150622Srik /* Reset the adapter. */ 611150622Srik cp_destroy = 1; 612150622Srik cp_interrupt_poll (b, 1); 613150622Srik cp_led_off (b); 614150622Srik cp_reset (b, 0 ,0); 615150622Srik callout_stop (&led_timo[b->num]); 616150622Srik 617150622Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 618150622Srik drv_t *d = (drv_t*) c->sys; 619150622Srik 620150622Srik if (! d || ! d->chan->type) 621150622Srik continue; 622150622Srik#ifndef NETGRAPH 623150622Srik /* Detach from the packet filter list of interfaces. */ 624150622Srik bpfdetach (d->ifp); 625150622Srik 626150622Srik /* Detach from the sync PPP list. */ 627150622Srik sppp_detach (d->ifp); 628150622Srik 629150622Srik /* Detach from the system list of interfaces. */ 630150622Srik if_detach (d->ifp); 631150622Srik if_free (d->ifp); 632150622Srik IF_DRAIN (&d->queue); 633150622Srik mtx_destroy (&d->queue.ifq_mtx); 634150622Srik#else 635150622Srik if (d->node) { 636150622Srik ng_rmnode_self (d->node); 637150622Srik NG_NODE_UNREF (d->node); 638150622Srik d->node = NULL; 639150622Srik } 640150622Srik mtx_destroy (&d->queue.ifq_mtx); 641150622Srik mtx_destroy (&d->hi_queue.ifq_mtx); 642150622Srik#endif 643150622Srik destroy_dev (d->devt); 644150622Srik } 645150622Srik 646150622Srik b->sys = NULL; 647150622Srik CP_UNLOCK (bd); 648150622Srik 649150622Srik /* Disable the interrupt request. */ 650150622Srik bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 651150622Srik bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 652150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 653150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 654150622Srik 655150622Srik CP_LOCK (bd); 656150622Srik cp_led_off (b); 657150622Srik CP_UNLOCK (bd); 658150622Srik callout_drain (&led_timo[b->num]); 659150622Srik splx (s); 660150622Srik 661150622Srik s = splimp (); 662150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 663150622Srik drv_t *d = (drv_t*) c->sys; 664150622Srik 665150622Srik if (! d || ! d->chan->type) 666150622Srik continue; 667150622Srik channel [b->num*NCHAN + c->num] = 0; 668150622Srik /* Deallocate buffers. */ 669150622Srik cp_bus_dma_mem_free (&d->dmamem); 670150622Srik } 671150622Srik adapter [b->num] = 0; 672150622Srik cp_bus_dma_mem_free (&bd->dmamem); 673150622Srik free (b, M_DEVBUF); 674150622Srik splx (s); 675150622Srik mtx_destroy (&bd->cp_mtx); 676150622Srik return 0; 677150622Srik} 678150622Srik 679150622Srik#ifndef NETGRAPH 680150622Srikstatic void cp_ifstart (struct ifnet *ifp) 681150622Srik{ 682150622Srik drv_t *d = ifp->if_softc; 683150622Srik bdrv_t *bd = d->board->sys; 684150622Srik 685150622Srik CP_LOCK (bd); 686150622Srik cp_start (d); 687150622Srik CP_UNLOCK (bd); 688150622Srik} 689150622Srik 690150622Srikstatic void cp_ifwatchdog (struct ifnet *ifp) 691150622Srik{ 692150622Srik drv_t *d = ifp->if_softc; 693150622Srik 694150622Srik cp_watchdog (d); 695150622Srik} 696150622Srik 697150622Srikstatic void cp_tlf (struct sppp *sp) 698150622Srik{ 699150622Srik drv_t *d = SP2IFP(sp)->if_softc; 700150622Srik 701150622Srik CP_DEBUG2 (d, ("cp_tlf\n")); 702150622Srik /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */ 703150622Srik/* cp_set_dtr (d->chan, 0);*/ 704150622Srik/* cp_set_rts (d->chan, 0);*/ 705150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 706150622Srik sp->pp_down (sp); 707150622Srik} 708150622Srik 709150622Srikstatic void cp_tls (struct sppp *sp) 710150622Srik{ 711150622Srik drv_t *d = SP2IFP(sp)->if_softc; 712150622Srik 713150622Srik CP_DEBUG2 (d, ("cp_tls\n")); 714150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 715150622Srik sp->pp_up (sp); 716150622Srik} 717150622Srik 718150622Srik/* 719150622Srik * Process an ioctl request. 720150622Srik */ 721150622Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 722150622Srik{ 723150622Srik drv_t *d = ifp->if_softc; 724150622Srik bdrv_t *bd = d->board->sys; 725150622Srik int error, s, was_up, should_be_up; 726150622Srik 727150622Srik was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 728150622Srik error = sppp_ioctl (ifp, cmd, data); 729150622Srik 730150622Srik if (error) 731150622Srik return error; 732150622Srik 733150622Srik if (! (ifp->if_flags & IFF_DEBUG)) 734150622Srik d->chan->debug = 0; 735150622Srik else if (! d->chan->debug) 736150622Srik d->chan->debug = 1; 737150622Srik 738150622Srik switch (cmd) { 739150622Srik default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 740150622Srik case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 741150622Srik case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 742150622Srik case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 743150622Srik case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 744150622Srik } 745150622Srik 746150622Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 747150622Srik s = splimp (); 748150622Srik CP_LOCK (bd); 749150622Srik should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 750150622Srik if (! was_up && should_be_up) { 751150622Srik /* Interface goes up -- start it. */ 752150622Srik cp_up (d); 753150622Srik cp_start (d); 754150622Srik } else if (was_up && ! should_be_up) { 755150622Srik /* Interface is going down -- stop it. */ 756150622Srik/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 757150622Srik cp_down (d); 758150622Srik } 759150622Srik CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 760150622Srik CP_UNLOCK (bd); 761150622Srik splx (s); 762150622Srik return 0; 763150622Srik} 764150622Srik 765150622Srik/* 766150622Srik * Initialization of interface. 767150622Srik * It seems to be never called by upper level? 768150622Srik */ 769150622Srikstatic void cp_initialize (void *softc) 770150622Srik{ 771150622Srik drv_t *d = softc; 772150622Srik 773150622Srik CP_DEBUG (d, ("cp_initialize\n")); 774150622Srik} 775150622Srik#endif /*NETGRAPH*/ 776150622Srik 777150622Srik/* 778150622Srik * Stop the interface. Called on splimp(). 779150622Srik */ 780150622Srikstatic void cp_down (drv_t *d) 781150622Srik{ 782150622Srik CP_DEBUG (d, ("cp_down\n")); 783150622Srik /* Interface is going down -- stop it. */ 784150622Srik cp_set_dtr (d->chan, 0); 785150622Srik cp_set_rts (d->chan, 0); 786150622Srik 787150622Srik d->running = 0; 788150622Srik} 789150622Srik 790150622Srik/* 791150622Srik * Start the interface. Called on splimp(). 792150622Srik */ 793150622Srikstatic void cp_up (drv_t *d) 794150622Srik{ 795150622Srik CP_DEBUG (d, ("cp_up\n")); 796150622Srik cp_set_dtr (d->chan, 1); 797150622Srik cp_set_rts (d->chan, 1); 798150622Srik d->running = 1; 799150622Srik} 800150622Srik 801150622Srik/* 802150622Srik * Start output on the interface. Get another datagram to send 803150622Srik * off of the interface queue, and copy it to the interface 804150622Srik * before starting the output. 805150622Srik */ 806150622Srikstatic void cp_send (drv_t *d) 807150622Srik{ 808150622Srik struct mbuf *m; 809150622Srik u_short len; 810150622Srik 811150622Srik CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 812150622Srik 813150622Srik /* No output if the interface is down. */ 814150622Srik if (! d->running) 815150622Srik return; 816150622Srik 817150622Srik /* No output if the modem is off. */ 818150622Srik if (! (d->chan->lloop || d->chan->type != T_SERIAL || 819150622Srik cp_get_dsr (d->chan))) 820150622Srik return; 821150622Srik 822150622Srik while (cp_transmit_space (d->chan)) { 823150622Srik /* Get the packet to send. */ 824150622Srik#ifdef NETGRAPH 825150622Srik IF_DEQUEUE (&d->hi_queue, m); 826150622Srik if (! m) 827150622Srik IF_DEQUEUE (&d->queue, m); 828150622Srik#else 829150622Srik m = sppp_dequeue (d->ifp); 830150622Srik#endif 831150622Srik if (! m) 832150622Srik return; 833150622Srik#ifndef NETGRAPH 834150622Srik if (d->ifp->if_bpf) 835150622Srik BPF_MTAP (d->ifp, m); 836150622Srik#endif 837150622Srik len = m_length (m, NULL); 838150622Srik if (len >= BUFSZ) 839150622Srik printf ("%s: too long packet: %d bytes: ", 840150622Srik d->name, len); 841150622Srik else if (! m->m_next) 842150622Srik cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 843150622Srik else { 844150622Srik u_char *buf = d->chan->tbuf[d->chan->te]; 845150622Srik m_copydata (m, 0, len, buf); 846150622Srik cp_send_packet (d->chan, buf, len, 0); 847150622Srik } 848150622Srik m_freem (m); 849150622Srik /* Set up transmit timeout, if the transmit ring is not empty.*/ 850150622Srik#ifdef NETGRAPH 851150622Srik d->timeout = 10; 852150622Srik#else 853150622Srik d->ifp->if_timer = 10; 854150622Srik#endif 855150622Srik } 856150622Srik#ifndef NETGRAPH 857150622Srik d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 858150622Srik#endif 859150622Srik} 860150622Srik 861150622Srik/* 862150622Srik * Start output on the interface. 863150622Srik * Always called on splimp(). 864150622Srik */ 865150622Srikstatic void cp_start (drv_t *d) 866150622Srik{ 867150622Srik if (d->running) { 868150622Srik if (! d->chan->dtr) 869150622Srik cp_set_dtr (d->chan, 1); 870150622Srik if (! d->chan->rts) 871150622Srik cp_set_rts (d->chan, 1); 872150622Srik cp_send (d); 873150622Srik } 874150622Srik} 875150622Srik 876150622Srik/* 877150622Srik * Handle transmit timeouts. 878150622Srik * Recover after lost transmit interrupts. 879150622Srik * Always called on splimp(). 880150622Srik */ 881150622Srikstatic void cp_watchdog (drv_t *d) 882150622Srik{ 883150622Srik bdrv_t *bd = d->board->sys; 884150622Srik CP_DEBUG (d, ("device timeout\n")); 885150622Srik if (d->running) { 886150622Srik int s = splimp (); 887150622Srik 888150622Srik CP_LOCK (bd); 889150622Srik cp_stop_chan (d->chan); 890150622Srik cp_stop_e1 (d->chan); 891150622Srik cp_start_e1 (d->chan); 892150622Srik cp_start_chan (d->chan, 1, 1, 0, 0); 893150622Srik cp_set_dtr (d->chan, 1); 894150622Srik cp_set_rts (d->chan, 1); 895150622Srik cp_start (d); 896150622Srik CP_UNLOCK (bd); 897150622Srik splx (s); 898150622Srik } 899150622Srik} 900150622Srik 901150622Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len) 902150622Srik{ 903150622Srik drv_t *d = c->sys; 904150622Srik 905150622Srik#ifdef NETGRAPH 906150622Srik d->timeout = 0; 907150622Srik#else 908150622Srik ++d->ifp->if_opackets; 909150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 910150622Srik d->ifp->if_timer = 0; 911150622Srik#endif 912150622Srik cp_start (d); 913150622Srik} 914150622Srik 915150622Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len) 916150622Srik{ 917150622Srik drv_t *d = c->sys; 918150622Srik struct mbuf *m; 919150622Srik#ifdef NETGRAPH 920150622Srik int error; 921150622Srik#endif 922150622Srik 923150622Srik if (! d->running) 924150622Srik return; 925150622Srik 926150622Srik m = makembuf (data, len); 927150622Srik if (! m) { 928150622Srik CP_DEBUG (d, ("no memory for packet\n")); 929150622Srik#ifndef NETGRAPH 930150622Srik ++d->ifp->if_iqdrops; 931150622Srik#endif 932150622Srik return; 933150622Srik } 934150622Srik if (c->debug > 1) 935150622Srik printmbuf (m); 936150622Srik#ifdef NETGRAPH 937150622Srik m->m_pkthdr.rcvif = 0; 938150622Srik NG_SEND_DATA_ONLY (error, d->hook, m); 939150622Srik#else 940150622Srik ++d->ifp->if_ipackets; 941150622Srik m->m_pkthdr.rcvif = d->ifp; 942150622Srik /* Check if there's a BPF listener on this interface. 943150622Srik * If so, hand off the raw packet to bpf. */ 944150622Srik if (d->ifp->if_bpf) 945150622Srik BPF_TAP (d->ifp, data, len); 946150622Srik IF_ENQUEUE (&d->queue, m); 947150622Srik#endif 948150622Srik} 949150622Srik 950150622Srikstatic void cp_error (cp_chan_t *c, int data) 951150622Srik{ 952150622Srik drv_t *d = c->sys; 953150622Srik 954150622Srik switch (data) { 955150622Srik case CP_FRAME: 956150622Srik CP_DEBUG (d, ("frame error\n")); 957150622Srik#ifndef NETGRAPH 958150622Srik ++d->ifp->if_ierrors; 959150622Srik#endif 960150622Srik break; 961150622Srik case CP_CRC: 962150622Srik CP_DEBUG (d, ("crc error\n")); 963150622Srik#ifndef NETGRAPH 964150622Srik ++d->ifp->if_ierrors; 965150622Srik#endif 966150622Srik break; 967150622Srik case CP_OVERRUN: 968150622Srik CP_DEBUG (d, ("overrun error\n")); 969150622Srik#ifndef NETGRAPH 970150622Srik ++d->ifp->if_collisions; 971150622Srik ++d->ifp->if_ierrors; 972150622Srik#endif 973150622Srik break; 974150622Srik case CP_OVERFLOW: 975150622Srik CP_DEBUG (d, ("overflow error\n")); 976150622Srik#ifndef NETGRAPH 977150622Srik ++d->ifp->if_ierrors; 978150622Srik#endif 979150622Srik break; 980150622Srik case CP_UNDERRUN: 981150622Srik CP_DEBUG (d, ("underrun error\n")); 982150622Srik#ifdef NETGRAPH 983150622Srik d->timeout = 0; 984150622Srik#else 985150622Srik ++d->ifp->if_oerrors; 986150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 987150622Srik d->ifp->if_timer = 0; 988150622Srik#endif 989150622Srik cp_start (d); 990150622Srik break; 991150622Srik default: 992150622Srik CP_DEBUG (d, ("error #%d\n", data)); 993150622Srik break; 994150622Srik } 995150622Srik} 996150622Srik 997150622Srik/* 998128967Srik * You also need read, write, open, close routines. 999128967Srik * This should get you started 1000128967Srik */ 1001130585Sphkstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 1002128967Srik{ 1003128967Srik int unit = minor (dev); 1004128967Srik drv_t *d; 1005128967Srik 1006128967Srik if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 1007128967Srik return ENXIO; 1008128967Srik CP_DEBUG2 (d, ("cp_open\n")); 1009128967Srik return 0; 1010128967Srik} 1011128967Srik 1012128967Srik/* 1013128967Srik * Only called on the LAST close. 1014128967Srik */ 1015130585Sphkstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 1016128967Srik{ 1017128967Srik drv_t *d = channel [minor (dev)]; 1018128967Srik 1019128967Srik CP_DEBUG2 (d, ("cp_close\n")); 1020128967Srik return 0; 1021128967Srik} 1022128967Srik 1023128967Srikstatic int cp_modem_status (cp_chan_t *c) 1024128967Srik{ 1025128967Srik drv_t *d = c->sys; 1026138823Srik bdrv_t *bd = d->board->sys; 1027128967Srik int status, s; 1028128967Srik 1029128967Srik status = d->running ? TIOCM_LE : 0; 1030128967Srik s = splimp (); 1031138823Srik CP_LOCK (bd); 1032128967Srik if (cp_get_cd (c)) status |= TIOCM_CD; 1033128967Srik if (cp_get_cts (c)) status |= TIOCM_CTS; 1034128967Srik if (cp_get_dsr (c)) status |= TIOCM_DSR; 1035128967Srik if (c->dtr) status |= TIOCM_DTR; 1036128967Srik if (c->rts) status |= TIOCM_RTS; 1037138823Srik CP_UNLOCK (bd); 1038128967Srik splx (s); 1039128967Srik return status; 1040128967Srik} 1041128967Srik 1042130585Sphkstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1043128967Srik{ 1044133646Srik drv_t *d = channel [minor (dev)]; 1045138823Srik bdrv_t *bd = d->board->sys; 1046128967Srik cp_chan_t *c = d->chan; 1047128967Srik struct serial_statistics *st; 1048128967Srik struct e1_statistics *opte1; 1049128967Srik struct e3_statistics *opte3; 1050128967Srik int error, s; 1051128967Srik char mask[16]; 1052128967Srik 1053128967Srik switch (cmd) { 1054128967Srik case SERIAL_GETREGISTERED: 1055133646Srik CP_DEBUG2 (d, ("ioctl: getregistered\n")); 1056128967Srik bzero (mask, sizeof(mask)); 1057128967Srik for (s=0; s<NBRD*NCHAN; ++s) 1058128967Srik if (channel [s]) 1059128967Srik mask [s/8] |= 1 << (s & 7); 1060133646Srik bcopy (mask, data, sizeof (mask)); 1061128967Srik return 0; 1062128967Srik 1063128967Srik#ifndef NETGRAPH 1064128967Srik case SERIAL_GETPROTO: 1065133646Srik CP_DEBUG2 (d, ("ioctl: getproto\n")); 1066147256Sbrooks strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1067147256Sbrooks (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1068133646Srik return 0; 1069128967Srik 1070128967Srik case SERIAL_SETPROTO: 1071133646Srik CP_DEBUG2 (d, ("ioctl: setproto\n")); 1072133646Srik /* Only for superuser! */ 1073133646Srik error = suser (td); 1074133646Srik if (error) 1075133646Srik return error; 1076148887Srwatson if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) 1077128967Srik return EBUSY; 1078133646Srik if (! strcmp ("cisco", (char*)data)) { 1079147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1080147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1081147256Sbrooks d->ifp->if_flags |= PP_CISCO; 1082138873Srik } else if (! strcmp ("fr", (char*)data) && PP_FR) { 1083147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1084147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1085133646Srik } else if (! strcmp ("ppp", (char*)data)) { 1086147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_FR; 1087147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1088147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1089133646Srik } else 1090128967Srik return EINVAL; 1091133646Srik return 0; 1092128967Srik 1093128967Srik case SERIAL_GETKEEPALIVE: 1094133646Srik CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1095147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1096147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1097128967Srik return EINVAL; 1098147256Sbrooks *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1099133646Srik return 0; 1100128967Srik 1101128967Srik case SERIAL_SETKEEPALIVE: 1102133646Srik CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1103133646Srik /* Only for superuser! */ 1104133646Srik error = suser (td); 1105133646Srik if (error) 1106133646Srik return error; 1107147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1108147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1109128967Srik return EINVAL; 1110128967Srik s = splimp (); 1111138823Srik CP_LOCK (bd); 1112133646Srik if (*(int*)data) 1113147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1114128967Srik else 1115147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1116138823Srik CP_UNLOCK (bd); 1117128967Srik splx (s); 1118133646Srik return 0; 1119128967Srik#endif /*NETGRAPH*/ 1120128967Srik 1121128967Srik case SERIAL_GETMODE: 1122133646Srik CP_DEBUG2 (d, ("ioctl: getmode\n")); 1123128967Srik *(int*)data = SERIAL_HDLC; 1124133646Srik return 0; 1125128967Srik 1126128967Srik case SERIAL_SETMODE: 1127133646Srik /* Only for superuser! */ 1128133646Srik error = suser (td); 1129133646Srik if (error) 1130133646Srik return error; 1131128967Srik if (*(int*)data != SERIAL_HDLC) 1132128967Srik return EINVAL; 1133133646Srik return 0; 1134128967Srik 1135128967Srik case SERIAL_GETCFG: 1136133646Srik CP_DEBUG2 (d, ("ioctl: getcfg\n")); 1137128967Srik if (c->type != T_E1 || c->unfram) 1138128967Srik return EINVAL; 1139128967Srik *(char*)data = c->board->mux ? 'c' : 'a'; 1140133646Srik return 0; 1141128967Srik 1142128967Srik case SERIAL_SETCFG: 1143133646Srik CP_DEBUG2 (d, ("ioctl: setcfg\n")); 1144133646Srik error = suser (td); 1145133646Srik if (error) 1146133646Srik return error; 1147128967Srik if (c->type != T_E1) 1148128967Srik return EINVAL; 1149133646Srik s = splimp (); 1150138823Srik CP_LOCK (bd); 1151128967Srik cp_set_mux (c->board, *((char*)data) == 'c'); 1152138823Srik CP_UNLOCK (bd); 1153133646Srik splx (s); 1154133646Srik return 0; 1155128967Srik 1156128967Srik case SERIAL_GETSTAT: 1157133646Srik CP_DEBUG2 (d, ("ioctl: getstat\n")); 1158133646Srik st = (struct serial_statistics*) data; 1159133646Srik st->rintr = c->rintr; 1160133646Srik st->tintr = c->tintr; 1161133646Srik st->mintr = 0; 1162133646Srik st->ibytes = c->ibytes; 1163133646Srik st->ipkts = c->ipkts; 1164133646Srik st->obytes = c->obytes; 1165133646Srik st->opkts = c->opkts; 1166128967Srik st->ierrs = c->overrun + c->frame + c->crc; 1167128967Srik st->oerrs = c->underrun; 1168133646Srik return 0; 1169128967Srik 1170128967Srik case SERIAL_GETESTAT: 1171133646Srik CP_DEBUG2 (d, ("ioctl: getestat\n")); 1172128967Srik if (c->type != T_E1 && c->type != T_G703) 1173128967Srik return EINVAL; 1174128967Srik opte1 = (struct e1_statistics*) data; 1175128967Srik opte1->status = c->status; 1176128967Srik opte1->cursec = c->cursec; 1177128967Srik opte1->totsec = c->totsec + c->cursec; 1178128967Srik 1179128967Srik opte1->currnt.bpv = c->currnt.bpv; 1180128967Srik opte1->currnt.fse = c->currnt.fse; 1181128967Srik opte1->currnt.crce = c->currnt.crce; 1182128967Srik opte1->currnt.rcrce = c->currnt.rcrce; 1183128967Srik opte1->currnt.uas = c->currnt.uas; 1184128967Srik opte1->currnt.les = c->currnt.les; 1185128967Srik opte1->currnt.es = c->currnt.es; 1186128967Srik opte1->currnt.bes = c->currnt.bes; 1187128967Srik opte1->currnt.ses = c->currnt.ses; 1188128967Srik opte1->currnt.oofs = c->currnt.oofs; 1189128967Srik opte1->currnt.css = c->currnt.css; 1190128967Srik opte1->currnt.dm = c->currnt.dm; 1191128967Srik 1192128967Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1193128967Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1194128967Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1195128967Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1196128967Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1197128967Srik opte1->total.les = c->total.les + c->currnt.les; 1198128967Srik opte1->total.es = c->total.es + c->currnt.es; 1199128967Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1200128967Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1201128967Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1202128967Srik opte1->total.css = c->total.css + c->currnt.css; 1203128967Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1204128967Srik for (s=0; s<48; ++s) { 1205128967Srik opte1->interval[s].bpv = c->interval[s].bpv; 1206128967Srik opte1->interval[s].fse = c->interval[s].fse; 1207128967Srik opte1->interval[s].crce = c->interval[s].crce; 1208128967Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1209128967Srik opte1->interval[s].uas = c->interval[s].uas; 1210128967Srik opte1->interval[s].les = c->interval[s].les; 1211128967Srik opte1->interval[s].es = c->interval[s].es; 1212128967Srik opte1->interval[s].bes = c->interval[s].bes; 1213128967Srik opte1->interval[s].ses = c->interval[s].ses; 1214128967Srik opte1->interval[s].oofs = c->interval[s].oofs; 1215128967Srik opte1->interval[s].css = c->interval[s].css; 1216128967Srik opte1->interval[s].dm = c->interval[s].dm; 1217128967Srik } 1218128967Srik return 0; 1219128967Srik 1220128967Srik case SERIAL_GETE3STAT: 1221133646Srik CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 1222128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1223128967Srik return EINVAL; 1224133646Srik opte3 = (struct e3_statistics*) data; 1225128967Srik 1226128967Srik opte3->status = c->e3status; 1227128967Srik opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 1228128967Srik opte3->totsec = c->e3tsec + opte3->cursec; 1229128967Srik 1230128967Srik opte3->ccv = c->e3ccv; 1231128967Srik opte3->tcv = c->e3tcv + opte3->ccv; 1232128967Srik 1233128967Srik for (s = 0; s < 48; ++s) { 1234128967Srik opte3->icv[s] = c->e3icv[s]; 1235128967Srik } 1236133646Srik return 0; 1237128967Srik 1238128967Srik case SERIAL_CLRSTAT: 1239133646Srik CP_DEBUG2 (d, ("ioctl: clrstat\n")); 1240133646Srik /* Only for superuser! */ 1241133646Srik error = suser (td); 1242133646Srik if (error) 1243133646Srik return error; 1244128967Srik c->rintr = 0; 1245128967Srik c->tintr = 0; 1246128967Srik c->ibytes = 0; 1247128967Srik c->obytes = 0; 1248128967Srik c->ipkts = 0; 1249128967Srik c->opkts = 0; 1250128967Srik c->overrun = 0; 1251128967Srik c->frame = 0; 1252133646Srik c->crc = 0; 1253128967Srik c->underrun = 0; 1254128967Srik bzero (&c->currnt, sizeof (c->currnt)); 1255128967Srik bzero (&c->total, sizeof (c->total)); 1256128967Srik bzero (c->interval, sizeof (c->interval)); 1257128967Srik c->e3ccv = 0; 1258128967Srik c->e3tcv = 0; 1259128967Srik bzero (c->e3icv, sizeof (c->e3icv)); 1260133646Srik return 0; 1261128967Srik 1262128967Srik case SERIAL_GETBAUD: 1263133646Srik CP_DEBUG2 (d, ("ioctl: getbaud\n")); 1264133646Srik *(long*)data = c->baud; 1265133646Srik return 0; 1266128967Srik 1267128967Srik case SERIAL_SETBAUD: 1268133646Srik CP_DEBUG2 (d, ("ioctl: setbaud\n")); 1269133646Srik /* Only for superuser! */ 1270133646Srik error = suser (td); 1271133646Srik if (error) 1272133646Srik return error; 1273133646Srik s = splimp (); 1274138823Srik CP_LOCK (bd); 1275133646Srik cp_set_baud (c, *(long*)data); 1276138823Srik CP_UNLOCK (bd); 1277133646Srik splx (s); 1278133646Srik return 0; 1279128967Srik 1280128967Srik case SERIAL_GETLOOP: 1281133646Srik CP_DEBUG2 (d, ("ioctl: getloop\n")); 1282133646Srik *(int*)data = c->lloop; 1283133646Srik return 0; 1284128967Srik 1285128967Srik case SERIAL_SETLOOP: 1286133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1287133646Srik /* Only for superuser! */ 1288133646Srik error = suser (td); 1289133646Srik if (error) 1290133646Srik return error; 1291133646Srik s = splimp (); 1292138823Srik CP_LOCK (bd); 1293128967Srik cp_set_lloop (c, *(int*)data); 1294138823Srik CP_UNLOCK (bd); 1295133646Srik splx (s); 1296133646Srik return 0; 1297128967Srik 1298128967Srik case SERIAL_GETDPLL: 1299133646Srik CP_DEBUG2 (d, ("ioctl: getdpll\n")); 1300133646Srik if (c->type != T_SERIAL) 1301133646Srik return EINVAL; 1302133646Srik *(int*)data = c->dpll; 1303133646Srik return 0; 1304128967Srik 1305128967Srik case SERIAL_SETDPLL: 1306133646Srik CP_DEBUG2 (d, ("ioctl: setdpll\n")); 1307133646Srik /* Only for superuser! */ 1308133646Srik error = suser (td); 1309133646Srik if (error) 1310133646Srik return error; 1311133646Srik if (c->type != T_SERIAL) 1312133646Srik return EINVAL; 1313133646Srik s = splimp (); 1314138823Srik CP_LOCK (bd); 1315133646Srik cp_set_dpll (c, *(int*)data); 1316138823Srik CP_UNLOCK (bd); 1317133646Srik splx (s); 1318133646Srik return 0; 1319128967Srik 1320128967Srik case SERIAL_GETNRZI: 1321133646Srik CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 1322133646Srik if (c->type != T_SERIAL) 1323133646Srik return EINVAL; 1324133646Srik *(int*)data = c->nrzi; 1325133646Srik return 0; 1326128967Srik 1327128967Srik case SERIAL_SETNRZI: 1328133646Srik CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 1329133646Srik /* Only for superuser! */ 1330133646Srik error = suser (td); 1331133646Srik if (error) 1332133646Srik return error; 1333133646Srik if (c->type != T_SERIAL) 1334133646Srik return EINVAL; 1335133646Srik s = splimp (); 1336138823Srik CP_LOCK (bd); 1337133646Srik cp_set_nrzi (c, *(int*)data); 1338138823Srik CP_UNLOCK (bd); 1339133646Srik splx (s); 1340133646Srik return 0; 1341128967Srik 1342128967Srik case SERIAL_GETDEBUG: 1343133646Srik CP_DEBUG2 (d, ("ioctl: getdebug\n")); 1344133646Srik *(int*)data = d->chan->debug; 1345133646Srik return 0; 1346128967Srik 1347128967Srik case SERIAL_SETDEBUG: 1348133646Srik CP_DEBUG2 (d, ("ioctl: setdebug\n")); 1349133646Srik /* Only for superuser! */ 1350133646Srik error = suser (td); 1351133646Srik if (error) 1352133646Srik return error; 1353133646Srik d->chan->debug = *(int*)data; 1354128967Srik#ifndef NETGRAPH 1355128967Srik if (d->chan->debug) 1356147256Sbrooks d->ifp->if_flags |= IFF_DEBUG; 1357128967Srik else 1358147256Sbrooks d->ifp->if_flags &= ~IFF_DEBUG; 1359128967Srik#endif 1360133646Srik return 0; 1361128967Srik 1362128967Srik case SERIAL_GETHIGAIN: 1363133646Srik CP_DEBUG2 (d, ("ioctl: gethigain\n")); 1364133646Srik if (c->type != T_E1) 1365133646Srik return EINVAL; 1366133646Srik *(int*)data = c->higain; 1367128967Srik return 0; 1368128967Srik 1369128967Srik case SERIAL_SETHIGAIN: 1370133646Srik CP_DEBUG2 (d, ("ioctl: sethigain\n")); 1371133646Srik /* Only for superuser! */ 1372133646Srik error = suser (td); 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_higain (c, *(int*)data); 1380138823Srik CP_UNLOCK (bd); 1381128967Srik splx (s); 1382128967Srik return 0; 1383128967Srik 1384128967Srik case SERIAL_GETPHONY: 1385128967Srik CP_DEBUG2 (d, ("ioctl: getphony\n")); 1386133646Srik if (c->type != T_E1) 1387133646Srik return EINVAL; 1388133646Srik *(int*)data = c->phony; 1389128967Srik return 0; 1390128967Srik 1391128967Srik case SERIAL_SETPHONY: 1392128967Srik CP_DEBUG2 (d, ("ioctl: setphony\n")); 1393133646Srik /* Only for superuser! */ 1394133646Srik error = suser (td); 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_phony (c, *(int*)data); 1402138823Srik CP_UNLOCK (bd); 1403128967Srik splx (s); 1404128967Srik return 0; 1405128967Srik 1406128967Srik case SERIAL_GETUNFRAM: 1407128967Srik CP_DEBUG2 (d, ("ioctl: getunfram\n")); 1408133646Srik if (c->type != T_E1) 1409133646Srik return EINVAL; 1410133646Srik *(int*)data = c->unfram; 1411128967Srik return 0; 1412128967Srik 1413128967Srik case SERIAL_SETUNFRAM: 1414128967Srik CP_DEBUG2 (d, ("ioctl: setunfram\n")); 1415133646Srik /* Only for superuser! */ 1416133646Srik error = suser (td); 1417133646Srik if (error) 1418133646Srik return error; 1419133646Srik if (c->type != T_E1) 1420133646Srik return EINVAL; 1421128967Srik s = splimp (); 1422138823Srik CP_LOCK (bd); 1423128967Srik cp_set_unfram (c, *(int*)data); 1424138823Srik CP_UNLOCK (bd); 1425128967Srik splx (s); 1426128967Srik return 0; 1427128967Srik 1428128967Srik case SERIAL_GETSCRAMBLER: 1429128967Srik CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 1430133646Srik if (c->type != T_G703 && !c->unfram) 1431133646Srik return EINVAL; 1432133646Srik *(int*)data = c->scrambler; 1433128967Srik return 0; 1434128967Srik 1435128967Srik case SERIAL_SETSCRAMBLER: 1436128967Srik CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 1437133646Srik /* Only for superuser! */ 1438133646Srik error = suser (td); 1439133646Srik if (error) 1440133646Srik return error; 1441133646Srik if (c->type != T_G703 && !c->unfram) 1442133646Srik return EINVAL; 1443128967Srik s = splimp (); 1444138823Srik CP_LOCK (bd); 1445128967Srik cp_set_scrambler (c, *(int*)data); 1446138823Srik CP_UNLOCK (bd); 1447128967Srik splx (s); 1448128967Srik return 0; 1449128967Srik 1450128967Srik case SERIAL_GETMONITOR: 1451128967Srik CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 1452133646Srik if (c->type != T_E1 && 1453128967Srik c->type != T_E3 && 1454128967Srik c->type != T_T3 && 1455128967Srik c->type != T_STS1) 1456133646Srik return EINVAL; 1457133646Srik *(int*)data = c->monitor; 1458128967Srik return 0; 1459128967Srik 1460128967Srik case SERIAL_SETMONITOR: 1461128967Srik CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 1462133646Srik /* Only for superuser! */ 1463133646Srik error = suser (td); 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_monitor (c, *(int*)data); 1471138823Srik CP_UNLOCK (bd); 1472128967Srik splx (s); 1473128967Srik return 0; 1474128967Srik 1475128967Srik case SERIAL_GETUSE16: 1476133646Srik CP_DEBUG2 (d, ("ioctl: getuse16\n")); 1477133646Srik if (c->type != T_E1 || c->unfram) 1478133646Srik return EINVAL; 1479133646Srik *(int*)data = c->use16; 1480128967Srik return 0; 1481128967Srik 1482128967Srik case SERIAL_SETUSE16: 1483133646Srik CP_DEBUG2 (d, ("ioctl: setuse16\n")); 1484133646Srik /* Only for superuser! */ 1485133646Srik error = suser (td); 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_use16 (c, *(int*)data); 1493138823Srik CP_UNLOCK (bd); 1494128967Srik splx (s); 1495128967Srik return 0; 1496128967Srik 1497128967Srik case SERIAL_GETCRC4: 1498133646Srik CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 1499133646Srik if (c->type != T_E1 || c->unfram) 1500133646Srik return EINVAL; 1501133646Srik *(int*)data = c->crc4; 1502128967Srik return 0; 1503128967Srik 1504128967Srik case SERIAL_SETCRC4: 1505133646Srik CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 1506133646Srik /* Only for superuser! */ 1507133646Srik error = suser (td); 1508133646Srik if (error) 1509133646Srik return error; 1510133646Srik if (c->type != T_E1) 1511133646Srik return EINVAL; 1512128967Srik s = splimp (); 1513138823Srik CP_LOCK (bd); 1514128967Srik cp_set_crc4 (c, *(int*)data); 1515138823Srik CP_UNLOCK (bd); 1516128967Srik splx (s); 1517128967Srik return 0; 1518128967Srik 1519128967Srik case SERIAL_GETCLK: 1520133646Srik CP_DEBUG2 (d, ("ioctl: getclk\n")); 1521133646Srik 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 switch (c->gsyn) { 1528128967Srik default: *(int*)data = E1CLK_INTERNAL; break; 1529128967Srik case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1530128967Srik case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1531128967Srik case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1532128967Srik case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 1533128967Srik case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 1534128967Srik } 1535128967Srik return 0; 1536128967Srik 1537128967Srik case SERIAL_SETCLK: 1538133646Srik CP_DEBUG2 (d, ("ioctl: setclk\n")); 1539133646Srik /* Only for superuser! */ 1540133646Srik error = suser (td); 1541133646Srik if (error) 1542133646Srik return error; 1543128967Srik if (c->type != T_E1 && 1544128967Srik c->type != T_G703 && 1545128967Srik c->type != T_E3 && 1546128967Srik c->type != T_T3 && 1547128967Srik c->type != T_STS1) 1548133646Srik return EINVAL; 1549128967Srik s = splimp (); 1550138823Srik CP_LOCK (bd); 1551128967Srik switch (*(int*)data) { 1552128967Srik default: cp_set_gsyn (c, GSYN_INT); break; 1553128967Srik case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 1554128967Srik case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 1555128967Srik case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 1556128967Srik case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 1557128967Srik case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 1558128967Srik } 1559138823Srik CP_UNLOCK (bd); 1560128967Srik splx (s); 1561128967Srik return 0; 1562128967Srik 1563128967Srik case SERIAL_GETTIMESLOTS: 1564133646Srik CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1565133646Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1566133646Srik return EINVAL; 1567133646Srik *(u_long*)data = c->ts; 1568128967Srik return 0; 1569128967Srik 1570128967Srik case SERIAL_SETTIMESLOTS: 1571133646Srik CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 1572133646Srik /* Only for superuser! */ 1573133646Srik error = suser (td); 1574133646Srik if (error) 1575133646Srik return error; 1576128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1577133646Srik return EINVAL; 1578128967Srik s = splimp (); 1579138823Srik CP_LOCK (bd); 1580128967Srik cp_set_ts (c, *(u_long*)data); 1581138823Srik CP_UNLOCK (bd); 1582128967Srik splx (s); 1583128967Srik return 0; 1584128967Srik 1585128967Srik case SERIAL_GETINVCLK: 1586133646Srik CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 1587128967Srik#if 1 1588128967Srik return EINVAL; 1589128967Srik#else 1590133646Srik if (c->type != T_SERIAL) 1591133646Srik return EINVAL; 1592133646Srik *(int*)data = c->invtxc; 1593128967Srik return 0; 1594128967Srik#endif 1595128967Srik 1596128967Srik case SERIAL_SETINVCLK: 1597133646Srik CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 1598133646Srik /* Only for superuser! */ 1599133646Srik error = suser (td); 1600133646Srik if (error) 1601133646Srik return error; 1602133646Srik if (c->type != T_SERIAL) 1603133646Srik return EINVAL; 1604128967Srik s = splimp (); 1605138823Srik CP_LOCK (bd); 1606128967Srik cp_set_invtxc (c, *(int*)data); 1607128967Srik cp_set_invrxc (c, *(int*)data); 1608138823Srik CP_UNLOCK (bd); 1609128967Srik splx (s); 1610128967Srik return 0; 1611128967Srik 1612128967Srik case SERIAL_GETINVTCLK: 1613133646Srik CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 1614133646Srik if (c->type != T_SERIAL) 1615133646Srik return EINVAL; 1616133646Srik *(int*)data = c->invtxc; 1617128967Srik return 0; 1618128967Srik 1619128967Srik case SERIAL_SETINVTCLK: 1620133646Srik CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 1621133646Srik /* Only for superuser! */ 1622133646Srik error = suser (td); 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_invtxc (c, *(int*)data); 1630138823Srik CP_UNLOCK (bd); 1631128967Srik splx (s); 1632128967Srik return 0; 1633128967Srik 1634128967Srik case SERIAL_GETINVRCLK: 1635133646Srik CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 1636133646Srik if (c->type != T_SERIAL) 1637133646Srik return EINVAL; 1638133646Srik *(int*)data = c->invrxc; 1639128967Srik return 0; 1640128967Srik 1641128967Srik case SERIAL_SETINVRCLK: 1642133646Srik CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 1643133646Srik /* Only for superuser! */ 1644133646Srik error = suser (td); 1645133646Srik if (error) 1646133646Srik return error; 1647133646Srik if (c->type != T_SERIAL) 1648133646Srik return EINVAL; 1649128967Srik s = splimp (); 1650138823Srik CP_LOCK (bd); 1651128967Srik cp_set_invrxc (c, *(int*)data); 1652138823Srik CP_UNLOCK (bd); 1653128967Srik splx (s); 1654128967Srik return 0; 1655128967Srik 1656128967Srik case SERIAL_GETLEVEL: 1657133646Srik CP_DEBUG2 (d, ("ioctl: getlevel\n")); 1658133646Srik if (c->type != T_G703) 1659133646Srik return EINVAL; 1660128967Srik s = splimp (); 1661138823Srik CP_LOCK (bd); 1662133646Srik *(int*)data = cp_get_lq (c); 1663138823Srik CP_UNLOCK (bd); 1664128967Srik splx (s); 1665128967Srik return 0; 1666128967Srik 1667128967Srik#if 0 1668128967Srik case SERIAL_RESET: 1669133646Srik CP_DEBUG2 (d, ("ioctl: reset\n")); 1670133646Srik /* Only for superuser! */ 1671133646Srik error = suser (td); 1672133646Srik if (error) 1673133646Srik return error; 1674128967Srik s = splimp (); 1675138823Srik CP_LOCK (bd); 1676128967Srik cp_reset (c->board, 0, 0); 1677138823Srik CP_UNLOCK (bd); 1678128967Srik splx (s); 1679128967Srik return 0; 1680128967Srik 1681128967Srik case SERIAL_HARDRESET: 1682133646Srik CP_DEBUG2 (d, ("ioctl: hardreset\n")); 1683133646Srik /* Only for superuser! */ 1684133646Srik error = suser (td); 1685133646Srik if (error) 1686133646Srik return error; 1687128967Srik s = splimp (); 1688138823Srik CP_LOCK (bd); 1689128967Srik /* hard_reset (c->board); */ 1690138823Srik CP_UNLOCK (bd); 1691128967Srik splx (s); 1692128967Srik return 0; 1693128967Srik#endif 1694128967Srik 1695128967Srik case SERIAL_GETCABLE: 1696133646Srik CP_DEBUG2 (d, ("ioctl: getcable\n")); 1697133646Srik if (c->type != T_SERIAL) 1698133646Srik return EINVAL; 1699128967Srik s = splimp (); 1700138823Srik CP_LOCK (bd); 1701128967Srik *(int*)data = cp_get_cable (c); 1702138823Srik CP_UNLOCK (bd); 1703128967Srik splx (s); 1704128967Srik return 0; 1705128967Srik 1706128967Srik case SERIAL_GETDIR: 1707133646Srik CP_DEBUG2 (d, ("ioctl: getdir\n")); 1708133646Srik if (c->type != T_E1 && c->type != T_DATA) 1709133646Srik return EINVAL; 1710128967Srik *(int*)data = c->dir; 1711128967Srik return 0; 1712128967Srik 1713128967Srik case SERIAL_SETDIR: 1714133646Srik CP_DEBUG2 (d, ("ioctl: setdir\n")); 1715133646Srik /* Only for superuser! */ 1716133646Srik error = suser (td); 1717133646Srik if (error) 1718133646Srik return error; 1719128967Srik s = splimp (); 1720138823Srik CP_LOCK (bd); 1721128967Srik cp_set_dir (c, *(int*)data); 1722138823Srik CP_UNLOCK (bd); 1723128967Srik splx (s); 1724128967Srik return 0; 1725128967Srik 1726128967Srik case SERIAL_GETRLOOP: 1727133646Srik CP_DEBUG2 (d, ("ioctl: getrloop\n")); 1728133646Srik if (c->type != T_G703 && 1729128967Srik c->type != T_E3 && 1730128967Srik c->type != T_T3 && 1731128967Srik c->type != T_STS1) 1732133646Srik return EINVAL; 1733133646Srik *(int*)data = cp_get_rloop (c); 1734133646Srik return 0; 1735128967Srik 1736128967Srik case SERIAL_SETRLOOP: 1737133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1738133646Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1739133646Srik return EINVAL; 1740133646Srik /* Only for superuser! */ 1741133646Srik error = suser (td); 1742133646Srik if (error) 1743133646Srik return error; 1744133646Srik s = splimp (); 1745138823Srik CP_LOCK (bd); 1746128967Srik cp_set_rloop (c, *(int*)data); 1747138823Srik CP_UNLOCK (bd); 1748133646Srik splx (s); 1749133646Srik return 0; 1750128967Srik 1751128967Srik case SERIAL_GETCABLEN: 1752133646Srik CP_DEBUG2 (d, ("ioctl: getcablen\n")); 1753133646Srik if (c->type != T_T3 && c->type != T_STS1) 1754133646Srik return EINVAL; 1755133646Srik *(int*)data = c->cablen; 1756133646Srik return 0; 1757128967Srik 1758128967Srik case SERIAL_SETCABLEN: 1759133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1760133646Srik if (c->type != T_T3 && c->type != T_STS1) 1761133646Srik return EINVAL; 1762133646Srik /* Only for superuser! */ 1763133646Srik error = suser (td); 1764133646Srik if (error) 1765133646Srik return error; 1766133646Srik s = splimp (); 1767138823Srik CP_LOCK (bd); 1768128967Srik cp_set_cablen (c, *(int*)data); 1769138823Srik CP_UNLOCK (bd); 1770133646Srik splx (s); 1771133646Srik return 0; 1772128967Srik 1773133646Srik case TIOCSDTR: /* Set DTR */ 1774128967Srik s = splimp (); 1775138823Srik CP_LOCK (bd); 1776128967Srik cp_set_dtr (c, 1); 1777138823Srik CP_UNLOCK (bd); 1778128967Srik splx (s); 1779128967Srik return 0; 1780128967Srik 1781133646Srik case TIOCCDTR: /* Clear DTR */ 1782128967Srik s = splimp (); 1783138823Srik CP_LOCK (bd); 1784128967Srik cp_set_dtr (c, 0); 1785138823Srik CP_UNLOCK (bd); 1786128967Srik splx (s); 1787128967Srik return 0; 1788128967Srik 1789133646Srik case TIOCMSET: /* Set DTR/RTS */ 1790128967Srik s = splimp (); 1791138823Srik CP_LOCK (bd); 1792128967Srik cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1793128967Srik cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1794138823Srik CP_UNLOCK (bd); 1795128967Srik splx (s); 1796128967Srik return 0; 1797128967Srik 1798133646Srik case TIOCMBIS: /* Add DTR/RTS */ 1799128967Srik s = splimp (); 1800138823Srik CP_LOCK (bd); 1801128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 1802128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 1803138823Srik CP_UNLOCK (bd); 1804128967Srik splx (s); 1805128967Srik return 0; 1806128967Srik 1807133646Srik case TIOCMBIC: /* Clear DTR/RTS */ 1808128967Srik s = splimp (); 1809138823Srik CP_LOCK (bd); 1810128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1811128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1812138823Srik CP_UNLOCK (bd); 1813128967Srik splx (s); 1814128967Srik return 0; 1815128967Srik 1816133646Srik case TIOCMGET: /* Get modem status */ 1817128967Srik *(int*)data = cp_modem_status (c); 1818128967Srik return 0; 1819128967Srik } 1820128967Srik return ENOTTY; 1821128967Srik} 1822128967Srik 1823128967Srik#ifdef NETGRAPH 1824128967Srikstatic int ng_cp_constructor (node_p node) 1825128967Srik{ 1826128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1827128967Srik CP_DEBUG (d, ("Constructor\n")); 1828128967Srik return EINVAL; 1829128967Srik} 1830128967Srik 1831128967Srikstatic int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1832128967Srik{ 1833128967Srik int s; 1834128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1835138823Srik bdrv_t *bd = d->board->sys; 1836128967Srik 1837128967Srik CP_DEBUG (d, ("Newhook\n")); 1838128967Srik /* Attach debug hook */ 1839128967Srik if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1840128967Srik NG_HOOK_SET_PRIVATE (hook, NULL); 1841128967Srik d->debug_hook = hook; 1842128967Srik return 0; 1843128967Srik } 1844128967Srik 1845128967Srik /* Check for raw hook */ 1846128967Srik if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1847128967Srik return EINVAL; 1848128967Srik 1849128967Srik NG_HOOK_SET_PRIVATE (hook, d); 1850128967Srik d->hook = hook; 1851128967Srik s = splimp (); 1852138823Srik CP_LOCK (bd); 1853128967Srik cp_up (d); 1854138823Srik CP_UNLOCK (bd); 1855128967Srik splx (s); 1856128967Srik return 0; 1857128967Srik} 1858128967Srik 1859128967Srikstatic char *format_timeslots (u_long s) 1860128967Srik{ 1861128967Srik static char buf [100]; 1862128967Srik char *p = buf; 1863128967Srik int i; 1864128967Srik 1865128967Srik for (i=1; i<32; ++i) 1866128967Srik if ((s >> i) & 1) { 1867128967Srik int prev = (i > 1) & (s >> (i-1)); 1868128967Srik int next = (i < 31) & (s >> (i+1)); 1869128967Srik 1870128967Srik if (prev) { 1871128967Srik if (next) 1872128967Srik continue; 1873128967Srik *p++ = '-'; 1874128967Srik } else if (p > buf) 1875128967Srik *p++ = ','; 1876128967Srik 1877128967Srik if (i >= 10) 1878128967Srik *p++ = '0' + i / 10; 1879128967Srik *p++ = '0' + i % 10; 1880128967Srik } 1881128967Srik *p = 0; 1882128967Srik return buf; 1883128967Srik} 1884128967Srik 1885128967Srikstatic int print_modems (char *s, cp_chan_t *c, int need_header) 1886128967Srik{ 1887128967Srik int status = cp_modem_status (c); 1888128967Srik int length = 0; 1889128967Srik 1890128967Srik if (need_header) 1891128967Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1892128967Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1893128967Srik status & TIOCM_LE ? "On" : "-", 1894128967Srik status & TIOCM_DTR ? "On" : "-", 1895128967Srik status & TIOCM_DSR ? "On" : "-", 1896128967Srik status & TIOCM_RTS ? "On" : "-", 1897128967Srik status & TIOCM_CTS ? "On" : "-", 1898128967Srik status & TIOCM_CD ? "On" : "-"); 1899128967Srik return length; 1900128967Srik} 1901128967Srik 1902128967Srikstatic int print_stats (char *s, cp_chan_t *c, int need_header) 1903128967Srik{ 1904128967Srik int length = 0; 1905128967Srik 1906128967Srik if (need_header) 1907128967Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1908128967Srik length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1909128967Srik c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1910128967Srik c->ipkts, c->overrun + c->frame + c->crc, 1911128967Srik (unsigned long) c->obytes, c->opkts, c->underrun); 1912128967Srik return length; 1913128967Srik} 1914128967Srik 1915128967Srikstatic char *format_e1_status (u_char status) 1916128967Srik{ 1917128967Srik static char buf [80]; 1918128967Srik 1919128967Srik if (status & E1_NOALARM) 1920128967Srik return "Ok"; 1921128967Srik buf[0] = 0; 1922128967Srik if (status & E1_LOS) strcat (buf, ",LOS"); 1923128967Srik if (status & E1_AIS) strcat (buf, ",AIS"); 1924128967Srik if (status & E1_LOF) strcat (buf, ",LOF"); 1925128967Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 1926128967Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1927128967Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 1928128967Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1929128967Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1930128967Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1931128967Srik if (buf[0] == ',') 1932128967Srik return buf+1; 1933128967Srik return "Unknown"; 1934128967Srik} 1935128967Srik 1936128967Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1937128967Srik{ 1938128967Srik int n, length = 0; 1939128967Srik 1940128967Srik if (numerator < 1 || divider < 1) { 1941128967Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 1942128967Srik return length; 1943128967Srik } 1944128967Srik n = (int) (0.5 + 1000.0 * numerator / divider); 1945128967Srik if (n < 1000) { 1946128967Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1947128967Srik return length; 1948128967Srik } 1949128967Srik *(s + length) = leftalign ? '/' : ' '; 1950128967Srik length ++; 1951128967Srik 1952128967Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 1953128967Srik else if (n >= 100000) n = (n+50) / 100 * 100; 1954128967Srik else if (n >= 10000) n = (n+5) / 10 * 10; 1955128967Srik 1956128967Srik switch (n) { 1957128967Srik case 1000: length += printf (s+length, ".999"); return length; 1958128967Srik case 10000: n = 9990; break; 1959128967Srik case 100000: n = 99900; break; 1960128967Srik case 1000000: n = 999000; break; 1961128967Srik } 1962133646Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1963128967Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1964128967Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1965133646Srik else length += sprintf (s+length, "%d", n/1000); 1966128967Srik 1967128967Srik return length; 1968128967Srik} 1969128967Srik 1970128967Srikstatic int print_e1_stats (char *s, cp_chan_t *c) 1971128967Srik{ 1972128967Srik struct e1_counters total; 1973128967Srik u_long totsec; 1974128967Srik int length = 0; 1975128967Srik 1976128967Srik totsec = c->totsec + c->cursec; 1977128967Srik total.bpv = c->total.bpv + c->currnt.bpv; 1978128967Srik total.fse = c->total.fse + c->currnt.fse; 1979128967Srik total.crce = c->total.crce + c->currnt.crce; 1980128967Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 1981128967Srik total.uas = c->total.uas + c->currnt.uas; 1982128967Srik total.les = c->total.les + c->currnt.les; 1983128967Srik total.es = c->total.es + c->currnt.es; 1984128967Srik total.bes = c->total.bes + c->currnt.bes; 1985128967Srik total.ses = c->total.ses + c->currnt.ses; 1986128967Srik total.oofs = c->total.oofs + c->currnt.oofs; 1987128967Srik total.css = c->total.css + c->currnt.css; 1988128967Srik total.dm = c->total.dm + c->currnt.dm; 1989128967Srik 1990128967Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1991128967Srik 1992128967Srik /* Unavailable seconds, degraded minutes */ 1993128967Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1994128967Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1995128967Srik 1996128967Srik /* Bipolar violations, frame sync errors */ 1997128967Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1998128967Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1999128967Srik 2000128967Srik /* CRC errors, remote CRC errors (E-bit) */ 2001128967Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 2002128967Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 2003128967Srik 2004128967Srik /* Errored seconds, line errored seconds */ 2005128967Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 2006128967Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 2007128967Srik 2008128967Srik /* Severely errored seconds, burst errored seconds */ 2009128967Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 2010128967Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 2011128967Srik 2012128967Srik /* Out of frame seconds, controlled slip seconds */ 2013128967Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 2014128967Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 2015128967Srik 2016128967Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 2017128967Srik 2018128967Srik /* Print total statistics. */ 2019128967Srik length += print_frac (s + length, 0, total.uas, totsec); 2020128967Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 2021128967Srik 2022128967Srik length += print_frac (s + length, 0, total.bpv, totsec); 2023128967Srik length += print_frac (s + length, 1, total.fse, totsec); 2024128967Srik 2025128967Srik length += print_frac (s + length, 0, total.crce, totsec); 2026128967Srik length += print_frac (s + length, 1, total.rcrce, totsec); 2027128967Srik 2028128967Srik length += print_frac (s + length, 0, total.es, totsec); 2029128967Srik length += print_frac (s + length, 1, total.les, totsec); 2030128967Srik 2031128967Srik length += print_frac (s + length, 0, total.ses, totsec); 2032128967Srik length += print_frac (s + length, 1, total.bes, totsec); 2033128967Srik 2034128967Srik length += print_frac (s + length, 0, total.oofs, totsec); 2035128967Srik length += print_frac (s + length, 1, total.css, totsec); 2036128967Srik 2037128967Srik length += sprintf (s + length, " -- Total\n"); 2038128967Srik return length; 2039128967Srik} 2040128967Srik 2041128967Srikstatic int print_chan (char *s, cp_chan_t *c) 2042128967Srik{ 2043128967Srik drv_t *d = c->sys; 2044138823Srik bdrv_t *bd = d->board->sys; 2045128967Srik int length = 0; 2046128967Srik 2047128967Srik length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2048128967Srik if (d->chan->debug) 2049128967Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 2050128967Srik 2051128967Srik if (c->board->mux) { 2052128967Srik length += sprintf (s + length, " cfg=C"); 2053128967Srik } else { 2054128967Srik length += sprintf (s + length, " cfg=A"); 2055128967Srik } 2056128967Srik 2057128967Srik if (c->baud) 2058128967Srik length += sprintf (s + length, " %ld", c->baud); 2059128967Srik else 2060128967Srik length += sprintf (s + length, " extclock"); 2061128967Srik 2062128967Srik if (c->type == T_E1 || c->type == T_G703) 2063128967Srik switch (c->gsyn) { 2064128967Srik case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2065128967Srik case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2066128967Srik case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2067128967Srik case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2068128967Srik case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2069128967Srik case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2070128967Srik } 2071128967Srik if (c->type == T_SERIAL) { 2072128967Srik length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2073128967Srik length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2074128967Srik length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2075128967Srik } 2076128967Srik if (c->type == T_E1) 2077128967Srik length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2078128967Srik 2079128967Srik length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2080128967Srik 2081128967Srik if (c->type == T_E1) 2082128967Srik length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2083128967Srik if (c->type == T_G703) { 2084128967Srik int lq, x; 2085128967Srik 2086128967Srik x = splimp (); 2087138823Srik CP_LOCK (bd); 2088128967Srik lq = cp_get_lq (c); 2089138823Srik CP_UNLOCK (bd); 2090128967Srik splx (x); 2091128967Srik length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2092128967Srik } 2093128967Srik length += sprintf (s + length, "\n"); 2094128967Srik return length; 2095128967Srik} 2096128967Srik 2097128967Srikstatic int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2098128967Srik{ 2099128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2100128967Srik struct ng_mesg *msg; 2101128967Srik struct ng_mesg *resp = NULL; 2102128967Srik int error = 0; 2103128967Srik 2104128967Srik CP_DEBUG (d, ("Rcvmsg\n")); 2105128967Srik NGI_GET_MSG (item, msg); 2106128967Srik switch (msg->header.typecookie) { 2107128967Srik default: 2108128967Srik error = EINVAL; 2109128967Srik break; 2110128967Srik 2111128967Srik case NGM_CP_COOKIE: 2112128967Srik printf ("Not implemented yet\n"); 2113128967Srik error = EINVAL; 2114128967Srik break; 2115128967Srik 2116128967Srik case NGM_GENERIC_COOKIE: 2117128967Srik switch (msg->header.cmd) { 2118128967Srik default: 2119128967Srik error = EINVAL; 2120128967Srik break; 2121128967Srik 2122128967Srik case NGM_TEXT_STATUS: { 2123128967Srik char *s; 2124128967Srik int l = 0; 2125128967Srik int dl = sizeof (struct ng_mesg) + 730; 2126128967Srik 2127128967Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2128128967Srik if (! resp) { 2129128967Srik error = ENOMEM; 2130128967Srik break; 2131128967Srik } 2132128967Srik s = (resp)->data; 2133128967Srik if (d) { 2134128967Srik l += print_chan (s + l, d->chan); 2135128967Srik l += print_stats (s + l, d->chan, 1); 2136128967Srik l += print_modems (s + l, d->chan, 1); 2137128967Srik l += print_e1_stats (s + l, d->chan); 2138128967Srik } else 2139128967Srik l += sprintf (s + l, "Error: node not connect to channel"); 2140128967Srik strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 2141128967Srik } 2142128967Srik break; 2143128967Srik } 2144128967Srik break; 2145128967Srik } 2146128967Srik NG_RESPOND_MSG (error, node, item, resp); 2147128967Srik NG_FREE_MSG (msg); 2148128967Srik return error; 2149128967Srik} 2150128967Srik 2151128967Srikstatic int ng_cp_rcvdata (hook_p hook, item_p item) 2152128967Srik{ 2153128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2154128967Srik struct mbuf *m; 2155131108Sjulian struct ng_tag_prio *ptag; 2156138823Srik bdrv_t *bd = d->board->sys; 2157128967Srik struct ifqueue *q; 2158128967Srik int s; 2159128967Srik 2160128967Srik CP_DEBUG2 (d, ("Rcvdata\n")); 2161128967Srik NGI_GET_M (item, m); 2162128967Srik NG_FREE_ITEM (item); 2163128967Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 2164128967Srik NG_FREE_M (m); 2165128967Srik return ENETDOWN; 2166128967Srik } 2167131108Sjulian 2168131108Sjulian /* Check for high priority data */ 2169131108Sjulian if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2170131108Sjulian NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2171131108Sjulian q = &d->hi_queue; 2172131108Sjulian else 2173131108Sjulian q = &d->queue; 2174131108Sjulian 2175128967Srik s = splimp (); 2176138823Srik CP_LOCK (bd); 2177128967Srik IF_LOCK (q); 2178128967Srik if (_IF_QFULL (q)) { 2179128967Srik _IF_DROP (q); 2180128967Srik IF_UNLOCK (q); 2181138823Srik CP_UNLOCK (bd); 2182128967Srik splx (s); 2183128967Srik NG_FREE_M (m); 2184128967Srik return ENOBUFS; 2185128967Srik } 2186128967Srik _IF_ENQUEUE (q, m); 2187128967Srik IF_UNLOCK (q); 2188128967Srik cp_start (d); 2189138823Srik CP_UNLOCK (bd); 2190128967Srik splx (s); 2191128967Srik return 0; 2192128967Srik} 2193128967Srik 2194128967Srikstatic int ng_cp_rmnode (node_p node) 2195128967Srik{ 2196128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2197128967Srik 2198128967Srik CP_DEBUG (d, ("Rmnode\n")); 2199128967Srik if (d && d->running) { 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 } 2207128967Srik#ifdef KLD_MODULE 2208132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 2209128967Srik NG_NODE_SET_PRIVATE (node, NULL); 2210128967Srik NG_NODE_UNREF (node); 2211128967Srik } 2212132464Sjulian NG_NODE_REVIVE(node); /* Persistant node */ 2213128967Srik#endif 2214128967Srik return 0; 2215128967Srik} 2216128967Srik 2217128967Srikstatic void ng_cp_watchdog (void *arg) 2218128967Srik{ 2219128967Srik drv_t *d = arg; 2220128967Srik 2221128967Srik if (d) { 2222128967Srik if (d->timeout == 1) 2223128967Srik cp_watchdog (d); 2224128967Srik if (d->timeout) 2225128967Srik d->timeout--; 2226138823Srik callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d); 2227128967Srik } 2228128967Srik} 2229128967Srik 2230128967Srikstatic int ng_cp_connect (hook_p hook) 2231128967Srik{ 2232128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2233128967Srik 2234128967Srik if (d) { 2235128967Srik CP_DEBUG (d, ("Connect\n")); 2236138823Srik callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d); 2237128967Srik } 2238128967Srik 2239128967Srik return 0; 2240128967Srik} 2241128967Srik 2242128967Srikstatic int ng_cp_disconnect (hook_p hook) 2243128967Srik{ 2244128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2245128967Srik 2246128967Srik if (d) { 2247128967Srik CP_DEBUG (d, ("Disconnect\n")); 2248128967Srik if (NG_HOOK_PRIVATE (hook)) 2249128967Srik { 2250138823Srik bdrv_t *bd = d->board->sys; 2251128967Srik int s = splimp (); 2252138823Srik CP_LOCK (bd); 2253128967Srik cp_down (d); 2254138823Srik CP_UNLOCK (bd); 2255128967Srik splx (s); 2256128967Srik } 2257138823Srik /* If we were wait it than it reasserted now, just stop it. */ 2258138823Srik if (!callout_drain (&d->timeout_handle)) 2259138823Srik callout_stop (&d->timeout_handle); 2260128967Srik } 2261128967Srik return 0; 2262128967Srik} 2263128967Srik#endif 2264128967Srik 2265128967Srikstatic int cp_modevent (module_t mod, int type, void *unused) 2266128967Srik{ 2267128967Srik static int load_count = 0; 2268128967Srik 2269138823Srik if (!debug_mpsafenet && cp_mpsafenet) { 2270138823Srik printf ("WORNING! Network stack is not MPSAFE. " 2271138823Srik "Turning off debug.cp.mpsafenet.\n"); 2272138823Srik cp_mpsafenet = 0; 2273138823Srik } 2274138823Srik if (cp_mpsafenet) 2275138823Srik cp_cdevsw.d_flags &= ~D_NEEDGIANT; 2276138823Srik 2277128967Srik switch (type) { 2278128967Srik case MOD_LOAD: 2279138673Srik#ifdef NETGRAPH 2280128967Srik if (ng_newtype (&typestruct)) 2281128967Srik printf ("Failed to register ng_cp\n"); 2282128967Srik#endif 2283128967Srik ++load_count; 2284138823Srik callout_init (&timeout_handle, cp_mpsafenet?CALLOUT_MPSAFE:0); 2285138823Srik callout_reset (&timeout_handle, hz*5, cp_timeout, 0); 2286128967Srik break; 2287128967Srik case MOD_UNLOAD: 2288128967Srik if (load_count == 1) { 2289128967Srik printf ("Removing device entry for Tau-PCI\n"); 2290138673Srik#ifdef NETGRAPH 2291128967Srik ng_rmtype (&typestruct); 2292128967Srik#endif 2293128967Srik } 2294138823Srik /* If we were wait it than it reasserted now, just stop it. 2295138823Srik * Actually we shouldn't get this condition. But code could be 2296138823Srik * changed in the future, so just be a litle paranoid. 2297138823Srik */ 2298138823Srik if (!callout_drain (&timeout_handle)) 2299138823Srik callout_stop (&timeout_handle); 2300128967Srik --load_count; 2301128967Srik break; 2302128967Srik case MOD_SHUTDOWN: 2303128967Srik break; 2304128967Srik } 2305128967Srik return 0; 2306128967Srik} 2307128967Srik 2308128967Srik#ifdef NETGRAPH 2309128967Srikstatic struct ng_type typestruct = { 2310129837Srik .version = NG_ABI_VERSION, 2311129837Srik .name = NG_CP_NODE_TYPE, 2312129837Srik .constructor = ng_cp_constructor, 2313129837Srik .rcvmsg = ng_cp_rcvmsg, 2314129837Srik .shutdown = ng_cp_rmnode, 2315129837Srik .newhook = ng_cp_newhook, 2316129837Srik .connect = ng_cp_connect, 2317129837Srik .rcvdata = ng_cp_rcvdata, 2318129837Srik .disconnect = ng_cp_disconnect, 2319128967Srik}; 2320128967Srik#endif /*NETGRAPH*/ 2321128967Srik 2322128967Srik#ifdef NETGRAPH 2323128967SrikMODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2324128967Srik#else 2325128967SrikMODULE_DEPEND (cp, sppp, 1, 1, 1); 2326128967Srik#endif 2327128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2328138823SrikMODULE_VERSION (cp, 1); 2329