1 /* 2 * Cronyx-Tau32-PCI adapter driver for FreeBSD. 3 * 4 * Copyright (C) 2003-2005 Cronyx Engineering. 5 * Copyright (C) 2003-2005 Kurakin Roman, <[email protected]> 6 * 7 * This software is distributed with NO WARRANTIES, not even the implied 8 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * 10 * Authors grant any other persons or organisations a permission to use, 11 * modify and redistribute this software in source and binary forms, 12 * as long as this message is kept with the software, all derivative 13 * works or modified versions. 14 * 15 * $Cronyx: if_ce.c,v 1.9.2.8 2005/11/21 14:17:44 rik Exp $ 16 */ 17 18 #include <sys/cdefs.h> 19 __FBSDID("$FreeBSD$"); 20 21 #include <sys/param.h> 22 23 #include <sys/ucred.h> 24 #include <sys/priv.h> 25 #include <sys/proc.h> 26 #include <sys/systm.h> 27 #include <sys/mbuf.h> 28 #include <sys/kernel.h> 29 #include <sys/module.h> 30 #include <sys/conf.h> 31 #include <sys/malloc.h> 32 #include <sys/socket.h> 33 #include <sys/sockio.h> 34 #include <sys/sysctl.h> 35 #include <sys/tty.h> 36 #include <sys/bus.h> 37 #include <vm/vm.h> 38 #include <vm/pmap.h> 39 #include <net/if.h> 40 #include <net/if_var.h> 41 # include <dev/pci/pcivar.h> 42 # include <dev/pci/pcireg.h> 43 #include <machine/bus.h> 44 #include <sys/rman.h> 45 #include "opt_ng_cronyx.h" 46 #ifdef NETGRAPH_CRONYX 47 # include "opt_netgraph.h" 48 # ifndef NETGRAPH 49 # error #option NETGRAPH missed from configuration 50 # endif 51 # include <netgraph/ng_message.h> 52 # include <netgraph/netgraph.h> 53 # include <dev/ce/ng_ce.h> 54 #else 55 # include <net/if_types.h> 56 # include <net/if_sppp.h> 57 # define PP_CISCO IFF_LINK2 58 # include <net/bpf.h> 59 #endif 60 #include <dev/ce/machdep.h> 61 #include <dev/ce/ceddk.h> 62 #include <machine/cserial.h> 63 #include <machine/resource.h> 64 65 /* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 66 #ifndef PP_FR 67 #define PP_FR 0 68 #endif 69 70 #ifndef IFP2SP 71 #define IFP2SP(ifp) ((struct sppp*)ifp) 72 #endif 73 #ifndef SP2IFP 74 #define SP2IFP(sp) ((struct ifnet*)sp) 75 #endif 76 77 #ifndef PCIR_BAR 78 #define PCIR_BAR(x) (PCIR_MAPS + (x) * 4) 79 #endif 80 81 /* define as our previous return value */ 82 #ifndef BUS_PROBE_DEFAULT 83 #define BUS_PROBE_DEFAULT 0 84 #endif 85 86 #define CE_DEBUG(d,s) ({if (d->chan->debug) {\ 87 printf ("%s: ", d->name); printf s;}}) 88 #define CE_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 89 printf ("%s: ", d->name); printf s;}}) 90 91 #ifndef IF_DRAIN 92 #define IF_DRAIN(ifq) do { \ 93 struct mbuf *m; \ 94 for (;;) { \ 95 IF_DEQUEUE(ifq, m); \ 96 if (m == NULL) \ 97 break; \ 98 m_freem(m); \ 99 } \ 100 } while (0) 101 #endif 102 103 #ifndef _IF_QLEN 104 #define _IF_QLEN(ifq) ((ifq)->ifq_len) 105 #endif 106 107 #ifndef callout_drain 108 #define callout_drain callout_stop 109 #endif 110 111 #define CE_LOCK_NAME "ceX" 112 113 #define CE_LOCK(_bd) mtx_lock (&(_bd)->ce_mtx) 114 #define CE_UNLOCK(_bd) mtx_unlock (&(_bd)->ce_mtx) 115 #define CE_LOCK_ASSERT(_bd) mtx_assert (&(_bd)->ce_mtx, MA_OWNED) 116 117 #define CDEV_MAJOR 185 118 119 static int ce_probe __P((device_t)); 120 static int ce_attach __P((device_t)); 121 static int ce_detach __P((device_t)); 122 123 static device_method_t ce_methods[] = { 124 /* Device interface */ 125 DEVMETHOD(device_probe, ce_probe), 126 DEVMETHOD(device_attach, ce_attach), 127 DEVMETHOD(device_detach, ce_detach), 128 129 DEVMETHOD_END 130 }; 131 132 typedef struct _ce_dma_mem_t { 133 unsigned long phys; 134 void *virt; 135 size_t size; 136 bus_dma_tag_t dmat; 137 bus_dmamap_t mapp; 138 } ce_dma_mem_t; 139 140 typedef struct _drv_t { 141 char name [8]; 142 int running; 143 ce_board_t *board; 144 ce_chan_t *chan; 145 struct ifqueue rqueue; 146 #ifdef NETGRAPH 147 char nodename [NG_NODESIZE]; 148 hook_p hook; 149 hook_p debug_hook; 150 node_p node; 151 struct ifqueue queue; 152 struct ifqueue hi_queue; 153 #else 154 struct ifnet *ifp; 155 #endif 156 short timeout; 157 struct callout timeout_handle; 158 struct cdev *devt; 159 ce_dma_mem_t dmamem; 160 } drv_t; 161 162 typedef struct _bdrv_t { 163 ce_board_t *board; 164 struct resource *ce_res; 165 struct resource *ce_irq; 166 void *ce_intrhand; 167 ce_dma_mem_t dmamem; 168 drv_t channel [NCHAN]; 169 struct mtx ce_mtx; 170 } bdrv_t; 171 172 static driver_t ce_driver = { 173 "ce", 174 ce_methods, 175 sizeof(bdrv_t), 176 }; 177 178 static devclass_t ce_devclass; 179 180 static void ce_receive (ce_chan_t *c, unsigned char *data, int len); 181 static void ce_transmit (ce_chan_t *c, void *attachment, int len); 182 static void ce_error (ce_chan_t *c, int data); 183 static void ce_up (drv_t *d); 184 static void ce_start (drv_t *d); 185 static void ce_down (drv_t *d); 186 static void ce_watchdog (drv_t *d); 187 static void ce_watchdog_timer (void *arg); 188 #ifdef NETGRAPH 189 extern struct ng_type typestruct; 190 #else 191 static void ce_ifstart (struct ifnet *ifp); 192 static void ce_tlf (struct sppp *sp); 193 static void ce_tls (struct sppp *sp); 194 static int ce_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 195 static void ce_initialize (void *softc); 196 #endif 197 198 static ce_board_t *adapter [NBRD]; 199 static drv_t *channel [NBRD*NCHAN]; 200 static struct callout led_timo [NBRD]; 201 static struct callout timeout_handle; 202 203 static int ce_destroy = 0; 204 205 static int ce_open (struct cdev *dev, int oflags, int devtype, struct thread *td); 206 static int ce_close (struct cdev *dev, int fflag, int devtype, struct thread *td); 207 static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); 208 static struct cdevsw ce_cdevsw = { 209 .d_version = D_VERSION, 210 .d_open = ce_open, 211 .d_close = ce_close, 212 .d_ioctl = ce_ioctl, 213 .d_name = "ce", 214 }; 215 216 /* 217 * Make an mbuf from data. 218 */ 219 static struct mbuf *makembuf (void *buf, unsigned len) 220 { 221 struct mbuf *m; 222 223 MGETHDR (m, M_NOWAIT, MT_DATA); 224 if (! m) 225 return 0; 226 if (!(MCLGET(m, M_NOWAIT))) { 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 235 static int ce_probe (device_t dev) 236 { 237 if ((pci_get_vendor (dev) == TAU32_PCI_VENDOR_ID) && 238 (pci_get_device (dev) == TAU32_PCI_DEVICE_ID)) { 239 device_set_desc (dev, "Cronyx-Tau32-PCI serial adapter"); 240 return BUS_PROBE_DEFAULT; 241 } 242 return ENXIO; 243 } 244 245 static void ce_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 (ce_destroy) { 256 splx (s); 257 return; 258 } 259 d = channel[i * NCHAN + k]; 260 if (!d) { 261 splx (s); 262 continue; 263 } 264 CE_LOCK ((bdrv_t *)d->board->sys); 265 switch (d->chan->type) { 266 case T_E1: 267 ce_e1_timer (d->chan); 268 break; 269 default: 270 break; 271 } 272 CE_UNLOCK ((bdrv_t *)d->board->sys); 273 splx (s); 274 } 275 } 276 s = splimp (); 277 if (!ce_destroy) 278 callout_reset (&timeout_handle, hz, ce_timeout, 0); 279 splx (s); 280 } 281 282 static void ce_led_off (void *arg) 283 { 284 ce_board_t *b = arg; 285 bdrv_t *bd = (bdrv_t *) b->sys; 286 int s; 287 s = splimp (); 288 if (ce_destroy) { 289 splx (s); 290 return; 291 } 292 CE_LOCK (bd); 293 TAU32_LedSet (b->ddk.pControllerObject, 0); 294 CE_UNLOCK (bd); 295 splx (s); 296 } 297 298 static void ce_intr (void *arg) 299 { 300 bdrv_t *bd = arg; 301 ce_board_t *b = bd->board; 302 int s; 303 int i; 304 #if __FreeBSD_version >= 500000 && defined NETGRAPH 305 int error; 306 #endif 307 s = splimp (); 308 if (ce_destroy) { 309 splx (s); 310 return; 311 } 312 CE_LOCK (bd); 313 /* Turn LED on. */ 314 TAU32_LedSet (b->ddk.pControllerObject, 1); 315 316 TAU32_HandleInterrupt (b->ddk.pControllerObject); 317 318 /* Turn LED off 50 msec later. */ 319 callout_reset (&led_timo[b->num], hz/20, ce_led_off, b); 320 CE_UNLOCK (bd); 321 splx (s); 322 323 /* Pass packets in a lock-free state */ 324 for (i = 0; i < NCHAN && b->chan[i].type; i++) { 325 drv_t *d = b->chan[i].sys; 326 struct mbuf *m; 327 if (!d || !d->running) 328 continue; 329 while (_IF_QLEN(&d->rqueue)) { 330 IF_DEQUEUE (&d->rqueue,m); 331 if (!m) 332 continue; 333 #ifdef NETGRAPH 334 if (d->hook) { 335 NG_SEND_DATA_ONLY (error, d->hook, m); 336 } else { 337 IF_DRAIN (&d->rqueue); 338 } 339 #else 340 sppp_input (d->ifp, m); 341 #endif 342 } 343 } 344 } 345 346 static void 347 ce_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 348 { 349 unsigned long *addr; 350 351 if (error) 352 return; 353 354 KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 355 addr = arg; 356 *addr = segs->ds_addr; 357 } 358 359 #ifndef BUS_DMA_ZERO 360 #define BUS_DMA_ZERO 0 361 #endif 362 363 static int 364 ce_bus_dma_mem_alloc (int bnum, int cnum, ce_dma_mem_t *dmem) 365 { 366 int error; 367 368 error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 369 BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 370 dmem->size, 0, 371 NULL, NULL, 372 &dmem->dmat); 373 if (error) { 374 if (cnum >= 0) printf ("ce%d-%d: ", bnum, cnum); 375 else printf ("ce%d: ", bnum); 376 printf ("couldn't allocate tag for dma memory\n"); 377 return 0; 378 } 379 error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 380 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 381 if (error) { 382 if (cnum >= 0) printf ("ce%d-%d: ", bnum, cnum); 383 else printf ("ce%d: ", bnum); 384 printf ("couldn't allocate mem for dma memory\n"); 385 bus_dma_tag_destroy (dmem->dmat); 386 return 0; 387 } 388 error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 389 dmem->size, ce_bus_dmamap_addr, &dmem->phys, 0); 390 if (error) { 391 if (cnum >= 0) printf ("ce%d-%d: ", bnum, cnum); 392 else printf ("ce%d: ", bnum); 393 printf ("couldn't load mem map for dma memory\n"); 394 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 395 bus_dma_tag_destroy (dmem->dmat); 396 return 0; 397 } 398 bzero (dmem->virt, dmem->size); 399 return 1; 400 } 401 402 static void 403 ce_bus_dma_mem_free (ce_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 */ 413 static int ce_attach (device_t dev) 414 { 415 bdrv_t *bd = device_get_softc (dev); 416 int unit = device_get_unit (dev); 417 char *ce_ln = CE_LOCK_NAME; 418 vm_offset_t vbase; 419 int rid, error; 420 ce_board_t *b; 421 ce_chan_t *c; 422 drv_t *d; 423 int s; 424 425 b = malloc (sizeof(ce_board_t), M_DEVBUF, M_WAITOK); 426 if (!b) { 427 printf ("ce%d: couldn't allocate memory\n", unit); 428 return (ENXIO); 429 } 430 bzero (b, sizeof(ce_board_t)); 431 432 b->ddk.sys = &b; 433 434 pci_enable_busmaster (dev); 435 436 bd->dmamem.size = TAU32_ControllerObjectSize; 437 if (! ce_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 438 free (b, M_DEVBUF); 439 return (ENXIO); 440 } 441 b->ddk.pControllerObject = bd->dmamem.virt; 442 443 bd->board = b; 444 b->sys = bd; 445 rid = PCIR_BAR(0); 446 bd->ce_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 447 0, ~0, 1, RF_ACTIVE); 448 if (! bd->ce_res) { 449 printf ("ce%d: cannot map memory\n", unit); 450 ce_bus_dma_mem_free (&bd->dmamem); 451 free (b, M_DEVBUF); 452 return (ENXIO); 453 } 454 vbase = (vm_offset_t) rman_get_virtual (bd->ce_res); 455 456 b->ddk.PciBar1VirtualAddress = (void *)vbase; 457 b->ddk.ControllerObjectPhysicalAddress = bd->dmamem.phys; 458 b->ddk.pErrorNotifyCallback = ce_error_callback; 459 b->ddk.pStatusNotifyCallback = ce_status_callback; 460 b->num = unit; 461 462 TAU32_BeforeReset(&b->ddk); 463 pci_write_config (dev, TAU32_PCI_RESET_ADDRESS, TAU32_PCI_RESET_ON, 4); 464 pci_write_config (dev, TAU32_PCI_RESET_ADDRESS, TAU32_PCI_RESET_OFF, 4); 465 466 if(!TAU32_Initialize(&b->ddk, 0)) 467 { 468 printf ("ce%d: init adapter error 0x%08x, bus dead bits 0x%08lx\n", 469 unit, b->ddk.InitErrors, b->ddk.DeadBits); 470 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->ce_res); 471 ce_bus_dma_mem_free (&bd->dmamem); 472 free (b, M_DEVBUF); 473 return (ENXIO); 474 } 475 476 s = splimp (); 477 478 ce_init_board (b); 479 480 rid = 0; 481 bd->ce_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 482 RF_SHAREABLE | RF_ACTIVE); 483 if (! bd->ce_irq) { 484 printf ("ce%d: cannot map interrupt\n", unit); 485 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->ce_res); 486 ce_bus_dma_mem_free (&bd->dmamem); 487 free (b, M_DEVBUF); 488 splx (s); 489 return (ENXIO); 490 } 491 callout_init (&led_timo[unit], 1); 492 error = bus_setup_intr (dev, bd->ce_irq, 493 INTR_TYPE_NET|INTR_MPSAFE, 494 NULL, ce_intr, bd, &bd->ce_intrhand); 495 if (error) { 496 printf ("ce%d: cannot set up irq\n", unit); 497 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->ce_irq); 498 bus_release_resource (dev, SYS_RES_MEMORY, 499 PCIR_BAR(0), bd->ce_res); 500 ce_bus_dma_mem_free (&bd->dmamem); 501 free (b, M_DEVBUF); 502 splx (s); 503 return (ENXIO); 504 } 505 506 switch (b->ddk.Model) { 507 case 1: strcpy (b->name, TAU32_BASE_NAME); break; 508 case 2: strcpy (b->name, TAU32_LITE_NAME); break; 509 case 3: strcpy (b->name, TAU32_ADPCM_NAME); break; 510 default: strcpy (b->name, TAU32_UNKNOWN_NAME); break; 511 } 512 513 printf ("ce%d: %s\n", unit, b->name); 514 515 for (c = b->chan; c < b->chan + NCHAN; ++c) { 516 c->num = (c - b->chan); 517 c->board = b; 518 519 d = &bd->channel[c->num]; 520 d->dmamem.size = sizeof(ce_buf_t); 521 if (! ce_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 522 continue; 523 524 channel [b->num * NCHAN + c->num] = d; 525 sprintf (d->name, "ce%d.%d", b->num, c->num); 526 d->board = b; 527 d->chan = c; 528 c->sys = d; 529 } 530 531 for (c = b->chan; c < b->chan + NCHAN; ++c) { 532 if (c->sys == NULL) 533 continue; 534 d = c->sys; 535 536 callout_init (&d->timeout_handle, 1); 537 #ifdef NETGRAPH 538 if (ng_make_node_common (&typestruct, &d->node) != 0) { 539 printf ("%s: cannot make common node\n", d->name); 540 d->node = NULL; 541 continue; 542 } 543 NG_NODE_SET_PRIVATE (d->node, d); 544 sprintf (d->nodename, "%s%d", NG_CE_NODE_TYPE, 545 c->board->num * NCHAN + c->num); 546 if (ng_name_node (d->node, d->nodename)) { 547 printf ("%s: cannot name node\n", d->nodename); 548 NG_NODE_UNREF (d->node); 549 continue; 550 } 551 d->queue.ifq_maxlen = ifqmaxlen; 552 d->hi_queue.ifq_maxlen = ifqmaxlen; 553 d->rqueue.ifq_maxlen = ifqmaxlen; 554 mtx_init (&d->queue.ifq_mtx, "ce_queue", NULL, MTX_DEF); 555 mtx_init (&d->hi_queue.ifq_mtx, "ce_queue_hi", NULL, MTX_DEF); 556 mtx_init (&d->rqueue.ifq_mtx, "ce_rqueue", NULL, MTX_DEF); 557 #else /*NETGRAPH*/ 558 d->ifp = if_alloc(IFT_PPP); 559 if (!d->ifp) { 560 printf ("%s: cannot if_alloc() interface\n", d->name); 561 continue; 562 } 563 d->ifp->if_softc = d; 564 if_initname (d->ifp, "ce", b->num * NCHAN + c->num); 565 d->ifp->if_mtu = PP_MTU; 566 d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 567 d->ifp->if_ioctl = ce_sioctl; 568 d->ifp->if_start = ce_ifstart; 569 d->ifp->if_init = ce_initialize; 570 d->rqueue.ifq_maxlen = ifqmaxlen; 571 mtx_init (&d->rqueue.ifq_mtx, "ce_rqueue", NULL, MTX_DEF); 572 sppp_attach (d->ifp); 573 if_attach (d->ifp); 574 IFP2SP(d->ifp)->pp_tlf = ce_tlf; 575 IFP2SP(d->ifp)->pp_tls = ce_tls; 576 /* If BPF is in the kernel, call the attach for it. 577 * The header size of PPP or Cisco/HDLC is 4 bytes. */ 578 bpfattach (d->ifp, DLT_PPP, 4); 579 #endif /*NETGRAPH*/ 580 ce_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 581 582 /* Register callback functions. */ 583 ce_register_transmit (c, &ce_transmit); 584 ce_register_receive (c, &ce_receive); 585 ce_register_error (c, &ce_error); 586 d->devt = make_dev (&ce_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 587 GID_WHEEL, 0600, "ce%d", b->num*NCHAN+c->num); 588 } 589 590 ce_ln[2] = '0' + unit; 591 mtx_init (&bd->ce_mtx, ce_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 592 CE_LOCK (bd); 593 TAU32_EnableInterrupts(b->ddk.pControllerObject); 594 adapter[unit] = b; 595 CE_UNLOCK (bd); 596 splx (s); 597 598 return 0; 599 } 600 601 static int ce_detach (device_t dev) 602 { 603 bdrv_t *bd = device_get_softc (dev); 604 ce_board_t *b = bd->board; 605 ce_chan_t *c; 606 int s; 607 608 KASSERT (mtx_initialized (&bd->ce_mtx), ("ce mutex not initialized")); 609 s = splimp (); 610 CE_LOCK (bd); 611 /* Check if the device is busy (open). */ 612 for (c = b->chan; c < b->chan + NCHAN; ++c) { 613 drv_t *d = (drv_t*) c->sys; 614 615 /* XXX Non existen chan! */ 616 if (! d || ! d->chan) 617 continue; 618 if (d->running) { 619 CE_UNLOCK (bd); 620 splx (s); 621 return EBUSY; 622 } 623 } 624 625 /* Ok, we can unload driver */ 626 /* At first we should disable interrupts */ 627 ce_destroy = 1; 628 TAU32_DisableInterrupts(b->ddk.pControllerObject); 629 630 callout_stop (&led_timo[b->num]); 631 632 for (c = b->chan; c < b->chan + NCHAN; ++c) { 633 drv_t *d = (drv_t*) c->sys; 634 635 if (! d || ! d->chan) 636 continue; 637 callout_stop (&d->timeout_handle); 638 #ifndef NETGRAPH 639 /* Detach from the packet filter list of interfaces. */ 640 bpfdetach (d->ifp); 641 642 /* Detach from the sync PPP list. */ 643 sppp_detach (d->ifp); 644 645 /* Detach from the system list of interfaces. */ 646 if_detach (d->ifp); 647 if_free(d->ifp); 648 649 IF_DRAIN (&d->rqueue); 650 mtx_destroy (&d->rqueue.ifq_mtx); 651 #else 652 if (d->node) { 653 ng_rmnode_self (d->node); 654 NG_NODE_UNREF (d->node); 655 d->node = NULL; 656 } 657 IF_DRAIN (&d->rqueue); 658 mtx_destroy (&d->queue.ifq_mtx); 659 mtx_destroy (&d->hi_queue.ifq_mtx); 660 mtx_destroy (&d->rqueue.ifq_mtx); 661 #endif 662 destroy_dev (d->devt); 663 } 664 665 CE_UNLOCK (bd); 666 splx (s); 667 668 callout_drain (&led_timo[b->num]); 669 670 /* Disable the interrupt request. */ 671 bus_teardown_intr (dev, bd->ce_irq, bd->ce_intrhand); 672 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->ce_irq); 673 TAU32_DestructiveHalt (b->ddk.pControllerObject, 0); 674 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->ce_res); 675 676 for (c = b->chan; c < b->chan + NCHAN; ++c) { 677 drv_t *d = (drv_t*) c->sys; 678 679 if (! d || ! d->chan) 680 continue; 681 callout_drain (&d->timeout_handle); 682 channel [b->num * NCHAN + c->num] = NULL; 683 /* Deallocate buffers. */ 684 ce_bus_dma_mem_free (&d->dmamem); 685 } 686 adapter [b->num] = NULL; 687 ce_bus_dma_mem_free (&bd->dmamem); 688 free (b, M_DEVBUF); 689 mtx_destroy (&bd->ce_mtx); 690 return 0; 691 } 692 693 #ifndef NETGRAPH 694 static void ce_ifstart (struct ifnet *ifp) 695 { 696 drv_t *d = ifp->if_softc; 697 bdrv_t *bd = d->board->sys; 698 699 CE_LOCK (bd); 700 ce_start (d); 701 CE_UNLOCK (bd); 702 } 703 704 static void ce_tlf (struct sppp *sp) 705 { 706 drv_t *d = SP2IFP(sp)->if_softc; 707 708 CE_DEBUG2 (d, ("ce_tlf\n")); 709 sp->pp_down (sp); 710 } 711 712 static void ce_tls (struct sppp *sp) 713 { 714 drv_t *d = SP2IFP(sp)->if_softc; 715 716 CE_DEBUG2 (d, ("ce_tls\n")); 717 sp->pp_up (sp); 718 } 719 720 /* 721 * Process an ioctl request. 722 */ 723 static int ce_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 738 d->chan->debug = d->chan->debug_shadow; 739 740 switch (cmd) { 741 default: CE_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 742 case SIOCADDMULTI: CE_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 743 case SIOCDELMULTI: CE_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 744 case SIOCSIFFLAGS: CE_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 745 case SIOCSIFADDR: CE_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 746 } 747 748 /* We get here only in case of SIFFLAGS or SIFADDR. */ 749 s = splimp (); 750 CE_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 ce_up (d); 755 ce_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 ce_down (d); 760 } 761 CE_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 762 CE_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 */ 771 static void ce_initialize (void *softc) 772 { 773 drv_t *d = softc; 774 775 CE_DEBUG (d, ("ce_initialize\n")); 776 } 777 #endif /*NETGRAPH*/ 778 779 /* 780 * Stop the interface. Called on splimp(). 781 */ 782 static void ce_down (drv_t *d) 783 { 784 CE_DEBUG (d, ("ce_down\n")); 785 /* Interface is going down -- stop it. */ 786 ce_set_dtr (d->chan, 0); 787 ce_set_rts (d->chan, 0); 788 789 d->running = 0; 790 callout_stop (&d->timeout_handle); 791 } 792 793 /* 794 * Start the interface. Called on splimp(). 795 */ 796 static void ce_up (drv_t *d) 797 { 798 CE_DEBUG (d, ("ce_up\n")); 799 ce_set_dtr (d->chan, 1); 800 ce_set_rts (d->chan, 1); 801 802 d->running = 1; 803 } 804 805 /* 806 * Start output on the interface. Get another datagram to send 807 * off of the interface queue, and copy it to the interface 808 * before starting the output. 809 */ 810 static void ce_send (drv_t *d) 811 { 812 struct mbuf *m; 813 u_short len; 814 815 CE_DEBUG2 (d, ("ce_send\n")); 816 817 /* No output if the interface is down. */ 818 if (! d->running) 819 return; 820 821 while (ce_transmit_space (d->chan)) { 822 /* Get the packet to send. */ 823 #ifdef NETGRAPH 824 IF_DEQUEUE (&d->hi_queue, m); 825 if (! m) 826 IF_DEQUEUE (&d->queue, m); 827 #else 828 m = sppp_dequeue (d->ifp); 829 #endif 830 if (! m) 831 return; 832 #ifndef NETGRAPH 833 BPF_MTAP (d->ifp, m); 834 #endif 835 len = m_length (m, NULL); 836 if (len >= BUFSZ) 837 printf ("%s: too long packet: %d bytes: ", 838 d->name, len); 839 else if (! m->m_next) 840 ce_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 841 else { 842 ce_buf_item_t *item = (ce_buf_item_t*)d->chan->tx_queue; 843 m_copydata (m, 0, len, item->buf); 844 ce_send_packet (d->chan, item->buf, len, 0); 845 } 846 m_freem (m); 847 /* Set up transmit timeout, if the transmit ring is not empty.*/ 848 d->timeout = 10; 849 } 850 #ifndef NETGRAPH 851 d->ifp->if_flags |= IFF_DRV_OACTIVE; 852 #endif 853 } 854 855 /* 856 * Start output on the interface. 857 * Always called on splimp(). 858 */ 859 static void ce_start (drv_t *d) 860 { 861 if (d->running) { 862 if (! d->chan->dtr) 863 ce_set_dtr (d->chan, 1); 864 if (! d->chan->rts) 865 ce_set_rts (d->chan, 1); 866 ce_send (d); 867 callout_reset (&d->timeout_handle, hz, ce_watchdog_timer, d); 868 } 869 } 870 871 /* 872 * Handle transmit timeouts. 873 * Recover after lost transmit interrupts. 874 * Always called on splimp(). 875 */ 876 static void ce_watchdog (drv_t *d) 877 { 878 CE_DEBUG (d, ("device timeout\n")); 879 if (d->running) { 880 ce_set_dtr (d->chan, 0); 881 ce_set_rts (d->chan, 0); 882 /* ce_stop_chan (d->chan);*/ 883 /* ce_start_chan (d->chan, 1, 1, 0, 0);*/ 884 ce_set_dtr (d->chan, 1); 885 ce_set_rts (d->chan, 1); 886 ce_start (d); 887 } 888 } 889 890 static void ce_watchdog_timer (void *arg) 891 { 892 drv_t *d = arg; 893 bdrv_t *bd = d->board->sys; 894 895 CE_LOCK(bd); 896 if (d->timeout == 1) 897 ce_watchdog (d); 898 if (d->timeout) 899 d->timeout--; 900 callout_reset (&d->timeout_handle, hz, ce_watchdog_timer, d); 901 CE_UNLOCK(bd); 902 } 903 904 static void ce_transmit (ce_chan_t *c, void *attachment, int len) 905 { 906 drv_t *d = c->sys; 907 908 d->timeout = 0; 909 #ifndef NETGRAPH 910 if_inc_counter(d->ifp, IFCOUNTER_OPACKETS, 1); 911 d->ifp->if_flags &= ~IFF_DRV_OACTIVE; 912 #endif 913 ce_start (d); 914 } 915 916 static void ce_receive (ce_chan_t *c, unsigned char *data, int len) 917 { 918 drv_t *d = c->sys; 919 struct mbuf *m; 920 921 if (! d->running) 922 return; 923 924 m = makembuf (data, len); 925 if (! m) { 926 CE_DEBUG (d, ("no memory for packet\n")); 927 #ifndef NETGRAPH 928 if_inc_counter(d->ifp, IFCOUNTER_IQDROPS, 1); 929 #endif 930 return; 931 } 932 if (c->debug > 1) 933 m_print (m, 0); 934 #ifdef NETGRAPH 935 m->m_pkthdr.rcvif = 0; 936 IF_ENQUEUE(&d->rqueue, m); 937 #else 938 if_inc_counter(d->ifp, IFCOUNTER_IPACKETS, 1); 939 m->m_pkthdr.rcvif = d->ifp; 940 /* Check if there's a BPF listener on this interface. 941 * If so, hand off the raw packet to bpf. */ 942 BPF_MTAP(d->ifp, m); 943 IF_ENQUEUE(&d->rqueue, m); 944 #endif 945 } 946 947 static void ce_error (ce_chan_t *c, int data) 948 { 949 drv_t *d = c->sys; 950 951 switch (data) { 952 case CE_FRAME: 953 CE_DEBUG (d, ("frame error\n")); 954 #ifndef NETGRAPH 955 if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 956 #endif 957 break; 958 case CE_CRC: 959 CE_DEBUG (d, ("crc error\n")); 960 #ifndef NETGRAPH 961 if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 962 #endif 963 break; 964 case CE_OVERRUN: 965 CE_DEBUG (d, ("overrun error\n")); 966 #ifndef NETGRAPH 967 if_inc_counter(d->ifp, IFCOUNTER_COLLISIONS, 1); 968 if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 969 #endif 970 break; 971 case CE_OVERFLOW: 972 CE_DEBUG (d, ("overflow error\n")); 973 #ifndef NETGRAPH 974 if_inc_counter(d->ifp, IFCOUNTER_IERRORS, 1); 975 #endif 976 break; 977 case CE_UNDERRUN: 978 CE_DEBUG (d, ("underrun error\n")); 979 d->timeout = 0; 980 #ifndef NETGRAPH 981 if_inc_counter(d->ifp, IFCOUNTER_OERRORS, 1); 982 d->ifp->if_flags &= ~IFF_DRV_OACTIVE; 983 #endif 984 ce_start (d); 985 break; 986 default: 987 CE_DEBUG (d, ("error #%d\n", data)); 988 break; 989 } 990 } 991 992 /* 993 * You also need read, write, open, close routines. 994 * This should get you started 995 */ 996 static int ce_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 997 { 998 int unit = dev2unit (dev); 999 drv_t *d; 1000 1001 if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 1002 return ENXIO; 1003 CE_DEBUG2 (d, ("ce_open\n")); 1004 return 0; 1005 } 1006 1007 /* 1008 * Only called on the LAST close. 1009 */ 1010 static int ce_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 1011 { 1012 drv_t *d = channel [dev2unit (dev)]; 1013 1014 CE_DEBUG2 (d, ("ce_close\n")); 1015 return 0; 1016 } 1017 1018 static int ce_modem_status (ce_chan_t *c) 1019 { 1020 drv_t *d = c->sys; 1021 bdrv_t *bd = d->board->sys; 1022 int status, s; 1023 1024 status = d->running ? TIOCM_LE : 0; 1025 s = splimp (); 1026 CE_LOCK (bd); 1027 if (ce_get_cd (c)) status |= TIOCM_CD; 1028 if (ce_get_cts (c)) status |= TIOCM_CTS; 1029 if (ce_get_dsr (c)) status |= TIOCM_DSR; 1030 if (c->dtr) status |= TIOCM_DTR; 1031 if (c->rts) status |= TIOCM_RTS; 1032 CE_UNLOCK (bd); 1033 splx (s); 1034 return status; 1035 } 1036 1037 static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1038 { 1039 drv_t *d = channel [dev2unit (dev)]; 1040 bdrv_t *bd = d->board->sys; 1041 ce_chan_t *c = d->chan; 1042 struct serial_statistics *st; 1043 struct e1_statistics *opte1; 1044 int error, s; 1045 char mask[16]; 1046 1047 switch (cmd) { 1048 case SERIAL_GETREGISTERED: 1049 CE_DEBUG2 (d, ("ioctl: getregistered\n")); 1050 bzero (mask, sizeof(mask)); 1051 for (s=0; s<NBRD*NCHAN; ++s) 1052 if (channel [s]) 1053 mask [s/8] |= 1 << (s & 7); 1054 bcopy (mask, data, sizeof (mask)); 1055 return 0; 1056 1057 #ifndef NETGRAPH 1058 case SERIAL_GETPROTO: 1059 CE_DEBUG2 (d, ("ioctl: getproto\n")); 1060 strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1061 (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1062 return 0; 1063 1064 case SERIAL_SETPROTO: 1065 CE_DEBUG2 (d, ("ioctl: setproto\n")); 1066 /* Only for superuser! */ 1067 error = priv_check (td, PRIV_DRIVER); 1068 if (error) 1069 return error; 1070 if (d->ifp->if_flags & IFF_DRV_RUNNING) 1071 return EBUSY; 1072 if (! strcmp ("cisco", (char*)data)) { 1073 IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1074 IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1075 d->ifp->if_flags |= PP_CISCO; 1076 #if PP_FR != 0 1077 } else if (! strcmp ("fr", (char*)data)) { 1078 d->ifp->if_flags &= ~(PP_CISCO); 1079 IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1080 #endif 1081 } else if (! strcmp ("ppp", (char*)data)) { 1082 IFP2SP(d->ifp)->pp_flags &= ~PP_FR; 1083 IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1084 d->ifp->if_flags &= ~(PP_CISCO); 1085 } else 1086 return EINVAL; 1087 return 0; 1088 1089 case SERIAL_GETKEEPALIVE: 1090 CE_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1091 if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1092 (d->ifp->if_flags & PP_CISCO)) 1093 return EINVAL; 1094 *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1095 return 0; 1096 1097 case SERIAL_SETKEEPALIVE: 1098 CE_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1099 /* Only for superuser! */ 1100 error = priv_check (td, PRIV_DRIVER); 1101 if (error) 1102 return error; 1103 if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1104 (d->ifp->if_flags & PP_CISCO)) 1105 return EINVAL; 1106 s = splimp (); 1107 CE_LOCK (bd); 1108 if (*(int*)data) 1109 IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1110 else 1111 IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1112 CE_UNLOCK (bd); 1113 splx (s); 1114 return 0; 1115 #endif /*NETGRAPH*/ 1116 1117 case SERIAL_GETMODE: 1118 CE_DEBUG2 (d, ("ioctl: getmode\n")); 1119 *(int*)data = SERIAL_HDLC; 1120 return 0; 1121 1122 case SERIAL_SETMODE: 1123 /* Only for superuser! */ 1124 error = priv_check (td, PRIV_DRIVER); 1125 if (error) 1126 return error; 1127 if (*(int*)data != SERIAL_HDLC) 1128 return EINVAL; 1129 return 0; 1130 1131 case SERIAL_GETCFG: 1132 CE_DEBUG2 (d, ("ioctl: getcfg\n")); 1133 *(char*)data = 'c'; 1134 return 0; 1135 1136 case SERIAL_SETCFG: 1137 CE_DEBUG2 (d, ("ioctl: setcfg\n")); 1138 error = priv_check (td, PRIV_DRIVER); 1139 if (error) 1140 return error; 1141 if (*((char*)data) != 'c') 1142 return EINVAL; 1143 return 0; 1144 1145 case SERIAL_GETSTAT: 1146 CE_DEBUG2 (d, ("ioctl: getstat\n")); 1147 st = (struct serial_statistics*) data; 1148 st->rintr = c->rintr; 1149 st->tintr = c->tintr; 1150 st->mintr = 0; 1151 st->ibytes = c->ibytes; 1152 st->ipkts = c->ipkts; 1153 st->obytes = c->obytes; 1154 st->opkts = c->opkts; 1155 st->ierrs = c->overrun + c->frame + c->crc; 1156 st->oerrs = c->underrun; 1157 return 0; 1158 1159 case SERIAL_GETESTAT: 1160 CE_DEBUG2 (d, ("ioctl: getestat\n")); 1161 if (c->type != T_E1) 1162 return EINVAL; 1163 opte1 = (struct e1_statistics*) data; 1164 1165 opte1->status = 0; 1166 if (c->status & ESTS_NOALARM) 1167 opte1->status |= E1_NOALARM; 1168 if (c->status & ESTS_LOS) 1169 opte1->status |= E1_LOS; 1170 if (c->status & ESTS_LOF) 1171 opte1->status |= E1_LOF; 1172 if (c->status & ESTS_AIS) 1173 opte1->status |= E1_AIS; 1174 if (c->status & ESTS_LOMF) 1175 opte1->status |= E1_LOMF; 1176 if (c->status & ESTS_AIS16) 1177 opte1->status |= E1_AIS16; 1178 if (c->status & ESTS_FARLOF) 1179 opte1->status |= E1_FARLOF; 1180 if (c->status & ESTS_FARLOMF) 1181 opte1->status |= E1_FARLOMF; 1182 if (c->status & ESTS_TSTREQ) 1183 opte1->status |= E1_TSTREQ; 1184 if (c->status & ESTS_TSTERR) 1185 opte1->status |= E1_TSTERR; 1186 1187 opte1->cursec = c->cursec; 1188 opte1->totsec = c->totsec + c->cursec; 1189 1190 opte1->currnt.bpv = c->currnt.bpv; 1191 opte1->currnt.fse = c->currnt.fse; 1192 opte1->currnt.crce = c->currnt.crce; 1193 opte1->currnt.rcrce = c->currnt.rcrce; 1194 opte1->currnt.uas = c->currnt.uas; 1195 opte1->currnt.les = c->currnt.les; 1196 opte1->currnt.es = c->currnt.es; 1197 opte1->currnt.bes = c->currnt.bes; 1198 opte1->currnt.ses = c->currnt.ses; 1199 opte1->currnt.oofs = c->currnt.oofs; 1200 opte1->currnt.css = c->currnt.css; 1201 opte1->currnt.dm = c->currnt.dm; 1202 1203 opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1204 opte1->total.fse = c->total.fse + c->currnt.fse; 1205 opte1->total.crce = c->total.crce + c->currnt.crce; 1206 opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1207 opte1->total.uas = c->total.uas + c->currnt.uas; 1208 opte1->total.les = c->total.les + c->currnt.les; 1209 opte1->total.es = c->total.es + c->currnt.es; 1210 opte1->total.bes = c->total.bes + c->currnt.bes; 1211 opte1->total.ses = c->total.ses + c->currnt.ses; 1212 opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1213 opte1->total.css = c->total.css + c->currnt.css; 1214 opte1->total.dm = c->total.dm + c->currnt.dm; 1215 for (s=0; s<48; ++s) { 1216 opte1->interval[s].bpv = c->interval[s].bpv; 1217 opte1->interval[s].fse = c->interval[s].fse; 1218 opte1->interval[s].crce = c->interval[s].crce; 1219 opte1->interval[s].rcrce = c->interval[s].rcrce; 1220 opte1->interval[s].uas = c->interval[s].uas; 1221 opte1->interval[s].les = c->interval[s].les; 1222 opte1->interval[s].es = c->interval[s].es; 1223 opte1->interval[s].bes = c->interval[s].bes; 1224 opte1->interval[s].ses = c->interval[s].ses; 1225 opte1->interval[s].oofs = c->interval[s].oofs; 1226 opte1->interval[s].css = c->interval[s].css; 1227 opte1->interval[s].dm = c->interval[s].dm; 1228 } 1229 return 0; 1230 1231 case SERIAL_CLRSTAT: 1232 CE_DEBUG2 (d, ("ioctl: clrstat\n")); 1233 /* Only for superuser! */ 1234 error = priv_check (td, PRIV_DRIVER); 1235 if (error) 1236 return error; 1237 c->rintr = 0; 1238 c->tintr = 0; 1239 c->ibytes = 0; 1240 c->obytes = 0; 1241 c->ipkts = 0; 1242 c->opkts = 0; 1243 c->overrun = 0; 1244 c->frame = 0; 1245 c->crc = 0; 1246 c->underrun = 0; 1247 bzero (&c->currnt, sizeof (c->currnt)); 1248 bzero (&c->total, sizeof (c->total)); 1249 bzero (c->interval, sizeof (c->interval)); 1250 return 0; 1251 1252 case SERIAL_GETLOOP: 1253 CE_DEBUG2 (d, ("ioctl: getloop\n")); 1254 if (c->type != T_E1) 1255 return EINVAL; 1256 *(int*)data = c->lloop; 1257 return 0; 1258 1259 case SERIAL_SETLOOP: 1260 CE_DEBUG2 (d, ("ioctl: setloop\n")); 1261 if (c->type != T_E1) 1262 return EINVAL; 1263 /* Only for superuser! */ 1264 error = priv_check (td, PRIV_DRIVER); 1265 if (error) 1266 return error; 1267 s = splimp (); 1268 CE_LOCK (bd); 1269 ce_set_lloop (c, *(int*)data); 1270 CE_UNLOCK (bd); 1271 splx (s); 1272 return 0; 1273 1274 case SERIAL_GETRLOOP: 1275 CE_DEBUG2 (d, ("ioctl: getrloop\n")); 1276 if (c->type != T_E1) 1277 return EINVAL; 1278 *(int*)data = c->rloop; 1279 return 0; 1280 1281 case SERIAL_SETRLOOP: 1282 CE_DEBUG2 (d, ("ioctl: setloop\n")); 1283 if (c->type != T_E1) 1284 return EINVAL; 1285 /* Only for superuser! */ 1286 error = priv_check (td, PRIV_DRIVER); 1287 if (error) 1288 return error; 1289 s = splimp (); 1290 CE_LOCK (bd); 1291 ce_set_rloop (c, *(int*)data); 1292 CE_UNLOCK (bd); 1293 splx (s); 1294 return 0; 1295 1296 case SERIAL_GETDEBUG: 1297 CE_DEBUG2 (d, ("ioctl: getdebug\n")); 1298 *(int*)data = d->chan->debug; 1299 return 0; 1300 1301 case SERIAL_SETDEBUG: 1302 CE_DEBUG2 (d, ("ioctl: setdebug\n")); 1303 /* Only for superuser! */ 1304 error = priv_check (td, PRIV_DRIVER); 1305 if (error) 1306 return error; 1307 #ifndef NETGRAPH 1308 /* 1309 * The debug_shadow is always greater than zero for logic 1310 * simplicity. For switching debug off the IFF_DEBUG is 1311 * responsible. 1312 */ 1313 d->chan->debug_shadow = (*(int*)data) ? (*(int*)data) : 1; 1314 if (d->ifp->if_flags & IFF_DEBUG) 1315 d->chan->debug = d->chan->debug_shadow; 1316 #else 1317 d->chan->debug = *(int*)data; 1318 #endif 1319 return 0; 1320 1321 case SERIAL_GETBAUD: 1322 CE_DEBUG2 (d, ("ioctl: getbaud\n")); 1323 *(long*)data = c->baud; 1324 return 0; 1325 1326 case SERIAL_SETBAUD: 1327 CE_DEBUG2 (d, ("ioctl: setbaud\n")); 1328 if (c->type != T_E1 || !c->unfram) 1329 return EINVAL; 1330 /* Only for superuser! */ 1331 error = priv_check (td, PRIV_DRIVER); 1332 if (error) 1333 return error; 1334 s = splimp (); 1335 CE_LOCK (bd); 1336 ce_set_baud (c, *(long*)data); 1337 CE_UNLOCK (bd); 1338 splx (s); 1339 return 0; 1340 1341 case SERIAL_GETTIMESLOTS: 1342 CE_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1343 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1344 return EINVAL; 1345 *(u_long*)data = c->ts; 1346 return 0; 1347 1348 case SERIAL_SETTIMESLOTS: 1349 CE_DEBUG2 (d, ("ioctl: settimeslots\n")); 1350 /* Only for superuser! */ 1351 error = priv_check (td, PRIV_DRIVER); 1352 if (error) 1353 return error; 1354 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1355 return EINVAL; 1356 s = splimp (); 1357 CE_LOCK (bd); 1358 ce_set_ts (c, *(u_long*)data); 1359 CE_UNLOCK (bd); 1360 splx (s); 1361 return 0; 1362 1363 case SERIAL_GETHIGAIN: 1364 CE_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 CE_DEBUG2 (d, ("ioctl: sethigain\n")); 1372 if (c->type != T_E1) 1373 return EINVAL; 1374 /* Only for superuser! */ 1375 error = priv_check (td, PRIV_DRIVER); 1376 if (error) 1377 return error; 1378 s = splimp (); 1379 CE_LOCK (bd); 1380 ce_set_higain (c, *(int*)data); 1381 CE_UNLOCK (bd); 1382 splx (s); 1383 return 0; 1384 1385 case SERIAL_GETPHONY: 1386 CE_DEBUG2 (d, ("ioctl: getphony\n")); 1387 *(int*)data = c->phony; 1388 return 0; 1389 1390 case SERIAL_SETPHONY: 1391 CE_DEBUG2 (d, ("ioctl: setphony\n")); 1392 /* Only for superuser! */ 1393 error = priv_check (td, PRIV_DRIVER); 1394 if (error) 1395 return error; 1396 s = splimp (); 1397 CE_LOCK (bd); 1398 ce_set_phony (c, *(int*)data); 1399 CE_UNLOCK (bd); 1400 splx (s); 1401 return 0; 1402 1403 case SERIAL_GETUNFRAM: 1404 CE_DEBUG2 (d, ("ioctl: getunfram\n")); 1405 if (c->type != T_E1 || c->num != 0) 1406 return EINVAL; 1407 *(int*)data = c->unfram; 1408 return 0; 1409 1410 case SERIAL_SETUNFRAM: 1411 CE_DEBUG2 (d, ("ioctl: setunfram\n")); 1412 if (c->type != T_E1 || c->num != 0) 1413 return EINVAL; 1414 /* Only for superuser! */ 1415 error = priv_check (td, PRIV_DRIVER); 1416 if (error) 1417 return error; 1418 s = splimp (); 1419 CE_LOCK (bd); 1420 ce_set_unfram (c, *(int*)data); 1421 CE_UNLOCK (bd); 1422 splx (s); 1423 return 0; 1424 1425 case SERIAL_GETSCRAMBLER: 1426 CE_DEBUG2 (d, ("ioctl: getscrambler\n")); 1427 if (!c->unfram) 1428 return EINVAL; 1429 *(int*)data = c->scrambler; 1430 return 0; 1431 1432 case SERIAL_SETSCRAMBLER: 1433 CE_DEBUG2 (d, ("ioctl: setscrambler\n")); 1434 /* Only for superuser! */ 1435 error = priv_check (td, PRIV_DRIVER); 1436 if (error) 1437 return error; 1438 if (!c->unfram) 1439 return EINVAL; 1440 s = splimp (); 1441 CE_LOCK (bd); 1442 ce_set_scrambler (c, *(int*)data); 1443 CE_UNLOCK (bd); 1444 splx (s); 1445 return 0; 1446 1447 case SERIAL_GETMONITOR: 1448 CE_DEBUG2 (d, ("ioctl: getmonitor\n")); 1449 if (c->type != T_E1) 1450 return EINVAL; 1451 *(int*)data = c->monitor; 1452 return 0; 1453 1454 case SERIAL_SETMONITOR: 1455 CE_DEBUG2 (d, ("ioctl: setmonitor\n")); 1456 /* Only for superuser! */ 1457 error = priv_check (td, PRIV_DRIVER); 1458 if (error) 1459 return error; 1460 if (c->type != T_E1) 1461 return EINVAL; 1462 s = splimp (); 1463 CE_LOCK (bd); 1464 ce_set_monitor (c, *(int*)data); 1465 CE_UNLOCK (bd); 1466 splx (s); 1467 return 0; 1468 1469 case SERIAL_GETUSE16: 1470 CE_DEBUG2 (d, ("ioctl: getuse16\n")); 1471 if (c->type != T_E1 || c->unfram) 1472 return EINVAL; 1473 *(int*)data = c->use16; 1474 return 0; 1475 1476 case SERIAL_SETUSE16: 1477 CE_DEBUG2 (d, ("ioctl: setuse16\n")); 1478 /* Only for superuser! */ 1479 error = priv_check (td, PRIV_DRIVER); 1480 if (error) 1481 return error; 1482 if (c->type != T_E1) 1483 return EINVAL; 1484 s = splimp (); 1485 CE_LOCK (bd); 1486 ce_set_use16 (c, *(int*)data); 1487 CE_UNLOCK (bd); 1488 splx (s); 1489 return 0; 1490 1491 case SERIAL_GETCRC4: 1492 CE_DEBUG2 (d, ("ioctl: getcrc4\n")); 1493 if (c->type != T_E1 || c->unfram) 1494 return EINVAL; 1495 *(int*)data = c->crc4; 1496 return 0; 1497 1498 case SERIAL_SETCRC4: 1499 CE_DEBUG2 (d, ("ioctl: setcrc4\n")); 1500 /* Only for superuser! */ 1501 error = priv_check (td, PRIV_DRIVER); 1502 if (error) 1503 return error; 1504 if (c->type != T_E1 || c->unfram) 1505 return EINVAL; 1506 s = splimp (); 1507 CE_LOCK (bd); 1508 ce_set_crc4 (c, *(int*)data); 1509 CE_UNLOCK (bd); 1510 splx (s); 1511 return 0; 1512 1513 case SERIAL_GETCLK: 1514 CE_DEBUG2 (d, ("ioctl: getclk\n")); 1515 if (c->type != T_E1) 1516 return EINVAL; 1517 switch (c->gsyn) { 1518 default: *(int*)data = E1CLK_INTERNAL; break; 1519 case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1520 case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1521 case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1522 } 1523 return 0; 1524 1525 case SERIAL_SETCLK: 1526 CE_DEBUG2 (d, ("ioctl: setclk\n")); 1527 /* Only for superuser! */ 1528 error = priv_check (td, PRIV_DRIVER); 1529 if (error) 1530 return error; 1531 if (c->type != T_E1) 1532 return EINVAL; 1533 s = splimp (); 1534 CE_LOCK (bd); 1535 switch (*(int*)data) { 1536 default: ce_set_gsyn (c, GSYN_INT); break; 1537 case E1CLK_RECEIVE: ce_set_gsyn (c, GSYN_RCV); break; 1538 case E1CLK_RECEIVE_CHAN0: ce_set_gsyn (c, GSYN_RCV0); break; 1539 case E1CLK_RECEIVE_CHAN1: ce_set_gsyn (c, GSYN_RCV1); break; 1540 } 1541 CE_UNLOCK (bd); 1542 splx (s); 1543 return 0; 1544 1545 #if 0 1546 case SERIAL_RESET: 1547 CE_DEBUG2 (d, ("ioctl: reset\n")); 1548 /* Only for superuser! */ 1549 error = priv_check (td, PRIV_DRIVER); 1550 if (error) 1551 return error; 1552 s = splimp (); 1553 CE_LOCK (bd); 1554 /* ce_reset (c->board, 0, 0);*/ 1555 CE_UNLOCK (bd); 1556 splx (s); 1557 return 0; 1558 1559 case SERIAL_HARDRESET: 1560 CE_DEBUG2 (d, ("ioctl: hardreset\n")); 1561 /* Only for superuser! */ 1562 error = priv_check (td, PRIV_DRIVER); 1563 if (error) 1564 return error; 1565 s = splimp (); 1566 CE_LOCK (bd); 1567 /* hard_reset (c->board); */ 1568 CE_UNLOCK (bd); 1569 splx (s); 1570 return 0; 1571 #endif 1572 1573 case SERIAL_GETCABLE: 1574 CE_DEBUG2 (d, ("ioctl: getcable\n")); 1575 if (c->type != T_E1) 1576 return EINVAL; 1577 s = splimp (); 1578 CE_LOCK (bd); 1579 *(int*)data = CABLE_TP; 1580 CE_UNLOCK (bd); 1581 splx (s); 1582 return 0; 1583 1584 case SERIAL_GETDIR: 1585 CE_DEBUG2 (d, ("ioctl: getdir\n")); 1586 if (c->type != T_E1 && c->type != T_DATA) 1587 return EINVAL; 1588 *(int*)data = c->dir; 1589 return 0; 1590 1591 case SERIAL_SETDIR: 1592 CE_DEBUG2 (d, ("ioctl: setdir\n")); 1593 /* Only for superuser! */ 1594 error = priv_check (td, PRIV_DRIVER); 1595 if (error) 1596 return error; 1597 s = splimp (); 1598 CE_LOCK (bd); 1599 ce_set_dir (c, *(int*)data); 1600 CE_UNLOCK (bd); 1601 splx (s); 1602 return 0; 1603 1604 case TIOCSDTR: /* Set DTR */ 1605 s = splimp (); 1606 CE_LOCK (bd); 1607 ce_set_dtr (c, 1); 1608 CE_UNLOCK (bd); 1609 splx (s); 1610 return 0; 1611 1612 case TIOCCDTR: /* Clear DTR */ 1613 s = splimp (); 1614 CE_LOCK (bd); 1615 ce_set_dtr (c, 0); 1616 CE_UNLOCK (bd); 1617 splx (s); 1618 return 0; 1619 1620 case TIOCMSET: /* Set DTR/RTS */ 1621 s = splimp (); 1622 CE_LOCK (bd); 1623 ce_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1624 ce_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1625 CE_UNLOCK (bd); 1626 splx (s); 1627 return 0; 1628 1629 case TIOCMBIS: /* Add DTR/RTS */ 1630 s = splimp (); 1631 CE_LOCK (bd); 1632 if (*(int*)data & TIOCM_DTR) ce_set_dtr (c, 1); 1633 if (*(int*)data & TIOCM_RTS) ce_set_rts (c, 1); 1634 CE_UNLOCK (bd); 1635 splx (s); 1636 return 0; 1637 1638 case TIOCMBIC: /* Clear DTR/RTS */ 1639 s = splimp (); 1640 CE_LOCK (bd); 1641 if (*(int*)data & TIOCM_DTR) ce_set_dtr (c, 0); 1642 if (*(int*)data & TIOCM_RTS) ce_set_rts (c, 0); 1643 CE_UNLOCK (bd); 1644 splx (s); 1645 return 0; 1646 1647 case TIOCMGET: /* Get modem status */ 1648 *(int*)data = ce_modem_status (c); 1649 return 0; 1650 } 1651 return ENOTTY; 1652 } 1653 1654 #ifdef NETGRAPH 1655 static int ng_ce_constructor (node_p node) 1656 { 1657 drv_t *d = NG_NODE_PRIVATE (node); 1658 CE_DEBUG (d, ("Constructor\n")); 1659 return EINVAL; 1660 } 1661 1662 static int ng_ce_newhook (node_p node, hook_p hook, const char *name) 1663 { 1664 int s; 1665 drv_t *d = NG_NODE_PRIVATE (node); 1666 bdrv_t *bd = d->board->sys; 1667 1668 CE_DEBUG (d, ("Newhook\n")); 1669 /* Attach debug hook */ 1670 if (strcmp (name, NG_CE_HOOK_DEBUG) == 0) { 1671 NG_HOOK_SET_PRIVATE (hook, NULL); 1672 d->debug_hook = hook; 1673 return 0; 1674 } 1675 1676 /* Check for raw hook */ 1677 if (strcmp (name, NG_CE_HOOK_RAW) != 0) 1678 return EINVAL; 1679 1680 NG_HOOK_SET_PRIVATE (hook, d); 1681 d->hook = hook; 1682 s = splimp (); 1683 CE_LOCK (bd); 1684 ce_up (d); 1685 CE_UNLOCK (bd); 1686 splx (s); 1687 return 0; 1688 } 1689 1690 static char *format_timeslots (u_long s) 1691 { 1692 static char buf [100]; 1693 char *p = buf; 1694 int i; 1695 1696 for (i=1; i<32; ++i) 1697 if ((s >> i) & 1) { 1698 int prev = (i > 1) & (s >> (i-1)); 1699 int next = (i < 31) & (s >> (i+1)); 1700 1701 if (prev) { 1702 if (next) 1703 continue; 1704 *p++ = '-'; 1705 } else if (p > buf) 1706 *p++ = ','; 1707 1708 if (i >= 10) 1709 *p++ = '0' + i / 10; 1710 *p++ = '0' + i % 10; 1711 } 1712 *p = 0; 1713 return buf; 1714 } 1715 1716 static int print_modems (char *s, ce_chan_t *c, int need_header) 1717 { 1718 int status = ce_modem_status (c); 1719 int length = 0; 1720 1721 if (need_header) 1722 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1723 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1724 status & TIOCM_LE ? "On" : "-", 1725 status & TIOCM_DTR ? "On" : "-", 1726 status & TIOCM_DSR ? "On" : "-", 1727 status & TIOCM_RTS ? "On" : "-", 1728 status & TIOCM_CTS ? "On" : "-", 1729 status & TIOCM_CD ? "On" : "-"); 1730 return length; 1731 } 1732 1733 static int print_stats (char *s, ce_chan_t *c, int need_header) 1734 { 1735 int length = 0; 1736 1737 if (need_header) 1738 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1739 length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1740 c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1741 c->ipkts, c->overrun + c->frame + c->crc, 1742 (unsigned long) c->obytes, c->opkts, c->underrun); 1743 return length; 1744 } 1745 1746 static char *format_e1_status (u_char status) 1747 { 1748 static char buf [80]; 1749 1750 if (status & E1_NOALARM) 1751 return "Ok"; 1752 buf[0] = 0; 1753 if (status & E1_LOS) strcat (buf, ",LOS"); 1754 if (status & E1_AIS) strcat (buf, ",AIS"); 1755 if (status & E1_LOF) strcat (buf, ",LOF"); 1756 if (status & E1_LOMF) strcat (buf, ",LOMF"); 1757 if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1758 if (status & E1_AIS16) strcat (buf, ",AIS16"); 1759 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1760 if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1761 if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1762 if (buf[0] == ',') 1763 return buf+1; 1764 return "Unknown"; 1765 } 1766 1767 static int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1768 { 1769 int n, length = 0; 1770 1771 if (numerator < 1 || divider < 1) { 1772 length += sprintf (s+length, leftalign ? "/- " : " -"); 1773 return length; 1774 } 1775 n = (int) (0.5 + 1000.0 * numerator / divider); 1776 if (n < 1000) { 1777 length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1778 return length; 1779 } 1780 *(s + length) = leftalign ? '/' : ' '; 1781 length ++; 1782 1783 if (n >= 1000000) n = (n+500) / 1000 * 1000; 1784 else if (n >= 100000) n = (n+50) / 100 * 100; 1785 else if (n >= 10000) n = (n+5) / 10 * 10; 1786 1787 switch (n) { 1788 case 1000: length += printf (s+length, ".999"); return length; 1789 case 10000: n = 9990; break; 1790 case 100000: n = 99900; break; 1791 case 1000000: n = 999000; break; 1792 } 1793 if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1794 else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1795 else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1796 else length += sprintf (s+length, "%d", n/1000); 1797 1798 return length; 1799 } 1800 1801 static int print_e1_stats (char *s, ce_chan_t *c) 1802 { 1803 struct e1_counters total; 1804 u_long totsec; 1805 int length = 0; 1806 1807 totsec = c->totsec + c->cursec; 1808 total.bpv = c->total.bpv + c->currnt.bpv; 1809 total.fse = c->total.fse + c->currnt.fse; 1810 total.crce = c->total.crce + c->currnt.crce; 1811 total.rcrce = c->total.rcrce + c->currnt.rcrce; 1812 total.uas = c->total.uas + c->currnt.uas; 1813 total.les = c->total.les + c->currnt.les; 1814 total.es = c->total.es + c->currnt.es; 1815 total.bes = c->total.bes + c->currnt.bes; 1816 total.ses = c->total.ses + c->currnt.ses; 1817 total.oofs = c->total.oofs + c->currnt.oofs; 1818 total.css = c->total.css + c->currnt.css; 1819 total.dm = c->total.dm + c->currnt.dm; 1820 1821 length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1822 1823 /* Unavailable seconds, degraded minutes */ 1824 length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1825 length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1826 1827 /* Bipolar violations, frame sync errors */ 1828 length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1829 length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1830 1831 /* CRC errors, remote CRC errors (E-bit) */ 1832 length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 1833 length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 1834 1835 /* Errored seconds, line errored seconds */ 1836 length += print_frac (s + length, 0, c->currnt.es, c->cursec); 1837 length += print_frac (s + length, 1, c->currnt.les, c->cursec); 1838 1839 /* Severely errored seconds, burst errored seconds */ 1840 length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 1841 length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 1842 1843 /* Out of frame seconds, controlled slip seconds */ 1844 length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 1845 length += print_frac (s + length, 1, c->currnt.css, c->cursec); 1846 1847 length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 1848 1849 /* Print total statistics. */ 1850 length += print_frac (s + length, 0, total.uas, totsec); 1851 length += print_frac (s + length, 1, 60 * total.dm, totsec); 1852 1853 length += print_frac (s + length, 0, total.bpv, totsec); 1854 length += print_frac (s + length, 1, total.fse, totsec); 1855 1856 length += print_frac (s + length, 0, total.crce, totsec); 1857 length += print_frac (s + length, 1, total.rcrce, totsec); 1858 1859 length += print_frac (s + length, 0, total.es, totsec); 1860 length += print_frac (s + length, 1, total.les, totsec); 1861 1862 length += print_frac (s + length, 0, total.ses, totsec); 1863 length += print_frac (s + length, 1, total.bes, totsec); 1864 1865 length += print_frac (s + length, 0, total.oofs, totsec); 1866 length += print_frac (s + length, 1, total.css, totsec); 1867 1868 length += sprintf (s + length, " -- Total\n"); 1869 return length; 1870 } 1871 1872 static int print_chan (char *s, ce_chan_t *c) 1873 { 1874 drv_t *d = c->sys; 1875 int length = 0; 1876 1877 length += sprintf (s + length, "ce%d", c->board->num * NCHAN + c->num); 1878 if (d->chan->debug) 1879 length += sprintf (s + length, " debug=%d", d->chan->debug); 1880 1881 if (c->board->mux) { 1882 length += sprintf (s + length, " cfg=C"); 1883 } else { 1884 length += sprintf (s + length, " cfg=A"); 1885 } 1886 1887 if (c->baud) 1888 length += sprintf (s + length, " %ld", c->baud); 1889 else 1890 length += sprintf (s + length, " extclock"); 1891 1892 if (c->type == T_E1) 1893 switch (c->gsyn) { 1894 case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 1895 case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 1896 case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 1897 case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 1898 } 1899 if (c->type == T_E1) 1900 length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 1901 1902 length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 1903 1904 if (c->type == T_E1) 1905 length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 1906 length += sprintf (s + length, "\n"); 1907 return length; 1908 } 1909 1910 static int ng_ce_rcvmsg (node_p node, item_p item, hook_p lasthook) 1911 { 1912 drv_t *d = NG_NODE_PRIVATE (node); 1913 struct ng_mesg *msg; 1914 struct ng_mesg *resp = NULL; 1915 int error = 0; 1916 1917 CE_DEBUG (d, ("Rcvmsg\n")); 1918 NGI_GET_MSG (item, msg); 1919 switch (msg->header.typecookie) { 1920 default: 1921 error = EINVAL; 1922 break; 1923 1924 case NGM_CE_COOKIE: 1925 printf ("Not implemented yet\n"); 1926 error = EINVAL; 1927 break; 1928 1929 case NGM_GENERIC_COOKIE: 1930 switch (msg->header.cmd) { 1931 default: 1932 error = EINVAL; 1933 break; 1934 1935 case NGM_TEXT_STATUS: { 1936 char *s; 1937 int l = 0; 1938 int dl = sizeof (struct ng_mesg) + 730; 1939 1940 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 1941 if (! resp) { 1942 error = ENOMEM; 1943 break; 1944 } 1945 s = (resp)->data; 1946 if (d) { 1947 l += print_chan (s + l, d->chan); 1948 l += print_stats (s + l, d->chan, 1); 1949 l += print_modems (s + l, d->chan, 1); 1950 l += print_e1_stats (s + l, d->chan); 1951 } else 1952 l += sprintf (s + l, "Error: node not connect to channel"); 1953 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRSIZ); 1954 } 1955 break; 1956 } 1957 break; 1958 } 1959 NG_RESPOND_MSG (error, node, item, resp); 1960 NG_FREE_MSG (msg); 1961 return error; 1962 } 1963 1964 static int ng_ce_rcvdata (hook_p hook, item_p item) 1965 { 1966 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 1967 struct mbuf *m; 1968 struct ng_tag_prio *ptag; 1969 bdrv_t *bd = d->board->sys; 1970 struct ifqueue *q; 1971 int s; 1972 1973 CE_DEBUG2 (d, ("Rcvdata\n")); 1974 NGI_GET_M (item, m); 1975 NG_FREE_ITEM (item); 1976 if (! NG_HOOK_PRIVATE (hook) || ! d) { 1977 NG_FREE_M (m); 1978 return ENETDOWN; 1979 } 1980 1981 /* Check for high priority data */ 1982 if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 1983 NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 1984 q = &d->hi_queue; 1985 else 1986 q = &d->queue; 1987 1988 s = splimp (); 1989 CE_LOCK (bd); 1990 IF_LOCK (q); 1991 if (_IF_QFULL (q)) { 1992 IF_UNLOCK (q); 1993 CE_UNLOCK (bd); 1994 splx (s); 1995 NG_FREE_M (m); 1996 return ENOBUFS; 1997 } 1998 _IF_ENQUEUE (q, m); 1999 IF_UNLOCK (q); 2000 ce_start (d); 2001 CE_UNLOCK (bd); 2002 splx (s); 2003 return 0; 2004 } 2005 2006 static int ng_ce_rmnode (node_p node) 2007 { 2008 drv_t *d = NG_NODE_PRIVATE (node); 2009 2010 CE_DEBUG (d, ("Rmnode\n")); 2011 if (d && d->running) { 2012 bdrv_t *bd = d->board->sys; 2013 int s = splimp (); 2014 CE_LOCK (bd); 2015 ce_down (d); 2016 CE_UNLOCK (bd); 2017 splx (s); 2018 } 2019 #ifdef KLD_MODULE 2020 if (node->nd_flags & NGF_REALLY_DIE) { 2021 NG_NODE_SET_PRIVATE (node, NULL); 2022 NG_NODE_UNREF (node); 2023 } 2024 NG_NODE_REVIVE(node); /* Persistent node */ 2025 #endif 2026 return 0; 2027 } 2028 2029 static int ng_ce_connect (hook_p hook) 2030 { 2031 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2032 2033 if (d) { 2034 CE_DEBUG (d, ("Connect\n")); 2035 callout_reset (&d->timeout_handle, hz, ce_watchdog_timer, d); 2036 } 2037 2038 return 0; 2039 } 2040 2041 static int ng_ce_disconnect (hook_p hook) 2042 { 2043 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2044 2045 if (d) { 2046 CE_DEBUG (d, ("Disconnect\n")); 2047 if (NG_HOOK_PRIVATE (hook)) 2048 { 2049 bdrv_t *bd = d->board->sys; 2050 int s = splimp (); 2051 CE_LOCK (bd); 2052 ce_down (d); 2053 CE_UNLOCK (bd); 2054 splx (s); 2055 } 2056 /* If we were wait it than it reasserted now, just stop it. */ 2057 if (!callout_drain (&d->timeout_handle)) 2058 callout_stop (&d->timeout_handle); 2059 } 2060 return 0; 2061 } 2062 #endif 2063 2064 static int ce_modevent (module_t mod, int type, void *unused) 2065 { 2066 static int load_count = 0; 2067 2068 2069 switch (type) { 2070 case MOD_LOAD: 2071 #if __FreeBSD_version >= 500000 && defined NETGRAPH 2072 if (ng_newtype (&typestruct)) 2073 printf ("Failed to register ng_ce\n"); 2074 #endif 2075 ++load_count; 2076 callout_init (&timeout_handle, 1); 2077 callout_reset (&timeout_handle, hz*5, ce_timeout, 0); 2078 break; 2079 case MOD_UNLOAD: 2080 if (load_count == 1) { 2081 printf ("Removing device entry for Tau32-PCI\n"); 2082 #if __FreeBSD_version >= 500000 && defined NETGRAPH 2083 ng_rmtype (&typestruct); 2084 #endif 2085 } 2086 /* If we were wait it than it reasserted now, just stop it. 2087 * Actually we shouldn't get this condition. But code could be 2088 * changed in the future, so just be a litle paranoid. 2089 */ 2090 if (!callout_drain (&timeout_handle)) 2091 callout_stop (&timeout_handle); 2092 --load_count; 2093 break; 2094 case MOD_SHUTDOWN: 2095 break; 2096 } 2097 return 0; 2098 } 2099 2100 #ifdef NETGRAPH 2101 static struct ng_type typestruct = { 2102 .version = NG_ABI_VERSION, 2103 .name = NG_CE_NODE_TYPE, 2104 .constructor = ng_ce_constructor, 2105 .rcvmsg = ng_ce_rcvmsg, 2106 .shutdown = ng_ce_rmnode, 2107 .newhook = ng_ce_newhook, 2108 .connect = ng_ce_connect, 2109 .rcvdata = ng_ce_rcvdata, 2110 .disconnect = ng_ce_disconnect, 2111 }; 2112 2113 #endif /*NETGRAPH*/ 2114 2115 #ifdef NETGRAPH 2116 MODULE_DEPEND (ng_ce, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2117 #else 2118 MODULE_DEPEND (ce, sppp, 1, 1, 1); 2119 #endif 2120 #ifdef KLD_MODULE 2121 DRIVER_MODULE (cemod, pci, ce_driver, ce_devclass, ce_modevent, NULL); 2122 #else 2123 DRIVER_MODULE (ce, pci, ce_driver, ce_devclass, ce_modevent, NULL); 2124 #endif 2125