1/*- 2 * Cronyx-Tau-PCI adapter driver for FreeBSD. 3 * Supports PPP/HDLC, Cisco/HDLC and FrameRelay protocol in synchronous mode, 4 * and asynchronous channels with full modem control. 5 * Keepalive protocol implemented in both Cisco and PPP modes. 6 * 7 * Copyright (C) 1999-2004 Cronyx Engineering. 8 * Author: Kurakin Roman, <rik@cronyx.ru> 9 * 10 * Copyright (C) 1999-2002 Cronyx Engineering. 11 * Author: Serge Vakulenko, <vak@cronyx.ru> 12 * 13 * This software is distributed with NO WARRANTIES, not even the implied 14 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15 * 16 * Authors grant any other persons or organisations a permission to use, 17 * modify and redistribute this software in source and binary forms, 18 * as long as this message is kept with the software, all derivative 19 * works or modified versions. 20 * 21 * Cronyx Id: if_cp.c,v 1.1.2.41 2004/06/23 17:09:13 rik Exp $ 22 */ 23 24#include <sys/cdefs.h> 25__FBSDID("$FreeBSD: stable/11/sys/dev/cp/if_cp.c 315221 2017-03-14 02:06:03Z pfg $"); 26 27#include <sys/param.h> 28#include <sys/ucred.h> 29#include <sys/proc.h> 30#include <sys/systm.h> 31#include <sys/mbuf.h> 32#include <sys/kernel.h> 33#include <sys/module.h> 34#include <sys/conf.h> 35#include <sys/malloc.h> 36#include <sys/priv.h> 37#include <sys/socket.h> 38#include <sys/sockio.h> 39#include <sys/sysctl.h> 40#include <sys/tty.h> 41#include <sys/bus.h> 42#include <vm/vm.h> 43#include <vm/pmap.h> 44#include <net/if.h> 45#include <net/if_var.h> 46#include <dev/pci/pcivar.h> 47#include <dev/pci/pcireg.h> 48#include <machine/bus.h> 49#include <sys/rman.h> 50#include "opt_ng_cronyx.h" 51#ifdef NETGRAPH_CRONYX 52# include "opt_netgraph.h" 53# ifndef NETGRAPH 54# error #option NETGRAPH missed from configuration 55# endif 56# include <netgraph/ng_message.h> 57# include <netgraph/netgraph.h> 58# include <dev/cp/ng_cp.h> 59#else 60# include <net/if_sppp.h> 61# include <net/if_types.h> 62#include <dev/pci/pcivar.h> 63# define PP_CISCO IFF_LINK2 64# include <net/bpf.h> 65#endif 66#include <dev/cx/machdep.h> 67#include <dev/cp/cpddk.h> 68#include <machine/cserial.h> 69#include <machine/resource.h> 70 71/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 72#ifndef PP_FR 73#define PP_FR 0 74#endif 75 76#define CP_DEBUG(d,s) ({if (d->chan->debug) {\ 77 printf ("%s: ", d->name); printf s;}}) 78#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 79 printf ("%s: ", d->name); printf s;}}) 80#define CP_LOCK_NAME "cpX" 81 82#define CP_LOCK(_bd) mtx_lock (&(_bd)->cp_mtx) 83#define CP_UNLOCK(_bd) mtx_unlock (&(_bd)->cp_mtx) 84#define CP_LOCK_ASSERT(_bd) mtx_assert (&(_bd)->cp_mtx, MA_OWNED) 85 86static int cp_probe __P((device_t)); 87static int cp_attach __P((device_t)); 88static int cp_detach __P((device_t)); 89 90static device_method_t cp_methods[] = { 91 /* Device interface */ 92 DEVMETHOD(device_probe, cp_probe), 93 DEVMETHOD(device_attach, cp_attach), 94 DEVMETHOD(device_detach, cp_detach), 95 96 DEVMETHOD_END 97}; 98 99typedef struct _cp_dma_mem_t { 100 unsigned long phys; 101 void *virt; 102 size_t size; 103 bus_dma_tag_t dmat; 104 bus_dmamap_t mapp; 105} cp_dma_mem_t; 106 107typedef struct _drv_t { 108 char name [8]; 109 int running; 110 cp_chan_t *chan; 111 cp_board_t *board; 112 cp_dma_mem_t dmamem; 113#ifdef NETGRAPH 114 char nodename [NG_NODESIZE]; 115 hook_p hook; 116 hook_p debug_hook; 117 node_p node; 118 struct ifqueue queue; 119 struct ifqueue hi_queue; 120#else 121 struct ifqueue queue; 122 struct ifnet *ifp; 123#endif 124 short timeout; 125 struct callout timeout_handle; 126 struct cdev *devt; 127} drv_t; 128 129typedef struct _bdrv_t { 130 cp_board_t *board; 131 struct resource *cp_res; 132 struct resource *cp_irq; 133 void *cp_intrhand; 134 cp_dma_mem_t dmamem; 135 drv_t channel [NCHAN]; 136 struct mtx cp_mtx; 137} bdrv_t; 138 139static driver_t cp_driver = { 140 "cp", 141 cp_methods, 142 sizeof(bdrv_t), 143}; 144 145static devclass_t cp_devclass; 146 147static void cp_receive (cp_chan_t *c, unsigned char *data, int len); 148static void cp_transmit (cp_chan_t *c, void *attachment, int len); 149static void cp_error (cp_chan_t *c, int data); 150static void cp_up (drv_t *d); 151static void cp_start (drv_t *d); 152static void cp_down (drv_t *d); 153static void cp_watchdog (drv_t *d); 154static void cp_watchdog_timer (void *arg); 155#ifdef NETGRAPH 156extern struct ng_type typestruct; 157#else 158static void cp_ifstart (struct ifnet *ifp); 159static void cp_tlf (struct sppp *sp); 160static void cp_tls (struct sppp *sp); 161static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 162static void cp_initialize (void *softc); 163#endif 164 165static cp_board_t *adapter [NBRD]; 166static drv_t *channel [NBRD*NCHAN]; 167static struct callout led_timo [NBRD]; 168static struct callout timeout_handle; 169 170static int cp_destroy = 0; 171 172static int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td); 173static int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td); 174static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); 175static struct cdevsw cp_cdevsw = { 176 .d_version = D_VERSION, 177 .d_open = cp_open, 178 .d_close = cp_close, 179 .d_ioctl = cp_ioctl, 180 .d_name = "cp", 181}; 182 183/* 184 * Make an mbuf from data. 185 */ 186static struct mbuf *makembuf (void *buf, unsigned len) 187{ 188 struct mbuf *m; 189 190 MGETHDR (m, M_NOWAIT, MT_DATA); 191 if (! m) 192 return 0; 193 if (!(MCLGET (m, M_NOWAIT))) { 194 m_freem (m); 195 return 0; 196 } 197 m->m_pkthdr.len = m->m_len = len; 198 bcopy (buf, mtod (m, caddr_t), len); 199 return m; 200} 201 202static int cp_probe (device_t dev) 203{ 204 if ((pci_get_vendor (dev) == cp_vendor_id) && 205 (pci_get_device (dev) == cp_device_id)) { 206 device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 207 return BUS_PROBE_DEFAULT; 208 } 209 return ENXIO; 210} 211 212static void cp_timeout (void *arg) 213{ 214 drv_t *d; 215 int s, i, k; 216 217 for (i = 0; i < NBRD; ++i) { 218 if (adapter[i] == NULL) 219 continue; 220 for (k = 0; k < NCHAN; ++k) { 221 s = splimp (); 222 if (cp_destroy) { 223 splx (s); 224 return; 225 } 226 d = channel[i * NCHAN + k]; 227 if (!d) { 228 splx (s); 229 continue; 230 } 231 CP_LOCK ((bdrv_t *)d->board->sys); 232 switch (d->chan->type) { 233 case T_G703: 234 cp_g703_timer (d->chan); 235 break; 236 case T_E1: 237 cp_e1_timer (d->chan); 238 break; 239 case T_E3: 240 case T_T3: 241 case T_STS1: 242 cp_e3_timer (d->chan); 243 break; 244 default: 245 break; 246 } 247 CP_UNLOCK ((bdrv_t *)d->board->sys); 248 splx (s); 249 } 250 } 251 s = splimp (); 252 if (!cp_destroy) 253 callout_reset (&timeout_handle, hz, cp_timeout, 0); 254 splx (s); 255} 256 257static void cp_led_off (void *arg) 258{ 259 cp_board_t *b = arg; 260 bdrv_t *bd = (bdrv_t *) b->sys; 261 int s; 262 s = splimp (); 263 if (cp_destroy) { 264 splx (s); 265 return; 266 } 267 CP_LOCK (bd); 268 cp_led (b, 0); 269 CP_UNLOCK (bd); 270 splx (s); 271} 272 273static void cp_intr (void *arg) 274{ 275 bdrv_t *bd = arg; 276 cp_board_t *b = bd->board; 277#ifndef NETGRAPH 278 int i; 279#endif 280 int s = splimp (); 281 if (cp_destroy) { 282 splx (s); 283 return; 284 } 285 CP_LOCK (bd); 286 /* Check if we are ready */ 287 if (b->sys == NULL) { 288 /* Not we are not, just cleanup. */ 289 cp_interrupt_poll (b, 1); 290 CP_UNLOCK (bd); 291 return; 292 } 293 /* Turn LED on. */ 294 cp_led (b, 1); 295 296 cp_interrupt (b); 297 298 /* Turn LED off 50 msec later. */ 299 callout_reset (&led_timo[b->num], hz/20, cp_led_off, b); 300 CP_UNLOCK (bd); 301 splx (s); 302 303#ifndef NETGRAPH 304 /* Pass packets in a lock-free state */ 305 for (i = 0; i < NCHAN && b->chan[i].type; i++) { 306 drv_t *d = b->chan[i].sys; 307 struct mbuf *m; 308 if (!d || !d->running) 309 continue; 310 while (_IF_QLEN(&d->queue)) { 311 IF_DEQUEUE (&d->queue,m); 312 if (!m) 313 continue; 314 sppp_input (d->ifp, m); 315 } 316 } 317#endif 318} 319 320static void 321cp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 322{ 323 unsigned long *addr; 324 325 if (error) 326 return; 327 328 KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 329 addr = arg; 330 *addr = segs->ds_addr; 331} 332 333static int 334cp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 335{ 336 int error; 337 338 error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 339 BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 340 dmem->size, 0, NULL, NULL, &dmem->dmat); 341 if (error) { 342 if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 343 else printf ("cp%d: ", bnum); 344 printf ("couldn't allocate tag for dma memory\n"); 345 return 0; 346 } 347 error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 348 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 349 if (error) { 350 if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 351 else printf ("cp%d: ", bnum); 352 printf ("couldn't allocate mem for dma memory\n"); 353 bus_dma_tag_destroy (dmem->dmat); 354 return 0; 355 } 356 error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 357 dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); 358 if (error) { 359 if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 360 else printf ("cp%d: ", bnum); 361 printf ("couldn't load mem map for dma memory\n"); 362 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 363 bus_dma_tag_destroy (dmem->dmat); 364 return 0; 365 } 366 return 1; 367} 368 369static void 370cp_bus_dma_mem_free (cp_dma_mem_t *dmem) 371{ 372 bus_dmamap_unload (dmem->dmat, dmem->mapp); 373 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 374 bus_dma_tag_destroy (dmem->dmat); 375} 376 377/* 378 * Called if the probe succeeded. 379 */ 380static int cp_attach (device_t dev) 381{ 382 bdrv_t *bd = device_get_softc (dev); 383 int unit = device_get_unit (dev); 384 char *cp_ln = CP_LOCK_NAME; 385 unsigned short res; 386 vm_offset_t vbase; 387 int rid, error; 388 cp_board_t *b; 389 cp_chan_t *c; 390 drv_t *d; 391 int s = splimp (); 392 393 b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 394 if (!b) { 395 printf ("cp%d: couldn't allocate memory\n", unit); 396 splx (s); 397 return (ENXIO); 398 } 399 bzero (b, sizeof(cp_board_t)); 400 401 bd->board = b; 402 rid = PCIR_BAR(0); 403 bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 404 0, ~0, 1, RF_ACTIVE); 405 if (! bd->cp_res) { 406 printf ("cp%d: cannot map memory\n", unit); 407 free (b, M_DEVBUF); 408 splx (s); 409 return (ENXIO); 410 } 411 vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 412 413 cp_ln[2] = '0' + unit; 414 mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 415 res = cp_init (b, unit, (u_char*) vbase); 416 if (res) { 417 printf ("cp%d: can't init, error code:%x\n", unit, res); 418 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 419 free (b, M_DEVBUF); 420 splx (s); 421 return (ENXIO); 422 } 423 424 bd->dmamem.size = sizeof(cp_qbuf_t); 425 if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 426 free (b, M_DEVBUF); 427 splx (s); 428 return (ENXIO); 429 } 430 CP_LOCK (bd); 431 cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); 432 CP_UNLOCK (bd); 433 434 rid = 0; 435 bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 436 RF_SHAREABLE | RF_ACTIVE); 437 if (! bd->cp_irq) { 438 cp_destroy = 1; 439 printf ("cp%d: cannot map interrupt\n", unit); 440 bus_release_resource (dev, SYS_RES_MEMORY, 441 PCIR_BAR(0), bd->cp_res); 442 mtx_destroy (&bd->cp_mtx); 443 free (b, M_DEVBUF); 444 splx (s); 445 return (ENXIO); 446 } 447 callout_init (&led_timo[unit], 1); 448 error = bus_setup_intr (dev, bd->cp_irq, 449 INTR_TYPE_NET|INTR_MPSAFE, 450 NULL, cp_intr, bd, &bd->cp_intrhand); 451 if (error) { 452 cp_destroy = 1; 453 printf ("cp%d: cannot set up irq\n", unit); 454 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 455 bus_release_resource (dev, SYS_RES_MEMORY, 456 PCIR_BAR(0), bd->cp_res); 457 mtx_destroy (&bd->cp_mtx); 458 free (b, M_DEVBUF); 459 splx (s); 460 return (ENXIO); 461 } 462 printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 463 464 for (c = b->chan; c < b->chan + NCHAN; ++c) { 465 if (! c->type) 466 continue; 467 d = &bd->channel[c->num]; 468 d->dmamem.size = sizeof(cp_buf_t); 469 if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 470 continue; 471 channel [b->num*NCHAN + c->num] = d; 472 sprintf (d->name, "cp%d.%d", b->num, c->num); 473 d->board = b; 474 d->chan = c; 475 c->sys = d; 476 callout_init (&d->timeout_handle, 1); 477#ifdef NETGRAPH 478 if (ng_make_node_common (&typestruct, &d->node) != 0) { 479 printf ("%s: cannot make common node\n", d->name); 480 d->node = NULL; 481 continue; 482 } 483 NG_NODE_SET_PRIVATE (d->node, d); 484 sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 485 c->board->num*NCHAN + c->num); 486 if (ng_name_node (d->node, d->nodename)) { 487 printf ("%s: cannot name node\n", d->nodename); 488 NG_NODE_UNREF (d->node); 489 continue; 490 } 491 d->queue.ifq_maxlen = ifqmaxlen; 492 d->hi_queue.ifq_maxlen = ifqmaxlen; 493 mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 494 mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 495#else /*NETGRAPH*/ 496 d->ifp = if_alloc(IFT_PPP); 497 if (d->ifp == NULL) { 498 printf ("%s: cannot if_alloc() interface\n", d->name); 499 continue; 500 } 501 d->ifp->if_softc = d; 502 if_initname (d->ifp, "cp", b->num * NCHAN + c->num); 503 d->ifp->if_mtu = PP_MTU; 504 d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 505 d->ifp->if_ioctl = cp_sioctl; 506 d->ifp->if_start = cp_ifstart; 507 d->ifp->if_init = cp_initialize; 508 d->queue.ifq_maxlen = NRBUF; 509 mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 510 sppp_attach (d->ifp); 511 if_attach (d->ifp); 512 IFP2SP(d->ifp)->pp_tlf = cp_tlf; 513 IFP2SP(d->ifp)->pp_tls = cp_tls; 514 /* If BPF is in the kernel, call the attach for it. 515 * The header size of PPP or Cisco/HDLC is 4 bytes. */ 516 bpfattach (d->ifp, DLT_PPP, 4); 517#endif /*NETGRAPH*/ 518 cp_start_e1 (c); 519 cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 520 521 /* Register callback functions. */ 522 cp_register_transmit (c, &cp_transmit); 523 cp_register_receive (c, &cp_receive); 524 cp_register_error (c, &cp_error); 525 d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 526 GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 527 } 528 CP_LOCK (bd); 529 b->sys = bd; 530 adapter[unit] = b; 531 CP_UNLOCK (bd); 532 splx (s); 533 return 0; 534} 535 536static int cp_detach (device_t dev) 537{ 538 bdrv_t *bd = device_get_softc (dev); 539 cp_board_t *b = bd->board; 540 cp_chan_t *c; 541 int s; 542 543 KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized")); 544 s = splimp (); 545 CP_LOCK (bd); 546 /* Check if the device is busy (open). */ 547 for (c = b->chan; c < b->chan + NCHAN; ++c) { 548 drv_t *d = (drv_t*) c->sys; 549 550 if (! d || ! d->chan->type) 551 continue; 552 if (d->running) { 553 CP_UNLOCK (bd); 554 splx (s); 555 return EBUSY; 556 } 557 } 558 559 /* Ok, we can unload driver */ 560 /* At first we should stop all channels */ 561 for (c = b->chan; c < b->chan + NCHAN; ++c) { 562 drv_t *d = (drv_t*) c->sys; 563 564 if (! d || ! d->chan->type) 565 continue; 566 567 cp_stop_chan (c); 568 cp_stop_e1 (c); 569 cp_set_dtr (d->chan, 0); 570 cp_set_rts (d->chan, 0); 571 } 572 573 /* Reset the adapter. */ 574 cp_destroy = 1; 575 cp_interrupt_poll (b, 1); 576 cp_led_off (b); 577 cp_reset (b, 0 ,0); 578 callout_stop (&led_timo[b->num]); 579 580 /* Disable the interrupt request. */ 581 bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 582 583 for (c=b->chan; c<b->chan+NCHAN; ++c) { 584 drv_t *d = (drv_t*) c->sys; 585 586 if (! d || ! d->chan->type) 587 continue; 588 callout_stop (&d->timeout_handle); 589#ifndef NETGRAPH 590 /* Detach from the packet filter list of interfaces. */ 591 bpfdetach (d->ifp); 592 593 /* Detach from the sync PPP list. */ 594 sppp_detach (d->ifp); 595 596 /* Detach from the system list of interfaces. */ 597 if_detach (d->ifp); 598 if_free (d->ifp); 599 IF_DRAIN (&d->queue); 600 mtx_destroy (&d->queue.ifq_mtx); 601#else 602 if (d->node) { 603 ng_rmnode_self (d->node); 604 NG_NODE_UNREF (d->node); 605 d->node = NULL; 606 } 607 mtx_destroy (&d->queue.ifq_mtx); 608 mtx_destroy (&d->hi_queue.ifq_mtx); 609#endif 610 destroy_dev (d->devt); 611 } 612 613 b->sys = NULL; 614 CP_UNLOCK (bd); 615 616 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 617 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 618 619 CP_LOCK (bd); 620 cp_led_off (b); 621 CP_UNLOCK (bd); 622 callout_drain (&led_timo[b->num]); 623 splx (s); 624 625 for (c = b->chan; c < b->chan + NCHAN; ++c) { 626 drv_t *d = (drv_t*) c->sys; 627 628 if (! d || ! d->chan->type) 629 continue; 630 callout_drain (&d->timeout_handle); 631 channel [b->num*NCHAN + c->num] = NULL; 632 /* Deallocate buffers. */ 633 cp_bus_dma_mem_free (&d->dmamem); 634 } 635 adapter [b->num] = NULL; 636 cp_bus_dma_mem_free (&bd->dmamem); 637 free (b, M_DEVBUF); 638 mtx_destroy (&bd->cp_mtx); 639 return 0; 640} 641 642#ifndef NETGRAPH 643static void cp_ifstart (struct ifnet *ifp) 644{ 645 drv_t *d = ifp->if_softc; 646 bdrv_t *bd = d->board->sys; 647 648 CP_LOCK (bd); 649 cp_start (d); 650 CP_UNLOCK (bd); 651} 652 653static void cp_tlf (struct sppp *sp) 654{ 655 drv_t *d = SP2IFP(sp)->if_softc; 656 657 CP_DEBUG2 (d, ("cp_tlf\n")); 658 /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */ 659/* cp_set_dtr (d->chan, 0);*/ 660/* cp_set_rts (d->chan, 0);*/ 661 if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 662 sp->pp_down (sp); 663} 664 665static void cp_tls (struct sppp *sp) 666{ 667 drv_t *d = SP2IFP(sp)->if_softc; 668 669 CP_DEBUG2 (d, ("cp_tls\n")); 670 if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 671 sp->pp_up (sp); 672} 673 674/* 675 * Process an ioctl request. 676 */ 677static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 678{ 679 drv_t *d = ifp->if_softc; 680 bdrv_t *bd = d->board->sys; 681 int error, s, was_up, should_be_up; 682 683 was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 684 error = sppp_ioctl (ifp, cmd, data); 685 686 if (error) 687 return error; 688 689 if (! (ifp->if_flags & IFF_DEBUG)) 690 d->chan->debug = 0; 691 else 692 d->chan->debug = d->chan->debug_shadow; 693 694 switch (cmd) { 695 default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 696 case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 697 case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 698 case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 699 case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 700 } 701 702 /* We get here only in case of SIFFLAGS or SIFADDR. */ 703 s = splimp (); 704 CP_LOCK (bd); 705 should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 706 if (! was_up && should_be_up) { 707 /* Interface goes up -- start it. */ 708 cp_up (d); 709 cp_start (d); 710 } else if (was_up && ! should_be_up) { 711 /* Interface is going down -- stop it. */ 712/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 713 cp_down (d); 714 } 715 CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 716 CP_UNLOCK (bd); 717 splx (s); 718 return 0; 719} 720 721/* 722 * Initialization of interface. 723 * It seems to be never called by upper level? 724 */ 725static void cp_initialize (void *softc) 726{ 727 drv_t *d = softc; 728 729 CP_DEBUG (d, ("cp_initialize\n")); 730} 731#endif /*NETGRAPH*/ 732 733/* 734 * Stop the interface. Called on splimp(). 735 */ 736static void cp_down (drv_t *d) 737{ 738 CP_DEBUG (d, ("cp_down\n")); 739 /* Interface is going down -- stop it. */ 740 cp_set_dtr (d->chan, 0); 741 cp_set_rts (d->chan, 0); 742 743 d->running = 0; 744 callout_stop (&d->timeout_handle); 745} 746 747/* 748 * Start the interface. Called on splimp(). 749 */ 750static void cp_up (drv_t *d) 751{ 752 CP_DEBUG (d, ("cp_up\n")); 753 cp_set_dtr (d->chan, 1); 754 cp_set_rts (d->chan, 1); 755 d->running = 1; 756} 757 758/* 759 * Start output on the interface. Get another datagram to send 760 * off of the interface queue, and copy it to the interface 761 * before starting the output. 762 */ 763static void cp_send (drv_t *d) 764{ 765 struct mbuf *m; 766 u_short len; 767 768 CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 769 770 /* No output if the interface is down. */ 771 if (! d->running) 772 return; 773 774 /* No output if the modem is off. */ 775 if (! (d->chan->lloop || d->chan->type != T_SERIAL || 776 cp_get_dsr (d->chan))) 777 return; 778 779 while (cp_transmit_space (d->chan)) { 780 /* Get the packet to send. */ 781#ifdef NETGRAPH 782 IF_DEQUEUE (&d->hi_queue, m); 783 if (! m) 784 IF_DEQUEUE (&d->queue, m); 785#else 786 m = sppp_dequeue (d->ifp); 787#endif 788 if (! m) 789 return; 790#ifndef NETGRAPH 791 BPF_MTAP (d->ifp, m); 792#endif 793 len = m_length (m, NULL); 794 if (len >= BUFSZ) 795 printf ("%s: too long packet: %d bytes: ", 796 d->name, len); 797 else if (! m->m_next) 798 cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 799 else { 800 u_char *buf = d->chan->tbuf[d->chan->te]; 801 m_copydata (m, 0, len, buf); 802 cp_send_packet (d->chan, buf, len, 0); 803 } 804 m_freem (m); 805 /* Set up transmit timeout, if the transmit ring is not empty.*/ 806 d->timeout = 10; 807 } 808#ifndef NETGRAPH 809 d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 810#endif 811} 812 813/* 814 * Start output on the interface. 815 * Always called on splimp(). 816 */ 817static void cp_start (drv_t *d) 818{ 819 if (d->running) { 820 if (! d->chan->dtr) 821 cp_set_dtr (d->chan, 1); 822 if (! d->chan->rts) 823 cp_set_rts (d->chan, 1); 824 cp_send (d); 825 callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 826 } 827} 828 829/* 830 * Handle transmit timeouts. 831 * Recover after lost transmit interrupts. 832 * Always called on splimp(). 833 */ 834static void cp_watchdog (drv_t *d) 835{ 836 CP_DEBUG (d, ("device timeout\n")); 837 if (d->running) { 838 cp_stop_chan (d->chan); 839 cp_stop_e1 (d->chan); 840 cp_start_e1 (d->chan); 841 cp_start_chan (d->chan, 1, 1, 0, 0); 842 cp_set_dtr (d->chan, 1); 843 cp_set_rts (d->chan, 1); 844 cp_start (d); 845 } 846} 847 848static void cp_watchdog_timer (void *arg) 849{ 850 drv_t *d = arg; 851 bdrv_t *bd = d->board->sys; 852 853 CP_LOCK (bd); 854 if (d->timeout == 1) 855 cp_watchdog (d); 856 if (d->timeout) 857 d->timeout--; 858 callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 859 CP_UNLOCK (bd); 860} 861 862static void cp_transmit (cp_chan_t *c, void *attachment, int len) 863{ 864 drv_t *d = c->sys; 865 866 d->timeout = 0; 867#ifndef NETGRAPH 868 if_inc_counter(d->ifp, IFCOUNTER_OPACKETS, 1); 869 d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 870#endif 871 cp_start (d); 872} 873 874static void cp_receive (cp_chan_t *c, unsigned char *data, int len) 875{ 876 drv_t *d = c->sys; 877 struct mbuf *m; 878#ifdef NETGRAPH 879 int error; 880#endif 881 882 if (! d->running) 883 return; 884 885 m = makembuf (data, len); 886 if (! m) { 887 CP_DEBUG (d, ("no memory for packet\n")); 888#ifndef NETGRAPH 889 if_inc_counter(d->ifp, IFCOUNTER_IQDROPS, 1); 890#endif 891 return; 892 } 893 if (c->debug > 1) 894 m_print (m, 0); 895#ifdef NETGRAPH 896 m->m_pkthdr.rcvif = 0; 897 NG_SEND_DATA_ONLY (error, d->hook, m); 898#else 899 if_inc_counter(d->ifp, IFCOUNTER_IPACKETS, 1); 900 m->m_pkthdr.rcvif = d->ifp; 901 /* Check if there's a BPF listener on this interface. 902 * If so, hand off the raw packet to bpf. */ 903 BPF_MTAP(d->ifp, m); 904 IF_ENQUEUE (&d->queue, m); 905#endif 906} 907 908static void cp_error (cp_chan_t *c, int data) 909{ 910 drv_t *d = c->sys; 911 912 switch (data) { 913 case CP_FRAME: 914 CP_DEBUG (d, ("frame error\n")); 915#ifndef NETGRAPH 916 if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 917#endif 918 break; 919 case CP_CRC: 920 CP_DEBUG (d, ("crc error\n")); 921#ifndef NETGRAPH 922 if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 923#endif 924 break; 925 case CP_OVERRUN: 926 CP_DEBUG (d, ("overrun error\n")); 927#ifndef NETGRAPH 928 if_inc_counter(d->ifp, IFCOUNTER_COLLISIONS, 1); 929 if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 930#endif 931 break; 932 case CP_OVERFLOW: 933 CP_DEBUG (d, ("overflow error\n")); 934#ifndef NETGRAPH 935 if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 936#endif 937 break; 938 case CP_UNDERRUN: 939 CP_DEBUG (d, ("underrun error\n")); 940 d->timeout = 0; 941#ifndef NETGRAPH 942 if_inc_counter(d->ifp, IFCOUNTER_OERRORS, 1); 943 d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 944#endif 945 cp_start (d); 946 break; 947 default: 948 CP_DEBUG (d, ("error #%d\n", data)); 949 break; 950 } 951} 952 953/* 954 * You also need read, write, open, close routines. 955 * This should get you started 956 */ 957static int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 958{ 959 int unit = dev2unit (dev); 960 drv_t *d; 961 962 if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 963 return ENXIO; 964 CP_DEBUG2 (d, ("cp_open\n")); 965 return 0; 966} 967 968/* 969 * Only called on the LAST close. 970 */ 971static int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 972{ 973 drv_t *d = channel [dev2unit (dev)]; 974 975 CP_DEBUG2 (d, ("cp_close\n")); 976 return 0; 977} 978 979static int cp_modem_status (cp_chan_t *c) 980{ 981 drv_t *d = c->sys; 982 bdrv_t *bd = d->board->sys; 983 int status, s; 984 985 status = d->running ? TIOCM_LE : 0; 986 s = splimp (); 987 CP_LOCK (bd); 988 if (cp_get_cd (c)) status |= TIOCM_CD; 989 if (cp_get_cts (c)) status |= TIOCM_CTS; 990 if (cp_get_dsr (c)) status |= TIOCM_DSR; 991 if (c->dtr) status |= TIOCM_DTR; 992 if (c->rts) status |= TIOCM_RTS; 993 CP_UNLOCK (bd); 994 splx (s); 995 return status; 996} 997 998static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 999{ 1000 drv_t *d = channel [dev2unit (dev)]; 1001 bdrv_t *bd = d->board->sys; 1002 cp_chan_t *c = d->chan; 1003 struct serial_statistics *st; 1004 struct e1_statistics *opte1; 1005 struct e3_statistics *opte3; 1006 int error, s; 1007 char mask[16]; 1008 1009 switch (cmd) { 1010 case SERIAL_GETREGISTERED: 1011 CP_DEBUG2 (d, ("ioctl: getregistered\n")); 1012 bzero (mask, sizeof(mask)); 1013 for (s=0; s<NBRD*NCHAN; ++s) 1014 if (channel [s]) 1015 mask [s/8] |= 1 << (s & 7); 1016 bcopy (mask, data, sizeof (mask)); 1017 return 0; 1018 1019#ifndef NETGRAPH 1020 case SERIAL_GETPROTO: 1021 CP_DEBUG2 (d, ("ioctl: getproto\n")); 1022 strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1023 (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1024 return 0; 1025 1026 case SERIAL_SETPROTO: 1027 CP_DEBUG2 (d, ("ioctl: setproto\n")); 1028 /* Only for superuser! */ 1029 error = priv_check (td, PRIV_DRIVER); 1030 if (error) 1031 return error; 1032 if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) 1033 return EBUSY; 1034 if (! strcmp ("cisco", (char*)data)) { 1035 IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1036 IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1037 d->ifp->if_flags |= PP_CISCO; 1038#if PP_FR != 0 1039 } else if (! strcmp ("fr", (char*)data)) { 1040 d->ifp->if_flags &= ~(PP_CISCO); 1041 IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1042#endif 1043 } else if (! strcmp ("ppp", (char*)data)) { 1044 IFP2SP(d->ifp)->pp_flags &= ~PP_FR; 1045 IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1046 d->ifp->if_flags &= ~(PP_CISCO); 1047 } else 1048 return EINVAL; 1049 return 0; 1050 1051 case SERIAL_GETKEEPALIVE: 1052 CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1053 if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1054 (d->ifp->if_flags & PP_CISCO)) 1055 return EINVAL; 1056 *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1057 return 0; 1058 1059 case SERIAL_SETKEEPALIVE: 1060 CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1061 /* Only for superuser! */ 1062 error = priv_check (td, PRIV_DRIVER); 1063 if (error) 1064 return error; 1065 if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1066 (d->ifp->if_flags & PP_CISCO)) 1067 return EINVAL; 1068 s = splimp (); 1069 CP_LOCK (bd); 1070 if (*(int*)data) 1071 IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1072 else 1073 IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1074 CP_UNLOCK (bd); 1075 splx (s); 1076 return 0; 1077#endif /*NETGRAPH*/ 1078 1079 case SERIAL_GETMODE: 1080 CP_DEBUG2 (d, ("ioctl: getmode\n")); 1081 *(int*)data = SERIAL_HDLC; 1082 return 0; 1083 1084 case SERIAL_SETMODE: 1085 /* Only for superuser! */ 1086 error = priv_check (td, PRIV_DRIVER); 1087 if (error) 1088 return error; 1089 if (*(int*)data != SERIAL_HDLC) 1090 return EINVAL; 1091 return 0; 1092 1093 case SERIAL_GETCFG: 1094 CP_DEBUG2 (d, ("ioctl: getcfg\n")); 1095 if (c->type != T_E1 || c->unfram) 1096 return EINVAL; 1097 *(char*)data = c->board->mux ? 'c' : 'a'; 1098 return 0; 1099 1100 case SERIAL_SETCFG: 1101 CP_DEBUG2 (d, ("ioctl: setcfg\n")); 1102 error = priv_check (td, PRIV_DRIVER); 1103 if (error) 1104 return error; 1105 if (c->type != T_E1) 1106 return EINVAL; 1107 s = splimp (); 1108 CP_LOCK (bd); 1109 cp_set_mux (c->board, *((char*)data) == 'c'); 1110 CP_UNLOCK (bd); 1111 splx (s); 1112 return 0; 1113 1114 case SERIAL_GETSTAT: 1115 CP_DEBUG2 (d, ("ioctl: getstat\n")); 1116 st = (struct serial_statistics*) data; 1117 st->rintr = c->rintr; 1118 st->tintr = c->tintr; 1119 st->mintr = 0; 1120 st->ibytes = c->ibytes; 1121 st->ipkts = c->ipkts; 1122 st->obytes = c->obytes; 1123 st->opkts = c->opkts; 1124 st->ierrs = c->overrun + c->frame + c->crc; 1125 st->oerrs = c->underrun; 1126 return 0; 1127 1128 case SERIAL_GETESTAT: 1129 CP_DEBUG2 (d, ("ioctl: getestat\n")); 1130 if (c->type != T_E1 && c->type != T_G703) 1131 return EINVAL; 1132 opte1 = (struct e1_statistics*) data; 1133 opte1->status = c->status; 1134 opte1->cursec = c->cursec; 1135 opte1->totsec = c->totsec + c->cursec; 1136 1137 opte1->currnt.bpv = c->currnt.bpv; 1138 opte1->currnt.fse = c->currnt.fse; 1139 opte1->currnt.crce = c->currnt.crce; 1140 opte1->currnt.rcrce = c->currnt.rcrce; 1141 opte1->currnt.uas = c->currnt.uas; 1142 opte1->currnt.les = c->currnt.les; 1143 opte1->currnt.es = c->currnt.es; 1144 opte1->currnt.bes = c->currnt.bes; 1145 opte1->currnt.ses = c->currnt.ses; 1146 opte1->currnt.oofs = c->currnt.oofs; 1147 opte1->currnt.css = c->currnt.css; 1148 opte1->currnt.dm = c->currnt.dm; 1149 1150 opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1151 opte1->total.fse = c->total.fse + c->currnt.fse; 1152 opte1->total.crce = c->total.crce + c->currnt.crce; 1153 opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1154 opte1->total.uas = c->total.uas + c->currnt.uas; 1155 opte1->total.les = c->total.les + c->currnt.les; 1156 opte1->total.es = c->total.es + c->currnt.es; 1157 opte1->total.bes = c->total.bes + c->currnt.bes; 1158 opte1->total.ses = c->total.ses + c->currnt.ses; 1159 opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1160 opte1->total.css = c->total.css + c->currnt.css; 1161 opte1->total.dm = c->total.dm + c->currnt.dm; 1162 for (s=0; s<48; ++s) { 1163 opte1->interval[s].bpv = c->interval[s].bpv; 1164 opte1->interval[s].fse = c->interval[s].fse; 1165 opte1->interval[s].crce = c->interval[s].crce; 1166 opte1->interval[s].rcrce = c->interval[s].rcrce; 1167 opte1->interval[s].uas = c->interval[s].uas; 1168 opte1->interval[s].les = c->interval[s].les; 1169 opte1->interval[s].es = c->interval[s].es; 1170 opte1->interval[s].bes = c->interval[s].bes; 1171 opte1->interval[s].ses = c->interval[s].ses; 1172 opte1->interval[s].oofs = c->interval[s].oofs; 1173 opte1->interval[s].css = c->interval[s].css; 1174 opte1->interval[s].dm = c->interval[s].dm; 1175 } 1176 return 0; 1177 1178 case SERIAL_GETE3STAT: 1179 CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 1180 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1181 return EINVAL; 1182 opte3 = (struct e3_statistics*) data; 1183 1184 opte3->status = c->e3status; 1185 opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 1186 opte3->totsec = c->e3tsec + opte3->cursec; 1187 1188 opte3->ccv = c->e3ccv; 1189 opte3->tcv = c->e3tcv + opte3->ccv; 1190 1191 for (s = 0; s < 48; ++s) { 1192 opte3->icv[s] = c->e3icv[s]; 1193 } 1194 return 0; 1195 1196 case SERIAL_CLRSTAT: 1197 CP_DEBUG2 (d, ("ioctl: clrstat\n")); 1198 /* Only for superuser! */ 1199 error = priv_check (td, PRIV_DRIVER); 1200 if (error) 1201 return error; 1202 c->rintr = 0; 1203 c->tintr = 0; 1204 c->ibytes = 0; 1205 c->obytes = 0; 1206 c->ipkts = 0; 1207 c->opkts = 0; 1208 c->overrun = 0; 1209 c->frame = 0; 1210 c->crc = 0; 1211 c->underrun = 0; 1212 bzero (&c->currnt, sizeof (c->currnt)); 1213 bzero (&c->total, sizeof (c->total)); 1214 bzero (c->interval, sizeof (c->interval)); 1215 c->e3ccv = 0; 1216 c->e3tcv = 0; 1217 bzero (c->e3icv, sizeof (c->e3icv)); 1218 return 0; 1219 1220 case SERIAL_GETBAUD: 1221 CP_DEBUG2 (d, ("ioctl: getbaud\n")); 1222 *(long*)data = c->baud; 1223 return 0; 1224 1225 case SERIAL_SETBAUD: 1226 CP_DEBUG2 (d, ("ioctl: setbaud\n")); 1227 /* Only for superuser! */ 1228 error = priv_check (td, PRIV_DRIVER); 1229 if (error) 1230 return error; 1231 s = splimp (); 1232 CP_LOCK (bd); 1233 cp_set_baud (c, *(long*)data); 1234 CP_UNLOCK (bd); 1235 splx (s); 1236 return 0; 1237 1238 case SERIAL_GETLOOP: 1239 CP_DEBUG2 (d, ("ioctl: getloop\n")); 1240 *(int*)data = c->lloop; 1241 return 0; 1242 1243 case SERIAL_SETLOOP: 1244 CP_DEBUG2 (d, ("ioctl: setloop\n")); 1245 /* Only for superuser! */ 1246 error = priv_check (td, PRIV_DRIVER); 1247 if (error) 1248 return error; 1249 s = splimp (); 1250 CP_LOCK (bd); 1251 cp_set_lloop (c, *(int*)data); 1252 CP_UNLOCK (bd); 1253 splx (s); 1254 return 0; 1255 1256 case SERIAL_GETDPLL: 1257 CP_DEBUG2 (d, ("ioctl: getdpll\n")); 1258 if (c->type != T_SERIAL) 1259 return EINVAL; 1260 *(int*)data = c->dpll; 1261 return 0; 1262 1263 case SERIAL_SETDPLL: 1264 CP_DEBUG2 (d, ("ioctl: setdpll\n")); 1265 /* Only for superuser! */ 1266 error = priv_check (td, PRIV_DRIVER); 1267 if (error) 1268 return error; 1269 if (c->type != T_SERIAL) 1270 return EINVAL; 1271 s = splimp (); 1272 CP_LOCK (bd); 1273 cp_set_dpll (c, *(int*)data); 1274 CP_UNLOCK (bd); 1275 splx (s); 1276 return 0; 1277 1278 case SERIAL_GETNRZI: 1279 CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 1280 if (c->type != T_SERIAL) 1281 return EINVAL; 1282 *(int*)data = c->nrzi; 1283 return 0; 1284 1285 case SERIAL_SETNRZI: 1286 CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 1287 /* Only for superuser! */ 1288 error = priv_check (td, PRIV_DRIVER); 1289 if (error) 1290 return error; 1291 if (c->type != T_SERIAL) 1292 return EINVAL; 1293 s = splimp (); 1294 CP_LOCK (bd); 1295 cp_set_nrzi (c, *(int*)data); 1296 CP_UNLOCK (bd); 1297 splx (s); 1298 return 0; 1299 1300 case SERIAL_GETDEBUG: 1301 CP_DEBUG2 (d, ("ioctl: getdebug\n")); 1302 *(int*)data = d->chan->debug; 1303 return 0; 1304 1305 case SERIAL_SETDEBUG: 1306 CP_DEBUG2 (d, ("ioctl: setdebug\n")); 1307 /* Only for superuser! */ 1308 error = priv_check (td, PRIV_DRIVER); 1309 if (error) 1310 return error; 1311#ifndef NETGRAPH 1312 /* 1313 * The debug_shadow is always greater than zero for logic 1314 * simplicity. For switching debug off the IFF_DEBUG is 1315 * responsible. 1316 */ 1317 d->chan->debug_shadow = (*(int*)data) ? (*(int*)data) : 1; 1318 if (d->ifp->if_flags & IFF_DEBUG) 1319 d->chan->debug = d->chan->debug_shadow; 1320#else 1321 d->chan->debug = *(int*)data; 1322#endif 1323 return 0; 1324 1325 case SERIAL_GETHIGAIN: 1326 CP_DEBUG2 (d, ("ioctl: gethigain\n")); 1327 if (c->type != T_E1) 1328 return EINVAL; 1329 *(int*)data = c->higain; 1330 return 0; 1331 1332 case SERIAL_SETHIGAIN: 1333 CP_DEBUG2 (d, ("ioctl: sethigain\n")); 1334 /* Only for superuser! */ 1335 error = priv_check (td, PRIV_DRIVER); 1336 if (error) 1337 return error; 1338 if (c->type != T_E1) 1339 return EINVAL; 1340 s = splimp (); 1341 CP_LOCK (bd); 1342 cp_set_higain (c, *(int*)data); 1343 CP_UNLOCK (bd); 1344 splx (s); 1345 return 0; 1346 1347 case SERIAL_GETPHONY: 1348 CP_DEBUG2 (d, ("ioctl: getphony\n")); 1349 if (c->type != T_E1) 1350 return EINVAL; 1351 *(int*)data = c->phony; 1352 return 0; 1353 1354 case SERIAL_SETPHONY: 1355 CP_DEBUG2 (d, ("ioctl: setphony\n")); 1356 /* Only for superuser! */ 1357 error = priv_check (td, PRIV_DRIVER); 1358 if (error) 1359 return error; 1360 if (c->type != T_E1) 1361 return EINVAL; 1362 s = splimp (); 1363 CP_LOCK (bd); 1364 cp_set_phony (c, *(int*)data); 1365 CP_UNLOCK (bd); 1366 splx (s); 1367 return 0; 1368 1369 case SERIAL_GETUNFRAM: 1370 CP_DEBUG2 (d, ("ioctl: getunfram\n")); 1371 if (c->type != T_E1) 1372 return EINVAL; 1373 *(int*)data = c->unfram; 1374 return 0; 1375 1376 case SERIAL_SETUNFRAM: 1377 CP_DEBUG2 (d, ("ioctl: setunfram\n")); 1378 /* Only for superuser! */ 1379 error = priv_check (td, PRIV_DRIVER); 1380 if (error) 1381 return error; 1382 if (c->type != T_E1) 1383 return EINVAL; 1384 s = splimp (); 1385 CP_LOCK (bd); 1386 cp_set_unfram (c, *(int*)data); 1387 CP_UNLOCK (bd); 1388 splx (s); 1389 return 0; 1390 1391 case SERIAL_GETSCRAMBLER: 1392 CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 1393 if (c->type != T_G703 && !c->unfram) 1394 return EINVAL; 1395 *(int*)data = c->scrambler; 1396 return 0; 1397 1398 case SERIAL_SETSCRAMBLER: 1399 CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 1400 /* Only for superuser! */ 1401 error = priv_check (td, PRIV_DRIVER); 1402 if (error) 1403 return error; 1404 if (c->type != T_G703 && !c->unfram) 1405 return EINVAL; 1406 s = splimp (); 1407 CP_LOCK (bd); 1408 cp_set_scrambler (c, *(int*)data); 1409 CP_UNLOCK (bd); 1410 splx (s); 1411 return 0; 1412 1413 case SERIAL_GETMONITOR: 1414 CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 1415 if (c->type != T_E1 && 1416 c->type != T_E3 && 1417 c->type != T_T3 && 1418 c->type != T_STS1) 1419 return EINVAL; 1420 *(int*)data = c->monitor; 1421 return 0; 1422 1423 case SERIAL_SETMONITOR: 1424 CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 1425 /* Only for superuser! */ 1426 error = priv_check (td, PRIV_DRIVER); 1427 if (error) 1428 return error; 1429 if (c->type != T_E1) 1430 return EINVAL; 1431 s = splimp (); 1432 CP_LOCK (bd); 1433 cp_set_monitor (c, *(int*)data); 1434 CP_UNLOCK (bd); 1435 splx (s); 1436 return 0; 1437 1438 case SERIAL_GETUSE16: 1439 CP_DEBUG2 (d, ("ioctl: getuse16\n")); 1440 if (c->type != T_E1 || c->unfram) 1441 return EINVAL; 1442 *(int*)data = c->use16; 1443 return 0; 1444 1445 case SERIAL_SETUSE16: 1446 CP_DEBUG2 (d, ("ioctl: setuse16\n")); 1447 /* Only for superuser! */ 1448 error = priv_check (td, PRIV_DRIVER); 1449 if (error) 1450 return error; 1451 if (c->type != T_E1) 1452 return EINVAL; 1453 s = splimp (); 1454 CP_LOCK (bd); 1455 cp_set_use16 (c, *(int*)data); 1456 CP_UNLOCK (bd); 1457 splx (s); 1458 return 0; 1459 1460 case SERIAL_GETCRC4: 1461 CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 1462 if (c->type != T_E1 || c->unfram) 1463 return EINVAL; 1464 *(int*)data = c->crc4; 1465 return 0; 1466 1467 case SERIAL_SETCRC4: 1468 CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 1469 /* Only for superuser! */ 1470 error = priv_check (td, PRIV_DRIVER); 1471 if (error) 1472 return error; 1473 if (c->type != T_E1) 1474 return EINVAL; 1475 s = splimp (); 1476 CP_LOCK (bd); 1477 cp_set_crc4 (c, *(int*)data); 1478 CP_UNLOCK (bd); 1479 splx (s); 1480 return 0; 1481 1482 case SERIAL_GETCLK: 1483 CP_DEBUG2 (d, ("ioctl: getclk\n")); 1484 if (c->type != T_E1 && 1485 c->type != T_G703 && 1486 c->type != T_E3 && 1487 c->type != T_T3 && 1488 c->type != T_STS1) 1489 return EINVAL; 1490 switch (c->gsyn) { 1491 default: *(int*)data = E1CLK_INTERNAL; break; 1492 case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1493 case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1494 case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1495 case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 1496 case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 1497 } 1498 return 0; 1499 1500 case SERIAL_SETCLK: 1501 CP_DEBUG2 (d, ("ioctl: setclk\n")); 1502 /* Only for superuser! */ 1503 error = priv_check (td, PRIV_DRIVER); 1504 if (error) 1505 return error; 1506 if (c->type != T_E1 && 1507 c->type != T_G703 && 1508 c->type != T_E3 && 1509 c->type != T_T3 && 1510 c->type != T_STS1) 1511 return EINVAL; 1512 s = splimp (); 1513 CP_LOCK (bd); 1514 switch (*(int*)data) { 1515 default: cp_set_gsyn (c, GSYN_INT); break; 1516 case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 1517 case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 1518 case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 1519 case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 1520 case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 1521 } 1522 CP_UNLOCK (bd); 1523 splx (s); 1524 return 0; 1525 1526 case SERIAL_GETTIMESLOTS: 1527 CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1528 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1529 return EINVAL; 1530 *(u_long*)data = c->ts; 1531 return 0; 1532 1533 case SERIAL_SETTIMESLOTS: 1534 CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 1535 /* Only for superuser! */ 1536 error = priv_check (td, PRIV_DRIVER); 1537 if (error) 1538 return error; 1539 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1540 return EINVAL; 1541 s = splimp (); 1542 CP_LOCK (bd); 1543 cp_set_ts (c, *(u_long*)data); 1544 CP_UNLOCK (bd); 1545 splx (s); 1546 return 0; 1547 1548 case SERIAL_GETINVCLK: 1549 CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 1550#if 1 1551 return EINVAL; 1552#else 1553 if (c->type != T_SERIAL) 1554 return EINVAL; 1555 *(int*)data = c->invtxc; 1556 return 0; 1557#endif 1558 1559 case SERIAL_SETINVCLK: 1560 CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 1561 /* Only for superuser! */ 1562 error = priv_check (td, PRIV_DRIVER); 1563 if (error) 1564 return error; 1565 if (c->type != T_SERIAL) 1566 return EINVAL; 1567 s = splimp (); 1568 CP_LOCK (bd); 1569 cp_set_invtxc (c, *(int*)data); 1570 cp_set_invrxc (c, *(int*)data); 1571 CP_UNLOCK (bd); 1572 splx (s); 1573 return 0; 1574 1575 case SERIAL_GETINVTCLK: 1576 CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 1577 if (c->type != T_SERIAL) 1578 return EINVAL; 1579 *(int*)data = c->invtxc; 1580 return 0; 1581 1582 case SERIAL_SETINVTCLK: 1583 CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 1584 /* Only for superuser! */ 1585 error = priv_check (td, PRIV_DRIVER); 1586 if (error) 1587 return error; 1588 if (c->type != T_SERIAL) 1589 return EINVAL; 1590 s = splimp (); 1591 CP_LOCK (bd); 1592 cp_set_invtxc (c, *(int*)data); 1593 CP_UNLOCK (bd); 1594 splx (s); 1595 return 0; 1596 1597 case SERIAL_GETINVRCLK: 1598 CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 1599 if (c->type != T_SERIAL) 1600 return EINVAL; 1601 *(int*)data = c->invrxc; 1602 return 0; 1603 1604 case SERIAL_SETINVRCLK: 1605 CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 1606 /* Only for superuser! */ 1607 error = priv_check (td, PRIV_DRIVER); 1608 if (error) 1609 return error; 1610 if (c->type != T_SERIAL) 1611 return EINVAL; 1612 s = splimp (); 1613 CP_LOCK (bd); 1614 cp_set_invrxc (c, *(int*)data); 1615 CP_UNLOCK (bd); 1616 splx (s); 1617 return 0; 1618 1619 case SERIAL_GETLEVEL: 1620 CP_DEBUG2 (d, ("ioctl: getlevel\n")); 1621 if (c->type != T_G703) 1622 return EINVAL; 1623 s = splimp (); 1624 CP_LOCK (bd); 1625 *(int*)data = cp_get_lq (c); 1626 CP_UNLOCK (bd); 1627 splx (s); 1628 return 0; 1629 1630#if 0 1631 case SERIAL_RESET: 1632 CP_DEBUG2 (d, ("ioctl: reset\n")); 1633 /* Only for superuser! */ 1634 error = priv_check (td, PRIV_DRIVER); 1635 if (error) 1636 return error; 1637 s = splimp (); 1638 CP_LOCK (bd); 1639 cp_reset (c->board, 0, 0); 1640 CP_UNLOCK (bd); 1641 splx (s); 1642 return 0; 1643 1644 case SERIAL_HARDRESET: 1645 CP_DEBUG2 (d, ("ioctl: hardreset\n")); 1646 /* Only for superuser! */ 1647 error = priv_check (td, PRIV_DRIVER); 1648 if (error) 1649 return error; 1650 s = splimp (); 1651 CP_LOCK (bd); 1652 /* hard_reset (c->board); */ 1653 CP_UNLOCK (bd); 1654 splx (s); 1655 return 0; 1656#endif 1657 1658 case SERIAL_GETCABLE: 1659 CP_DEBUG2 (d, ("ioctl: getcable\n")); 1660 if (c->type != T_SERIAL) 1661 return EINVAL; 1662 s = splimp (); 1663 CP_LOCK (bd); 1664 *(int*)data = cp_get_cable (c); 1665 CP_UNLOCK (bd); 1666 splx (s); 1667 return 0; 1668 1669 case SERIAL_GETDIR: 1670 CP_DEBUG2 (d, ("ioctl: getdir\n")); 1671 if (c->type != T_E1 && c->type != T_DATA) 1672 return EINVAL; 1673 *(int*)data = c->dir; 1674 return 0; 1675 1676 case SERIAL_SETDIR: 1677 CP_DEBUG2 (d, ("ioctl: setdir\n")); 1678 /* Only for superuser! */ 1679 error = priv_check (td, PRIV_DRIVER); 1680 if (error) 1681 return error; 1682 s = splimp (); 1683 CP_LOCK (bd); 1684 cp_set_dir (c, *(int*)data); 1685 CP_UNLOCK (bd); 1686 splx (s); 1687 return 0; 1688 1689 case SERIAL_GETRLOOP: 1690 CP_DEBUG2 (d, ("ioctl: getrloop\n")); 1691 if (c->type != T_G703 && 1692 c->type != T_E3 && 1693 c->type != T_T3 && 1694 c->type != T_STS1) 1695 return EINVAL; 1696 *(int*)data = cp_get_rloop (c); 1697 return 0; 1698 1699 case SERIAL_SETRLOOP: 1700 CP_DEBUG2 (d, ("ioctl: setloop\n")); 1701 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 1702 return EINVAL; 1703 /* Only for superuser! */ 1704 error = priv_check (td, PRIV_DRIVER); 1705 if (error) 1706 return error; 1707 s = splimp (); 1708 CP_LOCK (bd); 1709 cp_set_rloop (c, *(int*)data); 1710 CP_UNLOCK (bd); 1711 splx (s); 1712 return 0; 1713 1714 case SERIAL_GETCABLEN: 1715 CP_DEBUG2 (d, ("ioctl: getcablen\n")); 1716 if (c->type != T_T3 && c->type != T_STS1) 1717 return EINVAL; 1718 *(int*)data = c->cablen; 1719 return 0; 1720 1721 case SERIAL_SETCABLEN: 1722 CP_DEBUG2 (d, ("ioctl: setloop\n")); 1723 if (c->type != T_T3 && c->type != T_STS1) 1724 return EINVAL; 1725 /* Only for superuser! */ 1726 error = priv_check (td, PRIV_DRIVER); 1727 if (error) 1728 return error; 1729 s = splimp (); 1730 CP_LOCK (bd); 1731 cp_set_cablen (c, *(int*)data); 1732 CP_UNLOCK (bd); 1733 splx (s); 1734 return 0; 1735 1736 case TIOCSDTR: /* Set DTR */ 1737 s = splimp (); 1738 CP_LOCK (bd); 1739 cp_set_dtr (c, 1); 1740 CP_UNLOCK (bd); 1741 splx (s); 1742 return 0; 1743 1744 case TIOCCDTR: /* Clear DTR */ 1745 s = splimp (); 1746 CP_LOCK (bd); 1747 cp_set_dtr (c, 0); 1748 CP_UNLOCK (bd); 1749 splx (s); 1750 return 0; 1751 1752 case TIOCMSET: /* Set DTR/RTS */ 1753 s = splimp (); 1754 CP_LOCK (bd); 1755 cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1756 cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1757 CP_UNLOCK (bd); 1758 splx (s); 1759 return 0; 1760 1761 case TIOCMBIS: /* Add DTR/RTS */ 1762 s = splimp (); 1763 CP_LOCK (bd); 1764 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 1765 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 1766 CP_UNLOCK (bd); 1767 splx (s); 1768 return 0; 1769 1770 case TIOCMBIC: /* Clear DTR/RTS */ 1771 s = splimp (); 1772 CP_LOCK (bd); 1773 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1774 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1775 CP_UNLOCK (bd); 1776 splx (s); 1777 return 0; 1778 1779 case TIOCMGET: /* Get modem status */ 1780 *(int*)data = cp_modem_status (c); 1781 return 0; 1782 } 1783 return ENOTTY; 1784} 1785 1786#ifdef NETGRAPH 1787static int ng_cp_constructor (node_p node) 1788{ 1789 drv_t *d = NG_NODE_PRIVATE (node); 1790 CP_DEBUG (d, ("Constructor\n")); 1791 return EINVAL; 1792} 1793 1794static int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1795{ 1796 int s; 1797 drv_t *d = NG_NODE_PRIVATE (node); 1798 bdrv_t *bd = d->board->sys; 1799 1800 CP_DEBUG (d, ("Newhook\n")); 1801 /* Attach debug hook */ 1802 if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1803 NG_HOOK_SET_PRIVATE (hook, NULL); 1804 d->debug_hook = hook; 1805 return 0; 1806 } 1807 1808 /* Check for raw hook */ 1809 if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1810 return EINVAL; 1811 1812 NG_HOOK_SET_PRIVATE (hook, d); 1813 d->hook = hook; 1814 s = splimp (); 1815 CP_LOCK (bd); 1816 cp_up (d); 1817 CP_UNLOCK (bd); 1818 splx (s); 1819 return 0; 1820} 1821 1822static char *format_timeslots (u_long s) 1823{ 1824 static char buf [100]; 1825 char *p = buf; 1826 int i; 1827 1828 for (i=1; i<32; ++i) 1829 if ((s >> i) & 1) { 1830 int prev = (i > 1) & (s >> (i-1)); 1831 int next = (i < 31) & (s >> (i+1)); 1832 1833 if (prev) { 1834 if (next) 1835 continue; 1836 *p++ = '-'; 1837 } else if (p > buf) 1838 *p++ = ','; 1839 1840 if (i >= 10) 1841 *p++ = '0' + i / 10; 1842 *p++ = '0' + i % 10; 1843 } 1844 *p = 0; 1845 return buf; 1846} 1847 1848static int print_modems (char *s, cp_chan_t *c, int need_header) 1849{ 1850 int status = cp_modem_status (c); 1851 int length = 0; 1852 1853 if (need_header) 1854 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1855 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1856 status & TIOCM_LE ? "On" : "-", 1857 status & TIOCM_DTR ? "On" : "-", 1858 status & TIOCM_DSR ? "On" : "-", 1859 status & TIOCM_RTS ? "On" : "-", 1860 status & TIOCM_CTS ? "On" : "-", 1861 status & TIOCM_CD ? "On" : "-"); 1862 return length; 1863} 1864 1865static int print_stats (char *s, cp_chan_t *c, int need_header) 1866{ 1867 int length = 0; 1868 1869 if (need_header) 1870 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1871 length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1872 c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1873 c->ipkts, c->overrun + c->frame + c->crc, 1874 (unsigned long) c->obytes, c->opkts, c->underrun); 1875 return length; 1876} 1877 1878static char *format_e1_status (u_char status) 1879{ 1880 static char buf [80]; 1881 1882 if (status & E1_NOALARM) 1883 return "Ok"; 1884 buf[0] = 0; 1885 if (status & E1_LOS) strcat (buf, ",LOS"); 1886 if (status & E1_AIS) strcat (buf, ",AIS"); 1887 if (status & E1_LOF) strcat (buf, ",LOF"); 1888 if (status & E1_LOMF) strcat (buf, ",LOMF"); 1889 if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1890 if (status & E1_AIS16) strcat (buf, ",AIS16"); 1891 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1892 if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1893 if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1894 if (buf[0] == ',') 1895 return buf+1; 1896 return "Unknown"; 1897} 1898 1899static int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1900{ 1901 int n, length = 0; 1902 1903 if (numerator < 1 || divider < 1) { 1904 length += sprintf (s+length, leftalign ? "/- " : " -"); 1905 return length; 1906 } 1907 n = (int) (0.5 + 1000.0 * numerator / divider); 1908 if (n < 1000) { 1909 length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1910 return length; 1911 } 1912 *(s + length) = leftalign ? '/' : ' '; 1913 length ++; 1914 1915 if (n >= 1000000) n = (n+500) / 1000 * 1000; 1916 else if (n >= 100000) n = (n+50) / 100 * 100; 1917 else if (n >= 10000) n = (n+5) / 10 * 10; 1918 1919 switch (n) { 1920 case 1000: length += printf (s+length, ".999"); return length; 1921 case 10000: n = 9990; break; 1922 case 100000: n = 99900; break; 1923 case 1000000: n = 999000; break; 1924 } 1925 if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1926 else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1927 else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1928 else length += sprintf (s+length, "%d", n/1000); 1929 1930 return length; 1931} 1932 1933static int print_e1_stats (char *s, cp_chan_t *c) 1934{ 1935 struct e1_counters total; 1936 u_long totsec; 1937 int length = 0; 1938 1939 totsec = c->totsec + c->cursec; 1940 total.bpv = c->total.bpv + c->currnt.bpv; 1941 total.fse = c->total.fse + c->currnt.fse; 1942 total.crce = c->total.crce + c->currnt.crce; 1943 total.rcrce = c->total.rcrce + c->currnt.rcrce; 1944 total.uas = c->total.uas + c->currnt.uas; 1945 total.les = c->total.les + c->currnt.les; 1946 total.es = c->total.es + c->currnt.es; 1947 total.bes = c->total.bes + c->currnt.bes; 1948 total.ses = c->total.ses + c->currnt.ses; 1949 total.oofs = c->total.oofs + c->currnt.oofs; 1950 total.css = c->total.css + c->currnt.css; 1951 total.dm = c->total.dm + c->currnt.dm; 1952 1953 length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1954 1955 /* Unavailable seconds, degraded minutes */ 1956 length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1957 length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1958 1959 /* Bipolar violations, frame sync errors */ 1960 length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1961 length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1962 1963 /* CRC errors, remote CRC errors (E-bit) */ 1964 length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 1965 length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 1966 1967 /* Errored seconds, line errored seconds */ 1968 length += print_frac (s + length, 0, c->currnt.es, c->cursec); 1969 length += print_frac (s + length, 1, c->currnt.les, c->cursec); 1970 1971 /* Severely errored seconds, burst errored seconds */ 1972 length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 1973 length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 1974 1975 /* Out of frame seconds, controlled slip seconds */ 1976 length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 1977 length += print_frac (s + length, 1, c->currnt.css, c->cursec); 1978 1979 length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 1980 1981 /* Print total statistics. */ 1982 length += print_frac (s + length, 0, total.uas, totsec); 1983 length += print_frac (s + length, 1, 60 * total.dm, totsec); 1984 1985 length += print_frac (s + length, 0, total.bpv, totsec); 1986 length += print_frac (s + length, 1, total.fse, totsec); 1987 1988 length += print_frac (s + length, 0, total.crce, totsec); 1989 length += print_frac (s + length, 1, total.rcrce, totsec); 1990 1991 length += print_frac (s + length, 0, total.es, totsec); 1992 length += print_frac (s + length, 1, total.les, totsec); 1993 1994 length += print_frac (s + length, 0, total.ses, totsec); 1995 length += print_frac (s + length, 1, total.bes, totsec); 1996 1997 length += print_frac (s + length, 0, total.oofs, totsec); 1998 length += print_frac (s + length, 1, total.css, totsec); 1999 2000 length += sprintf (s + length, " -- Total\n"); 2001 return length; 2002} 2003 2004static int print_chan (char *s, cp_chan_t *c) 2005{ 2006 drv_t *d = c->sys; 2007 bdrv_t *bd = d->board->sys; 2008 int length = 0; 2009 2010 length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2011 if (d->chan->debug) 2012 length += sprintf (s + length, " debug=%d", d->chan->debug); 2013 2014 if (c->board->mux) { 2015 length += sprintf (s + length, " cfg=C"); 2016 } else { 2017 length += sprintf (s + length, " cfg=A"); 2018 } 2019 2020 if (c->baud) 2021 length += sprintf (s + length, " %ld", c->baud); 2022 else 2023 length += sprintf (s + length, " extclock"); 2024 2025 if (c->type == T_E1 || c->type == T_G703) 2026 switch (c->gsyn) { 2027 case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2028 case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2029 case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2030 case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2031 case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2032 case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2033 } 2034 if (c->type == T_SERIAL) { 2035 length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2036 length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2037 length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2038 } 2039 if (c->type == T_E1) 2040 length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2041 2042 length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2043 2044 if (c->type == T_E1) 2045 length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2046 if (c->type == T_G703) { 2047 int lq, x; 2048 2049 x = splimp (); 2050 CP_LOCK (bd); 2051 lq = cp_get_lq (c); 2052 CP_UNLOCK (bd); 2053 splx (x); 2054 length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2055 } 2056 length += sprintf (s + length, "\n"); 2057 return length; 2058} 2059 2060static int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2061{ 2062 drv_t *d = NG_NODE_PRIVATE (node); 2063 struct ng_mesg *msg; 2064 struct ng_mesg *resp = NULL; 2065 int error = 0; 2066 2067 CP_DEBUG (d, ("Rcvmsg\n")); 2068 NGI_GET_MSG (item, msg); 2069 switch (msg->header.typecookie) { 2070 default: 2071 error = EINVAL; 2072 break; 2073 2074 case NGM_CP_COOKIE: 2075 printf ("Not implemented yet\n"); 2076 error = EINVAL; 2077 break; 2078 2079 case NGM_GENERIC_COOKIE: 2080 switch (msg->header.cmd) { 2081 default: 2082 error = EINVAL; 2083 break; 2084 2085 case NGM_TEXT_STATUS: { 2086 char *s; 2087 int l = 0; 2088 int dl = sizeof (struct ng_mesg) + 730; 2089 2090 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2091 if (! resp) { 2092 error = ENOMEM; 2093 break; 2094 } 2095 s = (resp)->data; 2096 if (d) { 2097 l += print_chan (s + l, d->chan); 2098 l += print_stats (s + l, d->chan, 1); 2099 l += print_modems (s + l, d->chan, 1); 2100 l += print_e1_stats (s + l, d->chan); 2101 } else 2102 l += sprintf (s + l, "Error: node not connect to channel"); 2103 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRSIZ); 2104 } 2105 break; 2106 } 2107 break; 2108 } 2109 NG_RESPOND_MSG (error, node, item, resp); 2110 NG_FREE_MSG (msg); 2111 return error; 2112} 2113 2114static int ng_cp_rcvdata (hook_p hook, item_p item) 2115{ 2116 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2117 struct mbuf *m; 2118 struct ng_tag_prio *ptag; 2119 bdrv_t *bd = d->board->sys; 2120 struct ifqueue *q; 2121 int s; 2122 2123 CP_DEBUG2 (d, ("Rcvdata\n")); 2124 NGI_GET_M (item, m); 2125 NG_FREE_ITEM (item); 2126 if (! NG_HOOK_PRIVATE (hook) || ! d) { 2127 NG_FREE_M (m); 2128 return ENETDOWN; 2129 } 2130 2131 /* Check for high priority data */ 2132 if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2133 NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2134 q = &d->hi_queue; 2135 else 2136 q = &d->queue; 2137 2138 s = splimp (); 2139 CP_LOCK (bd); 2140 IF_LOCK (q); 2141 if (_IF_QFULL (q)) { 2142 IF_UNLOCK (q); 2143 CP_UNLOCK (bd); 2144 splx (s); 2145 NG_FREE_M (m); 2146 return ENOBUFS; 2147 } 2148 _IF_ENQUEUE (q, m); 2149 IF_UNLOCK (q); 2150 cp_start (d); 2151 CP_UNLOCK (bd); 2152 splx (s); 2153 return 0; 2154} 2155 2156static int ng_cp_rmnode (node_p node) 2157{ 2158 drv_t *d = NG_NODE_PRIVATE (node); 2159 2160 CP_DEBUG (d, ("Rmnode\n")); 2161 if (d && d->running) { 2162 bdrv_t *bd = d->board->sys; 2163 int s = splimp (); 2164 CP_LOCK (bd); 2165 cp_down (d); 2166 CP_UNLOCK (bd); 2167 splx (s); 2168 } 2169#ifdef KLD_MODULE 2170 if (node->nd_flags & NGF_REALLY_DIE) { 2171 NG_NODE_SET_PRIVATE (node, NULL); 2172 NG_NODE_UNREF (node); 2173 } 2174 NG_NODE_REVIVE(node); /* Persistent node */ 2175#endif 2176 return 0; 2177} 2178 2179static int ng_cp_connect (hook_p hook) 2180{ 2181 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2182 2183 if (d) { 2184 CP_DEBUG (d, ("Connect\n")); 2185 callout_reset (&d->timeout_handle, hz, cp_watchdog_timer, d); 2186 } 2187 2188 return 0; 2189} 2190 2191static int ng_cp_disconnect (hook_p hook) 2192{ 2193 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2194 2195 if (d) { 2196 CP_DEBUG (d, ("Disconnect\n")); 2197 if (NG_HOOK_PRIVATE (hook)) 2198 { 2199 bdrv_t *bd = d->board->sys; 2200 int s = splimp (); 2201 CP_LOCK (bd); 2202 cp_down (d); 2203 CP_UNLOCK (bd); 2204 splx (s); 2205 } 2206 /* If we were wait it than it reasserted now, just stop it. */ 2207 if (!callout_drain (&d->timeout_handle)) 2208 callout_stop (&d->timeout_handle); 2209 } 2210 return 0; 2211} 2212#endif 2213 2214static int cp_modevent (module_t mod, int type, void *unused) 2215{ 2216 static int load_count = 0; 2217 2218 switch (type) { 2219 case MOD_LOAD: 2220#ifdef NETGRAPH 2221 if (ng_newtype (&typestruct)) 2222 printf ("Failed to register ng_cp\n"); 2223#endif 2224 ++load_count; 2225 callout_init (&timeout_handle, 1); 2226 callout_reset (&timeout_handle, hz*5, cp_timeout, 0); 2227 break; 2228 case MOD_UNLOAD: 2229 if (load_count == 1) { 2230 printf ("Removing device entry for Tau-PCI\n"); 2231#ifdef NETGRAPH 2232 ng_rmtype (&typestruct); 2233#endif 2234 } 2235 /* If we were wait it than it reasserted now, just stop it. 2236 * Actually we shouldn't get this condition. But code could be 2237 * changed in the future, so just be a litle paranoid. 2238 */ 2239 if (!callout_drain (&timeout_handle)) 2240 callout_stop (&timeout_handle); 2241 --load_count; 2242 break; 2243 case MOD_SHUTDOWN: 2244 break; 2245 } 2246 return 0; 2247} 2248 2249#ifdef NETGRAPH 2250static struct ng_type typestruct = { 2251 .version = NG_ABI_VERSION, 2252 .name = NG_CP_NODE_TYPE, 2253 .constructor = ng_cp_constructor, 2254 .rcvmsg = ng_cp_rcvmsg, 2255 .shutdown = ng_cp_rmnode, 2256 .newhook = ng_cp_newhook, 2257 .connect = ng_cp_connect, 2258 .rcvdata = ng_cp_rcvdata, 2259 .disconnect = ng_cp_disconnect, 2260}; 2261#endif /*NETGRAPH*/ 2262 2263#ifdef NETGRAPH 2264MODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2265#else 2266MODULE_DEPEND (cp, sppp, 1, 1, 1); 2267#endif 2268DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2269MODULE_VERSION (cp, 1); 2270