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