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