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