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