if_cp.c revision 164033
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 164033 2006-11-06 13:42:10Z rwatson $"); 26128967Srik 27128967Srik#include <sys/param.h> 28128967Srik#include <sys/ucred.h> 29128967Srik#include <sys/proc.h> 30128967Srik#include <sys/systm.h> 31128967Srik#include <sys/mbuf.h> 32128967Srik#include <sys/kernel.h> 33129879Sphk#include <sys/module.h> 34128967Srik#include <sys/conf.h> 35128967Srik#include <sys/malloc.h> 36164033Srwatson#include <sys/priv.h> 37128967Srik#include <sys/socket.h> 38128967Srik#include <sys/sockio.h> 39138823Srik#include <sys/sysctl.h> 40128967Srik#include <sys/tty.h> 41130971Srik#include <sys/bus.h> 42128967Srik#include <vm/vm.h> 43128967Srik#include <vm/pmap.h> 44128967Srik#include <net/if.h> 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 82138823Srikstatic int cp_mpsafenet = 1; 83138823SrikTUNABLE_INT("debug.cp.mpsafenet", &cp_mpsafenet); 84138823SrikSYSCTL_NODE(_debug, OID_AUTO, cp, CTLFLAG_RD, 0, "Cronyx Tau-PCI Adapters"); 85138823SrikSYSCTL_INT(_debug_cp, OID_AUTO, mpsafenet, CTLFLAG_RD, &cp_mpsafenet, 0, 86138823Srik "Enable/disable MPSAFE network support for Cronyx Tau-PCI Adapters"); 87138823Srik 88138823Srik#define CP_LOCK(_bd) do { \ 89138823Srik if (cp_mpsafenet) \ 90138823Srik mtx_lock (&(_bd)->cp_mtx); \ 91138823Srik } while (0) 92138823Srik#define CP_UNLOCK(_bd) do { \ 93138823Srik if (cp_mpsafenet) \ 94138823Srik mtx_unlock (&(_bd)->cp_mtx); \ 95138823Srik } while (0) 96138823Srik 97138823Srik#define CP_LOCK_ASSERT(_bd) do { \ 98138823Srik if (cp_mpsafenet) \ 99138823Srik mtx_assert (&(_bd)->cp_mtx, MA_OWNED); \ 100138823Srik } while (0) 101138823Srik 102128967Srikstatic int cp_probe __P((device_t)); 103128967Srikstatic int cp_attach __P((device_t)); 104128967Srikstatic int cp_detach __P((device_t)); 105128967Srik 106128967Srikstatic device_method_t cp_methods[] = { 107128967Srik /* Device interface */ 108128967Srik DEVMETHOD(device_probe, cp_probe), 109128967Srik DEVMETHOD(device_attach, cp_attach), 110128967Srik DEVMETHOD(device_detach, cp_detach), 111128967Srik 112128967Srik {0, 0} 113128967Srik}; 114128967Srik 115130985Sriktypedef struct _cp_dma_mem_t { 116130985Srik unsigned long phys; 117130985Srik void *virt; 118130985Srik size_t size; 119130985Srik bus_dma_tag_t dmat; 120130985Srik bus_dmamap_t mapp; 121130985Srik} cp_dma_mem_t; 122128967Srik 123128967Sriktypedef struct _drv_t { 124138823Srik char name [8]; 125138823Srik int running; 126138823Srik cp_chan_t *chan; 127138823Srik cp_board_t *board; 128138823Srik cp_dma_mem_t dmamem; 129128967Srik#ifdef NETGRAPH 130128967Srik char nodename [NG_NODELEN+1]; 131128967Srik hook_p hook; 132128967Srik hook_p debug_hook; 133128967Srik node_p node; 134128967Srik struct ifqueue queue; 135128967Srik struct ifqueue hi_queue; 136128967Srik short timeout; 137138823Srik struct callout timeout_handle; 138128967Srik#else 139138823Srik struct ifqueue queue; 140147256Sbrooks struct ifnet *ifp; 141128967Srik#endif 142138823Srik struct cdev *devt; 143128967Srik} drv_t; 144128967Srik 145130985Sriktypedef struct _bdrv_t { 146130985Srik cp_board_t *board; 147130985Srik struct resource *cp_res; 148130985Srik struct resource *cp_irq; 149130985Srik void *cp_intrhand; 150130985Srik cp_dma_mem_t dmamem; 151130985Srik drv_t channel [NCHAN]; 152138823Srik struct mtx cp_mtx; 153130985Srik} bdrv_t; 154130985Srik 155130985Srikstatic driver_t cp_driver = { 156130985Srik "cp", 157130985Srik cp_methods, 158130985Srik sizeof(bdrv_t), 159130985Srik}; 160130985Srik 161130985Srikstatic devclass_t cp_devclass; 162130985Srik 163128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len); 164128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len); 165128967Srikstatic void cp_error (cp_chan_t *c, int data); 166128967Srikstatic void cp_up (drv_t *d); 167128967Srikstatic void cp_start (drv_t *d); 168128967Srikstatic void cp_down (drv_t *d); 169128967Srikstatic void cp_watchdog (drv_t *d); 170128967Srik#ifdef NETGRAPH 171128967Srikextern struct ng_type typestruct; 172128967Srik#else 173128967Srikstatic void cp_ifstart (struct ifnet *ifp); 174128967Srikstatic void cp_tlf (struct sppp *sp); 175128967Srikstatic void cp_tls (struct sppp *sp); 176128967Srikstatic void cp_ifwatchdog (struct ifnet *ifp); 177128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 178128967Srikstatic void cp_initialize (void *softc); 179128967Srik#endif 180128967Srik 181128967Srikstatic cp_board_t *adapter [NBRD]; 182128967Srikstatic drv_t *channel [NBRD*NCHAN]; 183138823Srikstatic struct callout led_timo [NBRD]; 184138823Srikstatic struct callout timeout_handle; 185128967Srik 186128967Srikstatic int cp_destroy = 0; 187128967Srik 188150622Srikstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td); 189150622Srikstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td); 190150622Srikstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); 191150622Srikstatic struct cdevsw cp_cdevsw = { 192150622Srik .d_version = D_VERSION, 193150622Srik .d_open = cp_open, 194150622Srik .d_close = cp_close, 195150622Srik .d_ioctl = cp_ioctl, 196150622Srik .d_name = "cp", 197150622Srik .d_flags = D_NEEDGIANT, 198150622Srik}; 199150622Srik 200128967Srik/* 201150622Srik * Print the mbuf chain, for debug purposes only. 202150622Srik */ 203150622Srikstatic void printmbuf (struct mbuf *m) 204150622Srik{ 205150622Srik printf ("mbuf:"); 206150622Srik for (; m; m=m->m_next) { 207150622Srik if (m->m_flags & M_PKTHDR) 208150622Srik printf (" HDR %d:", m->m_pkthdr.len); 209150622Srik if (m->m_flags & M_EXT) 210150622Srik printf (" EXT:"); 211150622Srik printf (" %d", m->m_len); 212150622Srik } 213150622Srik printf ("\n"); 214150622Srik} 215150622Srik 216150622Srik/* 217150622Srik * Make an mbuf from data. 218150622Srik */ 219150622Srikstatic struct mbuf *makembuf (void *buf, unsigned len) 220150622Srik{ 221150622Srik struct mbuf *m; 222150622Srik 223150622Srik MGETHDR (m, M_DONTWAIT, MT_DATA); 224150622Srik if (! m) 225150622Srik return 0; 226150622Srik MCLGET (m, M_DONTWAIT); 227150622Srik if (! (m->m_flags & M_EXT)) { 228150622Srik m_freem (m); 229150622Srik return 0; 230150622Srik } 231150622Srik m->m_pkthdr.len = m->m_len = len; 232150622Srik bcopy (buf, mtod (m, caddr_t), len); 233150622Srik return m; 234150622Srik} 235150622Srik 236150622Srikstatic int cp_probe (device_t dev) 237150622Srik{ 238150622Srik if ((pci_get_vendor (dev) == cp_vendor_id) && 239150622Srik (pci_get_device (dev) == cp_device_id)) { 240150622Srik device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 241150622Srik return BUS_PROBE_DEFAULT; 242150622Srik } 243150622Srik return ENXIO; 244150622Srik} 245150622Srik 246150622Srikstatic void cp_timeout (void *arg) 247150622Srik{ 248150622Srik drv_t *d; 249150622Srik int s, i, k; 250150622Srik 251150622Srik for (i = 0; i < NBRD; ++i) { 252150622Srik if (adapter[i] == NULL) 253150622Srik continue; 254150622Srik for (k = 0; k < NCHAN; ++k) { 255150622Srik s = splimp (); 256150622Srik if (cp_destroy) { 257150622Srik splx (s); 258150622Srik return; 259150622Srik } 260150622Srik d = channel[i * NCHAN + k]; 261150622Srik if (!d) { 262150622Srik splx (s); 263150622Srik continue; 264150622Srik } 265150622Srik CP_LOCK ((bdrv_t *)d->board->sys); 266150622Srik switch (d->chan->type) { 267150622Srik case T_G703: 268150622Srik cp_g703_timer (d->chan); 269150622Srik break; 270150622Srik case T_E1: 271150622Srik cp_e1_timer (d->chan); 272150622Srik break; 273150622Srik case T_E3: 274150622Srik case T_T3: 275150622Srik case T_STS1: 276150622Srik cp_e3_timer (d->chan); 277150622Srik break; 278150622Srik default: 279150622Srik break; 280150622Srik } 281150622Srik CP_UNLOCK ((bdrv_t *)d->board->sys); 282150622Srik splx (s); 283150622Srik } 284150622Srik } 285150622Srik s = splimp (); 286150622Srik if (!cp_destroy) 287150622Srik callout_reset (&timeout_handle, hz, cp_timeout, 0); 288150622Srik splx (s); 289150622Srik} 290150622Srik 291150622Srikstatic void cp_led_off (void *arg) 292150622Srik{ 293150622Srik cp_board_t *b = arg; 294150622Srik bdrv_t *bd = (bdrv_t *) b->sys; 295150622Srik int s; 296150622Srik s = splimp (); 297150622Srik if (cp_destroy) { 298150622Srik splx (s); 299150622Srik return; 300150622Srik } 301150622Srik CP_LOCK (bd); 302150622Srik cp_led (b, 0); 303150622Srik CP_UNLOCK (bd); 304150622Srik splx (s); 305150622Srik} 306150622Srik 307150622Srikstatic void cp_intr (void *arg) 308150622Srik{ 309150622Srik bdrv_t *bd = arg; 310150622Srik cp_board_t *b = bd->board; 311150622Srik#ifndef NETGRAPH 312150622Srik int i; 313150622Srik#endif 314150622Srik int s = splimp (); 315150622Srik if (cp_destroy) { 316150622Srik splx (s); 317150622Srik return; 318150622Srik } 319150622Srik CP_LOCK (bd); 320150622Srik /* Check if we are ready */ 321150622Srik if (b->sys == NULL) { 322150622Srik /* Not we are not, just cleanup. */ 323150622Srik cp_interrupt_poll (b, 1); 324150622Srik CP_UNLOCK (bd); 325150622Srik return; 326150622Srik } 327150622Srik /* Turn LED on. */ 328150622Srik cp_led (b, 1); 329150622Srik 330150622Srik cp_interrupt (b); 331150622Srik 332150622Srik /* Turn LED off 50 msec later. */ 333150622Srik callout_reset (&led_timo[b->num], hz/20, cp_led_off, b); 334150622Srik CP_UNLOCK (bd); 335150622Srik splx (s); 336150622Srik 337150622Srik#ifndef NETGRAPH 338150622Srik /* Pass packets in a lock-free state */ 339150622Srik for (i = 0; i < NCHAN && b->chan[i].type; i++) { 340150622Srik drv_t *d = b->chan[i].sys; 341150622Srik struct mbuf *m; 342150622Srik if (!d || !d->running) 343150622Srik continue; 344150622Srik while (_IF_QLEN(&d->queue)) { 345150622Srik IF_DEQUEUE (&d->queue,m); 346150622Srik if (!m) 347150622Srik continue; 348150622Srik sppp_input (d->ifp, m); 349150622Srik } 350150622Srik } 351150622Srik#endif 352150622Srik} 353150622Srik 354150622Srikstatic void 355150622Srikcp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 356150622Srik{ 357150622Srik unsigned long *addr; 358150622Srik 359150622Srik if (error) 360150622Srik return; 361150622Srik 362150622Srik KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 363150622Srik addr = arg; 364150622Srik *addr = segs->ds_addr; 365150622Srik} 366150622Srik 367150622Srikstatic int 368150622Srikcp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 369150622Srik{ 370150622Srik int error; 371150622Srik 372150622Srik error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 373150622Srik BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 374150622Srik dmem->size, 0, NULL, NULL, &dmem->dmat); 375150622Srik if (error) { 376150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 377150622Srik else printf ("cp%d: ", bnum); 378150622Srik printf ("couldn't allocate tag for dma memory\n"); 379150622Srik return 0; 380150622Srik } 381150622Srik error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 382150622Srik BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 383150622Srik if (error) { 384150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 385150622Srik else printf ("cp%d: ", bnum); 386150622Srik printf ("couldn't allocate mem for dma memory\n"); 387150622Srik bus_dma_tag_destroy (dmem->dmat); 388150622Srik return 0; 389150622Srik } 390150622Srik error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 391150622Srik dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); 392150622Srik if (error) { 393150622Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 394150622Srik else printf ("cp%d: ", bnum); 395150622Srik printf ("couldn't load mem map for dma memory\n"); 396150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 397150622Srik bus_dma_tag_destroy (dmem->dmat); 398150622Srik return 0; 399150622Srik } 400150622Srik return 1; 401150622Srik} 402150622Srik 403150622Srikstatic void 404150622Srikcp_bus_dma_mem_free (cp_dma_mem_t *dmem) 405150622Srik{ 406150622Srik bus_dmamap_unload (dmem->dmat, dmem->mapp); 407150622Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 408150622Srik bus_dma_tag_destroy (dmem->dmat); 409150622Srik} 410150622Srik 411150622Srik/* 412150622Srik * Called if the probe succeeded. 413150622Srik */ 414150622Srikstatic int cp_attach (device_t dev) 415150622Srik{ 416150622Srik bdrv_t *bd = device_get_softc (dev); 417150622Srik int unit = device_get_unit (dev); 418150622Srik char *cp_ln = CP_LOCK_NAME; 419150622Srik unsigned short res; 420150622Srik vm_offset_t vbase; 421150622Srik int rid, error; 422150622Srik cp_board_t *b; 423150622Srik cp_chan_t *c; 424150622Srik drv_t *d; 425150622Srik int s = splimp (); 426150622Srik 427150622Srik b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 428150622Srik if (!b) { 429150622Srik printf ("cp%d: couldn't allocate memory\n", unit); 430150622Srik splx (s); 431150622Srik return (ENXIO); 432150622Srik } 433150622Srik bzero (b, sizeof(cp_board_t)); 434150622Srik 435150622Srik bd->board = b; 436150622Srik rid = PCIR_BAR(0); 437150622Srik bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 438150622Srik 0, ~0, 1, RF_ACTIVE); 439150622Srik if (! bd->cp_res) { 440150622Srik printf ("cp%d: cannot map memory\n", unit); 441150622Srik free (b, M_DEVBUF); 442150622Srik splx (s); 443150622Srik return (ENXIO); 444150622Srik } 445150622Srik vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 446150622Srik 447150622Srik cp_ln[2] = '0' + unit; 448150622Srik mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 449150622Srik res = cp_init (b, unit, (u_char*) vbase); 450150622Srik if (res) { 451150622Srik printf ("cp%d: can't init, error code:%x\n", unit, res); 452150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 453150622Srik free (b, M_DEVBUF); 454150622Srik splx (s); 455150622Srik return (ENXIO); 456150622Srik } 457150622Srik 458150622Srik bd->dmamem.size = sizeof(cp_qbuf_t); 459150622Srik if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 460150622Srik free (b, M_DEVBUF); 461150622Srik splx (s); 462150622Srik return (ENXIO); 463150622Srik } 464150622Srik CP_LOCK (bd); 465150622Srik cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); 466150622Srik CP_UNLOCK (bd); 467150622Srik 468150622Srik rid = 0; 469150622Srik bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 470150622Srik RF_SHAREABLE | RF_ACTIVE); 471150622Srik if (! bd->cp_irq) { 472150622Srik cp_destroy = 1; 473150622Srik printf ("cp%d: cannot map interrupt\n", unit); 474150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 475150622Srik PCIR_BAR(0), bd->cp_res); 476150622Srik mtx_destroy (&bd->cp_mtx); 477150622Srik free (b, M_DEVBUF); 478150622Srik splx (s); 479150622Srik return (ENXIO); 480150622Srik } 481150622Srik callout_init (&led_timo[unit], cp_mpsafenet ? CALLOUT_MPSAFE : 0); 482150622Srik error = bus_setup_intr (dev, bd->cp_irq, 483150622Srik INTR_TYPE_NET|(cp_mpsafenet?INTR_MPSAFE:0), 484150622Srik cp_intr, bd, &bd->cp_intrhand); 485150622Srik if (error) { 486150622Srik cp_destroy = 1; 487150622Srik printf ("cp%d: cannot set up irq\n", unit); 488150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 489150622Srik bus_release_resource (dev, SYS_RES_MEMORY, 490150622Srik PCIR_BAR(0), bd->cp_res); 491150622Srik mtx_destroy (&bd->cp_mtx); 492150622Srik free (b, M_DEVBUF); 493150622Srik splx (s); 494150622Srik return (ENXIO); 495150622Srik } 496150622Srik printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 497150622Srik 498150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 499150622Srik if (! c->type) 500150622Srik continue; 501150622Srik d = &bd->channel[c->num]; 502150622Srik d->dmamem.size = sizeof(cp_buf_t); 503150622Srik if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 504150622Srik continue; 505150622Srik channel [b->num*NCHAN + c->num] = d; 506150622Srik sprintf (d->name, "cp%d.%d", b->num, c->num); 507150622Srik d->board = b; 508150622Srik d->chan = c; 509150622Srik c->sys = d; 510150622Srik#ifdef NETGRAPH 511150622Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 512150622Srik printf ("%s: cannot make common node\n", d->name); 513150622Srik d->node = NULL; 514150622Srik continue; 515150622Srik } 516150622Srik NG_NODE_SET_PRIVATE (d->node, d); 517150622Srik sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 518150622Srik c->board->num*NCHAN + c->num); 519150622Srik if (ng_name_node (d->node, d->nodename)) { 520150622Srik printf ("%s: cannot name node\n", d->nodename); 521150622Srik NG_NODE_UNREF (d->node); 522150622Srik continue; 523150622Srik } 524150622Srik d->queue.ifq_maxlen = IFQ_MAXLEN; 525150622Srik d->hi_queue.ifq_maxlen = IFQ_MAXLEN; 526150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 527150622Srik mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 528150622Srik callout_init (&d->timeout_handle, 529150622Srik cp_mpsafenet ? CALLOUT_MPSAFE : 0); 530150622Srik#else /*NETGRAPH*/ 531150622Srik d->ifp = if_alloc(IFT_PPP); 532150622Srik if (d->ifp == NULL) { 533150622Srik printf ("%s: cannot if_alloc() interface\n", d->name); 534150622Srik continue; 535150622Srik } 536150622Srik d->ifp->if_softc = d; 537150622Srik if_initname (d->ifp, "cp", b->num * NCHAN + c->num); 538150622Srik d->ifp->if_mtu = PP_MTU; 539150622Srik d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 540150622Srik if (!cp_mpsafenet) 541150622Srik d->ifp->if_flags |= IFF_NEEDSGIANT; 542150622Srik d->ifp->if_ioctl = cp_sioctl; 543150622Srik d->ifp->if_start = cp_ifstart; 544150622Srik d->ifp->if_watchdog = cp_ifwatchdog; 545150622Srik d->ifp->if_init = cp_initialize; 546150622Srik d->queue.ifq_maxlen = NRBUF; 547150622Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 548150622Srik sppp_attach (d->ifp); 549150622Srik if_attach (d->ifp); 550150622Srik IFP2SP(d->ifp)->pp_tlf = cp_tlf; 551150622Srik IFP2SP(d->ifp)->pp_tls = cp_tls; 552150622Srik /* If BPF is in the kernel, call the attach for it. 553150622Srik * The header size of PPP or Cisco/HDLC is 4 bytes. */ 554150622Srik bpfattach (d->ifp, DLT_PPP, 4); 555150622Srik#endif /*NETGRAPH*/ 556150622Srik cp_start_e1 (c); 557150622Srik cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 558150622Srik 559150622Srik /* Register callback functions. */ 560150622Srik cp_register_transmit (c, &cp_transmit); 561150622Srik cp_register_receive (c, &cp_receive); 562150622Srik cp_register_error (c, &cp_error); 563150622Srik d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 564150622Srik GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 565150622Srik } 566150622Srik CP_LOCK (bd); 567150622Srik b->sys = bd; 568150622Srik adapter[unit] = b; 569150622Srik CP_UNLOCK (bd); 570150622Srik splx (s); 571150622Srik return 0; 572150622Srik} 573150622Srik 574150622Srikstatic int cp_detach (device_t dev) 575150622Srik{ 576150622Srik bdrv_t *bd = device_get_softc (dev); 577150622Srik cp_board_t *b = bd->board; 578150622Srik cp_chan_t *c; 579150622Srik int s; 580150622Srik 581150622Srik KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized")); 582150622Srik s = splimp (); 583150622Srik CP_LOCK (bd); 584150622Srik /* Check if the device is busy (open). */ 585150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 586150622Srik drv_t *d = (drv_t*) c->sys; 587150622Srik 588150622Srik if (! d || ! d->chan->type) 589150622Srik continue; 590150622Srik if (d->running) { 591150622Srik CP_UNLOCK (bd); 592150622Srik splx (s); 593150622Srik return EBUSY; 594150622Srik } 595150622Srik } 596150622Srik 597150622Srik /* Ok, we can unload driver */ 598150622Srik /* At first we should stop all channels */ 599150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 600150622Srik drv_t *d = (drv_t*) c->sys; 601150622Srik 602150622Srik if (! d || ! d->chan->type) 603150622Srik continue; 604150622Srik 605150622Srik cp_stop_chan (c); 606150622Srik cp_stop_e1 (c); 607150622Srik cp_set_dtr (d->chan, 0); 608150622Srik cp_set_rts (d->chan, 0); 609150622Srik } 610150622Srik 611150622Srik /* Reset the adapter. */ 612150622Srik cp_destroy = 1; 613150622Srik cp_interrupt_poll (b, 1); 614150622Srik cp_led_off (b); 615150622Srik cp_reset (b, 0 ,0); 616150622Srik callout_stop (&led_timo[b->num]); 617150622Srik 618150624Srik /* Disable the interrupt request. */ 619150624Srik bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 620150624Srik 621150622Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 622150622Srik drv_t *d = (drv_t*) c->sys; 623150622Srik 624150622Srik if (! d || ! d->chan->type) 625150622Srik continue; 626150622Srik#ifndef NETGRAPH 627150622Srik /* Detach from the packet filter list of interfaces. */ 628150622Srik bpfdetach (d->ifp); 629150622Srik 630150622Srik /* Detach from the sync PPP list. */ 631150622Srik sppp_detach (d->ifp); 632150622Srik 633150622Srik /* Detach from the system list of interfaces. */ 634150622Srik if_detach (d->ifp); 635150622Srik if_free (d->ifp); 636150622Srik IF_DRAIN (&d->queue); 637150622Srik mtx_destroy (&d->queue.ifq_mtx); 638150622Srik#else 639150622Srik if (d->node) { 640150622Srik ng_rmnode_self (d->node); 641150622Srik NG_NODE_UNREF (d->node); 642150622Srik d->node = NULL; 643150622Srik } 644150622Srik mtx_destroy (&d->queue.ifq_mtx); 645150622Srik mtx_destroy (&d->hi_queue.ifq_mtx); 646150622Srik#endif 647150622Srik destroy_dev (d->devt); 648150622Srik } 649150622Srik 650150622Srik b->sys = NULL; 651150622Srik CP_UNLOCK (bd); 652150622Srik 653150622Srik bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 654150622Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 655150622Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 656150622Srik 657150622Srik CP_LOCK (bd); 658150622Srik cp_led_off (b); 659150622Srik CP_UNLOCK (bd); 660150622Srik callout_drain (&led_timo[b->num]); 661150622Srik splx (s); 662150622Srik 663150622Srik s = splimp (); 664150622Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 665150622Srik drv_t *d = (drv_t*) c->sys; 666150622Srik 667150622Srik if (! d || ! d->chan->type) 668150622Srik continue; 669150622Srik channel [b->num*NCHAN + c->num] = 0; 670150622Srik /* Deallocate buffers. */ 671150622Srik cp_bus_dma_mem_free (&d->dmamem); 672150622Srik } 673150622Srik adapter [b->num] = 0; 674150622Srik cp_bus_dma_mem_free (&bd->dmamem); 675150622Srik free (b, M_DEVBUF); 676150622Srik splx (s); 677150622Srik mtx_destroy (&bd->cp_mtx); 678150622Srik return 0; 679150622Srik} 680150622Srik 681150622Srik#ifndef NETGRAPH 682150622Srikstatic void cp_ifstart (struct ifnet *ifp) 683150622Srik{ 684150622Srik drv_t *d = ifp->if_softc; 685150622Srik bdrv_t *bd = d->board->sys; 686150622Srik 687150622Srik CP_LOCK (bd); 688150622Srik cp_start (d); 689150622Srik CP_UNLOCK (bd); 690150622Srik} 691150622Srik 692150622Srikstatic void cp_ifwatchdog (struct ifnet *ifp) 693150622Srik{ 694150622Srik drv_t *d = ifp->if_softc; 695150622Srik 696150622Srik cp_watchdog (d); 697150622Srik} 698150622Srik 699150622Srikstatic void cp_tlf (struct sppp *sp) 700150622Srik{ 701150622Srik drv_t *d = SP2IFP(sp)->if_softc; 702150622Srik 703150622Srik CP_DEBUG2 (d, ("cp_tlf\n")); 704150622Srik /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */ 705150622Srik/* cp_set_dtr (d->chan, 0);*/ 706150622Srik/* cp_set_rts (d->chan, 0);*/ 707150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 708150622Srik sp->pp_down (sp); 709150622Srik} 710150622Srik 711150622Srikstatic void cp_tls (struct sppp *sp) 712150622Srik{ 713150622Srik drv_t *d = SP2IFP(sp)->if_softc; 714150622Srik 715150622Srik CP_DEBUG2 (d, ("cp_tls\n")); 716150622Srik if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 717150622Srik sp->pp_up (sp); 718150622Srik} 719150622Srik 720150622Srik/* 721150622Srik * Process an ioctl request. 722150622Srik */ 723150622Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 724150622Srik{ 725150622Srik drv_t *d = ifp->if_softc; 726150622Srik bdrv_t *bd = d->board->sys; 727150622Srik int error, s, was_up, should_be_up; 728150622Srik 729150622Srik was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 730150622Srik error = sppp_ioctl (ifp, cmd, data); 731150622Srik 732150622Srik if (error) 733150622Srik return error; 734150622Srik 735150622Srik if (! (ifp->if_flags & IFF_DEBUG)) 736150622Srik d->chan->debug = 0; 737150622Srik else if (! d->chan->debug) 738150622Srik d->chan->debug = 1; 739150622Srik 740150622Srik switch (cmd) { 741150622Srik default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 742150622Srik case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 743150622Srik case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 744150622Srik case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 745150622Srik case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 746150622Srik } 747150622Srik 748150622Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 749150622Srik s = splimp (); 750150622Srik CP_LOCK (bd); 751150622Srik should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 752150622Srik if (! was_up && should_be_up) { 753150622Srik /* Interface goes up -- start it. */ 754150622Srik cp_up (d); 755150622Srik cp_start (d); 756150622Srik } else if (was_up && ! should_be_up) { 757150622Srik /* Interface is going down -- stop it. */ 758150622Srik/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 759150622Srik cp_down (d); 760150622Srik } 761150622Srik CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 762150622Srik CP_UNLOCK (bd); 763150622Srik splx (s); 764150622Srik return 0; 765150622Srik} 766150622Srik 767150622Srik/* 768150622Srik * Initialization of interface. 769150622Srik * It seems to be never called by upper level? 770150622Srik */ 771150622Srikstatic void cp_initialize (void *softc) 772150622Srik{ 773150622Srik drv_t *d = softc; 774150622Srik 775150622Srik CP_DEBUG (d, ("cp_initialize\n")); 776150622Srik} 777150622Srik#endif /*NETGRAPH*/ 778150622Srik 779150622Srik/* 780150622Srik * Stop the interface. Called on splimp(). 781150622Srik */ 782150622Srikstatic void cp_down (drv_t *d) 783150622Srik{ 784150622Srik CP_DEBUG (d, ("cp_down\n")); 785150622Srik /* Interface is going down -- stop it. */ 786150622Srik cp_set_dtr (d->chan, 0); 787150622Srik cp_set_rts (d->chan, 0); 788150622Srik 789150622Srik d->running = 0; 790150622Srik} 791150622Srik 792150622Srik/* 793150622Srik * Start the interface. Called on splimp(). 794150622Srik */ 795150622Srikstatic void cp_up (drv_t *d) 796150622Srik{ 797150622Srik CP_DEBUG (d, ("cp_up\n")); 798150622Srik cp_set_dtr (d->chan, 1); 799150622Srik cp_set_rts (d->chan, 1); 800150622Srik d->running = 1; 801150622Srik} 802150622Srik 803150622Srik/* 804150622Srik * Start output on the interface. Get another datagram to send 805150622Srik * off of the interface queue, and copy it to the interface 806150622Srik * before starting the output. 807150622Srik */ 808150622Srikstatic void cp_send (drv_t *d) 809150622Srik{ 810150622Srik struct mbuf *m; 811150622Srik u_short len; 812150622Srik 813150622Srik CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 814150622Srik 815150622Srik /* No output if the interface is down. */ 816150622Srik if (! d->running) 817150622Srik return; 818150622Srik 819150622Srik /* No output if the modem is off. */ 820150622Srik if (! (d->chan->lloop || d->chan->type != T_SERIAL || 821150622Srik cp_get_dsr (d->chan))) 822150622Srik return; 823150622Srik 824150622Srik while (cp_transmit_space (d->chan)) { 825150622Srik /* Get the packet to send. */ 826150622Srik#ifdef NETGRAPH 827150622Srik IF_DEQUEUE (&d->hi_queue, m); 828150622Srik if (! m) 829150622Srik IF_DEQUEUE (&d->queue, m); 830150622Srik#else 831150622Srik m = sppp_dequeue (d->ifp); 832150622Srik#endif 833150622Srik if (! m) 834150622Srik return; 835150622Srik#ifndef NETGRAPH 836150622Srik if (d->ifp->if_bpf) 837150622Srik BPF_MTAP (d->ifp, m); 838150622Srik#endif 839150622Srik len = m_length (m, NULL); 840150622Srik if (len >= BUFSZ) 841150622Srik printf ("%s: too long packet: %d bytes: ", 842150622Srik d->name, len); 843150622Srik else if (! m->m_next) 844150622Srik cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 845150622Srik else { 846150622Srik u_char *buf = d->chan->tbuf[d->chan->te]; 847150622Srik m_copydata (m, 0, len, buf); 848150622Srik cp_send_packet (d->chan, buf, len, 0); 849150622Srik } 850150622Srik m_freem (m); 851150622Srik /* Set up transmit timeout, if the transmit ring is not empty.*/ 852150622Srik#ifdef NETGRAPH 853150622Srik d->timeout = 10; 854150622Srik#else 855150622Srik d->ifp->if_timer = 10; 856150622Srik#endif 857150622Srik } 858150622Srik#ifndef NETGRAPH 859150622Srik d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 860150622Srik#endif 861150622Srik} 862150622Srik 863150622Srik/* 864150622Srik * Start output on the interface. 865150622Srik * Always called on splimp(). 866150622Srik */ 867150622Srikstatic void cp_start (drv_t *d) 868150622Srik{ 869150622Srik if (d->running) { 870150622Srik if (! d->chan->dtr) 871150622Srik cp_set_dtr (d->chan, 1); 872150622Srik if (! d->chan->rts) 873150622Srik cp_set_rts (d->chan, 1); 874150622Srik cp_send (d); 875150622Srik } 876150622Srik} 877150622Srik 878150622Srik/* 879150622Srik * Handle transmit timeouts. 880150622Srik * Recover after lost transmit interrupts. 881150622Srik * Always called on splimp(). 882150622Srik */ 883150622Srikstatic void cp_watchdog (drv_t *d) 884150622Srik{ 885150622Srik bdrv_t *bd = d->board->sys; 886150622Srik CP_DEBUG (d, ("device timeout\n")); 887150622Srik if (d->running) { 888150622Srik int s = splimp (); 889150622Srik 890150622Srik CP_LOCK (bd); 891150622Srik cp_stop_chan (d->chan); 892150622Srik cp_stop_e1 (d->chan); 893150622Srik cp_start_e1 (d->chan); 894150622Srik cp_start_chan (d->chan, 1, 1, 0, 0); 895150622Srik cp_set_dtr (d->chan, 1); 896150622Srik cp_set_rts (d->chan, 1); 897150622Srik cp_start (d); 898150622Srik CP_UNLOCK (bd); 899150622Srik splx (s); 900150622Srik } 901150622Srik} 902150622Srik 903150622Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len) 904150622Srik{ 905150622Srik drv_t *d = c->sys; 906150622Srik 907150622Srik#ifdef NETGRAPH 908150622Srik d->timeout = 0; 909150622Srik#else 910150622Srik ++d->ifp->if_opackets; 911150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 912150622Srik d->ifp->if_timer = 0; 913150622Srik#endif 914150622Srik cp_start (d); 915150622Srik} 916150622Srik 917150622Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len) 918150622Srik{ 919150622Srik drv_t *d = c->sys; 920150622Srik struct mbuf *m; 921150622Srik#ifdef NETGRAPH 922150622Srik int error; 923150622Srik#endif 924150622Srik 925150622Srik if (! d->running) 926150622Srik return; 927150622Srik 928150622Srik m = makembuf (data, len); 929150622Srik if (! m) { 930150622Srik CP_DEBUG (d, ("no memory for packet\n")); 931150622Srik#ifndef NETGRAPH 932150622Srik ++d->ifp->if_iqdrops; 933150622Srik#endif 934150622Srik return; 935150622Srik } 936150622Srik if (c->debug > 1) 937150622Srik printmbuf (m); 938150622Srik#ifdef NETGRAPH 939150622Srik m->m_pkthdr.rcvif = 0; 940150622Srik NG_SEND_DATA_ONLY (error, d->hook, m); 941150622Srik#else 942150622Srik ++d->ifp->if_ipackets; 943150622Srik m->m_pkthdr.rcvif = d->ifp; 944150622Srik /* Check if there's a BPF listener on this interface. 945150622Srik * If so, hand off the raw packet to bpf. */ 946150622Srik if (d->ifp->if_bpf) 947150622Srik BPF_TAP (d->ifp, data, len); 948150622Srik IF_ENQUEUE (&d->queue, m); 949150622Srik#endif 950150622Srik} 951150622Srik 952150622Srikstatic void cp_error (cp_chan_t *c, int data) 953150622Srik{ 954150622Srik drv_t *d = c->sys; 955150622Srik 956150622Srik switch (data) { 957150622Srik case CP_FRAME: 958150622Srik CP_DEBUG (d, ("frame error\n")); 959150622Srik#ifndef NETGRAPH 960150622Srik ++d->ifp->if_ierrors; 961150622Srik#endif 962150622Srik break; 963150622Srik case CP_CRC: 964150622Srik CP_DEBUG (d, ("crc error\n")); 965150622Srik#ifndef NETGRAPH 966150622Srik ++d->ifp->if_ierrors; 967150622Srik#endif 968150622Srik break; 969150622Srik case CP_OVERRUN: 970150622Srik CP_DEBUG (d, ("overrun error\n")); 971150622Srik#ifndef NETGRAPH 972150622Srik ++d->ifp->if_collisions; 973150622Srik ++d->ifp->if_ierrors; 974150622Srik#endif 975150622Srik break; 976150622Srik case CP_OVERFLOW: 977150622Srik CP_DEBUG (d, ("overflow error\n")); 978150622Srik#ifndef NETGRAPH 979150622Srik ++d->ifp->if_ierrors; 980150622Srik#endif 981150622Srik break; 982150622Srik case CP_UNDERRUN: 983150622Srik CP_DEBUG (d, ("underrun error\n")); 984150622Srik#ifdef NETGRAPH 985150622Srik d->timeout = 0; 986150622Srik#else 987150622Srik ++d->ifp->if_oerrors; 988150622Srik d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 989150622Srik d->ifp->if_timer = 0; 990150622Srik#endif 991150622Srik cp_start (d); 992150622Srik break; 993150622Srik default: 994150622Srik CP_DEBUG (d, ("error #%d\n", data)); 995150622Srik break; 996150622Srik } 997150622Srik} 998150622Srik 999150622Srik/* 1000128967Srik * You also need read, write, open, close routines. 1001128967Srik * This should get you started 1002128967Srik */ 1003130585Sphkstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 1004128967Srik{ 1005128967Srik int unit = minor (dev); 1006128967Srik drv_t *d; 1007128967Srik 1008128967Srik if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 1009128967Srik return ENXIO; 1010128967Srik CP_DEBUG2 (d, ("cp_open\n")); 1011128967Srik return 0; 1012128967Srik} 1013128967Srik 1014128967Srik/* 1015128967Srik * Only called on the LAST close. 1016128967Srik */ 1017130585Sphkstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 1018128967Srik{ 1019128967Srik drv_t *d = channel [minor (dev)]; 1020128967Srik 1021128967Srik CP_DEBUG2 (d, ("cp_close\n")); 1022128967Srik return 0; 1023128967Srik} 1024128967Srik 1025128967Srikstatic int cp_modem_status (cp_chan_t *c) 1026128967Srik{ 1027128967Srik drv_t *d = c->sys; 1028138823Srik bdrv_t *bd = d->board->sys; 1029128967Srik int status, s; 1030128967Srik 1031128967Srik status = d->running ? TIOCM_LE : 0; 1032128967Srik s = splimp (); 1033138823Srik CP_LOCK (bd); 1034128967Srik if (cp_get_cd (c)) status |= TIOCM_CD; 1035128967Srik if (cp_get_cts (c)) status |= TIOCM_CTS; 1036128967Srik if (cp_get_dsr (c)) status |= TIOCM_DSR; 1037128967Srik if (c->dtr) status |= TIOCM_DTR; 1038128967Srik if (c->rts) status |= TIOCM_RTS; 1039138823Srik CP_UNLOCK (bd); 1040128967Srik splx (s); 1041128967Srik return status; 1042128967Srik} 1043128967Srik 1044130585Sphkstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1045128967Srik{ 1046133646Srik drv_t *d = channel [minor (dev)]; 1047138823Srik bdrv_t *bd = d->board->sys; 1048128967Srik cp_chan_t *c = d->chan; 1049128967Srik struct serial_statistics *st; 1050128967Srik struct e1_statistics *opte1; 1051128967Srik struct e3_statistics *opte3; 1052128967Srik int error, s; 1053128967Srik char mask[16]; 1054128967Srik 1055128967Srik switch (cmd) { 1056128967Srik case SERIAL_GETREGISTERED: 1057133646Srik CP_DEBUG2 (d, ("ioctl: getregistered\n")); 1058128967Srik bzero (mask, sizeof(mask)); 1059128967Srik for (s=0; s<NBRD*NCHAN; ++s) 1060128967Srik if (channel [s]) 1061128967Srik mask [s/8] |= 1 << (s & 7); 1062133646Srik bcopy (mask, data, sizeof (mask)); 1063128967Srik return 0; 1064128967Srik 1065128967Srik#ifndef NETGRAPH 1066128967Srik case SERIAL_GETPROTO: 1067133646Srik CP_DEBUG2 (d, ("ioctl: getproto\n")); 1068147256Sbrooks strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1069147256Sbrooks (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1070133646Srik return 0; 1071128967Srik 1072128967Srik case SERIAL_SETPROTO: 1073133646Srik CP_DEBUG2 (d, ("ioctl: setproto\n")); 1074133646Srik /* Only for superuser! */ 1075164033Srwatson error = priv_check (td, PRIV_DRIVER); 1076133646Srik if (error) 1077133646Srik return error; 1078148887Srwatson if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) 1079128967Srik return EBUSY; 1080133646Srik if (! strcmp ("cisco", (char*)data)) { 1081147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1082147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1083147256Sbrooks d->ifp->if_flags |= PP_CISCO; 1084138873Srik } else if (! strcmp ("fr", (char*)data) && PP_FR) { 1085147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1086147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1087133646Srik } else if (! strcmp ("ppp", (char*)data)) { 1088147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_FR; 1089147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1090147256Sbrooks d->ifp->if_flags &= ~(PP_CISCO); 1091133646Srik } else 1092128967Srik return EINVAL; 1093133646Srik return 0; 1094128967Srik 1095128967Srik case SERIAL_GETKEEPALIVE: 1096133646Srik CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1097147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1098147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1099128967Srik return EINVAL; 1100147256Sbrooks *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1101133646Srik return 0; 1102128967Srik 1103128967Srik case SERIAL_SETKEEPALIVE: 1104133646Srik CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1105133646Srik /* Only for superuser! */ 1106164033Srwatson error = priv_check (td, PRIV_DRIVER); 1107133646Srik if (error) 1108133646Srik return error; 1109147256Sbrooks if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1110147256Sbrooks (d->ifp->if_flags & PP_CISCO)) 1111128967Srik return EINVAL; 1112128967Srik s = splimp (); 1113138823Srik CP_LOCK (bd); 1114133646Srik if (*(int*)data) 1115147256Sbrooks IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1116128967Srik else 1117147256Sbrooks IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1118138823Srik CP_UNLOCK (bd); 1119128967Srik splx (s); 1120133646Srik return 0; 1121128967Srik#endif /*NETGRAPH*/ 1122128967Srik 1123128967Srik case SERIAL_GETMODE: 1124133646Srik CP_DEBUG2 (d, ("ioctl: getmode\n")); 1125128967Srik *(int*)data = SERIAL_HDLC; 1126133646Srik return 0; 1127128967Srik 1128128967Srik case SERIAL_SETMODE: 1129133646Srik /* Only for superuser! */ 1130164033Srwatson error = priv_check (td, PRIV_DRIVER); 1131133646Srik if (error) 1132133646Srik return error; 1133128967Srik if (*(int*)data != SERIAL_HDLC) 1134128967Srik return EINVAL; 1135133646Srik return 0; 1136128967Srik 1137128967Srik case SERIAL_GETCFG: 1138133646Srik CP_DEBUG2 (d, ("ioctl: getcfg\n")); 1139128967Srik if (c->type != T_E1 || c->unfram) 1140128967Srik return EINVAL; 1141128967Srik *(char*)data = c->board->mux ? 'c' : 'a'; 1142133646Srik return 0; 1143128967Srik 1144128967Srik case SERIAL_SETCFG: 1145133646Srik CP_DEBUG2 (d, ("ioctl: setcfg\n")); 1146164033Srwatson error = priv_check (td, PRIV_DRIVER); 1147133646Srik if (error) 1148133646Srik return error; 1149128967Srik if (c->type != T_E1) 1150128967Srik return EINVAL; 1151133646Srik s = splimp (); 1152138823Srik CP_LOCK (bd); 1153128967Srik cp_set_mux (c->board, *((char*)data) == 'c'); 1154138823Srik CP_UNLOCK (bd); 1155133646Srik splx (s); 1156133646Srik return 0; 1157128967Srik 1158128967Srik case SERIAL_GETSTAT: 1159133646Srik CP_DEBUG2 (d, ("ioctl: getstat\n")); 1160133646Srik st = (struct serial_statistics*) data; 1161133646Srik st->rintr = c->rintr; 1162133646Srik st->tintr = c->tintr; 1163133646Srik st->mintr = 0; 1164133646Srik st->ibytes = c->ibytes; 1165133646Srik st->ipkts = c->ipkts; 1166133646Srik st->obytes = c->obytes; 1167133646Srik st->opkts = c->opkts; 1168128967Srik st->ierrs = c->overrun + c->frame + c->crc; 1169128967Srik st->oerrs = c->underrun; 1170133646Srik return 0; 1171128967Srik 1172128967Srik case SERIAL_GETESTAT: 1173133646Srik CP_DEBUG2 (d, ("ioctl: getestat\n")); 1174128967Srik if (c->type != T_E1 && c->type != T_G703) 1175128967Srik return EINVAL; 1176128967Srik opte1 = (struct e1_statistics*) data; 1177128967Srik opte1->status = c->status; 1178128967Srik opte1->cursec = c->cursec; 1179128967Srik opte1->totsec = c->totsec + c->cursec; 1180128967Srik 1181128967Srik opte1->currnt.bpv = c->currnt.bpv; 1182128967Srik opte1->currnt.fse = c->currnt.fse; 1183128967Srik opte1->currnt.crce = c->currnt.crce; 1184128967Srik opte1->currnt.rcrce = c->currnt.rcrce; 1185128967Srik opte1->currnt.uas = c->currnt.uas; 1186128967Srik opte1->currnt.les = c->currnt.les; 1187128967Srik opte1->currnt.es = c->currnt.es; 1188128967Srik opte1->currnt.bes = c->currnt.bes; 1189128967Srik opte1->currnt.ses = c->currnt.ses; 1190128967Srik opte1->currnt.oofs = c->currnt.oofs; 1191128967Srik opte1->currnt.css = c->currnt.css; 1192128967Srik opte1->currnt.dm = c->currnt.dm; 1193128967Srik 1194128967Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1195128967Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1196128967Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1197128967Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1198128967Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1199128967Srik opte1->total.les = c->total.les + c->currnt.les; 1200128967Srik opte1->total.es = c->total.es + c->currnt.es; 1201128967Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1202128967Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1203128967Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1204128967Srik opte1->total.css = c->total.css + c->currnt.css; 1205128967Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1206128967Srik for (s=0; s<48; ++s) { 1207128967Srik opte1->interval[s].bpv = c->interval[s].bpv; 1208128967Srik opte1->interval[s].fse = c->interval[s].fse; 1209128967Srik opte1->interval[s].crce = c->interval[s].crce; 1210128967Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1211128967Srik opte1->interval[s].uas = c->interval[s].uas; 1212128967Srik opte1->interval[s].les = c->interval[s].les; 1213128967Srik opte1->interval[s].es = c->interval[s].es; 1214128967Srik opte1->interval[s].bes = c->interval[s].bes; 1215128967Srik opte1->interval[s].ses = c->interval[s].ses; 1216128967Srik opte1->interval[s].oofs = c->interval[s].oofs; 1217128967Srik opte1->interval[s].css = c->interval[s].css; 1218128967Srik opte1->interval[s].dm = c->interval[s].dm; 1219128967Srik } 1220128967Srik return 0; 1221128967Srik 1222128967Srik case SERIAL_GETE3STAT: 1223133646Srik CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 1224128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1225128967Srik return EINVAL; 1226133646Srik opte3 = (struct e3_statistics*) data; 1227128967Srik 1228128967Srik opte3->status = c->e3status; 1229128967Srik opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 1230128967Srik opte3->totsec = c->e3tsec + opte3->cursec; 1231128967Srik 1232128967Srik opte3->ccv = c->e3ccv; 1233128967Srik opte3->tcv = c->e3tcv + opte3->ccv; 1234128967Srik 1235128967Srik for (s = 0; s < 48; ++s) { 1236128967Srik opte3->icv[s] = c->e3icv[s]; 1237128967Srik } 1238133646Srik return 0; 1239128967Srik 1240128967Srik case SERIAL_CLRSTAT: 1241133646Srik CP_DEBUG2 (d, ("ioctl: clrstat\n")); 1242133646Srik /* Only for superuser! */ 1243164033Srwatson error = priv_check (td, PRIV_DRIVER); 1244133646Srik if (error) 1245133646Srik return error; 1246128967Srik c->rintr = 0; 1247128967Srik c->tintr = 0; 1248128967Srik c->ibytes = 0; 1249128967Srik c->obytes = 0; 1250128967Srik c->ipkts = 0; 1251128967Srik c->opkts = 0; 1252128967Srik c->overrun = 0; 1253128967Srik c->frame = 0; 1254133646Srik c->crc = 0; 1255128967Srik c->underrun = 0; 1256128967Srik bzero (&c->currnt, sizeof (c->currnt)); 1257128967Srik bzero (&c->total, sizeof (c->total)); 1258128967Srik bzero (c->interval, sizeof (c->interval)); 1259128967Srik c->e3ccv = 0; 1260128967Srik c->e3tcv = 0; 1261128967Srik bzero (c->e3icv, sizeof (c->e3icv)); 1262133646Srik return 0; 1263128967Srik 1264128967Srik case SERIAL_GETBAUD: 1265133646Srik CP_DEBUG2 (d, ("ioctl: getbaud\n")); 1266133646Srik *(long*)data = c->baud; 1267133646Srik return 0; 1268128967Srik 1269128967Srik case SERIAL_SETBAUD: 1270133646Srik CP_DEBUG2 (d, ("ioctl: setbaud\n")); 1271133646Srik /* Only for superuser! */ 1272164033Srwatson error = priv_check (td, PRIV_DRIVER); 1273133646Srik if (error) 1274133646Srik return error; 1275133646Srik s = splimp (); 1276138823Srik CP_LOCK (bd); 1277133646Srik cp_set_baud (c, *(long*)data); 1278138823Srik CP_UNLOCK (bd); 1279133646Srik splx (s); 1280133646Srik return 0; 1281128967Srik 1282128967Srik case SERIAL_GETLOOP: 1283133646Srik CP_DEBUG2 (d, ("ioctl: getloop\n")); 1284133646Srik *(int*)data = c->lloop; 1285133646Srik return 0; 1286128967Srik 1287128967Srik case SERIAL_SETLOOP: 1288133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1289133646Srik /* Only for superuser! */ 1290164033Srwatson error = priv_check (td, PRIV_DRIVER); 1291133646Srik if (error) 1292133646Srik return error; 1293133646Srik s = splimp (); 1294138823Srik CP_LOCK (bd); 1295128967Srik cp_set_lloop (c, *(int*)data); 1296138823Srik CP_UNLOCK (bd); 1297133646Srik splx (s); 1298133646Srik return 0; 1299128967Srik 1300128967Srik case SERIAL_GETDPLL: 1301133646Srik CP_DEBUG2 (d, ("ioctl: getdpll\n")); 1302133646Srik if (c->type != T_SERIAL) 1303133646Srik return EINVAL; 1304133646Srik *(int*)data = c->dpll; 1305133646Srik return 0; 1306128967Srik 1307128967Srik case SERIAL_SETDPLL: 1308133646Srik CP_DEBUG2 (d, ("ioctl: setdpll\n")); 1309133646Srik /* Only for superuser! */ 1310164033Srwatson error = priv_check (td, PRIV_DRIVER); 1311133646Srik if (error) 1312133646Srik return error; 1313133646Srik if (c->type != T_SERIAL) 1314133646Srik return EINVAL; 1315133646Srik s = splimp (); 1316138823Srik CP_LOCK (bd); 1317133646Srik cp_set_dpll (c, *(int*)data); 1318138823Srik CP_UNLOCK (bd); 1319133646Srik splx (s); 1320133646Srik return 0; 1321128967Srik 1322128967Srik case SERIAL_GETNRZI: 1323133646Srik CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 1324133646Srik if (c->type != T_SERIAL) 1325133646Srik return EINVAL; 1326133646Srik *(int*)data = c->nrzi; 1327133646Srik return 0; 1328128967Srik 1329128967Srik case SERIAL_SETNRZI: 1330133646Srik CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 1331133646Srik /* Only for superuser! */ 1332164033Srwatson error = priv_check (td, PRIV_DRIVER); 1333133646Srik if (error) 1334133646Srik return error; 1335133646Srik if (c->type != T_SERIAL) 1336133646Srik return EINVAL; 1337133646Srik s = splimp (); 1338138823Srik CP_LOCK (bd); 1339133646Srik cp_set_nrzi (c, *(int*)data); 1340138823Srik CP_UNLOCK (bd); 1341133646Srik splx (s); 1342133646Srik return 0; 1343128967Srik 1344128967Srik case SERIAL_GETDEBUG: 1345133646Srik CP_DEBUG2 (d, ("ioctl: getdebug\n")); 1346133646Srik *(int*)data = d->chan->debug; 1347133646Srik return 0; 1348128967Srik 1349128967Srik case SERIAL_SETDEBUG: 1350133646Srik CP_DEBUG2 (d, ("ioctl: setdebug\n")); 1351133646Srik /* Only for superuser! */ 1352164033Srwatson error = priv_check (td, PRIV_DRIVER); 1353133646Srik if (error) 1354133646Srik return error; 1355133646Srik d->chan->debug = *(int*)data; 1356128967Srik#ifndef NETGRAPH 1357128967Srik if (d->chan->debug) 1358147256Sbrooks d->ifp->if_flags |= IFF_DEBUG; 1359128967Srik else 1360147256Sbrooks d->ifp->if_flags &= ~IFF_DEBUG; 1361128967Srik#endif 1362133646Srik return 0; 1363128967Srik 1364128967Srik case SERIAL_GETHIGAIN: 1365133646Srik CP_DEBUG2 (d, ("ioctl: gethigain\n")); 1366133646Srik if (c->type != T_E1) 1367133646Srik return EINVAL; 1368133646Srik *(int*)data = c->higain; 1369128967Srik return 0; 1370128967Srik 1371128967Srik case SERIAL_SETHIGAIN: 1372133646Srik CP_DEBUG2 (d, ("ioctl: sethigain\n")); 1373133646Srik /* Only for superuser! */ 1374164033Srwatson error = priv_check (td, PRIV_DRIVER); 1375133646Srik if (error) 1376133646Srik return error; 1377133646Srik if (c->type != T_E1) 1378133646Srik return EINVAL; 1379128967Srik s = splimp (); 1380138823Srik CP_LOCK (bd); 1381128967Srik cp_set_higain (c, *(int*)data); 1382138823Srik CP_UNLOCK (bd); 1383128967Srik splx (s); 1384128967Srik return 0; 1385128967Srik 1386128967Srik case SERIAL_GETPHONY: 1387128967Srik CP_DEBUG2 (d, ("ioctl: getphony\n")); 1388133646Srik if (c->type != T_E1) 1389133646Srik return EINVAL; 1390133646Srik *(int*)data = c->phony; 1391128967Srik return 0; 1392128967Srik 1393128967Srik case SERIAL_SETPHONY: 1394128967Srik CP_DEBUG2 (d, ("ioctl: setphony\n")); 1395133646Srik /* Only for superuser! */ 1396164033Srwatson error = priv_check (td, PRIV_DRIVER); 1397133646Srik if (error) 1398133646Srik return error; 1399133646Srik if (c->type != T_E1) 1400133646Srik return EINVAL; 1401128967Srik s = splimp (); 1402138823Srik CP_LOCK (bd); 1403128967Srik cp_set_phony (c, *(int*)data); 1404138823Srik CP_UNLOCK (bd); 1405128967Srik splx (s); 1406128967Srik return 0; 1407128967Srik 1408128967Srik case SERIAL_GETUNFRAM: 1409128967Srik CP_DEBUG2 (d, ("ioctl: getunfram\n")); 1410133646Srik if (c->type != T_E1) 1411133646Srik return EINVAL; 1412133646Srik *(int*)data = c->unfram; 1413128967Srik return 0; 1414128967Srik 1415128967Srik case SERIAL_SETUNFRAM: 1416128967Srik CP_DEBUG2 (d, ("ioctl: setunfram\n")); 1417133646Srik /* Only for superuser! */ 1418164033Srwatson error = priv_check (td, PRIV_DRIVER); 1419133646Srik if (error) 1420133646Srik return error; 1421133646Srik if (c->type != T_E1) 1422133646Srik return EINVAL; 1423128967Srik s = splimp (); 1424138823Srik CP_LOCK (bd); 1425128967Srik cp_set_unfram (c, *(int*)data); 1426138823Srik CP_UNLOCK (bd); 1427128967Srik splx (s); 1428128967Srik return 0; 1429128967Srik 1430128967Srik case SERIAL_GETSCRAMBLER: 1431128967Srik CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 1432133646Srik if (c->type != T_G703 && !c->unfram) 1433133646Srik return EINVAL; 1434133646Srik *(int*)data = c->scrambler; 1435128967Srik return 0; 1436128967Srik 1437128967Srik case SERIAL_SETSCRAMBLER: 1438128967Srik CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 1439133646Srik /* Only for superuser! */ 1440164033Srwatson error = priv_check (td, PRIV_DRIVER); 1441133646Srik if (error) 1442133646Srik return error; 1443133646Srik if (c->type != T_G703 && !c->unfram) 1444133646Srik return EINVAL; 1445128967Srik s = splimp (); 1446138823Srik CP_LOCK (bd); 1447128967Srik cp_set_scrambler (c, *(int*)data); 1448138823Srik CP_UNLOCK (bd); 1449128967Srik splx (s); 1450128967Srik return 0; 1451128967Srik 1452128967Srik case SERIAL_GETMONITOR: 1453128967Srik CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 1454133646Srik if (c->type != T_E1 && 1455128967Srik c->type != T_E3 && 1456128967Srik c->type != T_T3 && 1457128967Srik c->type != T_STS1) 1458133646Srik return EINVAL; 1459133646Srik *(int*)data = c->monitor; 1460128967Srik return 0; 1461128967Srik 1462128967Srik case SERIAL_SETMONITOR: 1463128967Srik CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 1464133646Srik /* Only for superuser! */ 1465164033Srwatson error = priv_check (td, PRIV_DRIVER); 1466133646Srik if (error) 1467133646Srik return error; 1468133646Srik if (c->type != T_E1) 1469133646Srik return EINVAL; 1470128967Srik s = splimp (); 1471138823Srik CP_LOCK (bd); 1472128967Srik cp_set_monitor (c, *(int*)data); 1473138823Srik CP_UNLOCK (bd); 1474128967Srik splx (s); 1475128967Srik return 0; 1476128967Srik 1477128967Srik case SERIAL_GETUSE16: 1478133646Srik CP_DEBUG2 (d, ("ioctl: getuse16\n")); 1479133646Srik if (c->type != T_E1 || c->unfram) 1480133646Srik return EINVAL; 1481133646Srik *(int*)data = c->use16; 1482128967Srik return 0; 1483128967Srik 1484128967Srik case SERIAL_SETUSE16: 1485133646Srik CP_DEBUG2 (d, ("ioctl: setuse16\n")); 1486133646Srik /* Only for superuser! */ 1487164033Srwatson error = priv_check (td, PRIV_DRIVER); 1488133646Srik if (error) 1489133646Srik return error; 1490133646Srik if (c->type != T_E1) 1491133646Srik return EINVAL; 1492128967Srik s = splimp (); 1493138823Srik CP_LOCK (bd); 1494128967Srik cp_set_use16 (c, *(int*)data); 1495138823Srik CP_UNLOCK (bd); 1496128967Srik splx (s); 1497128967Srik return 0; 1498128967Srik 1499128967Srik case SERIAL_GETCRC4: 1500133646Srik CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 1501133646Srik if (c->type != T_E1 || c->unfram) 1502133646Srik return EINVAL; 1503133646Srik *(int*)data = c->crc4; 1504128967Srik return 0; 1505128967Srik 1506128967Srik case SERIAL_SETCRC4: 1507133646Srik CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 1508133646Srik /* Only for superuser! */ 1509164033Srwatson error = priv_check (td, PRIV_DRIVER); 1510133646Srik if (error) 1511133646Srik return error; 1512133646Srik if (c->type != T_E1) 1513133646Srik return EINVAL; 1514128967Srik s = splimp (); 1515138823Srik CP_LOCK (bd); 1516128967Srik cp_set_crc4 (c, *(int*)data); 1517138823Srik CP_UNLOCK (bd); 1518128967Srik splx (s); 1519128967Srik return 0; 1520128967Srik 1521128967Srik case SERIAL_GETCLK: 1522133646Srik CP_DEBUG2 (d, ("ioctl: getclk\n")); 1523133646Srik if (c->type != T_E1 && 1524128967Srik c->type != T_G703 && 1525128967Srik c->type != T_E3 && 1526128967Srik c->type != T_T3 && 1527128967Srik c->type != T_STS1) 1528133646Srik return EINVAL; 1529128967Srik switch (c->gsyn) { 1530128967Srik default: *(int*)data = E1CLK_INTERNAL; break; 1531128967Srik case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1532128967Srik case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1533128967Srik case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1534128967Srik case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 1535128967Srik case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 1536128967Srik } 1537128967Srik return 0; 1538128967Srik 1539128967Srik case SERIAL_SETCLK: 1540133646Srik CP_DEBUG2 (d, ("ioctl: setclk\n")); 1541133646Srik /* Only for superuser! */ 1542164033Srwatson error = priv_check (td, PRIV_DRIVER); 1543133646Srik if (error) 1544133646Srik return error; 1545128967Srik if (c->type != T_E1 && 1546128967Srik c->type != T_G703 && 1547128967Srik c->type != T_E3 && 1548128967Srik c->type != T_T3 && 1549128967Srik c->type != T_STS1) 1550133646Srik return EINVAL; 1551128967Srik s = splimp (); 1552138823Srik CP_LOCK (bd); 1553128967Srik switch (*(int*)data) { 1554128967Srik default: cp_set_gsyn (c, GSYN_INT); break; 1555128967Srik case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 1556128967Srik case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 1557128967Srik case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 1558128967Srik case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 1559128967Srik case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 1560128967Srik } 1561138823Srik CP_UNLOCK (bd); 1562128967Srik splx (s); 1563128967Srik return 0; 1564128967Srik 1565128967Srik case SERIAL_GETTIMESLOTS: 1566133646Srik CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1567133646Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1568133646Srik return EINVAL; 1569133646Srik *(u_long*)data = c->ts; 1570128967Srik return 0; 1571128967Srik 1572128967Srik case SERIAL_SETTIMESLOTS: 1573133646Srik CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 1574133646Srik /* Only for superuser! */ 1575164033Srwatson error = priv_check (td, PRIV_DRIVER); 1576133646Srik if (error) 1577133646Srik return error; 1578128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1579133646Srik return EINVAL; 1580128967Srik s = splimp (); 1581138823Srik CP_LOCK (bd); 1582128967Srik cp_set_ts (c, *(u_long*)data); 1583138823Srik CP_UNLOCK (bd); 1584128967Srik splx (s); 1585128967Srik return 0; 1586128967Srik 1587128967Srik case SERIAL_GETINVCLK: 1588133646Srik CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 1589128967Srik#if 1 1590128967Srik return EINVAL; 1591128967Srik#else 1592133646Srik if (c->type != T_SERIAL) 1593133646Srik return EINVAL; 1594133646Srik *(int*)data = c->invtxc; 1595128967Srik return 0; 1596128967Srik#endif 1597128967Srik 1598128967Srik case SERIAL_SETINVCLK: 1599133646Srik CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 1600133646Srik /* Only for superuser! */ 1601164033Srwatson error = priv_check (td, PRIV_DRIVER); 1602133646Srik if (error) 1603133646Srik return error; 1604133646Srik if (c->type != T_SERIAL) 1605133646Srik return EINVAL; 1606128967Srik s = splimp (); 1607138823Srik CP_LOCK (bd); 1608128967Srik cp_set_invtxc (c, *(int*)data); 1609128967Srik cp_set_invrxc (c, *(int*)data); 1610138823Srik CP_UNLOCK (bd); 1611128967Srik splx (s); 1612128967Srik return 0; 1613128967Srik 1614128967Srik case SERIAL_GETINVTCLK: 1615133646Srik CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 1616133646Srik if (c->type != T_SERIAL) 1617133646Srik return EINVAL; 1618133646Srik *(int*)data = c->invtxc; 1619128967Srik return 0; 1620128967Srik 1621128967Srik case SERIAL_SETINVTCLK: 1622133646Srik CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 1623133646Srik /* Only for superuser! */ 1624164033Srwatson error = priv_check (td, PRIV_DRIVER); 1625133646Srik if (error) 1626133646Srik return error; 1627133646Srik if (c->type != T_SERIAL) 1628133646Srik return EINVAL; 1629128967Srik s = splimp (); 1630138823Srik CP_LOCK (bd); 1631128967Srik cp_set_invtxc (c, *(int*)data); 1632138823Srik CP_UNLOCK (bd); 1633128967Srik splx (s); 1634128967Srik return 0; 1635128967Srik 1636128967Srik case SERIAL_GETINVRCLK: 1637133646Srik CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 1638133646Srik if (c->type != T_SERIAL) 1639133646Srik return EINVAL; 1640133646Srik *(int*)data = c->invrxc; 1641128967Srik return 0; 1642128967Srik 1643128967Srik case SERIAL_SETINVRCLK: 1644133646Srik CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 1645133646Srik /* Only for superuser! */ 1646164033Srwatson error = priv_check (td, PRIV_DRIVER); 1647133646Srik if (error) 1648133646Srik return error; 1649133646Srik if (c->type != T_SERIAL) 1650133646Srik return EINVAL; 1651128967Srik s = splimp (); 1652138823Srik CP_LOCK (bd); 1653128967Srik cp_set_invrxc (c, *(int*)data); 1654138823Srik CP_UNLOCK (bd); 1655128967Srik splx (s); 1656128967Srik return 0; 1657128967Srik 1658128967Srik case SERIAL_GETLEVEL: 1659133646Srik CP_DEBUG2 (d, ("ioctl: getlevel\n")); 1660133646Srik if (c->type != T_G703) 1661133646Srik return EINVAL; 1662128967Srik s = splimp (); 1663138823Srik CP_LOCK (bd); 1664133646Srik *(int*)data = cp_get_lq (c); 1665138823Srik CP_UNLOCK (bd); 1666128967Srik splx (s); 1667128967Srik return 0; 1668128967Srik 1669128967Srik#if 0 1670128967Srik case SERIAL_RESET: 1671133646Srik CP_DEBUG2 (d, ("ioctl: reset\n")); 1672133646Srik /* Only for superuser! */ 1673164033Srwatson error = priv_check (td, PRIV_DRIVER); 1674133646Srik if (error) 1675133646Srik return error; 1676128967Srik s = splimp (); 1677138823Srik CP_LOCK (bd); 1678128967Srik cp_reset (c->board, 0, 0); 1679138823Srik CP_UNLOCK (bd); 1680128967Srik splx (s); 1681128967Srik return 0; 1682128967Srik 1683128967Srik case SERIAL_HARDRESET: 1684133646Srik CP_DEBUG2 (d, ("ioctl: hardreset\n")); 1685133646Srik /* Only for superuser! */ 1686164033Srwatson error = priv_check (td, PRIV_DRIVER); 1687133646Srik if (error) 1688133646Srik return error; 1689128967Srik s = splimp (); 1690138823Srik CP_LOCK (bd); 1691128967Srik /* hard_reset (c->board); */ 1692138823Srik CP_UNLOCK (bd); 1693128967Srik splx (s); 1694128967Srik return 0; 1695128967Srik#endif 1696128967Srik 1697128967Srik case SERIAL_GETCABLE: 1698133646Srik CP_DEBUG2 (d, ("ioctl: getcable\n")); 1699133646Srik if (c->type != T_SERIAL) 1700133646Srik return EINVAL; 1701128967Srik s = splimp (); 1702138823Srik CP_LOCK (bd); 1703128967Srik *(int*)data = cp_get_cable (c); 1704138823Srik CP_UNLOCK (bd); 1705128967Srik splx (s); 1706128967Srik return 0; 1707128967Srik 1708128967Srik case SERIAL_GETDIR: 1709133646Srik CP_DEBUG2 (d, ("ioctl: getdir\n")); 1710133646Srik if (c->type != T_E1 && c->type != T_DATA) 1711133646Srik return EINVAL; 1712128967Srik *(int*)data = c->dir; 1713128967Srik return 0; 1714128967Srik 1715128967Srik case SERIAL_SETDIR: 1716133646Srik CP_DEBUG2 (d, ("ioctl: setdir\n")); 1717133646Srik /* Only for superuser! */ 1718164033Srwatson error = priv_check (td, PRIV_DRIVER); 1719133646Srik if (error) 1720133646Srik return error; 1721128967Srik s = splimp (); 1722138823Srik CP_LOCK (bd); 1723128967Srik cp_set_dir (c, *(int*)data); 1724138823Srik CP_UNLOCK (bd); 1725128967Srik splx (s); 1726128967Srik return 0; 1727128967Srik 1728128967Srik case SERIAL_GETRLOOP: 1729133646Srik CP_DEBUG2 (d, ("ioctl: getrloop\n")); 1730133646Srik if (c->type != T_G703 && 1731128967Srik c->type != T_E3 && 1732128967Srik c->type != T_T3 && 1733128967Srik c->type != T_STS1) 1734133646Srik return EINVAL; 1735133646Srik *(int*)data = cp_get_rloop (c); 1736133646Srik return 0; 1737128967Srik 1738128967Srik case SERIAL_SETRLOOP: 1739133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1740133646Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1741133646Srik return EINVAL; 1742133646Srik /* Only for superuser! */ 1743164033Srwatson error = priv_check (td, PRIV_DRIVER); 1744133646Srik if (error) 1745133646Srik return error; 1746133646Srik s = splimp (); 1747138823Srik CP_LOCK (bd); 1748128967Srik cp_set_rloop (c, *(int*)data); 1749138823Srik CP_UNLOCK (bd); 1750133646Srik splx (s); 1751133646Srik return 0; 1752128967Srik 1753128967Srik case SERIAL_GETCABLEN: 1754133646Srik CP_DEBUG2 (d, ("ioctl: getcablen\n")); 1755133646Srik if (c->type != T_T3 && c->type != T_STS1) 1756133646Srik return EINVAL; 1757133646Srik *(int*)data = c->cablen; 1758133646Srik return 0; 1759128967Srik 1760128967Srik case SERIAL_SETCABLEN: 1761133646Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1762133646Srik if (c->type != T_T3 && c->type != T_STS1) 1763133646Srik return EINVAL; 1764133646Srik /* Only for superuser! */ 1765164033Srwatson error = priv_check (td, PRIV_DRIVER); 1766133646Srik if (error) 1767133646Srik return error; 1768133646Srik s = splimp (); 1769138823Srik CP_LOCK (bd); 1770128967Srik cp_set_cablen (c, *(int*)data); 1771138823Srik CP_UNLOCK (bd); 1772133646Srik splx (s); 1773133646Srik return 0; 1774128967Srik 1775133646Srik case TIOCSDTR: /* Set DTR */ 1776128967Srik s = splimp (); 1777138823Srik CP_LOCK (bd); 1778128967Srik cp_set_dtr (c, 1); 1779138823Srik CP_UNLOCK (bd); 1780128967Srik splx (s); 1781128967Srik return 0; 1782128967Srik 1783133646Srik case TIOCCDTR: /* Clear DTR */ 1784128967Srik s = splimp (); 1785138823Srik CP_LOCK (bd); 1786128967Srik cp_set_dtr (c, 0); 1787138823Srik CP_UNLOCK (bd); 1788128967Srik splx (s); 1789128967Srik return 0; 1790128967Srik 1791133646Srik case TIOCMSET: /* Set DTR/RTS */ 1792128967Srik s = splimp (); 1793138823Srik CP_LOCK (bd); 1794128967Srik cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1795128967Srik cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1796138823Srik CP_UNLOCK (bd); 1797128967Srik splx (s); 1798128967Srik return 0; 1799128967Srik 1800133646Srik case TIOCMBIS: /* Add DTR/RTS */ 1801128967Srik s = splimp (); 1802138823Srik CP_LOCK (bd); 1803128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 1804128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 1805138823Srik CP_UNLOCK (bd); 1806128967Srik splx (s); 1807128967Srik return 0; 1808128967Srik 1809133646Srik case TIOCMBIC: /* Clear DTR/RTS */ 1810128967Srik s = splimp (); 1811138823Srik CP_LOCK (bd); 1812128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1813128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1814138823Srik CP_UNLOCK (bd); 1815128967Srik splx (s); 1816128967Srik return 0; 1817128967Srik 1818133646Srik case TIOCMGET: /* Get modem status */ 1819128967Srik *(int*)data = cp_modem_status (c); 1820128967Srik return 0; 1821128967Srik } 1822128967Srik return ENOTTY; 1823128967Srik} 1824128967Srik 1825128967Srik#ifdef NETGRAPH 1826128967Srikstatic int ng_cp_constructor (node_p node) 1827128967Srik{ 1828128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1829128967Srik CP_DEBUG (d, ("Constructor\n")); 1830128967Srik return EINVAL; 1831128967Srik} 1832128967Srik 1833128967Srikstatic int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1834128967Srik{ 1835128967Srik int s; 1836128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1837138823Srik bdrv_t *bd = d->board->sys; 1838128967Srik 1839128967Srik CP_DEBUG (d, ("Newhook\n")); 1840128967Srik /* Attach debug hook */ 1841128967Srik if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1842128967Srik NG_HOOK_SET_PRIVATE (hook, NULL); 1843128967Srik d->debug_hook = hook; 1844128967Srik return 0; 1845128967Srik } 1846128967Srik 1847128967Srik /* Check for raw hook */ 1848128967Srik if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1849128967Srik return EINVAL; 1850128967Srik 1851128967Srik NG_HOOK_SET_PRIVATE (hook, d); 1852128967Srik d->hook = hook; 1853128967Srik s = splimp (); 1854138823Srik CP_LOCK (bd); 1855128967Srik cp_up (d); 1856138823Srik CP_UNLOCK (bd); 1857128967Srik splx (s); 1858128967Srik return 0; 1859128967Srik} 1860128967Srik 1861128967Srikstatic char *format_timeslots (u_long s) 1862128967Srik{ 1863128967Srik static char buf [100]; 1864128967Srik char *p = buf; 1865128967Srik int i; 1866128967Srik 1867128967Srik for (i=1; i<32; ++i) 1868128967Srik if ((s >> i) & 1) { 1869128967Srik int prev = (i > 1) & (s >> (i-1)); 1870128967Srik int next = (i < 31) & (s >> (i+1)); 1871128967Srik 1872128967Srik if (prev) { 1873128967Srik if (next) 1874128967Srik continue; 1875128967Srik *p++ = '-'; 1876128967Srik } else if (p > buf) 1877128967Srik *p++ = ','; 1878128967Srik 1879128967Srik if (i >= 10) 1880128967Srik *p++ = '0' + i / 10; 1881128967Srik *p++ = '0' + i % 10; 1882128967Srik } 1883128967Srik *p = 0; 1884128967Srik return buf; 1885128967Srik} 1886128967Srik 1887128967Srikstatic int print_modems (char *s, cp_chan_t *c, int need_header) 1888128967Srik{ 1889128967Srik int status = cp_modem_status (c); 1890128967Srik int length = 0; 1891128967Srik 1892128967Srik if (need_header) 1893128967Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1894128967Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1895128967Srik status & TIOCM_LE ? "On" : "-", 1896128967Srik status & TIOCM_DTR ? "On" : "-", 1897128967Srik status & TIOCM_DSR ? "On" : "-", 1898128967Srik status & TIOCM_RTS ? "On" : "-", 1899128967Srik status & TIOCM_CTS ? "On" : "-", 1900128967Srik status & TIOCM_CD ? "On" : "-"); 1901128967Srik return length; 1902128967Srik} 1903128967Srik 1904128967Srikstatic int print_stats (char *s, cp_chan_t *c, int need_header) 1905128967Srik{ 1906128967Srik int length = 0; 1907128967Srik 1908128967Srik if (need_header) 1909128967Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1910128967Srik length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1911128967Srik c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1912128967Srik c->ipkts, c->overrun + c->frame + c->crc, 1913128967Srik (unsigned long) c->obytes, c->opkts, c->underrun); 1914128967Srik return length; 1915128967Srik} 1916128967Srik 1917128967Srikstatic char *format_e1_status (u_char status) 1918128967Srik{ 1919128967Srik static char buf [80]; 1920128967Srik 1921128967Srik if (status & E1_NOALARM) 1922128967Srik return "Ok"; 1923128967Srik buf[0] = 0; 1924128967Srik if (status & E1_LOS) strcat (buf, ",LOS"); 1925128967Srik if (status & E1_AIS) strcat (buf, ",AIS"); 1926128967Srik if (status & E1_LOF) strcat (buf, ",LOF"); 1927128967Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 1928128967Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1929128967Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 1930128967Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1931128967Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1932128967Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1933128967Srik if (buf[0] == ',') 1934128967Srik return buf+1; 1935128967Srik return "Unknown"; 1936128967Srik} 1937128967Srik 1938128967Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1939128967Srik{ 1940128967Srik int n, length = 0; 1941128967Srik 1942128967Srik if (numerator < 1 || divider < 1) { 1943128967Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 1944128967Srik return length; 1945128967Srik } 1946128967Srik n = (int) (0.5 + 1000.0 * numerator / divider); 1947128967Srik if (n < 1000) { 1948128967Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1949128967Srik return length; 1950128967Srik } 1951128967Srik *(s + length) = leftalign ? '/' : ' '; 1952128967Srik length ++; 1953128967Srik 1954128967Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 1955128967Srik else if (n >= 100000) n = (n+50) / 100 * 100; 1956128967Srik else if (n >= 10000) n = (n+5) / 10 * 10; 1957128967Srik 1958128967Srik switch (n) { 1959128967Srik case 1000: length += printf (s+length, ".999"); return length; 1960128967Srik case 10000: n = 9990; break; 1961128967Srik case 100000: n = 99900; break; 1962128967Srik case 1000000: n = 999000; break; 1963128967Srik } 1964133646Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1965128967Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1966128967Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1967133646Srik else length += sprintf (s+length, "%d", n/1000); 1968128967Srik 1969128967Srik return length; 1970128967Srik} 1971128967Srik 1972128967Srikstatic int print_e1_stats (char *s, cp_chan_t *c) 1973128967Srik{ 1974128967Srik struct e1_counters total; 1975128967Srik u_long totsec; 1976128967Srik int length = 0; 1977128967Srik 1978128967Srik totsec = c->totsec + c->cursec; 1979128967Srik total.bpv = c->total.bpv + c->currnt.bpv; 1980128967Srik total.fse = c->total.fse + c->currnt.fse; 1981128967Srik total.crce = c->total.crce + c->currnt.crce; 1982128967Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 1983128967Srik total.uas = c->total.uas + c->currnt.uas; 1984128967Srik total.les = c->total.les + c->currnt.les; 1985128967Srik total.es = c->total.es + c->currnt.es; 1986128967Srik total.bes = c->total.bes + c->currnt.bes; 1987128967Srik total.ses = c->total.ses + c->currnt.ses; 1988128967Srik total.oofs = c->total.oofs + c->currnt.oofs; 1989128967Srik total.css = c->total.css + c->currnt.css; 1990128967Srik total.dm = c->total.dm + c->currnt.dm; 1991128967Srik 1992128967Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1993128967Srik 1994128967Srik /* Unavailable seconds, degraded minutes */ 1995128967Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1996128967Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1997128967Srik 1998128967Srik /* Bipolar violations, frame sync errors */ 1999128967Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 2000128967Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 2001128967Srik 2002128967Srik /* CRC errors, remote CRC errors (E-bit) */ 2003128967Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 2004128967Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 2005128967Srik 2006128967Srik /* Errored seconds, line errored seconds */ 2007128967Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 2008128967Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 2009128967Srik 2010128967Srik /* Severely errored seconds, burst errored seconds */ 2011128967Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 2012128967Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 2013128967Srik 2014128967Srik /* Out of frame seconds, controlled slip seconds */ 2015128967Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 2016128967Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 2017128967Srik 2018128967Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 2019128967Srik 2020128967Srik /* Print total statistics. */ 2021128967Srik length += print_frac (s + length, 0, total.uas, totsec); 2022128967Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 2023128967Srik 2024128967Srik length += print_frac (s + length, 0, total.bpv, totsec); 2025128967Srik length += print_frac (s + length, 1, total.fse, totsec); 2026128967Srik 2027128967Srik length += print_frac (s + length, 0, total.crce, totsec); 2028128967Srik length += print_frac (s + length, 1, total.rcrce, totsec); 2029128967Srik 2030128967Srik length += print_frac (s + length, 0, total.es, totsec); 2031128967Srik length += print_frac (s + length, 1, total.les, totsec); 2032128967Srik 2033128967Srik length += print_frac (s + length, 0, total.ses, totsec); 2034128967Srik length += print_frac (s + length, 1, total.bes, totsec); 2035128967Srik 2036128967Srik length += print_frac (s + length, 0, total.oofs, totsec); 2037128967Srik length += print_frac (s + length, 1, total.css, totsec); 2038128967Srik 2039128967Srik length += sprintf (s + length, " -- Total\n"); 2040128967Srik return length; 2041128967Srik} 2042128967Srik 2043128967Srikstatic int print_chan (char *s, cp_chan_t *c) 2044128967Srik{ 2045128967Srik drv_t *d = c->sys; 2046138823Srik bdrv_t *bd = d->board->sys; 2047128967Srik int length = 0; 2048128967Srik 2049128967Srik length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2050128967Srik if (d->chan->debug) 2051128967Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 2052128967Srik 2053128967Srik if (c->board->mux) { 2054128967Srik length += sprintf (s + length, " cfg=C"); 2055128967Srik } else { 2056128967Srik length += sprintf (s + length, " cfg=A"); 2057128967Srik } 2058128967Srik 2059128967Srik if (c->baud) 2060128967Srik length += sprintf (s + length, " %ld", c->baud); 2061128967Srik else 2062128967Srik length += sprintf (s + length, " extclock"); 2063128967Srik 2064128967Srik if (c->type == T_E1 || c->type == T_G703) 2065128967Srik switch (c->gsyn) { 2066128967Srik case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2067128967Srik case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2068128967Srik case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2069128967Srik case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2070128967Srik case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2071128967Srik case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2072128967Srik } 2073128967Srik if (c->type == T_SERIAL) { 2074128967Srik length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2075128967Srik length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2076128967Srik length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2077128967Srik } 2078128967Srik if (c->type == T_E1) 2079128967Srik length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2080128967Srik 2081128967Srik length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2082128967Srik 2083128967Srik if (c->type == T_E1) 2084128967Srik length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2085128967Srik if (c->type == T_G703) { 2086128967Srik int lq, x; 2087128967Srik 2088128967Srik x = splimp (); 2089138823Srik CP_LOCK (bd); 2090128967Srik lq = cp_get_lq (c); 2091138823Srik CP_UNLOCK (bd); 2092128967Srik splx (x); 2093128967Srik length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2094128967Srik } 2095128967Srik length += sprintf (s + length, "\n"); 2096128967Srik return length; 2097128967Srik} 2098128967Srik 2099128967Srikstatic int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2100128967Srik{ 2101128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2102128967Srik struct ng_mesg *msg; 2103128967Srik struct ng_mesg *resp = NULL; 2104128967Srik int error = 0; 2105128967Srik 2106128967Srik CP_DEBUG (d, ("Rcvmsg\n")); 2107128967Srik NGI_GET_MSG (item, msg); 2108128967Srik switch (msg->header.typecookie) { 2109128967Srik default: 2110128967Srik error = EINVAL; 2111128967Srik break; 2112128967Srik 2113128967Srik case NGM_CP_COOKIE: 2114128967Srik printf ("Not implemented yet\n"); 2115128967Srik error = EINVAL; 2116128967Srik break; 2117128967Srik 2118128967Srik case NGM_GENERIC_COOKIE: 2119128967Srik switch (msg->header.cmd) { 2120128967Srik default: 2121128967Srik error = EINVAL; 2122128967Srik break; 2123128967Srik 2124128967Srik case NGM_TEXT_STATUS: { 2125128967Srik char *s; 2126128967Srik int l = 0; 2127128967Srik int dl = sizeof (struct ng_mesg) + 730; 2128128967Srik 2129128967Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2130128967Srik if (! resp) { 2131128967Srik error = ENOMEM; 2132128967Srik break; 2133128967Srik } 2134128967Srik s = (resp)->data; 2135128967Srik if (d) { 2136128967Srik l += print_chan (s + l, d->chan); 2137128967Srik l += print_stats (s + l, d->chan, 1); 2138128967Srik l += print_modems (s + l, d->chan, 1); 2139128967Srik l += print_e1_stats (s + l, d->chan); 2140128967Srik } else 2141128967Srik l += sprintf (s + l, "Error: node not connect to channel"); 2142128967Srik strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 2143128967Srik } 2144128967Srik break; 2145128967Srik } 2146128967Srik break; 2147128967Srik } 2148128967Srik NG_RESPOND_MSG (error, node, item, resp); 2149128967Srik NG_FREE_MSG (msg); 2150128967Srik return error; 2151128967Srik} 2152128967Srik 2153128967Srikstatic int ng_cp_rcvdata (hook_p hook, item_p item) 2154128967Srik{ 2155128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2156128967Srik struct mbuf *m; 2157131108Sjulian struct ng_tag_prio *ptag; 2158138823Srik bdrv_t *bd = d->board->sys; 2159128967Srik struct ifqueue *q; 2160128967Srik int s; 2161128967Srik 2162128967Srik CP_DEBUG2 (d, ("Rcvdata\n")); 2163128967Srik NGI_GET_M (item, m); 2164128967Srik NG_FREE_ITEM (item); 2165128967Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 2166128967Srik NG_FREE_M (m); 2167128967Srik return ENETDOWN; 2168128967Srik } 2169131108Sjulian 2170131108Sjulian /* Check for high priority data */ 2171131108Sjulian if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2172131108Sjulian NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2173131108Sjulian q = &d->hi_queue; 2174131108Sjulian else 2175131108Sjulian q = &d->queue; 2176131108Sjulian 2177128967Srik s = splimp (); 2178138823Srik CP_LOCK (bd); 2179128967Srik IF_LOCK (q); 2180128967Srik if (_IF_QFULL (q)) { 2181128967Srik _IF_DROP (q); 2182128967Srik IF_UNLOCK (q); 2183138823Srik CP_UNLOCK (bd); 2184128967Srik splx (s); 2185128967Srik NG_FREE_M (m); 2186128967Srik return ENOBUFS; 2187128967Srik } 2188128967Srik _IF_ENQUEUE (q, m); 2189128967Srik IF_UNLOCK (q); 2190128967Srik cp_start (d); 2191138823Srik CP_UNLOCK (bd); 2192128967Srik splx (s); 2193128967Srik return 0; 2194128967Srik} 2195128967Srik 2196128967Srikstatic int ng_cp_rmnode (node_p node) 2197128967Srik{ 2198128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2199128967Srik 2200128967Srik CP_DEBUG (d, ("Rmnode\n")); 2201128967Srik if (d && d->running) { 2202138823Srik bdrv_t *bd = d->board->sys; 2203128967Srik int s = splimp (); 2204138823Srik CP_LOCK (bd); 2205128967Srik cp_down (d); 2206138823Srik CP_UNLOCK (bd); 2207128967Srik splx (s); 2208128967Srik } 2209128967Srik#ifdef KLD_MODULE 2210132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 2211128967Srik NG_NODE_SET_PRIVATE (node, NULL); 2212128967Srik NG_NODE_UNREF (node); 2213128967Srik } 2214132464Sjulian NG_NODE_REVIVE(node); /* Persistant node */ 2215128967Srik#endif 2216128967Srik return 0; 2217128967Srik} 2218128967Srik 2219128967Srikstatic void ng_cp_watchdog (void *arg) 2220128967Srik{ 2221128967Srik drv_t *d = arg; 2222128967Srik 2223128967Srik if (d) { 2224128967Srik if (d->timeout == 1) 2225128967Srik cp_watchdog (d); 2226128967Srik if (d->timeout) 2227128967Srik d->timeout--; 2228138823Srik callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d); 2229128967Srik } 2230128967Srik} 2231128967Srik 2232128967Srikstatic int ng_cp_connect (hook_p hook) 2233128967Srik{ 2234128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2235128967Srik 2236128967Srik if (d) { 2237128967Srik CP_DEBUG (d, ("Connect\n")); 2238138823Srik callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d); 2239128967Srik } 2240128967Srik 2241128967Srik return 0; 2242128967Srik} 2243128967Srik 2244128967Srikstatic int ng_cp_disconnect (hook_p hook) 2245128967Srik{ 2246128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2247128967Srik 2248128967Srik if (d) { 2249128967Srik CP_DEBUG (d, ("Disconnect\n")); 2250128967Srik if (NG_HOOK_PRIVATE (hook)) 2251128967Srik { 2252138823Srik bdrv_t *bd = d->board->sys; 2253128967Srik int s = splimp (); 2254138823Srik CP_LOCK (bd); 2255128967Srik cp_down (d); 2256138823Srik CP_UNLOCK (bd); 2257128967Srik splx (s); 2258128967Srik } 2259138823Srik /* If we were wait it than it reasserted now, just stop it. */ 2260138823Srik if (!callout_drain (&d->timeout_handle)) 2261138823Srik callout_stop (&d->timeout_handle); 2262128967Srik } 2263128967Srik return 0; 2264128967Srik} 2265128967Srik#endif 2266128967Srik 2267128967Srikstatic int cp_modevent (module_t mod, int type, void *unused) 2268128967Srik{ 2269128967Srik static int load_count = 0; 2270128967Srik 2271138823Srik if (!debug_mpsafenet && cp_mpsafenet) { 2272138823Srik printf ("WORNING! Network stack is not MPSAFE. " 2273138823Srik "Turning off debug.cp.mpsafenet.\n"); 2274138823Srik cp_mpsafenet = 0; 2275138823Srik } 2276138823Srik if (cp_mpsafenet) 2277138823Srik cp_cdevsw.d_flags &= ~D_NEEDGIANT; 2278138823Srik 2279128967Srik switch (type) { 2280128967Srik case MOD_LOAD: 2281138673Srik#ifdef NETGRAPH 2282128967Srik if (ng_newtype (&typestruct)) 2283128967Srik printf ("Failed to register ng_cp\n"); 2284128967Srik#endif 2285128967Srik ++load_count; 2286138823Srik callout_init (&timeout_handle, cp_mpsafenet?CALLOUT_MPSAFE:0); 2287138823Srik callout_reset (&timeout_handle, hz*5, cp_timeout, 0); 2288128967Srik break; 2289128967Srik case MOD_UNLOAD: 2290128967Srik if (load_count == 1) { 2291128967Srik printf ("Removing device entry for Tau-PCI\n"); 2292138673Srik#ifdef NETGRAPH 2293128967Srik ng_rmtype (&typestruct); 2294128967Srik#endif 2295128967Srik } 2296138823Srik /* If we were wait it than it reasserted now, just stop it. 2297138823Srik * Actually we shouldn't get this condition. But code could be 2298138823Srik * changed in the future, so just be a litle paranoid. 2299138823Srik */ 2300138823Srik if (!callout_drain (&timeout_handle)) 2301138823Srik callout_stop (&timeout_handle); 2302128967Srik --load_count; 2303128967Srik break; 2304128967Srik case MOD_SHUTDOWN: 2305128967Srik break; 2306128967Srik } 2307128967Srik return 0; 2308128967Srik} 2309128967Srik 2310128967Srik#ifdef NETGRAPH 2311128967Srikstatic struct ng_type typestruct = { 2312129837Srik .version = NG_ABI_VERSION, 2313129837Srik .name = NG_CP_NODE_TYPE, 2314129837Srik .constructor = ng_cp_constructor, 2315129837Srik .rcvmsg = ng_cp_rcvmsg, 2316129837Srik .shutdown = ng_cp_rmnode, 2317129837Srik .newhook = ng_cp_newhook, 2318129837Srik .connect = ng_cp_connect, 2319129837Srik .rcvdata = ng_cp_rcvdata, 2320129837Srik .disconnect = ng_cp_disconnect, 2321128967Srik}; 2322128967Srik#endif /*NETGRAPH*/ 2323128967Srik 2324128967Srik#ifdef NETGRAPH 2325128967SrikMODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2326128967Srik#else 2327128967SrikMODULE_DEPEND (cp, sppp, 1, 1, 1); 2328128967Srik#endif 2329128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2330138823SrikMODULE_VERSION (cp, 1); 2331