if_cp.c revision 131108
1128967Srik/* 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 131108 2004-06-25 19:22:05Z julian $"); 26128967Srik 27128967Srik#include <sys/param.h> 28128967Srik 29128967Srik#if __FreeBSD_version >= 500000 30128967Srik# define NPCI 1 31128967Srik#else 32128967Srik# include "pci.h" 33128967Srik#endif 34128967Srik 35128967Srik#if NPCI > 0 36128967Srik 37128967Srik#include <sys/ucred.h> 38128967Srik#include <sys/proc.h> 39128967Srik#include <sys/systm.h> 40128967Srik#include <sys/mbuf.h> 41128967Srik#include <sys/kernel.h> 42129879Sphk#include <sys/module.h> 43128967Srik#include <sys/conf.h> 44128967Srik#include <sys/malloc.h> 45128967Srik#include <sys/socket.h> 46128967Srik#include <sys/sockio.h> 47128967Srik#include <sys/tty.h> 48130971Srik#include <sys/bus.h> 49128967Srik#include <vm/vm.h> 50128967Srik#include <vm/pmap.h> 51128967Srik#include <net/if.h> 52128967Srik#if __FreeBSD_version > 501000 53128967Srik# include <dev/pci/pcivar.h> 54128967Srik# include <dev/pci/pcireg.h> 55128967Srik#else 56128967Srik# include <pci/pcivar.h> 57128967Srik# include <pci/pcireg.h> 58128967Srik#endif 59128967Srik#include <machine/bus.h> 60128967Srik#include <sys/rman.h> 61128967Srik#include "opt_ng_cronyx.h" 62128967Srik#ifdef NETGRAPH_CRONYX 63128967Srik# include "opt_netgraph.h" 64128967Srik# ifndef NETGRAPH 65128967Srik# error #option NETGRAPH missed from configuration 66128967Srik# endif 67128967Srik# include <netgraph/ng_message.h> 68128967Srik# include <netgraph/netgraph.h> 69130985Srik# include <dev/cp/ng_cp.h> 70128967Srik#else 71128967Srik# include <net/if_sppp.h> 72128967Srik# define PP_CISCO IFF_LINK2 73130971Srik# if __FreeBSD_version < 500000 74130971Srik# include <bpf.h> 75130971Srik# endif 76130971Srik# include <net/bpf.h> 77130971Srik# define NBPFILTER NBPF 78128967Srik#endif 79128967Srik#include <dev/cx/machdep.h> 80128967Srik#include <dev/cp/cpddk.h> 81128967Srik#include <machine/cserial.h> 82128967Srik#include <machine/resource.h> 83128967Srik#include <machine/pmap.h> 84128967Srik 85128967Srik/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 86128967Srik#ifndef PP_FR 87128967Srik#define PP_FR 0 88128967Srik#endif 89128967Srik 90128967Srik#define CP_DEBUG(d,s) ({if (d->chan->debug) {\ 91128967Srik printf ("%s: ", d->name); printf s;}}) 92128967Srik#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 93128967Srik printf ("%s: ", d->name); printf s;}}) 94128967Srik 95128967Srik#define CDEV_MAJOR 134 96128967Srik 97128967Srikstatic int cp_probe __P((device_t)); 98128967Srikstatic int cp_attach __P((device_t)); 99128967Srikstatic int cp_detach __P((device_t)); 100128967Srik 101128967Srikstatic device_method_t cp_methods[] = { 102128967Srik /* Device interface */ 103128967Srik DEVMETHOD(device_probe, cp_probe), 104128967Srik DEVMETHOD(device_attach, cp_attach), 105128967Srik DEVMETHOD(device_detach, cp_detach), 106128967Srik 107128967Srik {0, 0} 108128967Srik}; 109128967Srik 110130985Sriktypedef struct _cp_dma_mem_t { 111130985Srik unsigned long phys; 112130985Srik void *virt; 113130985Srik size_t size; 114130985Srik#if __FreeBSD_version >= 500000 115130985Srik bus_dma_tag_t dmat; 116130985Srik bus_dmamap_t mapp; 117130985Srik#endif 118130985Srik} cp_dma_mem_t; 119128967Srik 120128967Sriktypedef struct _drv_t { 121128967Srik char name [8]; 122128967Srik cp_chan_t *chan; 123128967Srik cp_board_t *board; 124130985Srik cp_dma_mem_t dmamem; 125128967Srik int running; 126128967Srik#ifdef NETGRAPH 127128967Srik char nodename [NG_NODELEN+1]; 128128967Srik hook_p hook; 129128967Srik hook_p debug_hook; 130128967Srik node_p node; 131128967Srik struct ifqueue queue; 132128967Srik struct ifqueue hi_queue; 133128967Srik short timeout; 134128967Srik struct callout_handle timeout_handle; 135128967Srik#else 136128967Srik struct sppp pp; 137128967Srik#endif 138130585Sphk struct cdev *devt; 139128967Srik} drv_t; 140128967Srik 141130985Sriktypedef struct _bdrv_t { 142130985Srik cp_board_t *board; 143130985Srik struct resource *cp_res; 144130985Srik struct resource *cp_irq; 145130985Srik void *cp_intrhand; 146130985Srik cp_dma_mem_t dmamem; 147130985Srik drv_t channel [NCHAN]; 148130985Srik} bdrv_t; 149130985Srik 150130985Srikstatic driver_t cp_driver = { 151130985Srik "cp", 152130985Srik cp_methods, 153130985Srik sizeof(bdrv_t), 154130985Srik}; 155130985Srik 156130985Srikstatic devclass_t cp_devclass; 157130985Srik 158128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len); 159128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len); 160128967Srikstatic void cp_error (cp_chan_t *c, int data); 161128967Srikstatic void cp_up (drv_t *d); 162128967Srikstatic void cp_start (drv_t *d); 163128967Srikstatic void cp_down (drv_t *d); 164128967Srikstatic void cp_watchdog (drv_t *d); 165128967Srik#ifdef NETGRAPH 166128967Srikextern struct ng_type typestruct; 167128967Srik#else 168128967Srikstatic void cp_ifstart (struct ifnet *ifp); 169128967Srikstatic void cp_tlf (struct sppp *sp); 170128967Srikstatic void cp_tls (struct sppp *sp); 171128967Srikstatic void cp_ifwatchdog (struct ifnet *ifp); 172128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 173128967Srikstatic void cp_initialize (void *softc); 174128967Srik#endif 175128967Srik 176128967Srikstatic cp_board_t *adapter [NBRD]; 177128967Srikstatic drv_t *channel [NBRD*NCHAN]; 178128967Srikstatic struct callout_handle led_timo [NBRD]; 179128967Srikstatic struct callout_handle timeout_handle; 180128967Srik 181128967Srikstatic int cp_destroy = 0; 182128967Srik 183128967Srik/* 184128967Srik * Print the mbuf chain, for debug purposes only. 185128967Srik */ 186128967Srikstatic void printmbuf (struct mbuf *m) 187128967Srik{ 188128967Srik printf ("mbuf:"); 189128967Srik for (; m; m=m->m_next) { 190128967Srik if (m->m_flags & M_PKTHDR) 191128967Srik printf (" HDR %d:", m->m_pkthdr.len); 192128967Srik if (m->m_flags & M_EXT) 193128967Srik printf (" EXT:"); 194128967Srik printf (" %d", m->m_len); 195128967Srik } 196128967Srik printf ("\n"); 197128967Srik} 198128967Srik 199128967Srik/* 200128967Srik * Make an mbuf from data. 201128967Srik */ 202128967Srikstatic struct mbuf *makembuf (void *buf, unsigned len) 203128967Srik{ 204128967Srik struct mbuf *m; 205128967Srik 206128967Srik MGETHDR (m, M_DONTWAIT, MT_DATA); 207128967Srik if (! m) 208128967Srik return 0; 209128967Srik MCLGET (m, M_DONTWAIT); 210128967Srik if (! (m->m_flags & M_EXT)) { 211128967Srik m_freem (m); 212128967Srik return 0; 213128967Srik } 214128967Srik m->m_pkthdr.len = m->m_len = len; 215128967Srik bcopy (buf, mtod (m, caddr_t), len); 216128967Srik return m; 217128967Srik} 218128967Srik 219128967Srikstatic int cp_probe (device_t dev) 220128967Srik{ 221128967Srik if ((pci_get_vendor (dev) == cp_vendor_id) && 222128967Srik (pci_get_device (dev) == cp_device_id)) { 223128967Srik device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 224128967Srik return 0; 225128967Srik } 226128967Srik return ENXIO; 227128967Srik} 228128967Srik 229128967Srikstatic void cp_timeout (void *arg) 230128967Srik{ 231128967Srik drv_t *d; 232128967Srik int s, i; 233128967Srik 234128967Srik for (i=0; i<NBRD*NCHAN; ++i) { 235128967Srik s = splimp (); 236128967Srik if (cp_destroy) { 237128967Srik splx (s); 238128967Srik return; 239128967Srik } 240128967Srik d = channel[i]; 241128967Srik if (!d) { 242128967Srik splx (s); 243128967Srik continue; 244128967Srik } 245128967Srik switch (d->chan->type) { 246128967Srik case T_G703: 247128967Srik cp_g703_timer (d->chan); 248128967Srik break; 249128967Srik case T_E1: 250128967Srik cp_e1_timer (d->chan); 251128967Srik break; 252128967Srik case T_E3: 253128967Srik case T_T3: 254128967Srik case T_STS1: 255128967Srik cp_e3_timer (d->chan); 256128967Srik break; 257128967Srik default: 258128967Srik break; 259128967Srik } 260128967Srik splx (s); 261128967Srik } 262128967Srik s = splimp (); 263128967Srik if (!cp_destroy) 264128967Srik timeout_handle = timeout (cp_timeout, 0, hz); 265128967Srik splx (s); 266128967Srik} 267128967Srik 268128967Srikstatic void cp_led_off (void *arg) 269128967Srik{ 270128967Srik cp_board_t *b = arg; 271128967Srik int s = splimp (); 272128967Srik if (cp_destroy) { 273128967Srik splx (s); 274128967Srik return; 275128967Srik } 276128967Srik cp_led (b, 0); 277128967Srik led_timo[b->num].callout = 0; 278128967Srik splx (s); 279128967Srik} 280128967Srik 281128967Srikstatic void cp_intr (void *arg) 282128967Srik{ 283128967Srik bdrv_t *bd = arg; 284128967Srik cp_board_t *b = bd->board; 285128967Srik int s = splimp (); 286128967Srik if (cp_destroy) { 287128967Srik splx (s); 288128967Srik return; 289128967Srik } 290128967Srik /* Turn LED on. */ 291128967Srik cp_led (b, 1); 292128967Srik 293128967Srik cp_interrupt (b); 294128967Srik 295128967Srik /* Turn LED off 50 msec later. */ 296128967Srik if (!led_timo[b->num].callout) 297128967Srik led_timo[b->num] = timeout (cp_led_off, b, hz/20); 298128967Srik splx (s); 299128967Srik} 300128967Srik 301128967Srikextern struct cdevsw cp_cdevsw; 302128967Srik 303130985Srik#if __FreeBSD_version >= 500000 304130985Srikstatic void 305130985Srikcp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 306130985Srik{ 307130985Srik unsigned long *addr; 308130985Srik 309130985Srik if (error) 310130985Srik return; 311130985Srik 312130985Srik KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 313130985Srik addr = arg; 314130985Srik *addr = segs->ds_addr; 315130985Srik} 316130985Srik 317130985Srikstatic int 318130985Srikcp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 319130985Srik{ 320130985Srik int error; 321130985Srik 322130985Srik error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 323130985Srik BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 324130985Srik dmem->size, 0, NULL, NULL, &dmem->dmat); 325130985Srik if (error) { 326130985Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 327130985Srik else printf ("cp%d: ", bnum); 328130985Srik printf ("couldn't allocate tag for dma memory\n"); 329130985Srik return 0; 330130985Srik } 331130985Srik error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 332130985Srik BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 333130985Srik if (error) { 334130985Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 335130985Srik else printf ("cp%d: ", bnum); 336130985Srik printf ("couldn't allocate mem for dma memory\n"); 337130985Srik bus_dma_tag_destroy (dmem->dmat); 338130985Srik return 0; 339130985Srik } 340130985Srik error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 341130985Srik dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); 342130985Srik if (error) { 343130985Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 344130985Srik else printf ("cp%d: ", bnum); 345130985Srik printf ("couldn't load mem map for dma memory\n"); 346130985Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 347130985Srik bus_dma_tag_destroy (dmem->dmat); 348130985Srik return 0; 349130985Srik } 350130985Srik return 1; 351130985Srik} 352130985Srik 353130985Srikstatic void 354130985Srikcp_bus_dma_mem_free (cp_dma_mem_t *dmem) 355130985Srik{ 356130985Srik bus_dmamap_unload (dmem->dmat, dmem->mapp); 357130985Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 358130985Srik bus_dma_tag_destroy (dmem->dmat); 359130985Srik} 360130985Srik#else 361130985Srikstatic int 362130985Srikcp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 363130985Srik{ 364130985Srik dmem->virt = contigmalloc (dmem->size, M_DEVBUF, M_WAITOK, 365130985Srik 0x100000, 0xffffffff, 16, 0); 366130985Srik if (dmem->virt == NULL) { 367130985Srik if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 368130985Srik else printf ("cp%d: ", bnum); 369130985Srik printf ("couldn't allocate memory for dma memory\n", unit); 370130985Srik return 0; 371130985Srik } 372130985Srik dmem->phys = vtophys (dmem->virt); 373130985Srik return 1; 374130985Srik} 375130985Srik 376130985Srikstatic void 377130985Srikcp_bus_dma_mem_free (cp_dma_mem_t *dmem) 378130985Srik{ 379130985Srik contigfree (dmem->virt, dmem->size, M_DEVBUF); 380130985Srik} 381130985Srik#endif 382130985Srik 383128967Srik/* 384128967Srik * Called if the probe succeeded. 385128967Srik */ 386128967Srikstatic int cp_attach (device_t dev) 387128967Srik{ 388128967Srik bdrv_t *bd = device_get_softc (dev); 389128967Srik int unit = device_get_unit (dev); 390130985Srik unsigned short res; 391130985Srik vm_offset_t vbase; 392128967Srik int rid, error; 393130985Srik cp_board_t *b; 394128967Srik cp_chan_t *c; 395130985Srik drv_t *d; 396128967Srik int s = splimp (); 397128967Srik 398128967Srik b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 399128967Srik if (!b) { 400128967Srik printf ("cp%d: couldn't allocate memory\n", unit); 401128967Srik splx (s); 402128967Srik return (ENXIO); 403128967Srik } 404128967Srik adapter[unit] = b; 405128967Srik bzero (b, sizeof(cp_board_t)); 406128967Srik 407128967Srik bd->board = b; 408128967Srik b->sys = bd; 409129673Sjhb rid = PCIR_BAR(0); 410128967Srik bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 411128967Srik 0, ~0, 1, RF_ACTIVE); 412128967Srik if (! bd->cp_res) { 413128967Srik printf ("cp%d: cannot map memory\n", unit); 414128967Srik free (b, M_DEVBUF); 415128967Srik splx (s); 416128967Srik return (ENXIO); 417128967Srik } 418128967Srik vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 419128967Srik 420128967Srik res = cp_init (b, unit, (u_char*) vbase); 421128967Srik if (res) { 422128967Srik printf ("cp%d: can't init, error code:%x\n", unit, res); 423129673Sjhb bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 424128967Srik free (b, M_DEVBUF); 425128967Srik splx (s); 426128967Srik return (ENXIO); 427128967Srik } 428130985Srik 429130985Srik bd->dmamem.size = sizeof(cp_qbuf_t); 430130985Srik if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 431128967Srik free (b, M_DEVBUF); 432128967Srik splx (s); 433128967Srik return (ENXIO); 434128967Srik } 435130985Srik cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); 436128967Srik 437128967Srik rid = 0; 438128967Srik bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 439128967Srik RF_SHAREABLE | RF_ACTIVE); 440128967Srik if (! bd->cp_irq) { 441128967Srik printf ("cp%d: cannot map interrupt\n", unit); 442128967Srik bus_release_resource (dev, SYS_RES_MEMORY, 443129673Sjhb PCIR_BAR(0), bd->cp_res); 444128967Srik free (b, M_DEVBUF); 445128967Srik splx (s); 446128967Srik return (ENXIO); 447128967Srik } 448128967Srik error = bus_setup_intr (dev, bd->cp_irq, INTR_TYPE_NET, cp_intr, bd, 449128967Srik &bd->cp_intrhand); 450128967Srik if (error) { 451128967Srik printf ("cp%d: cannot set up irq\n", unit); 452128967Srik bus_release_resource (dev, SYS_RES_MEMORY, 453129673Sjhb PCIR_BAR(0), bd->cp_res); 454128967Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 455128967Srik free (b, M_DEVBUF); 456128967Srik splx (s); 457128967Srik return (ENXIO); 458128967Srik } 459128967Srik printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 460128967Srik 461128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 462128967Srik if (! c->type) 463128967Srik continue; 464130985Srik d = &bd->channel[c->num]; 465130985Srik d->dmamem.size = sizeof(cp_buf_t); 466130985Srik if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 467130985Srik continue; 468128967Srik channel [b->num*NCHAN + c->num] = d; 469128967Srik sprintf (d->name, "cp%d.%d", b->num, c->num); 470128967Srik d->board = b; 471128967Srik d->chan = c; 472128967Srik c->sys = d; 473128967Srik#ifdef NETGRAPH 474128967Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 475128967Srik printf ("%s: cannot make common node\n", d->name); 476128967Srik d->node = NULL; 477128967Srik continue; 478128967Srik } 479128967Srik#if __FreeBSD_version >= 500000 480128967Srik NG_NODE_SET_PRIVATE (d->node, d); 481128967Srik#else 482128967Srik d->node->private = d; 483128967Srik#endif 484128967Srik sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 485128967Srik c->board->num*NCHAN + c->num); 486128967Srik if (ng_name_node (d->node, d->nodename)) { 487128967Srik printf ("%s: cannot name node\n", d->nodename); 488128967Srik#if __FreeBSD_version >= 500000 489128967Srik NG_NODE_UNREF (d->node); 490128967Srik#else 491128967Srik ng_rmnode (d->node); 492128967Srik ng_unref (d->node); 493128967Srik#endif 494128967Srik continue; 495128967Srik } 496128967Srik d->queue.ifq_maxlen = IFQ_MAXLEN; 497128967Srik d->hi_queue.ifq_maxlen = IFQ_MAXLEN; 498128967Srik#if __FreeBSD_version >= 500000 499128967Srik mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 500128967Srik mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 501128967Srik#endif 502128967Srik#else /*NETGRAPH*/ 503128967Srik d->pp.pp_if.if_softc = d; 504128967Srik#if __FreeBSD_version > 501000 505128967Srik if_initname (&d->pp.pp_if, "cp", b->num * NCHAN + c->num); 506128967Srik#else 507128967Srik d->pp.pp_if.if_unit = b->num * NCHAN + c->num; 508128967Srik d->pp.pp_if.if_name = "cp"; 509128967Srik#endif 510128967Srik d->pp.pp_if.if_mtu = PP_MTU; 511128967Srik d->pp.pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 512128967Srik d->pp.pp_if.if_ioctl = cp_sioctl; 513128967Srik d->pp.pp_if.if_start = cp_ifstart; 514128967Srik d->pp.pp_if.if_watchdog = cp_ifwatchdog; 515128967Srik d->pp.pp_if.if_init = cp_initialize; 516128967Srik sppp_attach (&d->pp.pp_if); 517128967Srik if_attach (&d->pp.pp_if); 518128967Srik d->pp.pp_tlf = cp_tlf; 519128967Srik d->pp.pp_tls = cp_tls; 520128967Srik /* If BPF is in the kernel, call the attach for it. 521128967Srik * The header size of PPP or Cisco/HDLC is 4 bytes. */ 522128967Srik bpfattach (&d->pp.pp_if, DLT_PPP, 4); 523128967Srik#endif /*NETGRAPH*/ 524128967Srik cp_start_e1 (c); 525130985Srik cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 526128967Srik 527128967Srik /* Register callback functions. */ 528128967Srik cp_register_transmit (c, &cp_transmit); 529128967Srik cp_register_receive (c, &cp_receive); 530128967Srik cp_register_error (c, &cp_error); 531128967Srik d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 532128967Srik GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 533128967Srik } 534128967Srik splx (s); 535128967Srik return 0; 536128967Srik} 537128967Srik 538128967Srikstatic int cp_detach (device_t dev) 539128967Srik{ 540128967Srik bdrv_t *bd = device_get_softc (dev); 541128967Srik cp_board_t *b = bd->board; 542128967Srik cp_chan_t *c; 543128967Srik int s = splimp (); 544128967Srik 545128967Srik /* Check if the device is busy (open). */ 546128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 547128967Srik drv_t *d = (drv_t*) c->sys; 548128967Srik 549128967Srik if (! d || ! d->chan->type) 550128967Srik continue; 551128967Srik if (d->running) { 552128967Srik splx (s); 553128967Srik return EBUSY; 554128967Srik } 555128967Srik } 556128967Srik 557128967Srik /* Ok, we can unload driver */ 558128967Srik /* At first we should stop all channels */ 559128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 560128967Srik drv_t *d = (drv_t*) c->sys; 561128967Srik 562128967Srik if (! d || ! d->chan->type) 563128967Srik continue; 564128967Srik 565128967Srik cp_stop_chan (c); 566128967Srik cp_stop_e1 (c); 567128967Srik cp_set_dtr (d->chan, 0); 568128967Srik cp_set_rts (d->chan, 0); 569128967Srik } 570128967Srik 571128967Srik /* Reset the adapter. */ 572128967Srik cp_destroy = 1; 573128967Srik cp_interrupt_poll (b, 1); 574128967Srik cp_led_off (b); 575128967Srik cp_reset (b, 0 ,0); 576128967Srik if (led_timo[b->num].callout) 577128967Srik untimeout (cp_led_off, b, led_timo[b->num]); 578128967Srik 579128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 580128967Srik drv_t *d = (drv_t*) c->sys; 581128967Srik 582128967Srik if (! d || ! d->chan->type) 583128967Srik continue; 584128967Srik#ifndef NETGRAPH 585128967Srik#if __FreeBSD_version >= 410000 && NBPFILTER > 0 586128967Srik /* Detach from the packet filter list of interfaces. */ 587128967Srik bpfdetach (&d->pp.pp_if); 588128967Srik#endif 589128967Srik /* Detach from the sync PPP list. */ 590128967Srik sppp_detach (&d->pp.pp_if); 591128967Srik 592128967Srik /* Detach from the system list of interfaces. */ 593128967Srik if_detach (&d->pp.pp_if); 594128967Srik#else 595128967Srik#if __FreeBSD_version >= 500000 596128967Srik if (d->node) { 597128967Srik ng_rmnode_self (d->node); 598128967Srik NG_NODE_UNREF (d->node); 599128967Srik d->node = NULL; 600128967Srik } 601128967Srik mtx_destroy (&d->queue.ifq_mtx); 602128967Srik mtx_destroy (&d->hi_queue.ifq_mtx); 603128967Srik#else 604128967Srik ng_rmnode (d->node); 605128967Srik d->node = 0; 606128967Srik#endif 607128967Srik#endif 608128967Srik destroy_dev (d->devt); 609128967Srik } 610128967Srik 611128967Srik /* Disable the interrupt request. */ 612128967Srik bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 613128967Srik bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 614128967Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 615129673Sjhb bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 616128967Srik cp_led_off (b); 617128967Srik if (led_timo[b->num].callout) 618128967Srik untimeout (cp_led_off, b, led_timo[b->num]); 619128967Srik splx (s); 620128967Srik 621128967Srik s = splimp (); 622128967Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 623128967Srik drv_t *d = (drv_t*) c->sys; 624128967Srik 625128967Srik if (! d || ! d->chan->type) 626128967Srik continue; 627128967Srik channel [b->num*NCHAN + c->num] = 0; 628128967Srik /* Deallocate buffers. */ 629130985Srik cp_bus_dma_mem_free (&d->dmamem); 630128967Srik } 631128967Srik adapter [b->num] = 0; 632130985Srik cp_bus_dma_mem_free (&bd->dmamem); 633128967Srik free (b, M_DEVBUF); 634128967Srik splx (s); 635128967Srik return 0; 636128967Srik} 637128967Srik 638128967Srik#ifndef NETGRAPH 639128967Srikstatic void cp_ifstart (struct ifnet *ifp) 640128967Srik{ 641128967Srik drv_t *d = ifp->if_softc; 642128967Srik 643128967Srik cp_start (d); 644128967Srik} 645128967Srik 646128967Srikstatic void cp_ifwatchdog (struct ifnet *ifp) 647128967Srik{ 648128967Srik drv_t *d = ifp->if_softc; 649128967Srik 650128967Srik cp_watchdog (d); 651128967Srik} 652128967Srik 653128967Srikstatic void cp_tlf (struct sppp *sp) 654128967Srik{ 655128967Srik drv_t *d = sp->pp_if.if_softc; 656128967Srik 657128967Srik CP_DEBUG2 (d, ("cp_tlf\n")); 658128967Srik/* cp_set_dtr (d->chan, 0);*/ 659128967Srik/* cp_set_rts (d->chan, 0);*/ 660128967Srik sp->pp_down (sp); 661128967Srik} 662128967Srik 663128967Srikstatic void cp_tls (struct sppp *sp) 664128967Srik{ 665128967Srik drv_t *d = sp->pp_if.if_softc; 666128967Srik 667128967Srik CP_DEBUG2 (d, ("cp_tls\n")); 668128967Srik sp->pp_up (sp); 669128967Srik} 670128967Srik 671128967Srik/* 672128967Srik * Process an ioctl request. 673128967Srik */ 674128967Srikstatic int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 675128967Srik{ 676128967Srik drv_t *d = ifp->if_softc; 677128967Srik int error, s, was_up, should_be_up; 678128967Srik 679128967Srik was_up = (ifp->if_flags & IFF_RUNNING) != 0; 680128967Srik error = sppp_ioctl (ifp, cmd, data); 681128967Srik 682128967Srik if (error) 683128967Srik return error; 684128967Srik 685128967Srik if (! (ifp->if_flags & IFF_DEBUG)) 686128967Srik d->chan->debug = 0; 687128967Srik else if (! d->chan->debug) 688128967Srik d->chan->debug = 1; 689128967Srik 690128967Srik switch (cmd) { 691128967Srik default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 692128967Srik case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 693128967Srik case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 694128967Srik case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 695128967Srik case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 696128967Srik } 697128967Srik 698128967Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 699128967Srik s = splimp (); 700128967Srik should_be_up = (ifp->if_flags & IFF_RUNNING) != 0; 701128967Srik if (! was_up && should_be_up) { 702128967Srik /* Interface goes up -- start it. */ 703128967Srik cp_up (d); 704128967Srik cp_start (d); 705128967Srik } else if (was_up && ! should_be_up) { 706128967Srik /* Interface is going down -- stop it. */ 707128967Srik/* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 708128967Srik cp_down (d); 709128967Srik } 710128967Srik CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 711128967Srik splx (s); 712128967Srik return 0; 713128967Srik} 714128967Srik 715128967Srik/* 716128967Srik * Initialization of interface. 717128967Srik * It seems to be never called by upper level? 718128967Srik */ 719128967Srikstatic void cp_initialize (void *softc) 720128967Srik{ 721128967Srik drv_t *d = softc; 722128967Srik 723128967Srik CP_DEBUG (d, ("cp_initialize\n")); 724128967Srik} 725128967Srik#endif /*NETGRAPH*/ 726128967Srik 727128967Srik/* 728128967Srik * Stop the interface. Called on splimp(). 729128967Srik */ 730128967Srikstatic void cp_down (drv_t *d) 731128967Srik{ 732128967Srik CP_DEBUG (d, ("cp_down\n")); 733128967Srik /* Interface is going down -- stop it. */ 734128967Srik cp_set_dtr (d->chan, 0); 735128967Srik cp_set_rts (d->chan, 0); 736128967Srik 737128967Srik d->running = 0; 738128967Srik} 739128967Srik 740128967Srik/* 741128967Srik * Start the interface. Called on splimp(). 742128967Srik */ 743128967Srikstatic void cp_up (drv_t *d) 744128967Srik{ 745128967Srik CP_DEBUG (d, ("cp_up\n")); 746128967Srik cp_set_dtr (d->chan, 1); 747128967Srik cp_set_rts (d->chan, 1); 748128967Srik d->running = 1; 749128967Srik} 750128967Srik 751128967Srik/* 752128967Srik * Start output on the interface. Get another datagram to send 753128967Srik * off of the interface queue, and copy it to the interface 754128967Srik * before starting the output. 755128967Srik */ 756128967Srikstatic void cp_send (drv_t *d) 757128967Srik{ 758128967Srik struct mbuf *m; 759128967Srik u_short len; 760128967Srik 761128967Srik CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 762128967Srik 763128967Srik /* No output if the interface is down. */ 764128967Srik if (! d->running) 765128967Srik return; 766128967Srik 767128967Srik /* No output if the modem is off. */ 768128967Srik if (! (d->chan->lloop || d->chan->type != T_SERIAL || 769128967Srik cp_get_dsr (d->chan))) 770128967Srik return; 771128967Srik 772128967Srik while (cp_transmit_space (d->chan)) { 773128967Srik /* Get the packet to send. */ 774128967Srik#ifdef NETGRAPH 775128967Srik IF_DEQUEUE (&d->hi_queue, m); 776128967Srik if (! m) 777128967Srik IF_DEQUEUE (&d->queue, m); 778128967Srik#else 779128967Srik m = sppp_dequeue (&d->pp.pp_if); 780128967Srik#endif 781128967Srik if (! m) 782128967Srik return; 783130971Srik#ifndef NETGRAPH 784128967Srik if (d->pp.pp_if.if_bpf) 785128967Srik#if __FreeBSD_version >= 500000 786128967Srik BPF_MTAP (&d->pp.pp_if, m); 787128967Srik#else 788128967Srik bpf_mtap (&d->pp.pp_if, m); 789128967Srik#endif 790128967Srik#endif 791128967Srik len = m->m_pkthdr.len; 792128967Srik if (len >= BUFSZ) 793128967Srik printf ("%s: too long packet: %d bytes: ", 794128967Srik d->name, len); 795128967Srik else if (! m->m_next) 796128967Srik cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 797128967Srik else { 798128967Srik u_char *buf = d->chan->tbuf[d->chan->te]; 799128967Srik m_copydata (m, 0, len, buf); 800128967Srik cp_send_packet (d->chan, buf, len, 0); 801128967Srik } 802128967Srik m_freem (m); 803128967Srik /* Set up transmit timeout, if the transmit ring is not empty.*/ 804128967Srik#ifdef NETGRAPH 805128967Srik d->timeout = 10; 806128967Srik#else 807128967Srik d->pp.pp_if.if_timer = 10; 808128967Srik#endif 809128967Srik } 810128967Srik#ifndef NETGRAPH 811128967Srik d->pp.pp_if.if_flags |= IFF_OACTIVE; 812128967Srik#endif 813128967Srik} 814128967Srik 815128967Srik/* 816128967Srik * Start output on the interface. 817128967Srik * Always called on splimp(). 818128967Srik */ 819128967Srikstatic void cp_start (drv_t *d) 820128967Srik{ 821128967Srik if (d->running) { 822128967Srik if (! d->chan->dtr) 823128967Srik cp_set_dtr (d->chan, 1); 824128967Srik if (! d->chan->rts) 825128967Srik cp_set_rts (d->chan, 1); 826128967Srik cp_send (d); 827128967Srik } 828128967Srik} 829128967Srik 830128967Srik/* 831128967Srik * Handle transmit timeouts. 832128967Srik * Recover after lost transmit interrupts. 833128967Srik * Always called on splimp(). 834128967Srik */ 835128967Srikstatic void cp_watchdog (drv_t *d) 836128967Srik{ 837128967Srik CP_DEBUG (d, ("device timeout\n")); 838128967Srik if (d->running) { 839128967Srik int s = splimp (); 840128967Srik 841128967Srik cp_stop_chan (d->chan); 842128967Srik cp_stop_e1 (d->chan); 843128967Srik cp_start_e1 (d->chan); 844128967Srik cp_start_chan (d->chan, 1, 1, 0, 0); 845128967Srik cp_set_dtr (d->chan, 1); 846128967Srik cp_set_rts (d->chan, 1); 847128967Srik cp_start (d); 848128967Srik splx (s); 849128967Srik } 850128967Srik} 851128967Srik 852128967Srikstatic void cp_transmit (cp_chan_t *c, void *attachment, int len) 853128967Srik{ 854128967Srik drv_t *d = c->sys; 855128967Srik 856128967Srik#ifdef NETGRAPH 857128967Srik d->timeout = 0; 858128967Srik#else 859128967Srik ++d->pp.pp_if.if_opackets; 860128967Srik d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 861128967Srik d->pp.pp_if.if_timer = 0; 862128967Srik#endif 863128967Srik cp_start (d); 864128967Srik} 865128967Srik 866128967Srikstatic void cp_receive (cp_chan_t *c, unsigned char *data, int len) 867128967Srik{ 868128967Srik drv_t *d = c->sys; 869128967Srik struct mbuf *m; 870128967Srik#if __FreeBSD_version >= 500000 && defined NETGRAPH 871128967Srik int error; 872128967Srik#endif 873128967Srik 874128967Srik if (! d->running) 875128967Srik return; 876128967Srik 877128967Srik m = makembuf (data, len); 878128967Srik if (! m) { 879128967Srik CP_DEBUG (d, ("no memory for packet\n")); 880128967Srik#ifndef NETGRAPH 881128967Srik ++d->pp.pp_if.if_iqdrops; 882128967Srik#endif 883128967Srik return; 884128967Srik } 885128967Srik if (c->debug > 1) 886128967Srik printmbuf (m); 887128967Srik#ifdef NETGRAPH 888128967Srik m->m_pkthdr.rcvif = 0; 889128967Srik#if __FreeBSD_version >= 500000 890128967Srik NG_SEND_DATA_ONLY (error, d->hook, m); 891128967Srik#else 892128967Srik ng_queue_data (d->hook, m, 0); 893128967Srik#endif 894128967Srik#else 895128967Srik ++d->pp.pp_if.if_ipackets; 896128967Srik m->m_pkthdr.rcvif = &d->pp.pp_if; 897128967Srik /* Check if there's a BPF listener on this interface. 898128967Srik * If so, hand off the raw packet to bpf. */ 899128967Srik if (d->pp.pp_if.if_bpf) 900128967Srik#if __FreeBSD_version >= 500000 901128967Srik BPF_TAP (&d->pp.pp_if, data, len); 902128967Srik#else 903128967Srik bpf_tap (&d->pp.pp_if, data, len); 904128967Srik#endif 905128967Srik sppp_input (&d->pp.pp_if, m); 906128967Srik#endif 907128967Srik} 908128967Srik 909128967Srikstatic void cp_error (cp_chan_t *c, int data) 910128967Srik{ 911128967Srik drv_t *d = c->sys; 912128967Srik 913128967Srik switch (data) { 914128967Srik case CP_FRAME: 915128967Srik CP_DEBUG (d, ("frame error\n")); 916128967Srik#ifndef NETGRAPH 917128967Srik ++d->pp.pp_if.if_ierrors; 918128967Srik#endif 919128967Srik break; 920128967Srik case CP_CRC: 921128967Srik CP_DEBUG (d, ("crc error\n")); 922128967Srik#ifndef NETGRAPH 923128967Srik ++d->pp.pp_if.if_ierrors; 924128967Srik#endif 925128967Srik break; 926128967Srik case CP_OVERRUN: 927128967Srik CP_DEBUG (d, ("overrun error\n")); 928128967Srik#ifndef NETGRAPH 929128967Srik ++d->pp.pp_if.if_collisions; 930128967Srik ++d->pp.pp_if.if_ierrors; 931128967Srik#endif 932128967Srik break; 933128967Srik case CP_OVERFLOW: 934128967Srik CP_DEBUG (d, ("overflow error\n")); 935128967Srik#ifndef NETGRAPH 936128967Srik ++d->pp.pp_if.if_ierrors; 937128967Srik#endif 938128967Srik break; 939128967Srik case CP_UNDERRUN: 940128967Srik CP_DEBUG (d, ("underrun error\n")); 941128967Srik#ifdef NETGRAPH 942128967Srik d->timeout = 0; 943128967Srik#else 944128967Srik ++d->pp.pp_if.if_oerrors; 945128967Srik d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 946128967Srik d->pp.pp_if.if_timer = 0; 947128967Srik#endif 948128967Srik cp_start (d); 949128967Srik break; 950128967Srik default: 951128967Srik CP_DEBUG (d, ("error #%d\n", data)); 952128967Srik break; 953128967Srik } 954128967Srik} 955128967Srik 956128967Srik/* 957128967Srik * You also need read, write, open, close routines. 958128967Srik * This should get you started 959128967Srik */ 960128967Srik#if __FreeBSD_version < 500000 961128967Srikstatic int cp_open (dev_t dev, int oflags, int devtype, struct proc *p) 962128967Srik#else 963130585Sphkstatic int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 964128967Srik#endif 965128967Srik{ 966128967Srik int unit = minor (dev); 967128967Srik drv_t *d; 968128967Srik 969128967Srik if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 970128967Srik return ENXIO; 971128967Srik CP_DEBUG2 (d, ("cp_open\n")); 972128967Srik return 0; 973128967Srik} 974128967Srik 975128967Srik/* 976128967Srik * Only called on the LAST close. 977128967Srik */ 978128967Srik#if __FreeBSD_version < 500000 979128967Srikstatic int cp_close (dev_t dev, int fflag, int devtype, struct proc *p) 980128967Srik#else 981130585Sphkstatic int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 982128967Srik#endif 983128967Srik{ 984128967Srik drv_t *d = channel [minor (dev)]; 985128967Srik 986128967Srik CP_DEBUG2 (d, ("cp_close\n")); 987128967Srik return 0; 988128967Srik} 989128967Srik 990128967Srikstatic int cp_modem_status (cp_chan_t *c) 991128967Srik{ 992128967Srik drv_t *d = c->sys; 993128967Srik int status, s; 994128967Srik 995128967Srik status = d->running ? TIOCM_LE : 0; 996128967Srik s = splimp (); 997128967Srik if (cp_get_cd (c)) status |= TIOCM_CD; 998128967Srik if (cp_get_cts (c)) status |= TIOCM_CTS; 999128967Srik if (cp_get_dsr (c)) status |= TIOCM_DSR; 1000128967Srik if (c->dtr) status |= TIOCM_DTR; 1001128967Srik if (c->rts) status |= TIOCM_RTS; 1002128967Srik splx (s); 1003128967Srik return status; 1004128967Srik} 1005128967Srik 1006128967Srik#if __FreeBSD_version < 500000 1007128967Srikstatic int cp_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1008128967Srik#else 1009130585Sphkstatic int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1010128967Srik#endif 1011128967Srik{ 1012128967Srik drv_t *d = channel [minor (dev)]; 1013128967Srik cp_chan_t *c = d->chan; 1014128967Srik struct serial_statistics *st; 1015128967Srik struct e1_statistics *opte1; 1016128967Srik struct e3_statistics *opte3; 1017128967Srik int error, s; 1018128967Srik char mask[16]; 1019128967Srik 1020128967Srik switch (cmd) { 1021128967Srik case SERIAL_GETREGISTERED: 1022128967Srik CP_DEBUG2 (d, ("ioctl: getregistered\n")); 1023128967Srik bzero (mask, sizeof(mask)); 1024128967Srik for (s=0; s<NBRD*NCHAN; ++s) 1025128967Srik if (channel [s]) 1026128967Srik mask [s/8] |= 1 << (s & 7); 1027128967Srik bcopy (mask, data, sizeof (mask)); 1028128967Srik return 0; 1029128967Srik 1030128967Srik#ifndef NETGRAPH 1031128967Srik case SERIAL_GETPROTO: 1032128967Srik CP_DEBUG2 (d, ("ioctl: getproto\n")); 1033128967Srik strcpy ((char*)data, (d->pp.pp_flags & PP_FR) ? "fr" : 1034128967Srik (d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp"); 1035128967Srik return 0; 1036128967Srik 1037128967Srik case SERIAL_SETPROTO: 1038128967Srik CP_DEBUG2 (d, ("ioctl: setproto\n")); 1039128967Srik /* Only for superuser! */ 1040130971Srik#if __FreeBSD_version < 500000 1041128967Srik error = suser (p); 1042128967Srik#else /* __FreeBSD_version >= 500000 */ 1043128967Srik error = suser (td); 1044128967Srik#endif /* __FreeBSD_version >= 500000 */ 1045128967Srik if (error) 1046128967Srik return error; 1047128967Srik if (d->pp.pp_if.if_flags & IFF_RUNNING) 1048128967Srik return EBUSY; 1049128967Srik if (! strcmp ("cisco", (char*)data)) { 1050128967Srik d->pp.pp_flags &= ~(PP_FR); 1051128967Srik d->pp.pp_flags |= PP_KEEPALIVE; 1052128967Srik d->pp.pp_if.if_flags |= PP_CISCO; 1053128967Srik } else if (! strcmp ("fr", (char*)data) && !PP_FR) { 1054128967Srik d->pp.pp_if.if_flags &= ~(PP_CISCO); 1055128967Srik d->pp.pp_flags |= PP_FR | PP_KEEPALIVE; 1056128967Srik } else if (! strcmp ("ppp", (char*)data)) { 1057128967Srik d->pp.pp_flags &= ~PP_FR; 1058128967Srik d->pp.pp_flags &= ~PP_KEEPALIVE; 1059128967Srik d->pp.pp_if.if_flags &= ~(PP_CISCO); 1060128967Srik } else 1061128967Srik return EINVAL; 1062128967Srik return 0; 1063128967Srik 1064128967Srik case SERIAL_GETKEEPALIVE: 1065128967Srik CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1066128967Srik if ((d->pp.pp_flags & PP_FR) || 1067128967Srik (d->pp.pp_if.if_flags & PP_CISCO)) 1068128967Srik return EINVAL; 1069128967Srik *(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0; 1070128967Srik return 0; 1071128967Srik 1072128967Srik case SERIAL_SETKEEPALIVE: 1073128967Srik CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1074128967Srik /* Only for superuser! */ 1075130971Srik#if __FreeBSD_version < 500000 1076128967Srik error = suser (p); 1077128967Srik#else 1078128967Srik error = suser (td); 1079128967Srik#endif 1080128967Srik if (error) 1081128967Srik return error; 1082128967Srik if ((d->pp.pp_flags & PP_FR) || 1083128967Srik (d->pp.pp_if.if_flags & PP_CISCO)) 1084128967Srik return EINVAL; 1085128967Srik s = splimp (); 1086128967Srik if (*(int*)data) 1087128967Srik d->pp.pp_flags |= PP_KEEPALIVE; 1088128967Srik else 1089128967Srik d->pp.pp_flags &= ~PP_KEEPALIVE; 1090128967Srik splx (s); 1091128967Srik return 0; 1092128967Srik#endif /*NETGRAPH*/ 1093128967Srik 1094128967Srik case SERIAL_GETMODE: 1095128967Srik CP_DEBUG2 (d, ("ioctl: getmode\n")); 1096128967Srik *(int*)data = SERIAL_HDLC; 1097128967Srik return 0; 1098128967Srik 1099128967Srik case SERIAL_SETMODE: 1100128967Srik /* Only for superuser! */ 1101130971Srik#if __FreeBSD_version < 500000 1102128967Srik error = suser (p); 1103128967Srik#else 1104128967Srik error = suser (td); 1105128967Srik#endif 1106128967Srik if (error) 1107128967Srik return error; 1108128967Srik if (*(int*)data != SERIAL_HDLC) 1109128967Srik return EINVAL; 1110128967Srik return 0; 1111128967Srik 1112128967Srik case SERIAL_GETCFG: 1113128967Srik CP_DEBUG2 (d, ("ioctl: getcfg\n")); 1114128967Srik if (c->type != T_E1 || c->unfram) 1115128967Srik return EINVAL; 1116128967Srik *(char*)data = c->board->mux ? 'c' : 'a'; 1117128967Srik return 0; 1118128967Srik 1119128967Srik case SERIAL_SETCFG: 1120128967Srik CP_DEBUG2 (d, ("ioctl: setcfg\n")); 1121130971Srik#if __FreeBSD_version < 500000 1122128967Srik error = suser (p); 1123128967Srik#else 1124128967Srik error = suser (td); 1125128967Srik#endif 1126128967Srik if (error) 1127128967Srik return error; 1128128967Srik if (c->type != T_E1) 1129128967Srik return EINVAL; 1130128967Srik s = splimp (); 1131128967Srik cp_set_mux (c->board, *((char*)data) == 'c'); 1132128967Srik splx (s); 1133128967Srik return 0; 1134128967Srik 1135128967Srik case SERIAL_GETSTAT: 1136128967Srik CP_DEBUG2 (d, ("ioctl: getstat\n")); 1137128967Srik st = (struct serial_statistics*) data; 1138128967Srik st->rintr = c->rintr; 1139128967Srik st->tintr = c->tintr; 1140128967Srik st->mintr = 0; 1141128967Srik st->ibytes = c->ibytes; 1142128967Srik st->ipkts = c->ipkts; 1143128967Srik st->obytes = c->obytes; 1144128967Srik st->opkts = c->opkts; 1145128967Srik st->ierrs = c->overrun + c->frame + c->crc; 1146128967Srik st->oerrs = c->underrun; 1147128967Srik return 0; 1148128967Srik 1149128967Srik case SERIAL_GETESTAT: 1150128967Srik CP_DEBUG2 (d, ("ioctl: getestat\n")); 1151128967Srik if (c->type != T_E1 && c->type != T_G703) 1152128967Srik return EINVAL; 1153128967Srik opte1 = (struct e1_statistics*) data; 1154128967Srik opte1->status = c->status; 1155128967Srik opte1->cursec = c->cursec; 1156128967Srik opte1->totsec = c->totsec + c->cursec; 1157128967Srik 1158128967Srik opte1->currnt.bpv = c->currnt.bpv; 1159128967Srik opte1->currnt.fse = c->currnt.fse; 1160128967Srik opte1->currnt.crce = c->currnt.crce; 1161128967Srik opte1->currnt.rcrce = c->currnt.rcrce; 1162128967Srik opte1->currnt.uas = c->currnt.uas; 1163128967Srik opte1->currnt.les = c->currnt.les; 1164128967Srik opte1->currnt.es = c->currnt.es; 1165128967Srik opte1->currnt.bes = c->currnt.bes; 1166128967Srik opte1->currnt.ses = c->currnt.ses; 1167128967Srik opte1->currnt.oofs = c->currnt.oofs; 1168128967Srik opte1->currnt.css = c->currnt.css; 1169128967Srik opte1->currnt.dm = c->currnt.dm; 1170128967Srik 1171128967Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1172128967Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1173128967Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1174128967Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1175128967Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1176128967Srik opte1->total.les = c->total.les + c->currnt.les; 1177128967Srik opte1->total.es = c->total.es + c->currnt.es; 1178128967Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1179128967Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1180128967Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1181128967Srik opte1->total.css = c->total.css + c->currnt.css; 1182128967Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1183128967Srik for (s=0; s<48; ++s) { 1184128967Srik opte1->interval[s].bpv = c->interval[s].bpv; 1185128967Srik opte1->interval[s].fse = c->interval[s].fse; 1186128967Srik opte1->interval[s].crce = c->interval[s].crce; 1187128967Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1188128967Srik opte1->interval[s].uas = c->interval[s].uas; 1189128967Srik opte1->interval[s].les = c->interval[s].les; 1190128967Srik opte1->interval[s].es = c->interval[s].es; 1191128967Srik opte1->interval[s].bes = c->interval[s].bes; 1192128967Srik opte1->interval[s].ses = c->interval[s].ses; 1193128967Srik opte1->interval[s].oofs = c->interval[s].oofs; 1194128967Srik opte1->interval[s].css = c->interval[s].css; 1195128967Srik opte1->interval[s].dm = c->interval[s].dm; 1196128967Srik } 1197128967Srik return 0; 1198128967Srik 1199128967Srik case SERIAL_GETE3STAT: 1200128967Srik CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 1201128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1202128967Srik return EINVAL; 1203128967Srik opte3 = (struct e3_statistics*) data; 1204128967Srik 1205128967Srik opte3->status = c->e3status; 1206128967Srik opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 1207128967Srik opte3->totsec = c->e3tsec + opte3->cursec; 1208128967Srik 1209128967Srik opte3->ccv = c->e3ccv; 1210128967Srik opte3->tcv = c->e3tcv + opte3->ccv; 1211128967Srik 1212128967Srik for (s = 0; s < 48; ++s) { 1213128967Srik opte3->icv[s] = c->e3icv[s]; 1214128967Srik } 1215128967Srik return 0; 1216128967Srik 1217128967Srik case SERIAL_CLRSTAT: 1218128967Srik CP_DEBUG2 (d, ("ioctl: clrstat\n")); 1219128967Srik /* Only for superuser! */ 1220130971Srik#if __FreeBSD_version < 500000 1221128967Srik error = suser (p); 1222128967Srik#else 1223128967Srik error = suser (td); 1224128967Srik#endif 1225128967Srik if (error) 1226128967Srik return error; 1227128967Srik c->rintr = 0; 1228128967Srik c->tintr = 0; 1229128967Srik c->ibytes = 0; 1230128967Srik c->obytes = 0; 1231128967Srik c->ipkts = 0; 1232128967Srik c->opkts = 0; 1233128967Srik c->overrun = 0; 1234128967Srik c->frame = 0; 1235128967Srik c->crc = 0; 1236128967Srik c->underrun = 0; 1237128967Srik bzero (&c->currnt, sizeof (c->currnt)); 1238128967Srik bzero (&c->total, sizeof (c->total)); 1239128967Srik bzero (c->interval, sizeof (c->interval)); 1240128967Srik c->e3ccv = 0; 1241128967Srik c->e3tcv = 0; 1242128967Srik bzero (c->e3icv, sizeof (c->e3icv)); 1243128967Srik return 0; 1244128967Srik 1245128967Srik case SERIAL_GETBAUD: 1246128967Srik CP_DEBUG2 (d, ("ioctl: getbaud\n")); 1247128967Srik *(long*)data = c->baud; 1248128967Srik return 0; 1249128967Srik 1250128967Srik case SERIAL_SETBAUD: 1251128967Srik CP_DEBUG2 (d, ("ioctl: setbaud\n")); 1252128967Srik /* Only for superuser! */ 1253130971Srik#if __FreeBSD_version < 500000 1254128967Srik error = suser (p); 1255128967Srik#else 1256128967Srik error = suser (td); 1257128967Srik#endif 1258128967Srik if (error) 1259128967Srik return error; 1260128967Srik s = splimp (); 1261128967Srik cp_set_baud (c, *(long*)data); 1262128967Srik splx (s); 1263128967Srik return 0; 1264128967Srik 1265128967Srik case SERIAL_GETLOOP: 1266128967Srik CP_DEBUG2 (d, ("ioctl: getloop\n")); 1267128967Srik *(int*)data = c->lloop; 1268128967Srik return 0; 1269128967Srik 1270128967Srik case SERIAL_SETLOOP: 1271128967Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1272128967Srik /* Only for superuser! */ 1273130971Srik#if __FreeBSD_version < 500000 1274128967Srik error = suser (p); 1275128967Srik#else 1276128967Srik error = suser (td); 1277128967Srik#endif 1278128967Srik if (error) 1279128967Srik return error; 1280128967Srik s = splimp (); 1281128967Srik cp_set_lloop (c, *(int*)data); 1282128967Srik splx (s); 1283128967Srik return 0; 1284128967Srik 1285128967Srik case SERIAL_GETDPLL: 1286128967Srik CP_DEBUG2 (d, ("ioctl: getdpll\n")); 1287128967Srik if (c->type != T_SERIAL) 1288128967Srik return EINVAL; 1289128967Srik *(int*)data = c->dpll; 1290128967Srik return 0; 1291128967Srik 1292128967Srik case SERIAL_SETDPLL: 1293128967Srik CP_DEBUG2 (d, ("ioctl: setdpll\n")); 1294128967Srik /* Only for superuser! */ 1295130971Srik#if __FreeBSD_version < 500000 1296128967Srik error = suser (p); 1297128967Srik#else 1298128967Srik error = suser (td); 1299128967Srik#endif 1300128967Srik if (error) 1301128967Srik return error; 1302128967Srik if (c->type != T_SERIAL) 1303128967Srik return EINVAL; 1304128967Srik s = splimp (); 1305128967Srik cp_set_dpll (c, *(int*)data); 1306128967Srik splx (s); 1307128967Srik return 0; 1308128967Srik 1309128967Srik case SERIAL_GETNRZI: 1310128967Srik CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 1311128967Srik if (c->type != T_SERIAL) 1312128967Srik return EINVAL; 1313128967Srik *(int*)data = c->nrzi; 1314128967Srik return 0; 1315128967Srik 1316128967Srik case SERIAL_SETNRZI: 1317128967Srik CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 1318128967Srik /* Only for superuser! */ 1319130971Srik#if __FreeBSD_version < 500000 1320128967Srik error = suser (p); 1321128967Srik#else 1322128967Srik error = suser (td); 1323128967Srik#endif 1324128967Srik if (error) 1325128967Srik return error; 1326128967Srik if (c->type != T_SERIAL) 1327128967Srik return EINVAL; 1328128967Srik s = splimp (); 1329128967Srik cp_set_nrzi (c, *(int*)data); 1330128967Srik splx (s); 1331128967Srik return 0; 1332128967Srik 1333128967Srik case SERIAL_GETDEBUG: 1334128967Srik CP_DEBUG2 (d, ("ioctl: getdebug\n")); 1335128967Srik *(int*)data = d->chan->debug; 1336128967Srik return 0; 1337128967Srik 1338128967Srik case SERIAL_SETDEBUG: 1339128967Srik CP_DEBUG2 (d, ("ioctl: setdebug\n")); 1340128967Srik /* Only for superuser! */ 1341130971Srik#if __FreeBSD_version < 500000 1342128967Srik error = suser (p); 1343128967Srik#else 1344128967Srik error = suser (td); 1345128967Srik#endif 1346128967Srik if (error) 1347128967Srik return error; 1348128967Srik d->chan->debug = *(int*)data; 1349128967Srik#ifndef NETGRAPH 1350128967Srik if (d->chan->debug) 1351128967Srik d->pp.pp_if.if_flags |= IFF_DEBUG; 1352128967Srik else 1353128967Srik d->pp.pp_if.if_flags &= ~IFF_DEBUG; 1354128967Srik#endif 1355128967Srik return 0; 1356128967Srik 1357128967Srik case SERIAL_GETHIGAIN: 1358128967Srik CP_DEBUG2 (d, ("ioctl: gethigain\n")); 1359128967Srik if (c->type != T_E1) 1360128967Srik return EINVAL; 1361128967Srik *(int*)data = c->higain; 1362128967Srik return 0; 1363128967Srik 1364128967Srik case SERIAL_SETHIGAIN: 1365128967Srik CP_DEBUG2 (d, ("ioctl: sethigain\n")); 1366128967Srik /* Only for superuser! */ 1367130971Srik#if __FreeBSD_version < 500000 1368128967Srik error = suser (p); 1369128967Srik#else 1370128967Srik error = suser (td); 1371128967Srik#endif 1372128967Srik if (error) 1373128967Srik return error; 1374128967Srik if (c->type != T_E1) 1375128967Srik return EINVAL; 1376128967Srik s = splimp (); 1377128967Srik cp_set_higain (c, *(int*)data); 1378128967Srik splx (s); 1379128967Srik return 0; 1380128967Srik 1381128967Srik case SERIAL_GETPHONY: 1382128967Srik CP_DEBUG2 (d, ("ioctl: getphony\n")); 1383128967Srik if (c->type != T_E1) 1384128967Srik return EINVAL; 1385128967Srik *(int*)data = c->phony; 1386128967Srik return 0; 1387128967Srik 1388128967Srik case SERIAL_SETPHONY: 1389128967Srik CP_DEBUG2 (d, ("ioctl: setphony\n")); 1390128967Srik /* Only for superuser! */ 1391130971Srik#if __FreeBSD_version < 500000 1392128967Srik error = suser (p); 1393128967Srik#else 1394128967Srik error = suser (td); 1395128967Srik#endif 1396128967Srik if (error) 1397128967Srik return error; 1398128967Srik if (c->type != T_E1) 1399128967Srik return EINVAL; 1400128967Srik s = splimp (); 1401128967Srik cp_set_phony (c, *(int*)data); 1402128967Srik splx (s); 1403128967Srik return 0; 1404128967Srik 1405128967Srik case SERIAL_GETUNFRAM: 1406128967Srik CP_DEBUG2 (d, ("ioctl: getunfram\n")); 1407128967Srik if (c->type != T_E1) 1408128967Srik return EINVAL; 1409128967Srik *(int*)data = c->unfram; 1410128967Srik return 0; 1411128967Srik 1412128967Srik case SERIAL_SETUNFRAM: 1413128967Srik CP_DEBUG2 (d, ("ioctl: setunfram\n")); 1414128967Srik /* Only for superuser! */ 1415130971Srik#if __FreeBSD_version < 500000 1416128967Srik error = suser (p); 1417128967Srik#else 1418128967Srik error = suser (td); 1419128967Srik#endif 1420128967Srik if (error) 1421128967Srik return error; 1422128967Srik if (c->type != T_E1) 1423128967Srik return EINVAL; 1424128967Srik s = splimp (); 1425128967Srik cp_set_unfram (c, *(int*)data); 1426128967Srik splx (s); 1427128967Srik return 0; 1428128967Srik 1429128967Srik case SERIAL_GETSCRAMBLER: 1430128967Srik CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 1431128967Srik if (c->type != T_G703 && !c->unfram) 1432128967Srik return EINVAL; 1433128967Srik *(int*)data = c->scrambler; 1434128967Srik return 0; 1435128967Srik 1436128967Srik case SERIAL_SETSCRAMBLER: 1437128967Srik CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 1438128967Srik /* Only for superuser! */ 1439130971Srik#if __FreeBSD_version < 500000 1440128967Srik error = suser (p); 1441128967Srik#else 1442128967Srik error = suser (td); 1443128967Srik#endif 1444128967Srik if (error) 1445128967Srik return error; 1446128967Srik if (c->type != T_G703 && !c->unfram) 1447128967Srik return EINVAL; 1448128967Srik s = splimp (); 1449128967Srik cp_set_scrambler (c, *(int*)data); 1450128967Srik splx (s); 1451128967Srik return 0; 1452128967Srik 1453128967Srik case SERIAL_GETMONITOR: 1454128967Srik CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 1455128967Srik if (c->type != T_E1 && 1456128967Srik c->type != T_E3 && 1457128967Srik c->type != T_T3 && 1458128967Srik c->type != T_STS1) 1459128967Srik return EINVAL; 1460128967Srik *(int*)data = c->monitor; 1461128967Srik return 0; 1462128967Srik 1463128967Srik case SERIAL_SETMONITOR: 1464128967Srik CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 1465128967Srik /* Only for superuser! */ 1466130971Srik#if __FreeBSD_version < 500000 1467128967Srik error = suser (p); 1468128967Srik#else 1469128967Srik error = suser (td); 1470128967Srik#endif 1471128967Srik if (error) 1472128967Srik return error; 1473128967Srik if (c->type != T_E1) 1474128967Srik return EINVAL; 1475128967Srik s = splimp (); 1476128967Srik cp_set_monitor (c, *(int*)data); 1477128967Srik splx (s); 1478128967Srik return 0; 1479128967Srik 1480128967Srik case SERIAL_GETUSE16: 1481128967Srik CP_DEBUG2 (d, ("ioctl: getuse16\n")); 1482128967Srik if (c->type != T_E1 || c->unfram) 1483128967Srik return EINVAL; 1484128967Srik *(int*)data = c->use16; 1485128967Srik return 0; 1486128967Srik 1487128967Srik case SERIAL_SETUSE16: 1488128967Srik CP_DEBUG2 (d, ("ioctl: setuse16\n")); 1489128967Srik /* Only for superuser! */ 1490130971Srik#if __FreeBSD_version < 500000 1491128967Srik error = suser (p); 1492128967Srik#else 1493128967Srik error = suser (td); 1494128967Srik#endif 1495128967Srik if (error) 1496128967Srik return error; 1497128967Srik if (c->type != T_E1) 1498128967Srik return EINVAL; 1499128967Srik s = splimp (); 1500128967Srik cp_set_use16 (c, *(int*)data); 1501128967Srik splx (s); 1502128967Srik return 0; 1503128967Srik 1504128967Srik case SERIAL_GETCRC4: 1505128967Srik CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 1506128967Srik if (c->type != T_E1 || c->unfram) 1507128967Srik return EINVAL; 1508128967Srik *(int*)data = c->crc4; 1509128967Srik return 0; 1510128967Srik 1511128967Srik case SERIAL_SETCRC4: 1512128967Srik CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 1513128967Srik /* Only for superuser! */ 1514130971Srik#if __FreeBSD_version < 500000 1515128967Srik error = suser (p); 1516128967Srik#else 1517128967Srik error = suser (td); 1518128967Srik#endif 1519128967Srik if (error) 1520128967Srik return error; 1521128967Srik if (c->type != T_E1) 1522128967Srik return EINVAL; 1523128967Srik s = splimp (); 1524128967Srik cp_set_crc4 (c, *(int*)data); 1525128967Srik splx (s); 1526128967Srik return 0; 1527128967Srik 1528128967Srik case SERIAL_GETCLK: 1529128967Srik CP_DEBUG2 (d, ("ioctl: getclk\n")); 1530128967Srik if (c->type != T_E1 && 1531128967Srik c->type != T_G703 && 1532128967Srik c->type != T_E3 && 1533128967Srik c->type != T_T3 && 1534128967Srik c->type != T_STS1) 1535128967Srik return EINVAL; 1536128967Srik switch (c->gsyn) { 1537128967Srik default: *(int*)data = E1CLK_INTERNAL; break; 1538128967Srik case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1539128967Srik case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1540128967Srik case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1541128967Srik case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 1542128967Srik case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 1543128967Srik } 1544128967Srik return 0; 1545128967Srik 1546128967Srik case SERIAL_SETCLK: 1547128967Srik CP_DEBUG2 (d, ("ioctl: setclk\n")); 1548128967Srik /* Only for superuser! */ 1549130971Srik#if __FreeBSD_version < 500000 1550128967Srik error = suser (p); 1551128967Srik#else 1552128967Srik error = suser (td); 1553128967Srik#endif 1554128967Srik if (error) 1555128967Srik return error; 1556128967Srik if (c->type != T_E1 && 1557128967Srik c->type != T_G703 && 1558128967Srik c->type != T_E3 && 1559128967Srik c->type != T_T3 && 1560128967Srik c->type != T_STS1) 1561128967Srik return EINVAL; 1562128967Srik s = splimp (); 1563128967Srik switch (*(int*)data) { 1564128967Srik default: cp_set_gsyn (c, GSYN_INT); break; 1565128967Srik case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 1566128967Srik case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 1567128967Srik case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 1568128967Srik case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 1569128967Srik case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 1570128967Srik } 1571128967Srik splx (s); 1572128967Srik return 0; 1573128967Srik 1574128967Srik case SERIAL_GETTIMESLOTS: 1575128967Srik CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1576128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1577128967Srik return EINVAL; 1578128967Srik *(u_long*)data = c->ts; 1579128967Srik return 0; 1580128967Srik 1581128967Srik case SERIAL_SETTIMESLOTS: 1582128967Srik CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 1583128967Srik /* Only for superuser! */ 1584130971Srik#if __FreeBSD_version < 500000 1585128967Srik error = suser (p); 1586128967Srik#else 1587128967Srik error = suser (td); 1588128967Srik#endif 1589128967Srik if (error) 1590128967Srik return error; 1591128967Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1592128967Srik return EINVAL; 1593128967Srik s = splimp (); 1594128967Srik cp_set_ts (c, *(u_long*)data); 1595128967Srik splx (s); 1596128967Srik return 0; 1597128967Srik 1598128967Srik case SERIAL_GETINVCLK: 1599128967Srik CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 1600128967Srik#if 1 1601128967Srik return EINVAL; 1602128967Srik#else 1603128967Srik if (c->type != T_SERIAL) 1604128967Srik return EINVAL; 1605128967Srik *(int*)data = c->invtxc; 1606128967Srik return 0; 1607128967Srik#endif 1608128967Srik 1609128967Srik case SERIAL_SETINVCLK: 1610128967Srik CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 1611128967Srik /* Only for superuser! */ 1612130971Srik#if __FreeBSD_version < 500000 1613128967Srik error = suser (p); 1614128967Srik#else 1615128967Srik error = suser (td); 1616128967Srik#endif 1617128967Srik if (error) 1618128967Srik return error; 1619128967Srik if (c->type != T_SERIAL) 1620128967Srik return EINVAL; 1621128967Srik s = splimp (); 1622128967Srik cp_set_invtxc (c, *(int*)data); 1623128967Srik cp_set_invrxc (c, *(int*)data); 1624128967Srik splx (s); 1625128967Srik return 0; 1626128967Srik 1627128967Srik case SERIAL_GETINVTCLK: 1628128967Srik CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 1629128967Srik if (c->type != T_SERIAL) 1630128967Srik return EINVAL; 1631128967Srik *(int*)data = c->invtxc; 1632128967Srik return 0; 1633128967Srik 1634128967Srik case SERIAL_SETINVTCLK: 1635128967Srik CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 1636128967Srik /* Only for superuser! */ 1637130971Srik#if __FreeBSD_version < 500000 1638128967Srik error = suser (p); 1639128967Srik#else 1640128967Srik error = suser (td); 1641128967Srik#endif 1642128967Srik if (error) 1643128967Srik return error; 1644128967Srik if (c->type != T_SERIAL) 1645128967Srik return EINVAL; 1646128967Srik s = splimp (); 1647128967Srik cp_set_invtxc (c, *(int*)data); 1648128967Srik splx (s); 1649128967Srik return 0; 1650128967Srik 1651128967Srik case SERIAL_GETINVRCLK: 1652128967Srik CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 1653128967Srik if (c->type != T_SERIAL) 1654128967Srik return EINVAL; 1655128967Srik *(int*)data = c->invrxc; 1656128967Srik return 0; 1657128967Srik 1658128967Srik case SERIAL_SETINVRCLK: 1659128967Srik CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 1660128967Srik /* Only for superuser! */ 1661130971Srik#if __FreeBSD_version < 500000 1662128967Srik error = suser (p); 1663128967Srik#else 1664128967Srik error = suser (td); 1665128967Srik#endif 1666128967Srik if (error) 1667128967Srik return error; 1668128967Srik if (c->type != T_SERIAL) 1669128967Srik return EINVAL; 1670128967Srik s = splimp (); 1671128967Srik cp_set_invrxc (c, *(int*)data); 1672128967Srik splx (s); 1673128967Srik return 0; 1674128967Srik 1675128967Srik case SERIAL_GETLEVEL: 1676128967Srik CP_DEBUG2 (d, ("ioctl: getlevel\n")); 1677128967Srik if (c->type != T_G703) 1678128967Srik return EINVAL; 1679128967Srik s = splimp (); 1680128967Srik *(int*)data = cp_get_lq (c); 1681128967Srik splx (s); 1682128967Srik return 0; 1683128967Srik 1684128967Srik#if 0 1685128967Srik case SERIAL_RESET: 1686128967Srik CP_DEBUG2 (d, ("ioctl: reset\n")); 1687128967Srik /* Only for superuser! */ 1688130971Srik#if __FreeBSD_version < 500000 1689128967Srik error = suser (p); 1690128967Srik#else 1691128967Srik error = suser (td); 1692128967Srik#endif 1693128967Srik if (error) 1694128967Srik return error; 1695128967Srik s = splimp (); 1696128967Srik cp_reset (c->board, 0, 0); 1697128967Srik splx (s); 1698128967Srik return 0; 1699128967Srik 1700128967Srik case SERIAL_HARDRESET: 1701128967Srik CP_DEBUG2 (d, ("ioctl: hardreset\n")); 1702128967Srik /* Only for superuser! */ 1703130971Srik#if __FreeBSD_version < 500000 1704128967Srik error = suser (p); 1705128967Srik#else 1706128967Srik error = suser (td); 1707128967Srik#endif 1708128967Srik if (error) 1709128967Srik return error; 1710128967Srik s = splimp (); 1711128967Srik /* hard_reset (c->board); */ 1712128967Srik splx (s); 1713128967Srik return 0; 1714128967Srik#endif 1715128967Srik 1716128967Srik case SERIAL_GETCABLE: 1717128967Srik CP_DEBUG2 (d, ("ioctl: getcable\n")); 1718128967Srik if (c->type != T_SERIAL) 1719128967Srik return EINVAL; 1720128967Srik s = splimp (); 1721128967Srik *(int*)data = cp_get_cable (c); 1722128967Srik splx (s); 1723128967Srik return 0; 1724128967Srik 1725128967Srik case SERIAL_GETDIR: 1726128967Srik CP_DEBUG2 (d, ("ioctl: getdir\n")); 1727128967Srik if (c->type != T_E1 && c->type != T_DATA) 1728128967Srik return EINVAL; 1729128967Srik *(int*)data = c->dir; 1730128967Srik return 0; 1731128967Srik 1732128967Srik case SERIAL_SETDIR: 1733128967Srik CP_DEBUG2 (d, ("ioctl: setdir\n")); 1734128967Srik /* Only for superuser! */ 1735130971Srik#if __FreeBSD_version < 500000 1736128967Srik error = suser (p); 1737128967Srik#else 1738128967Srik error = suser (td); 1739128967Srik#endif 1740128967Srik if (error) 1741128967Srik return error; 1742128967Srik s = splimp (); 1743128967Srik cp_set_dir (c, *(int*)data); 1744128967Srik splx (s); 1745128967Srik return 0; 1746128967Srik 1747128967Srik case SERIAL_GETRLOOP: 1748128967Srik CP_DEBUG2 (d, ("ioctl: getrloop\n")); 1749128967Srik if (c->type != T_G703 && 1750128967Srik c->type != T_E3 && 1751128967Srik c->type != T_T3 && 1752128967Srik c->type != T_STS1) 1753128967Srik return EINVAL; 1754128967Srik *(int*)data = cp_get_rloop (c); 1755128967Srik return 0; 1756128967Srik 1757128967Srik case SERIAL_SETRLOOP: 1758128967Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1759128967Srik if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1760128967Srik return EINVAL; 1761128967Srik /* Only for superuser! */ 1762130971Srik#if __FreeBSD_version < 500000 1763128967Srik error = suser (p); 1764128967Srik#else 1765128967Srik error = suser (td); 1766128967Srik#endif 1767128967Srik if (error) 1768128967Srik return error; 1769128967Srik s = splimp (); 1770128967Srik cp_set_rloop (c, *(int*)data); 1771128967Srik splx (s); 1772128967Srik return 0; 1773128967Srik 1774128967Srik case SERIAL_GETCABLEN: 1775128967Srik CP_DEBUG2 (d, ("ioctl: getcablen\n")); 1776128967Srik if (c->type != T_T3 && c->type != T_STS1) 1777128967Srik return EINVAL; 1778128967Srik *(int*)data = c->cablen; 1779128967Srik return 0; 1780128967Srik 1781128967Srik case SERIAL_SETCABLEN: 1782128967Srik CP_DEBUG2 (d, ("ioctl: setloop\n")); 1783128967Srik if (c->type != T_T3 && c->type != T_STS1) 1784128967Srik return EINVAL; 1785128967Srik /* Only for superuser! */ 1786130971Srik#if __FreeBSD_version < 500000 1787128967Srik error = suser (p); 1788128967Srik#else 1789128967Srik error = suser (td); 1790128967Srik#endif 1791128967Srik if (error) 1792128967Srik return error; 1793128967Srik s = splimp (); 1794128967Srik cp_set_cablen (c, *(int*)data); 1795128967Srik splx (s); 1796128967Srik return 0; 1797128967Srik 1798128967Srik case TIOCSDTR: /* Set DTR */ 1799128967Srik s = splimp (); 1800128967Srik cp_set_dtr (c, 1); 1801128967Srik splx (s); 1802128967Srik return 0; 1803128967Srik 1804128967Srik case TIOCCDTR: /* Clear DTR */ 1805128967Srik s = splimp (); 1806128967Srik cp_set_dtr (c, 0); 1807128967Srik splx (s); 1808128967Srik return 0; 1809128967Srik 1810128967Srik case TIOCMSET: /* Set DTR/RTS */ 1811128967Srik s = splimp (); 1812128967Srik cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1813128967Srik cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1814128967Srik splx (s); 1815128967Srik return 0; 1816128967Srik 1817128967Srik case TIOCMBIS: /* Add DTR/RTS */ 1818128967Srik s = splimp (); 1819128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 1820128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 1821128967Srik splx (s); 1822128967Srik return 0; 1823128967Srik 1824128967Srik case TIOCMBIC: /* Clear DTR/RTS */ 1825128967Srik s = splimp (); 1826128967Srik if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1827128967Srik if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1828128967Srik splx (s); 1829128967Srik return 0; 1830128967Srik 1831128967Srik case TIOCMGET: /* Get modem status */ 1832128967Srik *(int*)data = cp_modem_status (c); 1833128967Srik return 0; 1834128967Srik } 1835128967Srik return ENOTTY; 1836128967Srik} 1837128967Srik 1838130971Srik#if __FreeBSD_version < 500000 1839128967Srikstatic struct cdevsw cp_cdevsw = { 1840128967Srik cp_open, cp_close, noread, nowrite, 1841128967Srik cp_ioctl, nopoll, nommap, nostrategy, 1842128967Srik "cp", CDEV_MAJOR, nodump, nopsize, 1843128967Srik D_NAGGED, -1 1844128967Srik }; 1845128967Srik#elif __FreeBSD_version == 500000 1846128967Srikstatic struct cdevsw cp_cdevsw = { 1847128967Srik cp_open, cp_close, noread, nowrite, 1848128967Srik cp_ioctl, nopoll, nommap, nostrategy, 1849128967Srik "cp", CDEV_MAJOR, nodump, nopsize, 1850128967Srik D_NAGGED, 1851128967Srik }; 1852128967Srik#elif __FreeBSD_version <= 501000 1853128967Srikstatic struct cdevsw cp_cdevsw = { 1854128967Srik .d_open = cp_open, 1855128967Srik .d_close = cp_close, 1856128967Srik .d_read = noread, 1857128967Srik .d_write = nowrite, 1858128967Srik .d_ioctl = cp_ioctl, 1859128967Srik .d_poll = nopoll, 1860128967Srik .d_mmap = nommap, 1861128967Srik .d_strategy = nostrategy, 1862128967Srik .d_name = "cp", 1863128967Srik .d_maj = CDEV_MAJOR, 1864128967Srik .d_dump = nodump, 1865128967Srik .d_flags = D_NAGGED, 1866128967Srik}; 1867128967Srik#elif __FreeBSD_version < 502103 1868128967Srikstatic struct cdevsw cp_cdevsw = { 1869128967Srik .d_open = cp_open, 1870128967Srik .d_close = cp_close, 1871128967Srik .d_ioctl = cp_ioctl, 1872128967Srik .d_name = "cp", 1873128967Srik .d_maj = CDEV_MAJOR, 1874128967Srik .d_flags = D_NAGGED, 1875128967Srik}; 1876128967Srik#else /* __FreeBSD_version >= 502103 */ 1877128967Srikstatic struct cdevsw cp_cdevsw = { 1878128967Srik .d_version = D_VERSION, 1879128967Srik .d_open = cp_open, 1880128967Srik .d_close = cp_close, 1881128967Srik .d_ioctl = cp_ioctl, 1882128967Srik .d_name = "cp", 1883128967Srik .d_maj = CDEV_MAJOR, 1884128967Srik .d_flags = D_NEEDGIANT, 1885128967Srik}; 1886128967Srik#endif 1887128967Srik 1888128967Srik#ifdef NETGRAPH 1889128967Srik#if __FreeBSD_version >= 500000 1890128967Srikstatic int ng_cp_constructor (node_p node) 1891128967Srik{ 1892128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1893128967Srik#else 1894128967Srikstatic int ng_cp_constructor (node_p *node) 1895128967Srik{ 1896128967Srik drv_t *d = (*node)->private; 1897128967Srik#endif 1898128967Srik CP_DEBUG (d, ("Constructor\n")); 1899128967Srik return EINVAL; 1900128967Srik} 1901128967Srik 1902128967Srikstatic int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1903128967Srik{ 1904128967Srik int s; 1905128967Srik#if __FreeBSD_version >= 500000 1906128967Srik drv_t *d = NG_NODE_PRIVATE (node); 1907128967Srik#else 1908128967Srik drv_t *d = node->private; 1909128967Srik#endif 1910128967Srik 1911128967Srik CP_DEBUG (d, ("Newhook\n")); 1912128967Srik /* Attach debug hook */ 1913128967Srik if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1914128967Srik#if __FreeBSD_version >= 500000 1915128967Srik NG_HOOK_SET_PRIVATE (hook, NULL); 1916128967Srik#else 1917128967Srik hook->private = 0; 1918128967Srik#endif 1919128967Srik d->debug_hook = hook; 1920128967Srik return 0; 1921128967Srik } 1922128967Srik 1923128967Srik /* Check for raw hook */ 1924128967Srik if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1925128967Srik return EINVAL; 1926128967Srik 1927128967Srik#if __FreeBSD_version >= 500000 1928128967Srik NG_HOOK_SET_PRIVATE (hook, d); 1929128967Srik#else 1930128967Srik hook->private = d; 1931128967Srik#endif 1932128967Srik d->hook = hook; 1933128967Srik s = splimp (); 1934128967Srik cp_up (d); 1935128967Srik splx (s); 1936128967Srik return 0; 1937128967Srik} 1938128967Srik 1939128967Srikstatic char *format_timeslots (u_long s) 1940128967Srik{ 1941128967Srik static char buf [100]; 1942128967Srik char *p = buf; 1943128967Srik int i; 1944128967Srik 1945128967Srik for (i=1; i<32; ++i) 1946128967Srik if ((s >> i) & 1) { 1947128967Srik int prev = (i > 1) & (s >> (i-1)); 1948128967Srik int next = (i < 31) & (s >> (i+1)); 1949128967Srik 1950128967Srik if (prev) { 1951128967Srik if (next) 1952128967Srik continue; 1953128967Srik *p++ = '-'; 1954128967Srik } else if (p > buf) 1955128967Srik *p++ = ','; 1956128967Srik 1957128967Srik if (i >= 10) 1958128967Srik *p++ = '0' + i / 10; 1959128967Srik *p++ = '0' + i % 10; 1960128967Srik } 1961128967Srik *p = 0; 1962128967Srik return buf; 1963128967Srik} 1964128967Srik 1965128967Srikstatic int print_modems (char *s, cp_chan_t *c, int need_header) 1966128967Srik{ 1967128967Srik int status = cp_modem_status (c); 1968128967Srik int length = 0; 1969128967Srik 1970128967Srik if (need_header) 1971128967Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1972128967Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1973128967Srik status & TIOCM_LE ? "On" : "-", 1974128967Srik status & TIOCM_DTR ? "On" : "-", 1975128967Srik status & TIOCM_DSR ? "On" : "-", 1976128967Srik status & TIOCM_RTS ? "On" : "-", 1977128967Srik status & TIOCM_CTS ? "On" : "-", 1978128967Srik status & TIOCM_CD ? "On" : "-"); 1979128967Srik return length; 1980128967Srik} 1981128967Srik 1982128967Srikstatic int print_stats (char *s, cp_chan_t *c, int need_header) 1983128967Srik{ 1984128967Srik int length = 0; 1985128967Srik 1986128967Srik if (need_header) 1987128967Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1988128967Srik length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1989128967Srik c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1990128967Srik c->ipkts, c->overrun + c->frame + c->crc, 1991128967Srik (unsigned long) c->obytes, c->opkts, c->underrun); 1992128967Srik return length; 1993128967Srik} 1994128967Srik 1995128967Srikstatic char *format_e1_status (u_char status) 1996128967Srik{ 1997128967Srik static char buf [80]; 1998128967Srik 1999128967Srik if (status & E1_NOALARM) 2000128967Srik return "Ok"; 2001128967Srik buf[0] = 0; 2002128967Srik if (status & E1_LOS) strcat (buf, ",LOS"); 2003128967Srik if (status & E1_AIS) strcat (buf, ",AIS"); 2004128967Srik if (status & E1_LOF) strcat (buf, ",LOF"); 2005128967Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 2006128967Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 2007128967Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 2008128967Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 2009128967Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 2010128967Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 2011128967Srik if (buf[0] == ',') 2012128967Srik return buf+1; 2013128967Srik return "Unknown"; 2014128967Srik} 2015128967Srik 2016128967Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 2017128967Srik{ 2018128967Srik int n, length = 0; 2019128967Srik 2020128967Srik if (numerator < 1 || divider < 1) { 2021128967Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 2022128967Srik return length; 2023128967Srik } 2024128967Srik n = (int) (0.5 + 1000.0 * numerator / divider); 2025128967Srik if (n < 1000) { 2026128967Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 2027128967Srik return length; 2028128967Srik } 2029128967Srik *(s + length) = leftalign ? '/' : ' '; 2030128967Srik length ++; 2031128967Srik 2032128967Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 2033128967Srik else if (n >= 100000) n = (n+50) / 100 * 100; 2034128967Srik else if (n >= 10000) n = (n+5) / 10 * 10; 2035128967Srik 2036128967Srik switch (n) { 2037128967Srik case 1000: length += printf (s+length, ".999"); return length; 2038128967Srik case 10000: n = 9990; break; 2039128967Srik case 100000: n = 99900; break; 2040128967Srik case 1000000: n = 999000; break; 2041128967Srik } 2042128967Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 2043128967Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 2044128967Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 2045128967Srik else length += sprintf (s+length, "%d", n/1000); 2046128967Srik 2047128967Srik return length; 2048128967Srik} 2049128967Srik 2050128967Srikstatic int print_e1_stats (char *s, cp_chan_t *c) 2051128967Srik{ 2052128967Srik struct e1_counters total; 2053128967Srik u_long totsec; 2054128967Srik int length = 0; 2055128967Srik 2056128967Srik totsec = c->totsec + c->cursec; 2057128967Srik total.bpv = c->total.bpv + c->currnt.bpv; 2058128967Srik total.fse = c->total.fse + c->currnt.fse; 2059128967Srik total.crce = c->total.crce + c->currnt.crce; 2060128967Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 2061128967Srik total.uas = c->total.uas + c->currnt.uas; 2062128967Srik total.les = c->total.les + c->currnt.les; 2063128967Srik total.es = c->total.es + c->currnt.es; 2064128967Srik total.bes = c->total.bes + c->currnt.bes; 2065128967Srik total.ses = c->total.ses + c->currnt.ses; 2066128967Srik total.oofs = c->total.oofs + c->currnt.oofs; 2067128967Srik total.css = c->total.css + c->currnt.css; 2068128967Srik total.dm = c->total.dm + c->currnt.dm; 2069128967Srik 2070128967Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 2071128967Srik 2072128967Srik /* Unavailable seconds, degraded minutes */ 2073128967Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 2074128967Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 2075128967Srik 2076128967Srik /* Bipolar violations, frame sync errors */ 2077128967Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 2078128967Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 2079128967Srik 2080128967Srik /* CRC errors, remote CRC errors (E-bit) */ 2081128967Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 2082128967Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 2083128967Srik 2084128967Srik /* Errored seconds, line errored seconds */ 2085128967Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 2086128967Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 2087128967Srik 2088128967Srik /* Severely errored seconds, burst errored seconds */ 2089128967Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 2090128967Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 2091128967Srik 2092128967Srik /* Out of frame seconds, controlled slip seconds */ 2093128967Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 2094128967Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 2095128967Srik 2096128967Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 2097128967Srik 2098128967Srik /* Print total statistics. */ 2099128967Srik length += print_frac (s + length, 0, total.uas, totsec); 2100128967Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 2101128967Srik 2102128967Srik length += print_frac (s + length, 0, total.bpv, totsec); 2103128967Srik length += print_frac (s + length, 1, total.fse, totsec); 2104128967Srik 2105128967Srik length += print_frac (s + length, 0, total.crce, totsec); 2106128967Srik length += print_frac (s + length, 1, total.rcrce, totsec); 2107128967Srik 2108128967Srik length += print_frac (s + length, 0, total.es, totsec); 2109128967Srik length += print_frac (s + length, 1, total.les, totsec); 2110128967Srik 2111128967Srik length += print_frac (s + length, 0, total.ses, totsec); 2112128967Srik length += print_frac (s + length, 1, total.bes, totsec); 2113128967Srik 2114128967Srik length += print_frac (s + length, 0, total.oofs, totsec); 2115128967Srik length += print_frac (s + length, 1, total.css, totsec); 2116128967Srik 2117128967Srik length += sprintf (s + length, " -- Total\n"); 2118128967Srik return length; 2119128967Srik} 2120128967Srik 2121128967Srikstatic int print_chan (char *s, cp_chan_t *c) 2122128967Srik{ 2123128967Srik drv_t *d = c->sys; 2124128967Srik int length = 0; 2125128967Srik 2126128967Srik length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2127128967Srik if (d->chan->debug) 2128128967Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 2129128967Srik 2130128967Srik if (c->board->mux) { 2131128967Srik length += sprintf (s + length, " cfg=C"); 2132128967Srik } else { 2133128967Srik length += sprintf (s + length, " cfg=A"); 2134128967Srik } 2135128967Srik 2136128967Srik if (c->baud) 2137128967Srik length += sprintf (s + length, " %ld", c->baud); 2138128967Srik else 2139128967Srik length += sprintf (s + length, " extclock"); 2140128967Srik 2141128967Srik if (c->type == T_E1 || c->type == T_G703) 2142128967Srik switch (c->gsyn) { 2143128967Srik case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2144128967Srik case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2145128967Srik case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2146128967Srik case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2147128967Srik case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2148128967Srik case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2149128967Srik } 2150128967Srik if (c->type == T_SERIAL) { 2151128967Srik length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2152128967Srik length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2153128967Srik length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2154128967Srik } 2155128967Srik if (c->type == T_E1) 2156128967Srik length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2157128967Srik 2158128967Srik length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2159128967Srik 2160128967Srik if (c->type == T_E1) 2161128967Srik length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2162128967Srik if (c->type == T_G703) { 2163128967Srik int lq, x; 2164128967Srik 2165128967Srik x = splimp (); 2166128967Srik lq = cp_get_lq (c); 2167128967Srik splx (x); 2168128967Srik length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2169128967Srik } 2170128967Srik length += sprintf (s + length, "\n"); 2171128967Srik return length; 2172128967Srik} 2173128967Srik 2174128967Srik#if __FreeBSD_version >= 500000 2175128967Srikstatic int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2176128967Srik{ 2177128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2178128967Srik struct ng_mesg *msg; 2179128967Srik#else 2180128967Srikstatic int ng_cp_rcvmsg (node_p node, struct ng_mesg *msg, 2181128967Srik const char *retaddr, struct ng_mesg **rptr) 2182128967Srik{ 2183128967Srik drv_t *d = node->private; 2184128967Srik#endif 2185128967Srik struct ng_mesg *resp = NULL; 2186128967Srik int error = 0; 2187128967Srik 2188128967Srik CP_DEBUG (d, ("Rcvmsg\n")); 2189128967Srik#if __FreeBSD_version >= 500000 2190128967Srik NGI_GET_MSG (item, msg); 2191128967Srik#endif 2192128967Srik switch (msg->header.typecookie) { 2193128967Srik default: 2194128967Srik error = EINVAL; 2195128967Srik break; 2196128967Srik 2197128967Srik case NGM_CP_COOKIE: 2198128967Srik printf ("Not implemented yet\n"); 2199128967Srik error = EINVAL; 2200128967Srik break; 2201128967Srik 2202128967Srik case NGM_GENERIC_COOKIE: 2203128967Srik switch (msg->header.cmd) { 2204128967Srik default: 2205128967Srik error = EINVAL; 2206128967Srik break; 2207128967Srik 2208128967Srik case NGM_TEXT_STATUS: { 2209128967Srik char *s; 2210128967Srik int l = 0; 2211128967Srik int dl = sizeof (struct ng_mesg) + 730; 2212128967Srik 2213128967Srik#if __FreeBSD_version >= 500000 2214128967Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2215128967Srik if (! resp) { 2216128967Srik error = ENOMEM; 2217128967Srik break; 2218128967Srik } 2219128967Srik#else 2220128967Srik MALLOC (resp, struct ng_mesg *, dl, 2221128967Srik M_NETGRAPH, M_NOWAIT); 2222128967Srik if (! resp) { 2223128967Srik error = ENOMEM; 2224128967Srik break; 2225128967Srik } 2226128967Srik bzero (resp, dl); 2227128967Srik#endif 2228128967Srik s = (resp)->data; 2229128967Srik if (d) { 2230128967Srik l += print_chan (s + l, d->chan); 2231128967Srik l += print_stats (s + l, d->chan, 1); 2232128967Srik l += print_modems (s + l, d->chan, 1); 2233128967Srik l += print_e1_stats (s + l, d->chan); 2234128967Srik } else 2235128967Srik l += sprintf (s + l, "Error: node not connect to channel"); 2236128967Srik#if __FreeBSD_version < 500000 2237128967Srik (resp)->header.version = NG_VERSION; 2238128967Srik (resp)->header.arglen = strlen (s) + 1; 2239128967Srik (resp)->header.token = msg->header.token; 2240128967Srik (resp)->header.typecookie = NGM_CP_COOKIE; 2241128967Srik (resp)->header.cmd = msg->header.cmd; 2242128967Srik#endif 2243128967Srik strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 2244128967Srik } 2245128967Srik break; 2246128967Srik } 2247128967Srik break; 2248128967Srik } 2249128967Srik#if __FreeBSD_version >= 500000 2250128967Srik NG_RESPOND_MSG (error, node, item, resp); 2251128967Srik NG_FREE_MSG (msg); 2252128967Srik#else 2253128967Srik *rptr = resp; 2254128967Srik FREE (msg, M_NETGRAPH); 2255128967Srik#endif 2256128967Srik return error; 2257128967Srik} 2258128967Srik 2259128967Srik#if __FreeBSD_version >= 500000 2260128967Srikstatic int ng_cp_rcvdata (hook_p hook, item_p item) 2261128967Srik{ 2262128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2263128967Srik struct mbuf *m; 2264131108Sjulian struct ng_tag_prio *ptag; 2265128967Srik#else 2266128967Srikstatic int ng_cp_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) 2267128967Srik{ 2268128967Srik drv_t *d = hook->node->private; 2269128967Srik#endif 2270128967Srik struct ifqueue *q; 2271128967Srik int s; 2272128967Srik 2273128967Srik CP_DEBUG2 (d, ("Rcvdata\n")); 2274128967Srik#if __FreeBSD_version >= 500000 2275128967Srik NGI_GET_M (item, m); 2276128967Srik NG_FREE_ITEM (item); 2277128967Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 2278128967Srik NG_FREE_M (m); 2279128967Srik#else 2280128967Srik if (! hook->private || ! d) { 2281128967Srik NG_FREE_DATA (m,meta); 2282128967Srik#endif 2283128967Srik return ENETDOWN; 2284128967Srik } 2285131108Sjulian 2286131108Sjulian /* Check for high priority data */ 2287131108Sjulian if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2288131108Sjulian NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2289131108Sjulian q = &d->hi_queue; 2290131108Sjulian else 2291131108Sjulian q = &d->queue; 2292131108Sjulian 2293128967Srik s = splimp (); 2294128967Srik#if __FreeBSD_version >= 500000 2295128967Srik IF_LOCK (q); 2296128967Srik if (_IF_QFULL (q)) { 2297128967Srik _IF_DROP (q); 2298128967Srik IF_UNLOCK (q); 2299128967Srik splx (s); 2300128967Srik NG_FREE_M (m); 2301128967Srik return ENOBUFS; 2302128967Srik } 2303128967Srik _IF_ENQUEUE (q, m); 2304128967Srik IF_UNLOCK (q); 2305128967Srik#else 2306128967Srik if (IF_QFULL (q)) { 2307128967Srik IF_DROP (q); 2308128967Srik splx (s); 2309128967Srik NG_FREE_DATA (m, meta); 2310128967Srik return ENOBUFS; 2311128967Srik } 2312128967Srik IF_ENQUEUE (q, m); 2313128967Srik#endif 2314128967Srik cp_start (d); 2315128967Srik splx (s); 2316128967Srik return 0; 2317128967Srik} 2318128967Srik 2319128967Srikstatic int ng_cp_rmnode (node_p node) 2320128967Srik{ 2321128967Srik#if __FreeBSD_version >= 500000 2322128967Srik drv_t *d = NG_NODE_PRIVATE (node); 2323128967Srik 2324128967Srik CP_DEBUG (d, ("Rmnode\n")); 2325128967Srik if (d && d->running) { 2326128967Srik int s = splimp (); 2327128967Srik cp_down (d); 2328128967Srik splx (s); 2329128967Srik } 2330128967Srik#ifdef KLD_MODULE 2331128967Srik if (node->nd_flags & NG_REALLY_DIE) { 2332128967Srik NG_NODE_SET_PRIVATE (node, NULL); 2333128967Srik NG_NODE_UNREF (node); 2334128967Srik } 2335128967Srik node->nd_flags &= ~NG_INVALID; 2336128967Srik#endif 2337128967Srik#else /* __FreeBSD_version < 500000 */ 2338128967Srik drv_t *d = node->private; 2339128967Srik 2340128967Srik if (d && d->running) { 2341128967Srik int s = splimp (); 2342128967Srik cp_down (d); 2343128967Srik splx (s); 2344128967Srik } 2345128967Srik 2346128967Srik node->flags |= NG_INVALID; 2347128967Srik ng_cutlinks (node); 2348128967Srik#ifdef KLD_MODULE 2349128967Srik ng_unname (node); 2350128967Srik ng_unref (node); 2351128967Srik#endif 2352128967Srik#endif 2353128967Srik return 0; 2354128967Srik} 2355128967Srik 2356128967Srikstatic void ng_cp_watchdog (void *arg) 2357128967Srik{ 2358128967Srik drv_t *d = arg; 2359128967Srik 2360128967Srik if (d) { 2361128967Srik if (d->timeout == 1) 2362128967Srik cp_watchdog (d); 2363128967Srik if (d->timeout) 2364128967Srik d->timeout--; 2365128967Srik d->timeout_handle = timeout (ng_cp_watchdog, d, hz); 2366128967Srik } 2367128967Srik} 2368128967Srik 2369128967Srikstatic int ng_cp_connect (hook_p hook) 2370128967Srik{ 2371128967Srik#if __FreeBSD_version >= 500000 2372128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2373128967Srik#else 2374128967Srik drv_t *d = hook->node->private; 2375128967Srik#endif 2376128967Srik 2377128967Srik if (d) { 2378128967Srik CP_DEBUG (d, ("Connect\n")); 2379128967Srik d->timeout_handle = timeout (ng_cp_watchdog, d, hz); 2380128967Srik } 2381128967Srik 2382128967Srik return 0; 2383128967Srik} 2384128967Srik 2385128967Srikstatic int ng_cp_disconnect (hook_p hook) 2386128967Srik{ 2387128967Srik#if __FreeBSD_version >= 500000 2388128967Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2389128967Srik#else 2390128967Srik drv_t *d = hook->node->private; 2391128967Srik#endif 2392128967Srik 2393128967Srik if (d) { 2394128967Srik CP_DEBUG (d, ("Disconnect\n")); 2395128967Srik#if __FreeBSD_version >= 500000 2396128967Srik if (NG_HOOK_PRIVATE (hook)) 2397128967Srik#else 2398128967Srik if (hook->private) 2399128967Srik#endif 2400128967Srik { 2401128967Srik int s = splimp (); 2402128967Srik cp_down (d); 2403128967Srik splx (s); 2404128967Srik } 2405128967Srik untimeout (ng_cp_watchdog, d, d->timeout_handle); 2406128967Srik } 2407128967Srik return 0; 2408128967Srik} 2409128967Srik#endif 2410128967Srik 2411128967Srikstatic int cp_modevent (module_t mod, int type, void *unused) 2412128967Srik{ 2413130585Sphk struct cdev *dev; 2414128967Srik static int load_count = 0; 2415128967Srik struct cdevsw *cdsw; 2416128967Srik 2417128967Srik#if __FreeBSD_version >= 502103 2418130640Sphk dev = findcdev (makedev(CDEV_MAJOR, 0)); 2419128967Srik#else 2420128967Srik dev = makedev (CDEV_MAJOR, 0); 2421128967Srik#endif 2422128967Srik switch (type) { 2423128967Srik case MOD_LOAD: 2424130640Sphk if (dev != NULL && 2425128967Srik (cdsw = devsw (dev)) && 2426128967Srik cdsw->d_maj == CDEV_MAJOR) { 2427128967Srik printf ("Tau-PCI driver is already in system\n"); 2428128967Srik return (ENXIO); 2429128967Srik } 2430128967Srik#if __FreeBSD_version >= 500000 && defined NETGRAPH 2431128967Srik if (ng_newtype (&typestruct)) 2432128967Srik printf ("Failed to register ng_cp\n"); 2433128967Srik#endif 2434128967Srik ++load_count; 2435128967Srik#if __FreeBSD_version <= 500000 2436128967Srik cdevsw_add (&cp_cdevsw); 2437128967Srik#endif 2438128967Srik timeout_handle = timeout (cp_timeout, 0, hz*5); 2439128967Srik break; 2440128967Srik case MOD_UNLOAD: 2441128967Srik if (load_count == 1) { 2442128967Srik printf ("Removing device entry for Tau-PCI\n"); 2443128967Srik#if __FreeBSD_version <= 500000 2444128967Srik cdevsw_remove (&cp_cdevsw); 2445128967Srik#endif 2446128967Srik#if __FreeBSD_version >= 500000 && defined NETGRAPH 2447128967Srik ng_rmtype (&typestruct); 2448128967Srik#endif 2449128967Srik } 2450128967Srik untimeout (cp_timeout, 0, timeout_handle); 2451128967Srik --load_count; 2452128967Srik break; 2453128967Srik case MOD_SHUTDOWN: 2454128967Srik break; 2455128967Srik } 2456128967Srik return 0; 2457128967Srik} 2458128967Srik 2459128967Srik#ifdef NETGRAPH 2460128967Srikstatic struct ng_type typestruct = { 2461129837Srik .version = NG_ABI_VERSION, 2462129837Srik .name = NG_CP_NODE_TYPE, 2463129837Srik .constructor = ng_cp_constructor, 2464129837Srik .rcvmsg = ng_cp_rcvmsg, 2465129837Srik .shutdown = ng_cp_rmnode, 2466129837Srik .newhook = ng_cp_newhook, 2467129837Srik .connect = ng_cp_connect, 2468129837Srik .rcvdata = ng_cp_rcvdata, 2469129837Srik .disconnect = ng_cp_disconnect, 2470128967Srik}; 2471128967Srik#endif /*NETGRAPH*/ 2472128967Srik 2473128967Srik#if __FreeBSD_version >= 500000 2474128967Srik#ifdef NETGRAPH 2475128967SrikMODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2476128967Srik#else 2477128967SrikMODULE_DEPEND (cp, sppp, 1, 1, 1); 2478128967Srik#endif 2479128967Srik#ifdef KLD_MODULE 2480128967SrikDRIVER_MODULE (cpmod, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2481128967Srik#else 2482128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2483128967Srik#endif 2484130985Srik#elif __FreeBSD_version >= 400000 2485128967Srik#ifdef NETGRAPH 2486128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, ng_mod_event, &typestruct); 2487128967Srik#else 2488128967SrikDRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2489128967Srik#endif 2490130971Srik#endif /* __FreeBSD_version >= 400000 */ 2491128967Srik#endif /* NPCI */ 2492