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