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