if_ct.c revision 138651
1/* 2 * Cronyx-Tau adapter driver for FreeBSD. 3 * Supports PPP/HDLC and Cisco/HDLC protocol in synchronous mode, 4 * and asyncronous channels with full modem control. 5 * Keepalive protocol implemented in both Cisco and PPP modes. 6 * 7 * Copyright (C) 1994-2002 Cronyx Engineering. 8 * Author: Serge Vakulenko, <vak@cronyx.ru> 9 * 10 * Copyright (C) 1999-2004 Cronyx Engineering. 11 * Author: Roman Kurakin, <rik@cronyx.ru> 12 * 13 * This software is distributed with NO WARRANTIES, not even the implied 14 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15 * 16 * Authors grant any other persons or organisations a permission to use, 17 * modify and redistribute this software in source and binary forms, 18 * as long as this message is kept with the software, all derivative 19 * works or modified versions. 20 * 21 * Cronyx Id: if_ct.c,v 1.1.2.31 2004/06/23 17:09:13 rik Exp $ 22 */ 23 24#include <sys/cdefs.h> 25__FBSDID("$FreeBSD: head/sys/dev/ctau/if_ct.c 138651 2004-12-10 05:54:45Z rik $"); 26 27#include <sys/param.h> 28#include <sys/proc.h> 29#include <sys/systm.h> 30#include <sys/kernel.h> 31#include <sys/module.h> 32#include <sys/mbuf.h> 33#include <sys/sockio.h> 34#include <sys/malloc.h> 35#include <sys/socket.h> 36#include <sys/conf.h> 37#include <sys/errno.h> 38#include <sys/tty.h> 39#include <sys/bus.h> 40#include <machine/bus.h> 41#include <sys/rman.h> 42#include <isa/isavar.h> 43#include <sys/interrupt.h> 44#include <vm/vm.h> 45#include <vm/pmap.h> 46#include <net/if.h> 47#include <machine/cpufunc.h> 48#include <machine/cserial.h> 49#include <machine/clock.h> 50#include <machine/resource.h> 51#include <dev/cx/machdep.h> 52#include <dev/ctau/ctddk.h> 53#include <dev/cx/cronyxfw.h> 54#include "opt_ng_cronyx.h" 55#ifdef NETGRAPH_CRONYX 56# include "opt_netgraph.h" 57# include <netgraph/ng_message.h> 58# include <netgraph/netgraph.h> 59# include <dev/ctau/ng_ct.h> 60#else 61# include <net/if_types.h> 62# include <net/if_sppp.h> 63# define PP_CISCO IFF_LINK2 64# include <net/bpf.h> 65#endif 66 67#define NCTAU 1 68 69/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 70#ifndef PP_FR 71#define PP_FR 0 72#endif 73 74#define CT_DEBUG(d,s) ({if (d->chan->debug) {\ 75 printf ("%s: ", d->name); printf s;}}) 76#define CT_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 77 printf ("%s: ", d->name); printf s;}}) 78#define CDEV_MAJOR 99 79 80static void ct_identify __P((driver_t *, device_t)); 81static int ct_probe __P((device_t)); 82static int ct_attach __P((device_t)); 83static int ct_detach __P((device_t)); 84 85static device_method_t ct_isa_methods [] = { 86 DEVMETHOD(device_identify, ct_identify), 87 DEVMETHOD(device_probe, ct_probe), 88 DEVMETHOD(device_attach, ct_attach), 89 DEVMETHOD(device_detach, ct_detach), 90 {0, 0} 91}; 92 93typedef struct _ct_dma_mem_t { 94 unsigned long phys; 95 void *virt; 96 size_t size; 97 bus_dma_tag_t dmat; 98 bus_dmamap_t mapp; 99} ct_dma_mem_t; 100 101typedef struct _drv_t { 102 char name [8]; 103 ct_chan_t *chan; 104 ct_board_t *board; 105 ct_dma_mem_t dmamem; 106 int running; 107#ifdef NETGRAPH 108 char nodename [NG_NODELEN+1]; 109 hook_p hook; 110 hook_p debug_hook; 111 node_p node; 112 struct ifqueue queue; 113 struct ifqueue hi_queue; 114 short timeout; 115 struct callout_handle timeout_handle; 116#else 117 struct sppp pp; 118#endif 119 struct cdev *devt; 120} drv_t; 121 122typedef struct _bdrv_t { 123 ct_board_t *board; 124 struct resource *base_res; 125 struct resource *drq_res; 126 struct resource *irq_res; 127 int base_rid; 128 int drq_rid; 129 int irq_rid; 130 void *intrhand; 131 drv_t channel [NCHAN]; 132} bdrv_t; 133 134static driver_t ct_isa_driver = { 135 "ct", 136 ct_isa_methods, 137 sizeof (bdrv_t), 138}; 139 140static devclass_t ct_devclass; 141 142static void ct_receive (ct_chan_t *c, char *data, int len); 143static void ct_transmit (ct_chan_t *c, void *attachment, int len); 144static void ct_error (ct_chan_t *c, int data); 145static void ct_up (drv_t *d); 146static void ct_start (drv_t *d); 147static void ct_down (drv_t *d); 148static void ct_watchdog (drv_t *d); 149#ifdef NETGRAPH 150extern struct ng_type typestruct; 151#else 152static void ct_ifstart (struct ifnet *ifp); 153static void ct_tlf (struct sppp *sp); 154static void ct_tls (struct sppp *sp); 155static void ct_ifwatchdog (struct ifnet *ifp); 156static int ct_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 157static void ct_initialize (void *softc); 158#endif 159 160static ct_board_t *adapter [NCTAU]; 161static drv_t *channel [NCTAU*NCHAN]; 162static struct callout_handle led_timo [NCTAU]; 163static struct callout_handle timeout_handle; 164 165/* 166 * Print the mbuf chain, for debug purposes only. 167 */ 168static void printmbuf (struct mbuf *m) 169{ 170 printf ("mbuf:"); 171 for (; m; m=m->m_next) { 172 if (m->m_flags & M_PKTHDR) 173 printf (" HDR %d:", m->m_pkthdr.len); 174 if (m->m_flags & M_EXT) 175 printf (" EXT:"); 176 printf (" %d", m->m_len); 177 } 178 printf ("\n"); 179} 180 181/* 182 * Make an mbuf from data. 183 */ 184static struct mbuf *makembuf (void *buf, u_int len) 185{ 186 struct mbuf *m; 187 188 MGETHDR (m, M_DONTWAIT, MT_DATA); 189 if (! m) 190 return 0; 191 MCLGET (m, M_DONTWAIT); 192 if (! (m->m_flags & M_EXT)) { 193 m_freem (m); 194 return 0; 195 } 196 m->m_pkthdr.len = m->m_len = len; 197 bcopy (buf, mtod (m, caddr_t), len); 198 return m; 199} 200 201static void ct_timeout (void *arg) 202{ 203 drv_t *d; 204 int s, i; 205 206 for (i=0; i<NCTAU*NCHAN; ++i) { 207 d = channel[i]; 208 if (! d) 209 continue; 210 if (d->chan->mode != M_G703) 211 continue; 212 s = splimp (); 213 ct_g703_timer (d->chan); 214 splx (s); 215 } 216 timeout_handle = timeout (ct_timeout, 0, hz); 217} 218 219static void ct_led_off (void *arg) 220{ 221 ct_board_t *b = arg; 222 int s = splimp (); 223 224 ct_led (b, 0); 225 led_timo[b->num].callout = 0; 226 splx (s); 227} 228 229/* 230 * Activate interupt handler from DDK. 231 */ 232static void ct_intr (void *arg) 233{ 234 bdrv_t *bd = arg; 235 ct_board_t *b = bd->board; 236 int s = splimp (); 237 238 /* Turn LED on. */ 239 ct_led (b, 1); 240 241 ct_int_handler (b); 242 243 /* Turn LED off 50 msec later. */ 244 if (! led_timo[b->num].callout) 245 led_timo[b->num] = timeout (ct_led_off, b, hz/20); 246 splx (s); 247} 248 249static int probe_irq (ct_board_t *b, int irq) 250{ 251 int mask, busy, cnt; 252 253 /* Clear pending irq, if any. */ 254 ct_probe_irq (b, -irq); 255 DELAY (100); 256 for (cnt=0; cnt<5; ++cnt) { 257 /* Get the mask of pending irqs, assuming they are busy. 258 * Activate the adapter on given irq. */ 259 busy = ct_probe_irq (b, irq); 260 DELAY (1000); 261 262 /* Get the mask of active irqs. 263 * Deactivate our irq. */ 264 mask = ct_probe_irq (b, -irq); 265 DELAY (100); 266 if ((mask & ~busy) == 1 << irq) { 267 ct_probe_irq (b, 0); 268 /* printf ("ct%d: irq %d ok, mask=0x%04x, busy=0x%04x\n", 269 b->num, irq, mask, busy); */ 270 return 1; 271 } 272 } 273 /* printf ("ct%d: irq %d not functional, mask=0x%04x, busy=0x%04x\n", 274 b->num, irq, mask, busy); */ 275 ct_probe_irq (b, 0); 276 return 0; 277} 278 279static short porttab [] = { 280 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 281 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 282 }; 283static char dmatab [] = { 7, 6, 5, 0 }; 284static char irqtab [] = { 5, 10, 11, 7, 3, 15, 12, 0 }; 285 286static int ct_is_free_res (device_t dev, int rid, int type, u_long start, 287 u_long end, u_long count) 288{ 289 struct resource *res; 290 291 if (!(res = bus_alloc_resource (dev, type, &rid, start, end, count, 292 RF_ALLOCATED))) 293 return 0; 294 295 bus_release_resource (dev, type, rid, res); 296 297 return 1; 298} 299 300static void ct_identify (driver_t *driver, device_t dev) 301{ 302 u_long iobase, rescount; 303 int devcount; 304 device_t *devices; 305 device_t child; 306 devclass_t my_devclass; 307 int i, k; 308 309 if ((my_devclass = devclass_find ("ct")) == NULL) 310 return; 311 312 devclass_get_devices (my_devclass, &devices, &devcount); 313 314 if (devcount == 0) { 315 /* We should find all devices by our self. We could alter other 316 * devices, but we don't have a choise 317 */ 318 for (i = 0; (iobase = porttab [i]) != 0; i++) { 319 if (!ct_is_free_res (dev, 0, SYS_RES_IOPORT, 320 iobase, iobase + NPORT, NPORT)) 321 continue; 322 if (ct_probe_board (iobase, -1, -1) == 0) 323 continue; 324 325 devcount++; 326 child = BUS_ADD_CHILD (dev, ISA_ORDER_SPECULATIVE, "ct", 327 -1); 328 329 if (child == NULL) 330 return; 331 332 device_set_desc_copy (child, "Cronyx Tau-ISA"); 333 device_set_driver (child, driver); 334 bus_set_resource (child, SYS_RES_IOPORT, 0, 335 iobase, NPORT); 336 337 if (devcount >= NCTAU) 338 break; 339 } 340 } else { 341 static short porttab [] = { 342 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 343 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 344 }; 345 /* Lets check user choise. 346 */ 347 for (k = 0; k < devcount; k++) { 348 if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 349 &iobase, &rescount) != 0) 350 continue; 351 352 for (i = 0; porttab [i] != 0; i++) { 353 if (porttab [i] != iobase) 354 continue; 355 356 if (!ct_is_free_res (devices[k], 0, SYS_RES_IOPORT, 357 iobase, iobase + NPORT, NPORT)) 358 continue; 359 360 if (ct_probe_board (iobase, -1, -1) == 0) 361 continue; 362 porttab [i] = -1; 363 device_set_desc_copy (devices[k], "Cronyx Tau-ISA"); 364 break; 365 } 366 if (porttab [i] == 0) { 367 device_delete_child ( 368 device_get_parent (devices[k]), 369 devices [k]); 370 devices[k] = 0; 371 continue; 372 } 373 } 374 for (k = 0; k < devcount; k++) { 375 if (devices[k] == 0) 376 continue; 377 if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 378 &iobase, &rescount) == 0) 379 continue; 380 for (i = 0; (iobase = porttab [i]) != 0; i++) { 381 if (porttab [i] == -1) 382 continue; 383 if (!ct_is_free_res (devices[k], 0, SYS_RES_IOPORT, 384 iobase, iobase + NPORT, NPORT)) 385 continue; 386 if (ct_probe_board (iobase, -1, -1) == 0) 387 continue; 388 389 bus_set_resource (devices[k], SYS_RES_IOPORT, 0, 390 iobase, NPORT); 391 porttab [i] = -1; 392 device_set_desc_copy (devices[k], "Cronyx Tau-ISA"); 393 break; 394 } 395 if (porttab [i] == 0) { 396 device_delete_child ( 397 device_get_parent (devices[k]), 398 devices [k]); 399 } 400 } 401 free (devices, M_TEMP); 402 } 403 404 return; 405} 406 407static int ct_probe (device_t dev) 408{ 409 int unit = device_get_unit (dev); 410 u_long iobase, rescount; 411 412 if (!device_get_desc (dev) || 413 strcmp (device_get_desc (dev), "Cronyx Tau-ISA")) 414 return ENXIO; 415 416/* KASSERT ((bd != NULL), ("ct%d: NULL device softc\n", unit));*/ 417 if (bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount) != 0) { 418 printf ("ct%d: Couldn't get IOPORT\n", unit); 419 return ENXIO; 420 } 421 422 if (!ct_is_free_res (dev, 0, SYS_RES_IOPORT, 423 iobase, iobase + NPORT, NPORT)) { 424 printf ("ct%d: Resource IOPORT isn't free\n", unit); 425 return ENXIO; 426 } 427 428 if (!ct_probe_board (iobase, -1, -1)) { 429 printf ("ct%d: probing for Tau-ISA at %lx faild\n", unit, iobase); 430 return ENXIO; 431 } 432 433 return 0; 434} 435 436extern struct cdevsw ct_cdevsw; 437 438static void 439ct_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 440{ 441 unsigned long *addr; 442 443 if (error) 444 return; 445 446 KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 447 addr = arg; 448 *addr = segs->ds_addr; 449} 450 451static int 452ct_bus_dma_mem_alloc (int bnum, int cnum, ct_dma_mem_t *dmem) 453{ 454 int error; 455 456 error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_24BIT, 457 BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 458 dmem->size, 0, NULL, NULL, &dmem->dmat); 459 if (error) { 460 if (cnum >= 0) printf ("ct%d-%d: ", bnum, cnum); 461 else printf ("ct%d: ", bnum); 462 printf ("couldn't allocate tag for dma memory\n"); 463 return 0; 464 } 465 error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 466 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 467 if (error) { 468 if (cnum >= 0) printf ("ct%d-%d: ", bnum, cnum); 469 else printf ("ct%d: ", bnum); 470 printf ("couldn't allocate mem for dma memory\n"); 471 bus_dma_tag_destroy (dmem->dmat); 472 return 0; 473 } 474 error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 475 dmem->size, ct_bus_dmamap_addr, &dmem->phys, 0); 476 if (error) { 477 if (cnum >= 0) printf ("ct%d-%d: ", bnum, cnum); 478 else printf ("ct%d: ", bnum); 479 printf ("couldn't load mem map for dma memory\n"); 480 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 481 bus_dma_tag_destroy (dmem->dmat); 482 return 0; 483 } 484 return 1; 485} 486 487static void 488ct_bus_dma_mem_free (ct_dma_mem_t *dmem) 489{ 490 bus_dmamap_unload (dmem->dmat, dmem->mapp); 491 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 492 bus_dma_tag_destroy (dmem->dmat); 493} 494 495/* 496 * The adapter is present, initialize the driver structures. 497 */ 498static int ct_attach (device_t dev) 499{ 500 bdrv_t *bd = device_get_softc (dev); 501 u_long iobase, drq, irq, rescount; 502 int unit = device_get_unit (dev); 503 ct_board_t *b; 504 ct_chan_t *c; 505 drv_t *d; 506 int i; 507 int s; 508 509 KASSERT ((bd != NULL), ("ct%d: NULL device softc\n", unit)); 510 511 bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount); 512 bd->base_rid = 0; 513 bd->base_res = bus_alloc_resource (dev, SYS_RES_IOPORT, &bd->base_rid, 514 iobase, iobase + NPORT, NPORT, RF_ACTIVE); 515 if (! bd->base_res) { 516 printf ("ct%d: cannot alloc base address\n", unit); 517 return ENXIO; 518 } 519 520 if (bus_get_resource (dev, SYS_RES_DRQ, 0, &drq, &rescount) != 0) { 521 for (i = 0; (drq = dmatab [i]) != 0; i++) { 522 if (!ct_is_free_res (dev, 0, SYS_RES_DRQ, 523 drq, drq + 1, 1)) 524 continue; 525 bus_set_resource (dev, SYS_RES_DRQ, 0, drq, 1); 526 break; 527 } 528 529 if (dmatab[i] == 0) { 530 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 531 bd->base_res); 532 printf ("ct%d: Couldn't get DRQ\n", unit); 533 return ENXIO; 534 } 535 } 536 537 bd->drq_rid = 0; 538 bd->drq_res = bus_alloc_resource (dev, SYS_RES_DRQ, &bd->drq_rid, 539 drq, drq + 1, 1, RF_ACTIVE); 540 if (! bd->drq_res) { 541 printf ("ct%d: cannot allocate drq\n", unit); 542 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 543 bd->base_res); 544 return ENXIO; 545 } 546 547 if (bus_get_resource (dev, SYS_RES_IRQ, 0, &irq, &rescount) != 0) { 548 for (i = 0; (irq = irqtab [i]) != 0; i++) { 549 if (!ct_is_free_res (dev, 0, SYS_RES_IRQ, 550 irq, irq + 1, 1)) 551 continue; 552 bus_set_resource (dev, SYS_RES_IRQ, 0, irq, 1); 553 break; 554 } 555 556 if (irqtab[i] == 0) { 557 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 558 bd->drq_res); 559 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 560 bd->base_res); 561 printf ("ct%d: Couldn't get IRQ\n", unit); 562 return ENXIO; 563 } 564 } 565 566 bd->irq_rid = 0; 567 bd->irq_res = bus_alloc_resource (dev, SYS_RES_IRQ, &bd->irq_rid, 568 irq, irq + 1, 1, RF_ACTIVE); 569 if (! bd->irq_res) { 570 printf ("ct%d: Couldn't allocate irq\n", unit); 571 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 572 bd->drq_res); 573 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 574 bd->base_res); 575 return ENXIO; 576 } 577 578 b = malloc (sizeof (ct_board_t), M_DEVBUF, M_WAITOK); 579 if (!b) { 580 printf ("ct:%d: Couldn't allocate memory\n", unit); 581 return (ENXIO); 582 } 583 adapter[unit] = b; 584 bzero (b, sizeof(ct_board_t)); 585 586 if (! ct_open_board (b, unit, iobase, irq, drq)) { 587 printf ("ct%d: error loading firmware\n", unit); 588 free (b, M_DEVBUF); 589 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 590 bd->irq_res); 591 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 592 bd->drq_res); 593 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 594 bd->base_res); 595 return ENXIO; 596 } 597 598 bd->board = b; 599 600 if (! probe_irq (b, irq)) { 601 printf ("ct%d: irq %ld not functional\n", unit, irq); 602 bd->board = 0; 603 adapter [unit] = 0; 604 free (b, M_DEVBUF); 605 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 606 bd->irq_res); 607 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 608 bd->drq_res); 609 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 610 bd->base_res); 611 return ENXIO; 612 } 613 614 s = splimp (); 615 if (bus_setup_intr (dev, bd->irq_res, INTR_TYPE_NET, ct_intr, bd, 616 &bd->intrhand)) { 617 printf ("ct%d: Can't setup irq %ld\n", unit, irq); 618 bd->board = 0; 619 adapter [unit] = 0; 620 free (b, M_DEVBUF); 621 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 622 bd->irq_res); 623 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 624 bd->drq_res); 625 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 626 bd->base_res); 627 splx (s); 628 return ENXIO; 629 } 630 631 ct_init_board (b, b->num, b->port, irq, drq, b->type, b->osc); 632 ct_setup_board (b, 0, 0, 0); 633 634 printf ("ct%d: <Cronyx-%s>, clock %s MHz\n", b->num, b->name, 635 b->osc == 20000000 ? "20" : "16.384"); 636 637 for (c=b->chan; c<b->chan+NCHAN; ++c) { 638 d = &bd->channel[c->num]; 639 d->dmamem.size = sizeof(ct_buf_t); 640 if (! ct_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 641 continue; 642 channel [b->num*NCHAN + c->num] = d; 643 sprintf (d->name, "ct%d.%d", b->num, c->num); 644 d->board = b; 645 d->chan = c; 646 c->sys = d; 647 648#ifdef NETGRAPH 649 if (ng_make_node_common (&typestruct, &d->node) != 0) { 650 printf ("%s: cannot make common node\n", d->name); 651 channel [b->num*NCHAN + c->num] = 0; 652 c->sys = 0; 653 ct_bus_dma_mem_free (&d->dmamem); 654 continue; 655 } 656 NG_NODE_SET_PRIVATE (d->node, d); 657 sprintf (d->nodename, "%s%d", NG_CT_NODE_TYPE, 658 c->board->num*NCHAN + c->num); 659 if (ng_name_node (d->node, d->nodename)) { 660 printf ("%s: cannot name node\n", d->nodename); 661 NG_NODE_UNREF (d->node); 662 channel [b->num*NCHAN + c->num] = 0; 663 c->sys = 0; 664 ct_bus_dma_mem_free (&d->dmamem); 665 continue; 666 } 667 d->queue.ifq_maxlen = IFQ_MAXLEN; 668 d->hi_queue.ifq_maxlen = IFQ_MAXLEN; 669 mtx_init (&d->queue.ifq_mtx, "ct_queue", NULL, MTX_DEF); 670 mtx_init (&d->hi_queue.ifq_mtx, "ct_queue_hi", NULL, MTX_DEF); 671#else /*NETGRAPH*/ 672 d->pp.pp_if.if_softc = d; 673 if_initname (&d->pp.pp_if, "ct", b->num * NCHAN + c->num); 674 d->pp.pp_if.if_mtu = PP_MTU; 675 d->pp.pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST | 676 IFF_NEEDSGIANT; 677 d->pp.pp_if.if_ioctl = ct_sioctl; 678 d->pp.pp_if.if_start = ct_ifstart; 679 d->pp.pp_if.if_watchdog = ct_ifwatchdog; 680 d->pp.pp_if.if_init = ct_initialize; 681 sppp_attach (&d->pp.pp_if); 682 if_attach (&d->pp.pp_if); 683 d->pp.pp_tlf = ct_tlf; 684 d->pp.pp_tls = ct_tls; 685 /* If BPF is in the kernel, call the attach for it. 686 * Header size is 4 bytes. */ 687 bpfattach (&d->pp.pp_if, DLT_PPP, 4); 688#endif /*NETGRAPH*/ 689 ct_start_chan (c, d->dmamem.virt, d->dmamem.phys); 690 ct_register_receive (c, &ct_receive); 691 ct_register_transmit (c, &ct_transmit); 692 ct_register_error (c, &ct_error); 693 d->devt = make_dev (&ct_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 694 GID_WHEEL, 0600, "ct%d", b->num*NCHAN+c->num); 695 } 696 splx (s); 697 698 return 0; 699} 700 701static int ct_detach (device_t dev) 702{ 703 bdrv_t *bd = device_get_softc (dev); 704 ct_board_t *b = bd->board; 705 ct_chan_t *c; 706 int s = splimp (); 707 708 /* Check if the device is busy (open). */ 709 for (c = b->chan; c < b->chan + NCHAN; ++c) { 710 drv_t *d = (drv_t*) c->sys; 711 712 if (!d || !d->chan->type) 713 continue; 714 715 if (d->running) { 716 splx (s); 717 return EBUSY; 718 } 719 } 720 721 /* Deactivate the timeout routine. */ 722 if (led_timo[b->num].callout) 723 untimeout (ct_led_off, b, led_timo[b->num]); 724 725 bus_teardown_intr (dev, bd->irq_res, bd->intrhand); 726 bus_deactivate_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res); 727 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res); 728 729 bus_deactivate_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res); 730 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res); 731 732 bus_deactivate_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->irq_res); 733 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->base_res); 734 735 ct_close_board (b); 736 737 /* Detach the interfaces, free buffer memory. */ 738 for (c = b->chan; c < b->chan + NCHAN; ++c) { 739 drv_t *d = (drv_t*) c->sys; 740 741 if (!d || !d->chan->type) 742 continue; 743 744#ifdef NETGRAPH 745 if (d->node) { 746 ng_rmnode_self (d->node); 747 NG_NODE_UNREF (d->node); 748 d->node = NULL; 749 } 750 mtx_destroy (&d->queue.ifq_mtx); 751 mtx_destroy (&d->hi_queue.ifq_mtx); 752#else 753 /* Detach from the packet filter list of interfaces. */ 754 bpfdetach (&d->pp.pp_if); 755 /* Detach from the sync PPP list. */ 756 sppp_detach (&d->pp.pp_if); 757 758 if_detach (&d->pp.pp_if); 759#endif 760 destroy_dev (d->devt); 761 } 762 763 ct_led_off (b); 764 if (led_timo[b->num].callout) 765 untimeout (ct_led_off, b, led_timo[b->num]); 766 splx (s); 767 768 s = splimp (); 769 for (c = b->chan; c < b->chan + NCHAN; ++c) { 770 drv_t *d = (drv_t*) c->sys; 771 772 if (!d || !d->chan->type) 773 continue; 774 775 /* Deallocate buffers. */ 776 ct_bus_dma_mem_free (&d->dmamem); 777 } 778 bd->board = 0; 779 adapter [b->num] = 0; 780 free (b, M_DEVBUF); 781 splx (s); 782 783 return 0; 784} 785 786#ifndef NETGRAPH 787static void ct_ifstart (struct ifnet *ifp) 788{ 789 drv_t *d = ifp->if_softc; 790 791 ct_start (d); 792} 793 794static void ct_ifwatchdog (struct ifnet *ifp) 795{ 796 drv_t *d = ifp->if_softc; 797 798 ct_watchdog (d); 799} 800 801static void ct_tlf (struct sppp *sp) 802{ 803 drv_t *d = sp->pp_if.if_softc; 804 805 CT_DEBUG (d, ("ct_tlf\n")); 806/* ct_set_dtr (d->chan, 0);*/ 807/* ct_set_rts (d->chan, 0);*/ 808 if (!(d->pp.pp_flags & PP_FR) && !(d->pp.pp_if.if_flags & PP_CISCO)) 809 sp->pp_down (sp); 810} 811 812static void ct_tls (struct sppp *sp) 813{ 814 drv_t *d = sp->pp_if.if_softc; 815 816 CT_DEBUG (d, ("ct_tls\n")); 817 if (!(d->pp.pp_flags & PP_FR) && !(d->pp.pp_if.if_flags & PP_CISCO)) 818 sp->pp_up (sp); 819} 820 821/* 822 * Initialization of interface. 823 * Ii seems to be never called by upper level. 824 */ 825static void ct_initialize (void *softc) 826{ 827 drv_t *d = softc; 828 829 CT_DEBUG (d, ("ct_initialize\n")); 830} 831 832/* 833 * Process an ioctl request. 834 */ 835static int ct_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 836{ 837 drv_t *d = ifp->if_softc; 838 int error, s, was_up, should_be_up; 839 840 was_up = (ifp->if_flags & IFF_RUNNING) != 0; 841 error = sppp_ioctl (ifp, cmd, data); 842 if (error) 843 return error; 844 845 if (! (ifp->if_flags & IFF_DEBUG)) 846 d->chan->debug = 0; 847 else if (! d->chan->debug) 848 d->chan->debug = 1; 849 850 switch (cmd) { 851 default: CT_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 852 case SIOCADDMULTI: CT_DEBUG2 (d, ("SIOCADDMULTI\n")); return 0; 853 case SIOCDELMULTI: CT_DEBUG2 (d, ("SIOCDELMULTI\n")); return 0; 854 case SIOCSIFFLAGS: CT_DEBUG2 (d, ("SIOCSIFFLAGS\n")); break; 855 case SIOCSIFADDR: CT_DEBUG2 (d, ("SIOCSIFADDR\n")); break; 856 } 857 858 /* We get here only in case of SIFFLAGS or SIFADDR. */ 859 s = splimp (); 860 should_be_up = (ifp->if_flags & IFF_RUNNING) != 0; 861 if (! was_up && should_be_up) { 862 /* Interface goes up -- start it. */ 863 ct_up (d); 864 ct_start (d); 865 } else if (was_up && ! should_be_up) { 866 /* Interface is going down -- stop it. */ 867 /* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 868 ct_down (d); 869 } 870 splx (s); 871 return 0; 872} 873#endif /*NETGRAPH*/ 874 875/* 876 * Stop the interface. Called on splimp(). 877 */ 878static void ct_down (drv_t *d) 879{ 880 int s = splimp (); 881 CT_DEBUG (d, ("ct_down\n")); 882 ct_set_dtr (d->chan, 0); 883 ct_set_rts (d->chan, 0); 884 d->running = 0; 885 splx (s); 886} 887 888/* 889 * Start the interface. Called on splimp(). 890 */ 891static void ct_up (drv_t *d) 892{ 893 int s = splimp (); 894 CT_DEBUG (d, ("ct_up\n")); 895 ct_set_dtr (d->chan, 1); 896 ct_set_rts (d->chan, 1); 897 d->running = 1; 898 splx (s); 899} 900 901/* 902 * Start output on the (slave) interface. Get another datagram to send 903 * off of the interface queue, and copy it to the interface 904 * before starting the output. 905 */ 906static void ct_send (drv_t *d) 907{ 908 struct mbuf *m; 909 u_short len; 910 911 CT_DEBUG2 (d, ("ct_send, tn=%d\n", d->chan->tn)); 912 913 /* No output if the interface is down. */ 914 if (! d->running) 915 return; 916 917 /* No output if the modem is off. */ 918 if (! ct_get_dsr (d->chan) && !ct_get_loop (d->chan)) 919 return; 920 921 while (ct_buf_free (d->chan)) { 922 /* Get the packet to send. */ 923#ifdef NETGRAPH 924 IF_DEQUEUE (&d->hi_queue, m); 925 if (! m) 926 IF_DEQUEUE (&d->queue, m); 927#else 928 m = sppp_dequeue (&d->pp.pp_if); 929#endif 930 if (! m) 931 return; 932#ifndef NETGRAPH 933 if (d->pp.pp_if.if_bpf) 934 BPF_MTAP (&d->pp.pp_if, m); 935#endif 936 len = m->m_pkthdr.len; 937 if (! m->m_next) 938 ct_send_packet (d->chan, (u_char*)mtod (m, caddr_t), 939 len, 0); 940 else { 941 m_copydata (m, 0, len, d->chan->tbuf[d->chan->te]); 942 ct_send_packet (d->chan, d->chan->tbuf[d->chan->te], 943 len, 0); 944 } 945 m_freem (m); 946 947 /* Set up transmit timeout, if the transmit ring is not empty. 948 * Transmit timeout is 10 seconds. */ 949#ifdef NETGRAPH 950 d->timeout = 10; 951#else 952 d->pp.pp_if.if_timer = 10; 953#endif 954 } 955#ifndef NETGRAPH 956 d->pp.pp_if.if_flags |= IFF_OACTIVE; 957#endif 958} 959 960/* 961 * Start output on the interface. 962 * Always called on splimp(). 963 */ 964static void ct_start (drv_t *d) 965{ 966 int s = splimp (); 967 968 if (d->running) { 969 if (! d->chan->dtr) 970 ct_set_dtr (d->chan, 1); 971 if (! d->chan->rts) 972 ct_set_rts (d->chan, 1); 973 ct_send (d); 974 } 975 976 splx (s); 977} 978 979/* 980 * Handle transmit timeouts. 981 * Recover after lost transmit interrupts. 982 * Always called on splimp(). 983 */ 984static void ct_watchdog (drv_t *d) 985{ 986 int s = splimp (); 987 988 CT_DEBUG (d, ("device timeout\n")); 989 if (d->running) { 990 ct_setup_chan (d->chan); 991 ct_start_chan (d->chan, 0, 0); 992 ct_set_dtr (d->chan, 1); 993 ct_set_rts (d->chan, 1); 994 ct_start (d); 995 } 996 997 splx (s); 998} 999 1000/* 1001 * Transmit callback function. 1002 */ 1003static void ct_transmit (ct_chan_t *c, void *attachment, int len) 1004{ 1005 drv_t *d = c->sys; 1006 1007 if (!d) 1008 return; 1009#ifdef NETGRAPH 1010 d->timeout = 0; 1011#else 1012 ++d->pp.pp_if.if_opackets; 1013 d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 1014 d->pp.pp_if.if_timer = 0; 1015#endif 1016 ct_start (d); 1017} 1018 1019/* 1020 * Process the received packet. 1021 */ 1022static void ct_receive (ct_chan_t *c, char *data, int len) 1023{ 1024 drv_t *d = c->sys; 1025 struct mbuf *m; 1026#ifdef NETGRAPH 1027 int error; 1028#endif 1029 1030 if (!d || !d->running) 1031 return; 1032 1033 m = makembuf (data, len); 1034 if (! m) { 1035 CT_DEBUG (d, ("no memory for packet\n")); 1036#ifndef NETGRAPH 1037 ++d->pp.pp_if.if_iqdrops; 1038#endif 1039 return; 1040 } 1041 if (c->debug > 1) 1042 printmbuf (m); 1043#ifdef NETGRAPH 1044 m->m_pkthdr.rcvif = 0; 1045 NG_SEND_DATA_ONLY (error, d->hook, m); 1046#else 1047 ++d->pp.pp_if.if_ipackets; 1048 m->m_pkthdr.rcvif = &d->pp.pp_if; 1049 /* Check if there's a BPF listener on this interface. 1050 * If so, hand off the raw packet to bpf. */ 1051 if (d->pp.pp_if.if_bpf) 1052 BPF_TAP (&d->pp.pp_if, data, len); 1053 sppp_input (&d->pp.pp_if, m); 1054#endif 1055} 1056 1057/* 1058 * Error callback function. 1059 */ 1060static void ct_error (ct_chan_t *c, int data) 1061{ 1062 drv_t *d = c->sys; 1063 1064 if (!d) 1065 return; 1066 1067 switch (data) { 1068 case CT_FRAME: 1069 CT_DEBUG (d, ("frame error\n")); 1070#ifndef NETGRAPH 1071 ++d->pp.pp_if.if_ierrors; 1072#endif 1073 break; 1074 case CT_CRC: 1075 CT_DEBUG (d, ("crc error\n")); 1076#ifndef NETGRAPH 1077 ++d->pp.pp_if.if_ierrors; 1078#endif 1079 break; 1080 case CT_OVERRUN: 1081 CT_DEBUG (d, ("overrun error\n")); 1082#ifndef NETGRAPH 1083 ++d->pp.pp_if.if_collisions; 1084 ++d->pp.pp_if.if_ierrors; 1085#endif 1086 break; 1087 case CT_OVERFLOW: 1088 CT_DEBUG (d, ("overflow error\n")); 1089#ifndef NETGRAPH 1090 ++d->pp.pp_if.if_ierrors; 1091#endif 1092 break; 1093 case CT_UNDERRUN: 1094 CT_DEBUG (d, ("underrun error\n")); 1095#ifdef NETGRAPH 1096 d->timeout = 0; 1097#else 1098 ++d->pp.pp_if.if_oerrors; 1099 d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 1100 d->pp.pp_if.if_timer = 0; 1101#endif 1102 ct_start (d); 1103 break; 1104 default: 1105 CT_DEBUG (d, ("error #%d\n", data)); 1106 } 1107} 1108 1109static int ct_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 1110{ 1111 drv_t *d; 1112 1113 if (minor(dev) >= NCTAU*NCHAN || ! (d = channel[minor(dev)])) 1114 return ENXIO; 1115 1116 CT_DEBUG2 (d, ("ct_open\n")); 1117 return 0; 1118} 1119 1120static int ct_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 1121{ 1122 drv_t *d = channel [minor(dev)]; 1123 1124 if (!d) 1125 return 0; 1126 1127 CT_DEBUG2 (d, ("ct_close\n")); 1128 return 0; 1129} 1130 1131static int ct_modem_status (ct_chan_t *c) 1132{ 1133 drv_t *d = c->sys; 1134 int status, s; 1135 1136 if (!d) 1137 return 0; 1138 1139 status = d->running ? TIOCM_LE : 0; 1140 s = splimp (); 1141 if (ct_get_cd (c)) status |= TIOCM_CD; 1142 if (ct_get_cts (c)) status |= TIOCM_CTS; 1143 if (ct_get_dsr (c)) status |= TIOCM_DSR; 1144 if (c->dtr) status |= TIOCM_DTR; 1145 if (c->rts) status |= TIOCM_RTS; 1146 splx (s); 1147 return status; 1148} 1149 1150/* 1151 * Process an ioctl request on /dev/cronyx/ctauN. 1152 */ 1153static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1154{ 1155 drv_t *d = channel [minor (dev)]; 1156 ct_chan_t *c; 1157 struct serial_statistics *st; 1158 struct e1_statistics *opte1; 1159 int error, s; 1160 char mask[16]; 1161 1162 if (!d || !d->chan) 1163 return 0; 1164 1165 c = d->chan; 1166 1167 switch (cmd) { 1168 case SERIAL_GETREGISTERED: 1169 bzero (mask, sizeof(mask)); 1170 for (s=0; s<NCTAU*NCHAN; ++s) 1171 if (channel [s]) 1172 mask [s/8] |= 1 << (s & 7); 1173 bcopy (mask, data, sizeof (mask)); 1174 return 0; 1175 1176#ifndef NETGRAPH 1177 case SERIAL_GETPROTO: 1178 strcpy ((char*)data, (d->pp.pp_flags & PP_FR) ? "fr" : 1179 (d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp"); 1180 return 0; 1181 1182 case SERIAL_SETPROTO: 1183 /* Only for superuser! */ 1184 error = suser (td); 1185 if (error) 1186 return error; 1187 if (d->pp.pp_if.if_flags & IFF_RUNNING) 1188 return EBUSY; 1189 if (! strcmp ("cisco", (char*)data)) { 1190 d->pp.pp_flags &= ~(PP_FR); 1191 d->pp.pp_flags |= PP_KEEPALIVE; 1192 d->pp.pp_if.if_flags |= PP_CISCO; 1193 } else if (! strcmp ("fr", (char*)data)) { 1194 d->pp.pp_if.if_flags &= ~(PP_CISCO); 1195 d->pp.pp_flags |= PP_FR | PP_KEEPALIVE; 1196 } else if (! strcmp ("ppp", (char*)data)) { 1197 d->pp.pp_flags &= ~(PP_FR | PP_KEEPALIVE); 1198 d->pp.pp_if.if_flags &= ~(PP_CISCO); 1199 } else 1200 return EINVAL; 1201 return 0; 1202 1203 case SERIAL_GETKEEPALIVE: 1204 if ((d->pp.pp_flags & PP_FR) || 1205 (d->pp.pp_if.if_flags & PP_CISCO)) 1206 return EINVAL; 1207 *(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0; 1208 return 0; 1209 1210 case SERIAL_SETKEEPALIVE: 1211 /* Only for superuser! */ 1212 error = suser (td); 1213 if (error) 1214 return error; 1215 if ((d->pp.pp_flags & PP_FR) || 1216 (d->pp.pp_if.if_flags & PP_CISCO)) 1217 return EINVAL; 1218 if (*(int*)data) 1219 d->pp.pp_flags |= PP_KEEPALIVE; 1220 else 1221 d->pp.pp_flags &= ~PP_KEEPALIVE; 1222 return 0; 1223#endif /*NETGRAPH*/ 1224 1225 case SERIAL_GETMODE: 1226 *(int*)data = SERIAL_HDLC; 1227 return 0; 1228 1229 case SERIAL_GETCFG: 1230 if (c->mode == M_HDLC) 1231 return EINVAL; 1232 switch (ct_get_config (c->board)) { 1233 default: *(char*)data = 'a'; break; 1234 case CFG_B: *(char*)data = 'b'; break; 1235 case CFG_C: *(char*)data = 'c'; break; 1236 } 1237 return 0; 1238 1239 case SERIAL_SETCFG: 1240 /* Only for superuser! */ 1241 error = suser (td); 1242 if (error) 1243 return error; 1244 if (c->mode == M_HDLC) 1245 return EINVAL; 1246 s = splimp (); 1247 switch (*(char*)data) { 1248 case 'a': ct_set_config (c->board, CFG_A); break; 1249 case 'b': ct_set_config (c->board, CFG_B); break; 1250 case 'c': ct_set_config (c->board, CFG_C); break; 1251 } 1252 splx (s); 1253 return 0; 1254 1255 case SERIAL_GETSTAT: 1256 st = (struct serial_statistics*) data; 1257 st->rintr = c->rintr; 1258 st->tintr = c->tintr; 1259 st->mintr = c->mintr; 1260 st->ibytes = c->ibytes; 1261 st->ipkts = c->ipkts; 1262 st->ierrs = c->ierrs; 1263 st->obytes = c->obytes; 1264 st->opkts = c->opkts; 1265 st->oerrs = c->oerrs; 1266 return 0; 1267 1268 case SERIAL_GETESTAT: 1269 opte1 = (struct e1_statistics*)data; 1270 opte1->status = c->status; 1271 opte1->cursec = c->cursec; 1272 opte1->totsec = c->totsec + c->cursec; 1273 1274 opte1->currnt.bpv = c->currnt.bpv; 1275 opte1->currnt.fse = c->currnt.fse; 1276 opte1->currnt.crce = c->currnt.crce; 1277 opte1->currnt.rcrce = c->currnt.rcrce; 1278 opte1->currnt.uas = c->currnt.uas; 1279 opte1->currnt.les = c->currnt.les; 1280 opte1->currnt.es = c->currnt.es; 1281 opte1->currnt.bes = c->currnt.bes; 1282 opte1->currnt.ses = c->currnt.ses; 1283 opte1->currnt.oofs = c->currnt.oofs; 1284 opte1->currnt.css = c->currnt.css; 1285 opte1->currnt.dm = c->currnt.dm; 1286 1287 opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1288 opte1->total.fse = c->total.fse + c->currnt.fse; 1289 opte1->total.crce = c->total.crce + c->currnt.crce; 1290 opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1291 opte1->total.uas = c->total.uas + c->currnt.uas; 1292 opte1->total.les = c->total.les + c->currnt.les; 1293 opte1->total.es = c->total.es + c->currnt.es; 1294 opte1->total.bes = c->total.bes + c->currnt.bes; 1295 opte1->total.ses = c->total.ses + c->currnt.ses; 1296 opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1297 opte1->total.css = c->total.css + c->currnt.css; 1298 opte1->total.dm = c->total.dm + c->currnt.dm; 1299 for (s=0; s<48; ++s) { 1300 opte1->interval[s].bpv = c->interval[s].bpv; 1301 opte1->interval[s].fse = c->interval[s].fse; 1302 opte1->interval[s].crce = c->interval[s].crce; 1303 opte1->interval[s].rcrce = c->interval[s].rcrce; 1304 opte1->interval[s].uas = c->interval[s].uas; 1305 opte1->interval[s].les = c->interval[s].les; 1306 opte1->interval[s].es = c->interval[s].es; 1307 opte1->interval[s].bes = c->interval[s].bes; 1308 opte1->interval[s].ses = c->interval[s].ses; 1309 opte1->interval[s].oofs = c->interval[s].oofs; 1310 opte1->interval[s].css = c->interval[s].css; 1311 opte1->interval[s].dm = c->interval[s].dm; 1312 } 1313 return 0; 1314 1315 case SERIAL_CLRSTAT: 1316 /* Only for superuser! */ 1317 error = suser (td); 1318 if (error) 1319 return error; 1320 c->rintr = 0; 1321 c->tintr = 0; 1322 c->mintr = 0; 1323 c->ibytes = 0; 1324 c->ipkts = 0; 1325 c->ierrs = 0; 1326 c->obytes = 0; 1327 c->opkts = 0; 1328 c->oerrs = 0; 1329 bzero (&c->currnt, sizeof (c->currnt)); 1330 bzero (&c->total, sizeof (c->total)); 1331 bzero (c->interval, sizeof (c->interval)); 1332 return 0; 1333 1334 case SERIAL_GETBAUD: 1335 *(long*)data = ct_get_baud(c); 1336 return 0; 1337 1338 case SERIAL_SETBAUD: 1339 /* Only for superuser! */ 1340 error = suser (td); 1341 if (error) 1342 return error; 1343 s = splimp (); 1344 ct_set_baud (c, *(long*)data); 1345 splx (s); 1346 return 0; 1347 1348 case SERIAL_GETLOOP: 1349 *(int*)data = ct_get_loop (c); 1350 return 0; 1351 1352 case SERIAL_SETLOOP: 1353 /* Only for superuser! */ 1354 error = suser (td); 1355 if (error) 1356 return error; 1357 s = splimp (); 1358 ct_set_loop (c, *(int*)data); 1359 splx (s); 1360 return 0; 1361 1362 case SERIAL_GETDPLL: 1363 if (c->mode == M_E1 || c->mode == M_G703) 1364 return EINVAL; 1365 *(int*)data = ct_get_dpll (c); 1366 return 0; 1367 1368 case SERIAL_SETDPLL: 1369 /* Only for superuser! */ 1370 error = suser (td); 1371 if (error) 1372 return error; 1373 if (c->mode == M_E1 || c->mode == M_G703) 1374 return EINVAL; 1375 s = splimp (); 1376 ct_set_dpll (c, *(int*)data); 1377 splx (s); 1378 return 0; 1379 1380 case SERIAL_GETNRZI: 1381 if (c->mode == M_E1 || c->mode == M_G703) 1382 return EINVAL; 1383 *(int*)data = ct_get_nrzi (c); 1384 return 0; 1385 1386 case SERIAL_SETNRZI: 1387 /* Only for superuser! */ 1388 error = suser (td); 1389 if (error) 1390 return error; 1391 if (c->mode == M_E1 || c->mode == M_G703) 1392 return EINVAL; 1393 s = splimp (); 1394 ct_set_nrzi (c, *(int*)data); 1395 splx (s); 1396 return 0; 1397 1398 case SERIAL_GETDEBUG: 1399 *(int*)data = c->debug; 1400 return 0; 1401 1402 case SERIAL_SETDEBUG: 1403 /* Only for superuser! */ 1404 error = suser (td); 1405 if (error) 1406 return error; 1407 c->debug = *(int*)data; 1408#ifndef NETGRAPH 1409 if (d->chan->debug) 1410 d->pp.pp_if.if_flags |= IFF_DEBUG; 1411 else 1412 d->pp.pp_if.if_flags &= (~IFF_DEBUG); 1413#endif 1414 return 0; 1415 1416 case SERIAL_GETHIGAIN: 1417 if (c->mode != M_E1) 1418 return EINVAL; 1419 *(int*)data = ct_get_higain (c); 1420 return 0; 1421 1422 case SERIAL_SETHIGAIN: 1423 /* Only for superuser! */ 1424 error = suser (td); 1425 if (error) 1426 return error; 1427 s = splimp (); 1428 ct_set_higain (c, *(int*)data); 1429 splx (s); 1430 return 0; 1431 1432 case SERIAL_GETPHONY: 1433 CT_DEBUG2 (d, ("ioctl: getphony\n")); 1434 if (c->mode != M_E1) 1435 return EINVAL; 1436 *(int*)data = c->gopt.phony; 1437 return 0; 1438 1439 case SERIAL_SETPHONY: 1440 CT_DEBUG2 (d, ("ioctl: setphony\n")); 1441 if (c->mode != M_E1) 1442 return EINVAL; 1443 /* Only for superuser! */ 1444 error = suser (td); 1445 if (error) 1446 return error; 1447 s = splimp (); 1448 ct_set_phony (c, *(int*)data); 1449 splx (s); 1450 return 0; 1451 1452 case SERIAL_GETCLK: 1453 if (c->mode != M_E1 && c->mode != M_G703) 1454 return EINVAL; 1455 switch (ct_get_clk(c)) { 1456 default: *(int*)data = E1CLK_INTERNAL; break; 1457 case GCLK_RCV: *(int*)data = E1CLK_RECEIVE; break; 1458 case GCLK_RCLKO: *(int*)data = c->num ? 1459 E1CLK_RECEIVE_CHAN0 : E1CLK_RECEIVE_CHAN1; break; 1460 } 1461 return 0; 1462 1463 case SERIAL_SETCLK: 1464 /* Only for superuser! */ 1465 error = suser (td); 1466 if (error) 1467 return error; 1468 s = splimp (); 1469 switch (*(int*)data) { 1470 default: ct_set_clk (c, GCLK_INT); break; 1471 case E1CLK_RECEIVE: ct_set_clk (c, GCLK_RCV); break; 1472 case E1CLK_RECEIVE_CHAN0: 1473 case E1CLK_RECEIVE_CHAN1: 1474 ct_set_clk (c, GCLK_RCLKO); break; 1475 } 1476 splx (s); 1477 return 0; 1478 1479 case SERIAL_GETTIMESLOTS: 1480 if (c->mode != M_E1) 1481 return EINVAL; 1482 *(long*)data = ct_get_ts (c); 1483 return 0; 1484 1485 case SERIAL_SETTIMESLOTS: 1486 /* Only for superuser! */ 1487 error = suser (td); 1488 if (error) 1489 return error; 1490 s = splimp (); 1491 ct_set_ts (c, *(long*)data); 1492 splx (s); 1493 return 0; 1494 1495 case SERIAL_GETSUBCHAN: 1496 if (c->mode != M_E1) 1497 return EINVAL; 1498 *(long*)data = ct_get_subchan (c->board); 1499 return 0; 1500 1501 case SERIAL_SETSUBCHAN: 1502 /* Only for superuser! */ 1503 error = suser (td); 1504 if (error) 1505 return error; 1506 s = splimp (); 1507 ct_set_subchan (c->board, *(long*)data); 1508 splx (s); 1509 return 0; 1510 1511 case SERIAL_GETINVCLK: 1512 case SERIAL_GETINVTCLK: 1513 if (c->mode == M_E1 || c->mode == M_G703) 1514 return EINVAL; 1515 *(int*)data = ct_get_invtxc (c); 1516 return 0; 1517 1518 case SERIAL_GETINVRCLK: 1519 if (c->mode == M_E1 || c->mode == M_G703) 1520 return EINVAL; 1521 *(int*)data = ct_get_invrxc (c); 1522 return 0; 1523 1524 case SERIAL_SETINVCLK: 1525 case SERIAL_SETINVTCLK: 1526 /* Only for superuser! */ 1527 error = suser (td); 1528 if (error) 1529 return error; 1530 if (c->mode == M_E1 || c->mode == M_G703) 1531 return EINVAL; 1532 s = splimp (); 1533 ct_set_invtxc (c, *(int*)data); 1534 splx (s); 1535 return 0; 1536 1537 case SERIAL_SETINVRCLK: 1538 /* Only for superuser! */ 1539 error = suser (td); 1540 if (error) 1541 return error; 1542 if (c->mode == M_E1 || c->mode == M_G703) 1543 return EINVAL; 1544 s = splimp (); 1545 ct_set_invrxc (c, *(int*)data); 1546 splx (s); 1547 return 0; 1548 1549 case SERIAL_GETLEVEL: 1550 if (c->mode != M_G703) 1551 return EINVAL; 1552 s = splimp (); 1553 *(int*)data = ct_get_lq (c); 1554 splx (s); 1555 return 0; 1556 1557 case TIOCSDTR: /* Set DTR */ 1558 s = splimp (); 1559 ct_set_dtr (c, 1); 1560 splx (s); 1561 return 0; 1562 1563 case TIOCCDTR: /* Clear DTR */ 1564 s = splimp (); 1565 ct_set_dtr (c, 0); 1566 splx (s); 1567 return 0; 1568 1569 case TIOCMSET: /* Set DTR/RTS */ 1570 s = splimp (); 1571 ct_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1572 ct_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1573 splx (s); 1574 return 0; 1575 1576 case TIOCMBIS: /* Add DTR/RTS */ 1577 s = splimp (); 1578 if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 1); 1579 if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 1); 1580 splx (s); 1581 return 0; 1582 1583 case TIOCMBIC: /* Clear DTR/RTS */ 1584 s = splimp (); 1585 if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 0); 1586 if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 0); 1587 splx (s); 1588 return 0; 1589 1590 case TIOCMGET: /* Get modem status */ 1591 *(int*)data = ct_modem_status (c); 1592 return 0; 1593 } 1594 return ENOTTY; 1595} 1596 1597static struct cdevsw ct_cdevsw = { 1598 .d_version = D_VERSION, 1599 .d_open = ct_open, 1600 .d_close = ct_close, 1601 .d_ioctl = ct_ioctl, 1602 .d_name = "ct", 1603 .d_maj = CDEV_MAJOR, 1604 .d_flags = D_NEEDGIANT, 1605}; 1606 1607#ifdef NETGRAPH 1608static int ng_ct_constructor (node_p node) 1609{ 1610 drv_t *d = NG_NODE_PRIVATE (node); 1611 CT_DEBUG (d, ("Constructor\n")); 1612 return EINVAL; 1613} 1614 1615static int ng_ct_newhook (node_p node, hook_p hook, const char *name) 1616{ 1617 int s; 1618 drv_t *d = NG_NODE_PRIVATE (node); 1619 1620 if (!d) 1621 return EINVAL; 1622 1623 /* Attach debug hook */ 1624 if (strcmp (name, NG_CT_HOOK_DEBUG) == 0) { 1625 NG_HOOK_SET_PRIVATE (hook, NULL); 1626 d->debug_hook = hook; 1627 return 0; 1628 } 1629 1630 /* Check for raw hook */ 1631 if (strcmp (name, NG_CT_HOOK_RAW) != 0) 1632 return EINVAL; 1633 1634 NG_HOOK_SET_PRIVATE (hook, d); 1635 d->hook = hook; 1636 s = splimp (); 1637 ct_up (d); 1638 splx (s); 1639 return 0; 1640} 1641 1642static char *format_timeslots (u_long s) 1643{ 1644 static char buf [100]; 1645 char *p = buf; 1646 int i; 1647 1648 for (i=1; i<32; ++i) 1649 if ((s >> i) & 1) { 1650 int prev = (i > 1) & (s >> (i-1)); 1651 int next = (i < 31) & (s >> (i+1)); 1652 1653 if (prev) { 1654 if (next) 1655 continue; 1656 *p++ = '-'; 1657 } else if (p > buf) 1658 *p++ = ','; 1659 1660 if (i >= 10) 1661 *p++ = '0' + i / 10; 1662 *p++ = '0' + i % 10; 1663 } 1664 *p = 0; 1665 return buf; 1666} 1667 1668static int print_modems (char *s, ct_chan_t *c, int need_header) 1669{ 1670 int status = ct_modem_status (c); 1671 int length = 0; 1672 1673 if (need_header) 1674 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1675 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1676 status & TIOCM_LE ? "On" : "-", 1677 status & TIOCM_DTR ? "On" : "-", 1678 status & TIOCM_DSR ? "On" : "-", 1679 status & TIOCM_RTS ? "On" : "-", 1680 status & TIOCM_CTS ? "On" : "-", 1681 status & TIOCM_CD ? "On" : "-"); 1682 return length; 1683} 1684 1685static int print_stats (char *s, ct_chan_t *c, int need_header) 1686{ 1687 struct serial_statistics st; 1688 int length = 0; 1689 1690 st.rintr = c->rintr; 1691 st.tintr = c->tintr; 1692 st.mintr = c->mintr; 1693 st.ibytes = c->ibytes; 1694 st.ipkts = c->ipkts; 1695 st.ierrs = c->ierrs; 1696 st.obytes = c->obytes; 1697 st.opkts = c->opkts; 1698 st.oerrs = c->oerrs; 1699 if (need_header) 1700 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1701 length += sprintf (s + length, "%7ld %7ld %7ld %8ld %7ld %7ld %8ld %7ld %7ld\n", 1702 st.rintr, st.tintr, st.mintr, st.ibytes, st.ipkts, 1703 st.ierrs, st.obytes, st.opkts, st.oerrs); 1704 return length; 1705} 1706 1707static char *format_e1_status (u_char status) 1708{ 1709 static char buf [80]; 1710 1711 if (status & E1_NOALARM) 1712 return "Ok"; 1713 buf[0] = 0; 1714 if (status & E1_LOS) strcat (buf, ",LOS"); 1715 if (status & E1_AIS) strcat (buf, ",AIS"); 1716 if (status & E1_LOF) strcat (buf, ",LOF"); 1717 if (status & E1_LOMF) strcat (buf, ",LOMF"); 1718 if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1719 if (status & E1_AIS16) strcat (buf, ",AIS16"); 1720 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1721 if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1722 if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1723 if (buf[0] == ',') 1724 return buf+1; 1725 return "Unknown"; 1726} 1727 1728static int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1729{ 1730 int n, length = 0; 1731 1732 if (numerator < 1 || divider < 1) { 1733 length += sprintf (s+length, leftalign ? "/- " : " -"); 1734 return length; 1735 } 1736 n = (int) (0.5 + 1000.0 * numerator / divider); 1737 if (n < 1000) { 1738 length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1739 return length; 1740 } 1741 *(s + length) = leftalign ? '/' : ' '; 1742 length ++; 1743 1744 if (n >= 1000000) n = (n+500) / 1000 * 1000; 1745 else if (n >= 100000) n = (n+50) / 100 * 100; 1746 else if (n >= 10000) n = (n+5) / 10 * 10; 1747 1748 switch (n) { 1749 case 1000: length += printf (s+length, ".999"); return length; 1750 case 10000: n = 9990; break; 1751 case 100000: n = 99900; break; 1752 case 1000000: n = 999000; break; 1753 } 1754 if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1755 else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1756 else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1757 else length += sprintf (s+length, "%d", n/1000); 1758 1759 return length; 1760} 1761 1762static int print_e1_stats (char *s, ct_chan_t *c) 1763{ 1764 struct e1_counters total; 1765 u_long totsec; 1766 int length = 0; 1767 1768 totsec = c->totsec + c->cursec; 1769 total.bpv = c->total.bpv + c->currnt.bpv; 1770 total.fse = c->total.fse + c->currnt.fse; 1771 total.crce = c->total.crce + c->currnt.crce; 1772 total.rcrce = c->total.rcrce + c->currnt.rcrce; 1773 total.uas = c->total.uas + c->currnt.uas; 1774 total.les = c->total.les + c->currnt.les; 1775 total.es = c->total.es + c->currnt.es; 1776 total.bes = c->total.bes + c->currnt.bes; 1777 total.ses = c->total.ses + c->currnt.ses; 1778 total.oofs = c->total.oofs + c->currnt.oofs; 1779 total.css = c->total.css + c->currnt.css; 1780 total.dm = c->total.dm + c->currnt.dm; 1781 1782 length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1783 1784 /* Unavailable seconds, degraded minutes */ 1785 length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1786 length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1787 1788 /* Bipolar violations, frame sync errors */ 1789 length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1790 length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1791 1792 /* CRC errors, remote CRC errors (E-bit) */ 1793 length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 1794 length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 1795 1796 /* Errored seconds, line errored seconds */ 1797 length += print_frac (s + length, 0, c->currnt.es, c->cursec); 1798 length += print_frac (s + length, 1, c->currnt.les, c->cursec); 1799 1800 /* Severely errored seconds, burst errored seconds */ 1801 length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 1802 length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 1803 1804 /* Out of frame seconds, controlled slip seconds */ 1805 length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 1806 length += print_frac (s + length, 1, c->currnt.css, c->cursec); 1807 1808 length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 1809 1810 /* Print total statistics. */ 1811 length += print_frac (s + length, 0, total.uas, totsec); 1812 length += print_frac (s + length, 1, 60 * total.dm, totsec); 1813 1814 length += print_frac (s + length, 0, total.bpv, totsec); 1815 length += print_frac (s + length, 1, total.fse, totsec); 1816 1817 length += print_frac (s + length, 0, total.crce, totsec); 1818 length += print_frac (s + length, 1, total.rcrce, totsec); 1819 1820 length += print_frac (s + length, 0, total.es, totsec); 1821 length += print_frac (s + length, 1, total.les, totsec); 1822 1823 length += print_frac (s + length, 0, total.ses, totsec); 1824 length += print_frac (s + length, 1, total.bes, totsec); 1825 1826 length += print_frac (s + length, 0, total.oofs, totsec); 1827 length += print_frac (s + length, 1, total.css, totsec); 1828 1829 length += sprintf (s + length, " -- Total\n"); 1830 return length; 1831} 1832 1833static int print_chan (char *s, ct_chan_t *c) 1834{ 1835 drv_t *d = c->sys; 1836 int length = 0; 1837 1838 length += sprintf (s + length, "ct%d", c->board->num * NCHAN + c->num); 1839 if (d->chan->debug) 1840 length += sprintf (s + length, " debug=%d", d->chan->debug); 1841 1842 switch (ct_get_config (c->board)) { 1843 case CFG_A: length += sprintf (s + length, " cfg=A"); break; 1844 case CFG_B: length += sprintf (s + length, " cfg=B"); break; 1845 case CFG_C: length += sprintf (s + length, " cfg=C"); break; 1846 default: length += sprintf (s + length, " cfg=unknown"); break; 1847 } 1848 1849 if (ct_get_baud (c)) 1850 length += sprintf (s + length, " %ld", ct_get_baud (c)); 1851 else 1852 length += sprintf (s + length, " extclock"); 1853 1854 if (c->mode == M_E1 || c->mode == M_G703) 1855 switch (ct_get_clk(c)) { 1856 case GCLK_INT : length += sprintf (s + length, " syn=int"); break; 1857 case GCLK_RCV : length += sprintf (s + length, " syn=rcv"); break; 1858 case GCLK_RCLKO : length += sprintf (s + length, " syn=xrcv"); break; 1859 } 1860 if (c->mode == M_HDLC) { 1861 length += sprintf (s + length, " dpll=%s", ct_get_dpll (c) ? "on" : "off"); 1862 length += sprintf (s + length, " nrzi=%s", ct_get_nrzi (c) ? "on" : "off"); 1863 length += sprintf (s + length, " invtclk=%s", ct_get_invtxc (c) ? "on" : "off"); 1864 length += sprintf (s + length, " invrclk=%s", ct_get_invrxc (c) ? "on" : "off"); 1865 } 1866 if (c->mode == M_E1) 1867 length += sprintf (s + length, " higain=%s", ct_get_higain (c)? "on" : "off"); 1868 1869 length += sprintf (s + length, " loop=%s", ct_get_loop (c) ? "on" : "off"); 1870 1871 if (c->mode == M_E1) 1872 length += sprintf (s + length, " ts=%s", format_timeslots (ct_get_ts(c))); 1873 if (c->mode == M_E1 && ct_get_config (c->board) != CFG_A) 1874 length += sprintf (s + length, " pass=%s", format_timeslots (ct_get_subchan(c->board))); 1875 if (c->mode == M_G703) { 1876 int lq, x; 1877 1878 x = splimp (); 1879 lq = ct_get_lq (c); 1880 splx (x); 1881 length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 1882 } 1883 length += sprintf (s + length, "\n"); 1884 return length; 1885} 1886 1887static int ng_ct_rcvmsg (node_p node, item_p item, hook_p lasthook) 1888{ 1889 drv_t *d = NG_NODE_PRIVATE (node); 1890 struct ng_mesg *msg; 1891 struct ng_mesg *resp = NULL; 1892 int error = 0; 1893 1894 if (!d) 1895 return EINVAL; 1896 1897 CT_DEBUG (d, ("Rcvmsg\n")); 1898 NGI_GET_MSG (item, msg); 1899 switch (msg->header.typecookie) { 1900 default: 1901 error = EINVAL; 1902 break; 1903 1904 case NGM_CT_COOKIE: 1905 printf ("Don't forget to implement\n"); 1906 error = EINVAL; 1907 break; 1908 1909 case NGM_GENERIC_COOKIE: 1910 switch (msg->header.cmd) { 1911 default: 1912 error = EINVAL; 1913 break; 1914 1915 case NGM_TEXT_STATUS: { 1916 char *s; 1917 int l = 0; 1918 int dl = sizeof (struct ng_mesg) + 730; 1919 1920 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 1921 if (! resp) { 1922 error = ENOMEM; 1923 break; 1924 } 1925 s = (resp)->data; 1926 l += print_chan (s + l, d->chan); 1927 l += print_stats (s + l, d->chan, 1); 1928 l += print_modems (s + l, d->chan, 1); 1929 l += print_e1_stats (s + l, d->chan); 1930 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 1931 } 1932 break; 1933 } 1934 break; 1935 } 1936 NG_RESPOND_MSG (error, node, item, resp); 1937 NG_FREE_MSG (msg); 1938 return error; 1939} 1940 1941static int ng_ct_rcvdata (hook_p hook, item_p item) 1942{ 1943 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 1944 struct mbuf *m; 1945 struct ng_tag_prio *ptag; 1946 struct ifqueue *q; 1947 int s; 1948 1949 if (!d) 1950 return ENETDOWN; 1951 1952 NGI_GET_M (item, m); 1953 NG_FREE_ITEM (item); 1954 if (! NG_HOOK_PRIVATE (hook) || ! d) { 1955 NG_FREE_M (m); 1956 return ENETDOWN; 1957 } 1958 1959 /* Check for high priority data */ 1960 if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 1961 NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 1962 q = &d->hi_queue; 1963 else 1964 q = &d->queue; 1965 1966 s = splimp (); 1967 IF_LOCK (q); 1968 if (_IF_QFULL (q)) { 1969 _IF_DROP (q); 1970 IF_UNLOCK (q); 1971 splx (s); 1972 NG_FREE_M (m); 1973 return ENOBUFS; 1974 } 1975 _IF_ENQUEUE (q, m); 1976 IF_UNLOCK (q); 1977 ct_start (d); 1978 splx (s); 1979 return 0; 1980} 1981 1982static int ng_ct_rmnode (node_p node) 1983{ 1984 drv_t *d = NG_NODE_PRIVATE (node); 1985 1986 CT_DEBUG (d, ("Rmnode\n")); 1987 if (d && d->running) { 1988 int s = splimp (); 1989 ct_down (d); 1990 splx (s); 1991 } 1992#ifdef KLD_MODULE 1993 if (node->nd_flags & NGF_REALLY_DIE) { 1994 NG_NODE_SET_PRIVATE (node, NULL); 1995 NG_NODE_UNREF (node); 1996 } 1997 NG_NODE_REVIVE(node); /* Persistant node */ 1998#endif 1999 return 0; 2000} 2001 2002static void ng_ct_watchdog (void *arg) 2003{ 2004 drv_t *d = arg; 2005 2006 if (!d) 2007 return; 2008 2009 if (d->timeout == 1) 2010 ct_watchdog (d); 2011 if (d->timeout) 2012 d->timeout--; 2013 d->timeout_handle = timeout (ng_ct_watchdog, d, hz); 2014} 2015 2016static int ng_ct_connect (hook_p hook) 2017{ 2018 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2019 2020 if (!d) 2021 return 0; 2022 2023 d->timeout_handle = timeout (ng_ct_watchdog, d, hz); 2024 return 0; 2025} 2026 2027static int ng_ct_disconnect (hook_p hook) 2028{ 2029 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2030 2031 if (!d) 2032 return 0; 2033 2034 if (NG_HOOK_PRIVATE (hook)) 2035 ct_down (d); 2036 untimeout (ng_ct_watchdog, d, d->timeout_handle); 2037 return 0; 2038} 2039#endif 2040 2041static int ct_modevent (module_t mod, int type, void *unused) 2042{ 2043 static int load_count = 0; 2044 2045 switch (type) { 2046 case MOD_LOAD: 2047#ifdef NETGRAPH 2048 if (ng_newtype (&typestruct)) 2049 printf ("Failed to register ng_ct\n"); 2050#endif 2051 ++load_count; 2052 timeout_handle = timeout (ct_timeout, 0, hz*5); 2053 break; 2054 case MOD_UNLOAD: 2055 if (load_count == 1) { 2056 printf ("Removing device entry for Tau-ISA\n"); 2057#ifdef NETGRAPH 2058 ng_rmtype (&typestruct); 2059#endif 2060 } 2061 if (timeout_handle.callout) 2062 untimeout (ct_timeout, 0, timeout_handle); 2063 --load_count; 2064 break; 2065 case MOD_SHUTDOWN: 2066 break; 2067 } 2068 return 0; 2069} 2070 2071#ifdef NETGRAPH 2072static struct ng_type typestruct = { 2073 .version = NG_ABI_VERSION, 2074 .name = NG_CT_NODE_TYPE, 2075 .constructor = ng_ct_constructor, 2076 .rcvmsg = ng_ct_rcvmsg, 2077 .shutdown = ng_ct_rmnode, 2078 .newhook = ng_ct_newhook, 2079 .connect = ng_ct_connect, 2080 .rcvdata = ng_ct_rcvdata, 2081 .disconnect = ng_ct_disconnect, 2082}; 2083#endif /*NETGRAPH*/ 2084 2085#ifdef NETGRAPH 2086MODULE_DEPEND (ng_ct, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2087#else 2088MODULE_DEPEND (ct, sppp, 1, 1, 1); 2089#endif 2090#ifdef KLD_MODULE 2091DRIVER_MODULE (ctmod, isa, ct_isa_driver, ct_devclass, ct_modevent, NULL); 2092#else 2093DRIVER_MODULE (ct, isa, ct_isa_driver, ct_devclass, ct_modevent, NULL); 2094#endif 2095