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