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