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