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