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