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