if_ct.c revision 129879
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.22 2004/02/26 19:06:51 rik Exp $ 22 */ 23#include <sys/cdefs.h> 24__FBSDID("$FreeBSD: head/sys/dev/ctau/if_ct.c 129879 2004-05-30 20:08:47Z phk $"); 25 26#include <sys/param.h> 27 28#if __FreeBSD_version >= 500000 29# define NCTAU 1 30#else 31# include "ctau.h" 32#endif 33 34#if NCTAU > 0 35#include <sys/proc.h> 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/module.h> 39#include <sys/mbuf.h> 40#include <sys/sockio.h> 41#include <sys/malloc.h> 42#include <sys/socket.h> 43#include <sys/conf.h> 44#include <sys/errno.h> 45#include <sys/tty.h> 46#if __FreeBSD_version >= 400000 47# include <sys/bus.h> 48# include <machine/bus.h> 49# include <sys/rman.h> 50# include <isa/isavar.h> 51#endif 52#include <sys/interrupt.h> 53#include <vm/vm.h> 54#include <vm/pmap.h> 55#include <net/if.h> 56#include <machine/cpufunc.h> 57#include <machine/cserial.h> 58#include <machine/clock.h> 59#if __FreeBSD_version < 500000 60#include <i386/isa/isa_device.h> 61#endif 62#if __FreeBSD_version >= 400000 63#include <machine/resource.h> 64# if __FreeBSD_version <= 501000 65# include <i386/isa/intr_machdep.h> 66# endif 67#endif 68#if __FreeBSD_version >= 400000 69#include <dev/cx/machdep.h> 70#include <dev/ctau/ctddk.h> 71#include <dev/cx/cronyxfw.h> 72#else 73#include <i386/isa/cronyx/machdep.h> 74#include <i386/isa/cronyx/ctddk.h> 75#include <i386/isa/cronyx/cronyxfw.h> 76#endif 77#include "opt_ng_cronyx.h" 78#ifdef NETGRAPH_CRONYX 79# include "opt_netgraph.h" 80# include <netgraph/ng_message.h> 81# include <netgraph/netgraph.h> 82#if __FreeBSD_version >= 400000 83# include <dev/ctau/ng_ct.h> 84#else 85# include <netgraph/ng_ct.h> 86#endif 87#else 88# include <net/if_types.h> 89# if __FreeBSD_version < 500000 90# include "sppp.h" 91# if NSPPP <= 0 92# error The device ctau requires sppp or netgraph. 93# endif 94# endif 95# include <net/if_sppp.h> 96# define PP_CISCO IFF_LINK2 97#if __FreeBSD_version < 400000 98# include <bpfilter.h> 99# if NBPFILTER > 0 100# include <net/bpf.h> 101# endif 102#else 103# if __FreeBSD_version < 500000 104# include <bpf.h> 105# endif 106# include <net/bpf.h> 107# define NBPFILTER NBPF 108#endif 109#endif 110 111/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 112#ifndef PP_FR 113#define PP_FR 0 114#endif 115 116#define CT_DEBUG(d,s) ({if (d->chan->debug) {\ 117 printf ("%s: ", d->name); printf s;}}) 118#define CT_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 119 printf ("%s: ", d->name); printf s;}}) 120#define CDEV_MAJOR 99 121 122#if __FreeBSD_version >= 400000 123static void ct_identify __P((driver_t *, device_t)); 124static int ct_probe __P((device_t)); 125static int ct_attach __P((device_t)); 126static int ct_detach __P((device_t)); 127 128static device_method_t ct_isa_methods [] = { 129 DEVMETHOD(device_identify, ct_identify), 130 DEVMETHOD(device_probe, ct_probe), 131 DEVMETHOD(device_attach, ct_attach), 132 DEVMETHOD(device_detach, ct_detach), 133 {0, 0} 134}; 135 136typedef struct _bdrv_t { 137 ct_board_t *board; 138 struct resource *base_res; 139 struct resource *drq_res; 140 struct resource *irq_res; 141 int base_rid; 142 int drq_rid; 143 int irq_rid; 144 void *intrhand; 145} bdrv_t; 146 147static driver_t ct_isa_driver = { 148 "ct", 149 ct_isa_methods, 150 sizeof (bdrv_t), 151}; 152 153static devclass_t ct_devclass; 154#endif 155 156typedef struct _drv_t { 157 char name [8]; 158 ct_chan_t *chan; 159 ct_board_t *board; 160 ct_buf_t buf; 161 int running; 162#ifdef NETGRAPH 163 char nodename [NG_NODELEN+1]; 164 hook_p hook; 165 hook_p debug_hook; 166 node_p node; 167 struct ifqueue queue; 168 struct ifqueue hi_queue; 169 short timeout; 170 struct callout_handle timeout_handle; 171#else 172 struct sppp pp; 173#endif 174#if __FreeBSD_version >= 400000 175 dev_t devt; 176#endif 177} drv_t; 178 179static void ct_receive (ct_chan_t *c, char *data, int len); 180static void ct_transmit (ct_chan_t *c, void *attachment, int len); 181static void ct_error (ct_chan_t *c, int data); 182static void ct_up (drv_t *d); 183static void ct_start (drv_t *d); 184static void ct_down (drv_t *d); 185static void ct_watchdog (drv_t *d); 186#ifdef NETGRAPH 187extern struct ng_type typestruct; 188#else 189static void ct_ifstart (struct ifnet *ifp); 190static void ct_tlf (struct sppp *sp); 191static void ct_tls (struct sppp *sp); 192static void ct_ifwatchdog (struct ifnet *ifp); 193static int ct_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 194static void ct_initialize (void *softc); 195#endif 196 197static ct_board_t *adapter [NCTAU]; 198static drv_t *channel [NCTAU*NCHAN]; 199static struct callout_handle led_timo [NCTAU]; 200static struct callout_handle timeout_handle; 201 202/* 203 * Print the mbuf chain, for debug purposes only. 204 */ 205static void printmbuf (struct mbuf *m) 206{ 207 printf ("mbuf:"); 208 for (; m; m=m->m_next) { 209 if (m->m_flags & M_PKTHDR) 210 printf (" HDR %d:", m->m_pkthdr.len); 211 if (m->m_flags & M_EXT) 212 printf (" EXT:"); 213 printf (" %d", m->m_len); 214 } 215 printf ("\n"); 216} 217 218/* 219 * Make an mbuf from data. 220 */ 221static struct mbuf *makembuf (void *buf, u_int len) 222{ 223 struct mbuf *m; 224 225 MGETHDR (m, M_DONTWAIT, MT_DATA); 226 if (! m) 227 return 0; 228 MCLGET (m, M_DONTWAIT); 229 if (! (m->m_flags & M_EXT)) { 230 m_freem (m); 231 return 0; 232 } 233 m->m_pkthdr.len = m->m_len = len; 234 bcopy (buf, mtod (m, caddr_t), len); 235 return m; 236} 237 238static void ct_timeout (void *arg) 239{ 240 drv_t *d; 241 int s, i; 242 243 for (i=0; i<NCTAU*NCHAN; ++i) { 244 d = channel[i]; 245 if (! d) 246 continue; 247 if (d->chan->mode != M_G703) 248 continue; 249 s = splimp (); 250 ct_g703_timer (d->chan); 251 splx (s); 252 } 253 timeout_handle = timeout (ct_timeout, 0, hz); 254} 255 256static void ct_led_off (void *arg) 257{ 258 ct_board_t *b = arg; 259 int s = splimp (); 260 261 ct_led (b, 0); 262 led_timo[b->num].callout = 0; 263 splx (s); 264} 265 266/* 267 * Activate interupt handler from DDK. 268 */ 269#if __FreeBSD_version >= 400000 270static void ct_intr (void *arg) 271{ 272 bdrv_t *bd = arg; 273 ct_board_t *b = bd->board; 274#else 275static void ct_intr (int bnum) 276{ 277 ct_board_t *b = adapter [bnum]; 278#endif 279 int s = splimp (); 280 281 /* Turn LED on. */ 282 ct_led (b, 1); 283 284 ct_int_handler (b); 285 286 /* Turn LED off 50 msec later. */ 287 if (! led_timo[b->num].callout) 288 led_timo[b->num] = timeout (ct_led_off, b, hz/20); 289 splx (s); 290} 291 292static int probe_irq (ct_board_t *b, int irq) 293{ 294 int mask, busy, cnt; 295 296 /* Clear pending irq, if any. */ 297 ct_probe_irq (b, -irq); 298 DELAY (100); 299 for (cnt=0; cnt<5; ++cnt) { 300 /* Get the mask of pending irqs, assuming they are busy. 301 * Activate the adapter on given irq. */ 302 busy = ct_probe_irq (b, irq); 303 DELAY (1000); 304 305 /* Get the mask of active irqs. 306 * Deactivate our irq. */ 307 mask = ct_probe_irq (b, -irq); 308 DELAY (100); 309 if ((mask & ~busy) == 1 << irq) { 310 ct_probe_irq (b, 0); 311 /* printf ("ct%d: irq %d ok, mask=0x%04x, busy=0x%04x\n", 312 b->num, irq, mask, busy); */ 313 return 1; 314 } 315 } 316 /* printf ("ct%d: irq %d not functional, mask=0x%04x, busy=0x%04x\n", 317 b->num, irq, mask, busy); */ 318 ct_probe_irq (b, 0); 319 return 0; 320} 321 322static short porttab [] = { 323 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 324 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 325 }; 326static char dmatab [] = { 7, 6, 5, 0 }; 327static char irqtab [] = { 5, 10, 11, 7, 3, 15, 12, 0 }; 328 329#if __FreeBSD_version >= 400000 330static int ct_is_free_res (device_t dev, int rid, int type, u_long start, 331 u_long end, u_long count) 332{ 333 struct resource *res; 334 335 if (!(res = bus_alloc_resource (dev, type, &rid, start, end, count, 336 RF_ALLOCATED))) 337 return 0; 338 339 bus_release_resource (dev, type, rid, res); 340 341 return 1; 342} 343 344static void ct_identify (driver_t *driver, device_t dev) 345{ 346 u_long iobase, rescount; 347 int devcount; 348 device_t *devices; 349 device_t child; 350 devclass_t my_devclass; 351 int i, k; 352 353 if ((my_devclass = devclass_find ("ct")) == NULL) 354 return; 355 356 devclass_get_devices (my_devclass, &devices, &devcount); 357 358 if (devcount == 0) { 359 /* We should find all devices by our self. We could alter other 360 * devices, but we don't have a choise 361 */ 362 for (i = 0; (iobase = porttab [i]) != 0; i++) { 363 if (!ct_is_free_res (dev, 1, SYS_RES_IOPORT, 364 iobase, iobase + NPORT, NPORT)) 365 continue; 366 if (ct_probe_board (iobase, -1, -1) == 0) 367 continue; 368 369 devcount++; 370 child = BUS_ADD_CHILD (dev, ISA_ORDER_SPECULATIVE, "ct", 371 -1); 372 373 if (child == NULL) 374 return; 375 376 device_set_desc_copy (child, "Cronyx Tau-ISA"); 377 device_set_driver (child, driver); 378 bus_set_resource (child, SYS_RES_IOPORT, 0, 379 iobase, NPORT); 380 381 if (devcount >= NCTAU) 382 break; 383 } 384 } else { 385 static short porttab [] = { 386 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 387 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 388 }; 389 /* Lets check user choise. 390 */ 391 for (k = 0; k < devcount; k++) { 392 if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 393 &iobase, &rescount) != 0) 394 continue; 395 396 for (i = 0; porttab [i] != 0; i++) { 397 if (porttab [i] != iobase) 398 continue; 399 400 if (!ct_is_free_res (devices[k], 1, SYS_RES_IOPORT, 401 iobase, iobase + NPORT, NPORT)) 402 continue; 403 404 if (ct_probe_board (iobase, -1, -1) == 0) 405 continue; 406 porttab [i] = -1; 407 device_set_desc_copy (devices[k], "Cronyx Tau-ISA"); 408 break; 409 } 410 if (porttab [i] == 0) { 411 device_delete_child ( 412 device_get_parent (devices[k]), 413 devices [k]); 414 devices[k] = 0; 415 continue; 416 } 417 } 418 for (k = 0; k < devcount; k++) { 419 if (devices[k] == 0) 420 continue; 421 if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 422 &iobase, &rescount) == 0) 423 continue; 424 for (i = 0; (iobase = porttab [i]) != 0; i++) { 425 if (porttab [i] == -1) 426 continue; 427 if (!ct_is_free_res (devices[k], 1, SYS_RES_IOPORT, 428 iobase, iobase + NPORT, NPORT)) 429 continue; 430 if (ct_probe_board (iobase, -1, -1) == 0) 431 continue; 432 433 bus_set_resource (devices[k], SYS_RES_IOPORT, 0, 434 iobase, NPORT); 435 porttab [i] = -1; 436 device_set_desc_copy (devices[k], "Cronyx Tau-ISA"); 437 break; 438 } 439 if (porttab [i] == 0) { 440 device_delete_child ( 441 device_get_parent (devices[k]), 442 devices [k]); 443 } 444 } 445 free (devices, M_TEMP); 446 } 447 448 return; 449} 450 451static int ct_probe (device_t dev) 452{ 453 int unit = device_get_unit (dev); 454 u_long iobase, rescount; 455 456 if (!device_get_desc (dev) || 457 strcmp (device_get_desc (dev), "Cronyx Tau-ISA")) 458 return ENXIO; 459 460/* KASSERT ((bd != NULL), ("ct%d: NULL device softc\n", unit));*/ 461 if (bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount) != 0) { 462 printf ("ct%d: Couldn't get IOPORT\n", unit); 463 return ENXIO; 464 } 465 466 if (!ct_is_free_res (dev, 1, SYS_RES_IOPORT, 467 iobase, iobase + NPORT, NPORT)) { 468 printf ("ct%d: Resource IOPORT isn't free\n", unit); 469 return ENXIO; 470 } 471 472 if (!ct_probe_board (iobase, -1, -1)) { 473 printf ("ct%d: probing for Tau-ISA at %lx faild\n", unit, iobase); 474 return ENXIO; 475 } 476 477 return 0; 478} 479#else /* __FreeBSD_version < 400000 */ 480static int ct_probe (struct isa_device *id) 481{ 482 int unit = id->id_unit; 483 int iobase; 484 ct_board_t *b; 485 int i; 486 487 iobase = id->id_iobase; 488 if (iobase < 0) { 489 /* Autodetect the adapter. */ 490 491 for (i=0; ; i++) { 492 if (! porttab[i]) { 493 iobase = -1; 494 return 0; 495 } 496 iobase = porttab[i]; 497 if (unit > 0 && adapter[0] && adapter[0]->port == iobase) 498 continue; 499 if (unit > 1 && adapter[1] && adapter[1]->port == iobase) 500 continue; 501 if (! haveseen_isadev (id, CC_IOADDR | CC_QUIET) && 502 ct_probe_board (iobase, -1, -1)) 503 break; 504 } 505 } else if (! ct_probe_board (iobase, -1, -1)) 506 return 0; 507 508 if (id->id_drq < 0) { 509 /* Find available 16-bit DRQ. */ 510 511 for (i=0; ; ++i) { 512 if (! dmatab[i]) { 513 printf ("ct%d: no available drq found\n", 514 unit); 515 id->id_drq = -1; 516 return 0; 517 } 518 id->id_drq = dmatab[i]; 519 if (! haveseen_isadev (id, CC_DRQ | CC_QUIET) 520 && !isa_dma_acquire (id->id_drq)) 521 break; 522 } 523 } 524 525 b = malloc (sizeof (ct_board_t), M_DEVBUF, M_WAITOK); 526 if (!b) { 527 printf ("ct:%d: Couldn't allocate memory\n", unit); 528 return (ENXIO); 529 } 530 adapter[unit] = b; 531 bzero (b, sizeof(ct_board_t)); 532 533 if (! ct_open_board (b, unit, iobase, 534 id->id_irq ? ffs (id->id_irq) - 1 : -1, id->id_drq)) { 535 printf ("ct%d: error loading firmware\n", unit); 536 adapter [unit] = 0; 537 free (b, M_DEVBUF); 538 isa_dma_release (id->id_drq); 539 return 0; 540 } 541 542 if (id->id_irq) { 543 if (! probe_irq (b, ffs (id->id_irq) - 1)) 544 printf ("ct%d: irq %d not functional\n", 545 unit, ffs (id->id_irq) - 1); 546 } else { 547 /* Find available IRQ. */ 548 549 for (i=0; ; ++i) { 550 if (! irqtab[i]) { 551 printf ("ct%d: no available irq found\n", 552 unit); 553 id->id_irq = -1; 554 isa_dma_release (id->id_drq); 555 adapter [unit] = 0; 556 free (b, M_DEVBUF); 557 return 0; 558 } 559 id->id_irq = 1 << irqtab[i]; 560 if (haveseen_isadev (id, CC_IRQ | CC_QUIET)) 561 continue; 562#ifdef KLD_MODULE 563 if (register_intr (irqtab[i], 0, 0, (inthand2_t*) 564 ct_intr, &net_imask, unit) != 0) 565 continue; 566 unregister_intr (irqtab[i], (inthand2_t*) ct_intr); 567#endif 568 if (probe_irq (b, irqtab[i])) 569 break; 570 } 571 } 572 ct_init_board (b, b->num, b->port, ffs (id->id_irq) - 1, b->dma, 573 b->type, b->osc); 574 ct_setup_board (b, 0, 0, 0); 575 576 return 1; 577} 578#endif /* __FreeBSD_version < 400000 */ 579 580extern struct cdevsw ct_cdevsw; 581/* 582 * The adapter is present, initialize the driver structures. 583 */ 584#if __FreeBSD_version < 400000 585static int ct_attach (struct isa_device *id) 586{ 587#else 588static int ct_attach (device_t dev) 589{ 590 bdrv_t *bd = device_get_softc (dev); 591 u_long iobase, drq, irq, rescount; 592 int unit = device_get_unit (dev); 593 int i; 594 int s; 595#endif 596 ct_board_t *b; 597 ct_chan_t *c; 598 drv_t *d; 599 600#if __FreeBSD_version >= 400000 601 KASSERT ((bd != NULL), ("ct%d: NULL device softc\n", unit)); 602 603 bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount); 604 bd->base_rid = 0; 605 bd->base_res = bus_alloc_resource (dev, SYS_RES_IOPORT, &bd->base_rid, 606 iobase, iobase + NPORT, NPORT, RF_ACTIVE); 607 if (! bd->base_res) { 608 printf ("ct%d: cannot alloc base address\n", unit); 609 return ENXIO; 610 } 611 612 if (bus_get_resource (dev, SYS_RES_DRQ, 0, &drq, &rescount) != 0) { 613 for (i = 0; (drq = dmatab [i]) != 0; i++) { 614 if (!ct_is_free_res (dev, 1, SYS_RES_DRQ, 615 drq, drq + 1, 1)) 616 continue; 617 bus_set_resource (dev, SYS_RES_DRQ, 0, drq, 1); 618 break; 619 } 620 621 if (dmatab[i] == 0) { 622 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 623 bd->base_res); 624 printf ("ct%d: Couldn't get DRQ\n", unit); 625 return ENXIO; 626 } 627 } 628 629 bd->drq_rid = 0; 630 bd->drq_res = bus_alloc_resource (dev, SYS_RES_DRQ, &bd->drq_rid, 631 drq, drq + 1, 1, RF_ACTIVE); 632 if (! bd->drq_res) { 633 printf ("ct%d: cannot allocate drq\n", unit); 634 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 635 bd->base_res); 636 return ENXIO; 637 } 638 639 if (bus_get_resource (dev, SYS_RES_IRQ, 0, &irq, &rescount) != 0) { 640 for (i = 0; (irq = irqtab [i]) != 0; i++) { 641 if (!ct_is_free_res (dev, 1, SYS_RES_IRQ, 642 irq, irq + 1, 1)) 643 continue; 644 bus_set_resource (dev, SYS_RES_IRQ, 0, irq, 1); 645 break; 646 } 647 648 if (irqtab[i] == 0) { 649 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 650 bd->drq_res); 651 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 652 bd->base_res); 653 printf ("ct%d: Couldn't get IRQ\n", unit); 654 return ENXIO; 655 } 656 } 657 658 bd->irq_rid = 0; 659 bd->irq_res = bus_alloc_resource (dev, SYS_RES_IRQ, &bd->irq_rid, 660 irq, irq + 1, 1, RF_ACTIVE); 661 if (! bd->irq_res) { 662 printf ("ct%d: Couldn't allocate irq\n", unit); 663 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 664 bd->drq_res); 665 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 666 bd->base_res); 667 return ENXIO; 668 } 669 670 b = malloc (sizeof (ct_board_t), M_DEVBUF, M_WAITOK); 671 if (!b) { 672 printf ("ct:%d: Couldn't allocate memory\n", unit); 673 return (ENXIO); 674 } 675 adapter[unit] = b; 676 bzero (b, sizeof(ct_board_t)); 677 678 if (! ct_open_board (b, unit, iobase, irq, drq)) { 679 printf ("ct%d: error loading firmware\n", unit); 680 free (b, M_DEVBUF); 681 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 682 bd->irq_res); 683 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 684 bd->drq_res); 685 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 686 bd->base_res); 687 return ENXIO; 688 } 689 690 bd->board = b; 691 692 if (! probe_irq (b, irq)) { 693 printf ("ct%d: irq %ld not functional\n", unit, irq); 694 bd->board = 0; 695 adapter [unit] = 0; 696 free (b, M_DEVBUF); 697 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 698 bd->irq_res); 699 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 700 bd->drq_res); 701 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 702 bd->base_res); 703 return ENXIO; 704 } 705 706 s = splimp (); 707 if (bus_setup_intr (dev, bd->irq_res, INTR_TYPE_NET, ct_intr, bd, 708 &bd->intrhand)) { 709 printf ("ct%d: Can't setup irq %ld\n", unit, irq); 710 bd->board = 0; 711 adapter [unit] = 0; 712 free (b, M_DEVBUF); 713 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 714 bd->irq_res); 715 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 716 bd->drq_res); 717 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 718 bd->base_res); 719 splx (s); 720 return ENXIO; 721 } 722 723 ct_init_board (b, b->num, b->port, irq, drq, b->type, b->osc); 724 ct_setup_board (b, 0, 0, 0); 725#else 726 b = adapter [id->id_unit]; 727#endif 728 729 printf ("ct%d: <Cronyx-%s>, clock %s MHz\n", b->num, b->name, 730 b->osc == 20000000 ? "20" : "16.384"); 731#if __FreeBSD_version < 400000 732 id->id_ointr = ct_intr; 733#endif 734 735 for (c=b->chan; c<b->chan+NCHAN; ++c) { 736 d = contigmalloc (sizeof(drv_t), M_DEVBUF, M_WAITOK, 737 0x100000, 0x1000000, 16, 0); 738 channel [b->num*NCHAN + c->num] = d; 739 bzero (d, sizeof(drv_t)); 740 sprintf (d->name, "ct%d.%d", b->num, c->num); 741 d->board = b; 742 d->chan = c; 743 c->sys = d; 744 745#ifdef NETGRAPH 746 if (ng_make_node_common (&typestruct, &d->node) != 0) { 747 printf ("%s: cannot make common node\n", d->name); 748 channel [b->num*NCHAN + c->num] = 0; 749 c->sys = 0; 750#if __FreeBSD_version < 400000 751 free (d, M_DEVBUF); 752#else 753 contigfree (d, sizeof (*d), M_DEVBUF); 754#endif 755 continue; 756 } 757#if __FreeBSD_version >= 500000 758 NG_NODE_SET_PRIVATE (d->node, d); 759#else 760 d->node->private = d; 761#endif 762 sprintf (d->nodename, "%s%d", NG_CT_NODE_TYPE, 763 c->board->num*NCHAN + c->num); 764 if (ng_name_node (d->node, d->nodename)) { 765 printf ("%s: cannot name node\n", d->nodename); 766#if __FreeBSD_version >= 500000 767 NG_NODE_UNREF (d->node); 768#else 769 ng_rmnode (d->node); 770 ng_unref (d->node); 771#endif 772 channel [b->num*NCHAN + c->num] = 0; 773 c->sys = 0; 774#if __FreeBSD_version < 400000 775 free (d, M_DEVBUF); 776#else 777 contigfree (d, sizeof (*d), M_DEVBUF); 778#endif 779 continue; 780 } 781 d->queue.ifq_maxlen = IFQ_MAXLEN; 782 d->hi_queue.ifq_maxlen = IFQ_MAXLEN; 783#if __FreeBSD_version >= 500000 784 mtx_init (&d->queue.ifq_mtx, "ct_queue", NULL, MTX_DEF); 785 mtx_init (&d->hi_queue.ifq_mtx, "ct_queue_hi", NULL, MTX_DEF); 786#endif 787#else /*NETGRAPH*/ 788 d->pp.pp_if.if_softc = d; 789#if __FreeBSD_version > 501000 790 if_initname (&d->pp.pp_if, "ct", b->num * NCHAN + c->num); 791#else 792 d->pp.pp_if.if_unit = b->num * NCHAN + c->num; 793 d->pp.pp_if.if_name = "ct"; 794#endif 795 d->pp.pp_if.if_mtu = PP_MTU; 796 d->pp.pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 797 d->pp.pp_if.if_ioctl = ct_sioctl; 798 d->pp.pp_if.if_start = ct_ifstart; 799 d->pp.pp_if.if_watchdog = ct_ifwatchdog; 800 d->pp.pp_if.if_init = ct_initialize; 801 sppp_attach (&d->pp.pp_if); 802 if_attach (&d->pp.pp_if); 803 d->pp.pp_tlf = ct_tlf; 804 d->pp.pp_tls = ct_tls; 805#if __FreeBSD_version >= 400000 || NBPFILTER > 0 806 /* If BPF is in the kernel, call the attach for it. 807 * Header size is 4 bytes. */ 808 bpfattach (&d->pp.pp_if, DLT_PPP, 4); 809#endif 810#endif /*NETGRAPH*/ 811 ct_start_chan (c, &d->buf, vtophys (&d->buf)); 812 ct_register_receive (c, &ct_receive); 813 ct_register_transmit (c, &ct_transmit); 814 ct_register_error (c, &ct_error); 815#if __FreeBSD_version >= 400000 816 d->devt = make_dev (&ct_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 817 GID_WHEEL, 0600, "ct%d", b->num*NCHAN+c->num); 818 } 819 splx (s); 820 821 return 0; 822#else /* __FreeBSD_version < 400000 */ 823 } 824 return 1; 825#endif /*__FreeBSD_version */ 826} 827 828#if __FreeBSD_version >= 400000 829static int ct_detach (device_t dev) 830{ 831 bdrv_t *bd = device_get_softc (dev); 832 ct_board_t *b = bd->board; 833 ct_chan_t *c; 834 int s = splimp (); 835 836 /* Check if the device is busy (open). */ 837 for (c = b->chan; c < b->chan + NCHAN; ++c) { 838 drv_t *d = (drv_t*) c->sys; 839 840 if (!d || !d->chan->type) 841 continue; 842 843 if (d->running) { 844 splx (s); 845 return EBUSY; 846 } 847 } 848 849 /* Deactivate the timeout routine. */ 850 if (led_timo[b->num].callout) 851 untimeout (ct_led_off, b, led_timo[b->num]); 852 853 bus_teardown_intr (dev, bd->irq_res, bd->intrhand); 854 bus_deactivate_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res); 855 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res); 856 857 bus_deactivate_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res); 858 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res); 859 860 bus_deactivate_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->irq_res); 861 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->base_res); 862 863 ct_close_board (b); 864 865 /* Detach the interfaces, free buffer memory. */ 866 for (c = b->chan; c < b->chan + NCHAN; ++c) { 867 drv_t *d = (drv_t*) c->sys; 868 869 if (!d || !d->chan->type) 870 continue; 871 872#ifdef NETGRAPH 873#if __FreeBSD_version >= 500000 874 if (d->node) { 875 ng_rmnode_self (d->node); 876 NG_NODE_UNREF (d->node); 877 d->node = NULL; 878 } 879 mtx_destroy (&d->queue.ifq_mtx); 880 mtx_destroy (&d->hi_queue.ifq_mtx); 881#else 882 ng_rmnode (d->node); 883 d->node = 0; 884#endif 885#else 886#if __FreeBSD_version >= 410000 && NBPFILTER > 0 887 /* Detach from the packet filter list of interfaces. */ 888 bpfdetach (&d->pp.pp_if); 889#endif 890 /* Detach from the sync PPP list. */ 891 sppp_detach (&d->pp.pp_if); 892 893 if_detach (&d->pp.pp_if); 894#endif 895 destroy_dev (d->devt); 896 } 897 898 ct_led_off (b); 899 if (led_timo[b->num].callout) 900 untimeout (ct_led_off, b, led_timo[b->num]); 901 splx (s); 902 903 s = splimp (); 904 for (c = b->chan; c < b->chan + NCHAN; ++c) { 905 drv_t *d = (drv_t*) c->sys; 906 907 if (!d || !d->chan->type) 908 continue; 909 910 /* Deallocate buffers. */ 911#if __FreeBSD_version < 400000 912 free (d, M_DEVBUF); 913#else 914 contigfree (d, sizeof (*d), M_DEVBUF); 915#endif 916 } 917 bd->board = 0; 918 adapter [b->num] = 0; 919 free (b, M_DEVBUF); 920 splx (s); 921 922 return 0; 923} 924#endif 925 926#ifndef NETGRAPH 927static void ct_ifstart (struct ifnet *ifp) 928{ 929 drv_t *d = ifp->if_softc; 930 931 ct_start (d); 932} 933 934static void ct_ifwatchdog (struct ifnet *ifp) 935{ 936 drv_t *d = ifp->if_softc; 937 938 ct_watchdog (d); 939} 940 941static void ct_tlf (struct sppp *sp) 942{ 943 drv_t *d = sp->pp_if.if_softc; 944 945 CT_DEBUG (d, ("ct_tlf\n")); 946/* ct_set_dtr (d->chan, 0);*/ 947/* ct_set_rts (d->chan, 0);*/ 948 sp->pp_down (sp); 949} 950 951static void ct_tls (struct sppp *sp) 952{ 953 drv_t *d = sp->pp_if.if_softc; 954 955 CT_DEBUG (d, ("ct_tls\n")); 956 sp->pp_up (sp); 957} 958 959/* 960 * Initialization of interface. 961 * Ii seems to be never called by upper level. 962 */ 963static void ct_initialize (void *softc) 964{ 965 drv_t *d = softc; 966 967 CT_DEBUG (d, ("ct_initialize\n")); 968} 969 970/* 971 * Process an ioctl request. 972 */ 973static int ct_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 974{ 975 drv_t *d = ifp->if_softc; 976 int error, s, was_up, should_be_up; 977 978 was_up = (ifp->if_flags & IFF_RUNNING) != 0; 979 error = sppp_ioctl (ifp, cmd, data); 980 if (error) 981 return error; 982 983 if (! (ifp->if_flags & IFF_DEBUG)) 984 d->chan->debug = 0; 985 else if (! d->chan->debug) 986 d->chan->debug = 1; 987 988 switch (cmd) { 989 default: CT_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 990 case SIOCADDMULTI: CT_DEBUG2 (d, ("SIOCADDMULTI\n")); return 0; 991 case SIOCDELMULTI: CT_DEBUG2 (d, ("SIOCDELMULTI\n")); return 0; 992 case SIOCSIFFLAGS: CT_DEBUG2 (d, ("SIOCSIFFLAGS\n")); break; 993 case SIOCSIFADDR: CT_DEBUG2 (d, ("SIOCSIFADDR\n")); break; 994 } 995 996 /* We get here only in case of SIFFLAGS or SIFADDR. */ 997 s = splimp (); 998 should_be_up = (ifp->if_flags & IFF_RUNNING) != 0; 999 if (! was_up && should_be_up) { 1000 /* Interface goes up -- start it. */ 1001 ct_up (d); 1002 ct_start (d); 1003 } else if (was_up && ! should_be_up) { 1004 /* Interface is going down -- stop it. */ 1005 /* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 1006 ct_down (d); 1007 } 1008 splx (s); 1009 return 0; 1010} 1011#endif /*NETGRAPH*/ 1012 1013/* 1014 * Stop the interface. Called on splimp(). 1015 */ 1016static void ct_down (drv_t *d) 1017{ 1018 int s = splimp (); 1019 CT_DEBUG (d, ("ct_down\n")); 1020 ct_set_dtr (d->chan, 0); 1021 ct_set_rts (d->chan, 0); 1022 d->running = 0; 1023 splx (s); 1024} 1025 1026/* 1027 * Start the interface. Called on splimp(). 1028 */ 1029static void ct_up (drv_t *d) 1030{ 1031 int s = splimp (); 1032 CT_DEBUG (d, ("ct_up\n")); 1033 ct_set_dtr (d->chan, 1); 1034 ct_set_rts (d->chan, 1); 1035 d->running = 1; 1036 splx (s); 1037} 1038 1039/* 1040 * Start output on the (slave) interface. Get another datagram to send 1041 * off of the interface queue, and copy it to the interface 1042 * before starting the output. 1043 */ 1044static void ct_send (drv_t *d) 1045{ 1046 struct mbuf *m; 1047 u_short len; 1048 1049 CT_DEBUG2 (d, ("ct_send, tn=%d\n", d->chan->tn)); 1050 1051 /* No output if the interface is down. */ 1052 if (! d->running) 1053 return; 1054 1055 /* No output if the modem is off. */ 1056 if (! ct_get_dsr (d->chan) && !ct_get_loop (d->chan)) 1057 return; 1058 1059 while (ct_buf_free (d->chan)) { 1060 /* Get the packet to send. */ 1061#ifdef NETGRAPH 1062 IF_DEQUEUE (&d->hi_queue, m); 1063 if (! m) 1064 IF_DEQUEUE (&d->queue, m); 1065#else 1066 m = sppp_dequeue (&d->pp.pp_if); 1067#endif 1068 if (! m) 1069 return; 1070#if (__FreeBSD_version >= 400000 || NBPFILTER > 0) && !defined (NETGRAPH) 1071 if (d->pp.pp_if.if_bpf) 1072#if __FreeBSD_version >= 500000 1073 BPF_MTAP (&d->pp.pp_if, m); 1074#else 1075 bpf_mtap (&d->pp.pp_if, m); 1076#endif 1077#endif 1078 len = m->m_pkthdr.len; 1079 if (! m->m_next) 1080 ct_send_packet (d->chan, (u_char*)mtod (m, caddr_t), 1081 len, 0); 1082 else { 1083 m_copydata (m, 0, len, d->chan->tbuf[d->chan->te]); 1084 ct_send_packet (d->chan, d->chan->tbuf[d->chan->te], 1085 len, 0); 1086 } 1087 m_freem (m); 1088 1089 /* Set up transmit timeout, if the transmit ring is not empty. 1090 * Transmit timeout is 10 seconds. */ 1091#ifdef NETGRAPH 1092 d->timeout = 10; 1093#else 1094 d->pp.pp_if.if_timer = 10; 1095#endif 1096 } 1097#ifndef NETGRAPH 1098 d->pp.pp_if.if_flags |= IFF_OACTIVE; 1099#endif 1100} 1101 1102/* 1103 * Start output on the interface. 1104 * Always called on splimp(). 1105 */ 1106static void ct_start (drv_t *d) 1107{ 1108 int s = splimp (); 1109 1110 if (d->running) { 1111 if (! d->chan->dtr) 1112 ct_set_dtr (d->chan, 1); 1113 if (! d->chan->rts) 1114 ct_set_rts (d->chan, 1); 1115 ct_send (d); 1116 } 1117 1118 splx (s); 1119} 1120 1121/* 1122 * Handle transmit timeouts. 1123 * Recover after lost transmit interrupts. 1124 * Always called on splimp(). 1125 */ 1126static void ct_watchdog (drv_t *d) 1127{ 1128 int s = splimp (); 1129 1130 CT_DEBUG (d, ("device timeout\n")); 1131 if (d->running) { 1132 ct_setup_chan (d->chan); 1133 ct_start_chan (d->chan, 0, 0); 1134 ct_set_dtr (d->chan, 1); 1135 ct_set_rts (d->chan, 1); 1136 ct_start (d); 1137 } 1138 1139 splx (s); 1140} 1141 1142/* 1143 * Transmit callback function. 1144 */ 1145static void ct_transmit (ct_chan_t *c, void *attachment, int len) 1146{ 1147 drv_t *d = c->sys; 1148 1149 if (!d) 1150 return; 1151#ifdef NETGRAPH 1152 d->timeout = 0; 1153#else 1154 ++d->pp.pp_if.if_opackets; 1155 d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 1156 d->pp.pp_if.if_timer = 0; 1157#endif 1158 ct_start (d); 1159} 1160 1161/* 1162 * Process the received packet. 1163 */ 1164static void ct_receive (ct_chan_t *c, char *data, int len) 1165{ 1166 drv_t *d = c->sys; 1167 struct mbuf *m; 1168#if __FreeBSD_version >= 500000 && defined NETGRAPH 1169 int error; 1170#endif 1171 1172 if (!d || !d->running) 1173 return; 1174 1175 m = makembuf (data, len); 1176 if (! m) { 1177 CT_DEBUG (d, ("no memory for packet\n")); 1178#ifndef NETGRAPH 1179 ++d->pp.pp_if.if_iqdrops; 1180#endif 1181 return; 1182 } 1183 if (c->debug > 1) 1184 printmbuf (m); 1185#ifdef NETGRAPH 1186 m->m_pkthdr.rcvif = 0; 1187#if __FreeBSD_version >= 500000 1188 NG_SEND_DATA_ONLY (error, d->hook, m); 1189#else 1190 ng_queue_data (d->hook, m, 0); 1191#endif 1192#else 1193 ++d->pp.pp_if.if_ipackets; 1194 m->m_pkthdr.rcvif = &d->pp.pp_if; 1195#if __FreeBSD_version >= 400000 || NBPFILTER > 0 1196 /* Check if there's a BPF listener on this interface. 1197 * If so, hand off the raw packet to bpf. */ 1198 if (d->pp.pp_if.if_bpf) 1199#if __FreeBSD_version >= 500000 1200 BPF_TAP (&d->pp.pp_if, data, len); 1201#else 1202 bpf_tap (&d->pp.pp_if, data, len); 1203#endif 1204#endif 1205 sppp_input (&d->pp.pp_if, m); 1206#endif 1207} 1208 1209/* 1210 * Error callback function. 1211 */ 1212static void ct_error (ct_chan_t *c, int data) 1213{ 1214 drv_t *d = c->sys; 1215 1216 if (!d) 1217 return; 1218 1219 switch (data) { 1220 case CT_FRAME: 1221 CT_DEBUG (d, ("frame error\n")); 1222#ifndef NETGRAPH 1223 ++d->pp.pp_if.if_ierrors; 1224#endif 1225 break; 1226 case CT_CRC: 1227 CT_DEBUG (d, ("crc error\n")); 1228#ifndef NETGRAPH 1229 ++d->pp.pp_if.if_ierrors; 1230#endif 1231 break; 1232 case CT_OVERRUN: 1233 CT_DEBUG (d, ("overrun error\n")); 1234#ifndef NETGRAPH 1235 ++d->pp.pp_if.if_collisions; 1236 ++d->pp.pp_if.if_ierrors; 1237#endif 1238 break; 1239 case CT_OVERFLOW: 1240 CT_DEBUG (d, ("overflow error\n")); 1241#ifndef NETGRAPH 1242 ++d->pp.pp_if.if_ierrors; 1243#endif 1244 break; 1245 case CT_UNDERRUN: 1246 CT_DEBUG (d, ("underrun error\n")); 1247#ifdef NETGRAPH 1248 d->timeout = 0; 1249#else 1250 ++d->pp.pp_if.if_oerrors; 1251 d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 1252 d->pp.pp_if.if_timer = 0; 1253#endif 1254 ct_start (d); 1255 break; 1256 default: 1257 CT_DEBUG (d, ("error #%d\n", data)); 1258 } 1259} 1260 1261#if __FreeBSD_version < 500000 1262static int ct_open (dev_t dev, int oflags, int devtype, struct proc *p) 1263#else 1264static int ct_open (dev_t dev, int oflags, int devtype, struct thread *td) 1265#endif 1266{ 1267 drv_t *d; 1268 1269 if (minor(dev) >= NCTAU*NCHAN || ! (d = channel[minor(dev)])) 1270 return ENXIO; 1271 1272 CT_DEBUG2 (d, ("ct_open\n")); 1273 return 0; 1274} 1275 1276#if __FreeBSD_version < 500000 1277static int ct_close (dev_t dev, int fflag, int devtype, struct proc *p) 1278#else 1279static int ct_close (dev_t dev, int fflag, int devtype, struct thread *td) 1280#endif 1281{ 1282 drv_t *d = channel [minor(dev)]; 1283 1284 if (!d) 1285 return 0; 1286 1287 CT_DEBUG2 (d, ("ct_close\n")); 1288 return 0; 1289} 1290 1291static int ct_modem_status (ct_chan_t *c) 1292{ 1293 drv_t *d = c->sys; 1294 int status, s; 1295 1296 if (!d) 1297 return 0; 1298 1299 status = d->running ? TIOCM_LE : 0; 1300 s = splimp (); 1301 if (ct_get_cd (c)) status |= TIOCM_CD; 1302 if (ct_get_cts (c)) status |= TIOCM_CTS; 1303 if (ct_get_dsr (c)) status |= TIOCM_DSR; 1304 if (c->dtr) status |= TIOCM_DTR; 1305 if (c->rts) status |= TIOCM_RTS; 1306 splx (s); 1307 return status; 1308} 1309 1310/* 1311 * Process an ioctl request on /dev/cronyx/ctauN. 1312 */ 1313#if __FreeBSD_version < 500000 1314static int ct_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1315#else 1316static int ct_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1317#endif 1318{ 1319 drv_t *d = channel [minor (dev)]; 1320 ct_chan_t *c; 1321 struct serial_statistics *st; 1322 struct e1_statistics *opte1; 1323 int error, s; 1324 char mask[16]; 1325 1326 if (!d || !d->chan) 1327 return 0; 1328 1329 c = d->chan; 1330 1331 switch (cmd) { 1332 case SERIAL_GETREGISTERED: 1333 bzero (mask, sizeof(mask)); 1334 for (s=0; s<NCTAU*NCHAN; ++s) 1335 if (channel [s]) 1336 mask [s/8] |= 1 << (s & 7); 1337 bcopy (mask, data, sizeof (mask)); 1338 return 0; 1339 1340#ifndef NETGRAPH 1341 case SERIAL_GETPROTO: 1342 strcpy ((char*)data, (d->pp.pp_flags & PP_FR) ? "fr" : 1343 (d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp"); 1344 return 0; 1345 1346 case SERIAL_SETPROTO: 1347 /* Only for superuser! */ 1348#if __FreeBSD_version < 400000 1349 error = suser (p->p_ucred, &p->p_acflag); 1350#elif __FreeBSD_version < 500000 1351 error = suser (p); 1352#else /* __FreeBSD_version >= 500000 */ 1353 error = suser (td); 1354#endif /* __FreeBSD_version >= 500000 */ 1355 if (error) 1356 return error; 1357 if (d->pp.pp_if.if_flags & IFF_RUNNING) 1358 return EBUSY; 1359 if (! strcmp ("cisco", (char*)data)) { 1360 d->pp.pp_flags &= ~(PP_FR); 1361 d->pp.pp_flags |= PP_KEEPALIVE; 1362 d->pp.pp_if.if_flags |= PP_CISCO; 1363 } else if (! strcmp ("fr", (char*)data)) { 1364 d->pp.pp_if.if_flags &= ~(PP_CISCO); 1365 d->pp.pp_flags |= PP_FR | PP_KEEPALIVE; 1366 } else if (! strcmp ("ppp", (char*)data)) { 1367 d->pp.pp_flags &= ~(PP_FR | PP_KEEPALIVE); 1368 d->pp.pp_if.if_flags &= ~(PP_CISCO); 1369 } else 1370 return EINVAL; 1371 return 0; 1372 1373 case SERIAL_GETKEEPALIVE: 1374 if ((d->pp.pp_flags & PP_FR) || 1375 (d->pp.pp_if.if_flags & PP_CISCO)) 1376 return EINVAL; 1377 *(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0; 1378 return 0; 1379 1380 case SERIAL_SETKEEPALIVE: 1381 /* Only for superuser! */ 1382#if __FreeBSD_version < 400000 1383 error = suser (p->p_ucred, &p->p_acflag); 1384#elif __FreeBSD_version < 500000 1385 error = suser (p); 1386#else /* __FreeBSD_version >= 500000 */ 1387 error = suser (td); 1388#endif /* __FreeBSD_version >= 500000 */ 1389 if (error) 1390 return error; 1391 if ((d->pp.pp_flags & PP_FR) || 1392 (d->pp.pp_if.if_flags & PP_CISCO)) 1393 return EINVAL; 1394 if (*(int*)data) 1395 d->pp.pp_flags |= PP_KEEPALIVE; 1396 else 1397 d->pp.pp_flags &= ~PP_KEEPALIVE; 1398 return 0; 1399#endif /*NETGRAPH*/ 1400 1401 case SERIAL_GETMODE: 1402 *(int*)data = SERIAL_HDLC; 1403 return 0; 1404 1405 case SERIAL_GETCFG: 1406 if (c->mode == M_HDLC) 1407 return EINVAL; 1408 switch (ct_get_config (c->board)) { 1409 default: *(char*)data = 'a'; break; 1410 case CFG_B: *(char*)data = 'b'; break; 1411 case CFG_C: *(char*)data = 'c'; break; 1412 } 1413 return 0; 1414 1415 case SERIAL_SETCFG: 1416 /* Only for superuser! */ 1417#if __FreeBSD_version < 400000 1418 error = suser (p->p_ucred, &p->p_acflag); 1419#elif __FreeBSD_version < 500000 1420 error = suser (p); 1421#else /* __FreeBSD_version >= 500000 */ 1422 error = suser (td); 1423#endif /* __FreeBSD_version >= 500000 */ 1424 if (error) 1425 return error; 1426 if (c->mode == M_HDLC) 1427 return EINVAL; 1428 s = splimp (); 1429 switch (*(char*)data) { 1430 case 'a': ct_set_config (c->board, CFG_A); break; 1431 case 'b': ct_set_config (c->board, CFG_B); break; 1432 case 'c': ct_set_config (c->board, CFG_C); break; 1433 } 1434 splx (s); 1435 return 0; 1436 1437 case SERIAL_GETSTAT: 1438 st = (struct serial_statistics*) data; 1439 st->rintr = c->rintr; 1440 st->tintr = c->tintr; 1441 st->mintr = c->mintr; 1442 st->ibytes = c->ibytes; 1443 st->ipkts = c->ipkts; 1444 st->ierrs = c->ierrs; 1445 st->obytes = c->obytes; 1446 st->opkts = c->opkts; 1447 st->oerrs = c->oerrs; 1448 return 0; 1449 1450 case SERIAL_GETESTAT: 1451 opte1 = (struct e1_statistics*)data; 1452 opte1->status = c->status; 1453 opte1->cursec = c->cursec; 1454 opte1->totsec = c->totsec + c->cursec; 1455 1456 opte1->currnt.bpv = c->currnt.bpv; 1457 opte1->currnt.fse = c->currnt.fse; 1458 opte1->currnt.crce = c->currnt.crce; 1459 opte1->currnt.rcrce = c->currnt.rcrce; 1460 opte1->currnt.uas = c->currnt.uas; 1461 opte1->currnt.les = c->currnt.les; 1462 opte1->currnt.es = c->currnt.es; 1463 opte1->currnt.bes = c->currnt.bes; 1464 opte1->currnt.ses = c->currnt.ses; 1465 opte1->currnt.oofs = c->currnt.oofs; 1466 opte1->currnt.css = c->currnt.css; 1467 opte1->currnt.dm = c->currnt.dm; 1468 1469 opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1470 opte1->total.fse = c->total.fse + c->currnt.fse; 1471 opte1->total.crce = c->total.crce + c->currnt.crce; 1472 opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1473 opte1->total.uas = c->total.uas + c->currnt.uas; 1474 opte1->total.les = c->total.les + c->currnt.les; 1475 opte1->total.es = c->total.es + c->currnt.es; 1476 opte1->total.bes = c->total.bes + c->currnt.bes; 1477 opte1->total.ses = c->total.ses + c->currnt.ses; 1478 opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1479 opte1->total.css = c->total.css + c->currnt.css; 1480 opte1->total.dm = c->total.dm + c->currnt.dm; 1481 for (s=0; s<48; ++s) { 1482 opte1->interval[s].bpv = c->interval[s].bpv; 1483 opte1->interval[s].fse = c->interval[s].fse; 1484 opte1->interval[s].crce = c->interval[s].crce; 1485 opte1->interval[s].rcrce = c->interval[s].rcrce; 1486 opte1->interval[s].uas = c->interval[s].uas; 1487 opte1->interval[s].les = c->interval[s].les; 1488 opte1->interval[s].es = c->interval[s].es; 1489 opte1->interval[s].bes = c->interval[s].bes; 1490 opte1->interval[s].ses = c->interval[s].ses; 1491 opte1->interval[s].oofs = c->interval[s].oofs; 1492 opte1->interval[s].css = c->interval[s].css; 1493 opte1->interval[s].dm = c->interval[s].dm; 1494 } 1495 return 0; 1496 1497 case SERIAL_CLRSTAT: 1498 /* Only for superuser! */ 1499#if __FreeBSD_version < 400000 1500 error = suser (p->p_ucred, &p->p_acflag); 1501#elif __FreeBSD_version < 500000 1502 error = suser (p); 1503#else /* __FreeBSD_version >= 500000 */ 1504 error = suser (td); 1505#endif /* __FreeBSD_version >= 500000 */ 1506 if (error) 1507 return error; 1508 c->rintr = 0; 1509 c->tintr = 0; 1510 c->mintr = 0; 1511 c->ibytes = 0; 1512 c->ipkts = 0; 1513 c->ierrs = 0; 1514 c->obytes = 0; 1515 c->opkts = 0; 1516 c->oerrs = 0; 1517 bzero (&c->currnt, sizeof (c->currnt)); 1518 bzero (&c->total, sizeof (c->total)); 1519 bzero (c->interval, sizeof (c->interval)); 1520 return 0; 1521 1522 case SERIAL_GETBAUD: 1523 *(long*)data = ct_get_baud(c); 1524 return 0; 1525 1526 case SERIAL_SETBAUD: 1527 /* Only for superuser! */ 1528#if __FreeBSD_version < 400000 1529 error = suser (p->p_ucred, &p->p_acflag); 1530#elif __FreeBSD_version < 500000 1531 error = suser (p); 1532#else /* __FreeBSD_version >= 500000 */ 1533 error = suser (td); 1534#endif /* __FreeBSD_version >= 500000 */ 1535 if (error) 1536 return error; 1537 s = splimp (); 1538 ct_set_baud (c, *(long*)data); 1539 splx (s); 1540 return 0; 1541 1542 case SERIAL_GETLOOP: 1543 *(int*)data = ct_get_loop (c); 1544 return 0; 1545 1546 case SERIAL_SETLOOP: 1547 /* Only for superuser! */ 1548#if __FreeBSD_version < 400000 1549 error = suser (p->p_ucred, &p->p_acflag); 1550#elif __FreeBSD_version < 500000 1551 error = suser (p); 1552#else /* __FreeBSD_version >= 500000 */ 1553 error = suser (td); 1554#endif /* __FreeBSD_version >= 500000 */ 1555 if (error) 1556 return error; 1557 s = splimp (); 1558 ct_set_loop (c, *(int*)data); 1559 splx (s); 1560 return 0; 1561 1562 case SERIAL_GETDPLL: 1563 if (c->mode == M_E1 || c->mode == M_G703) 1564 return EINVAL; 1565 *(int*)data = ct_get_dpll (c); 1566 return 0; 1567 1568 case SERIAL_SETDPLL: 1569 /* Only for superuser! */ 1570#if __FreeBSD_version < 400000 1571 error = suser (p->p_ucred, &p->p_acflag); 1572#elif __FreeBSD_version < 500000 1573 error = suser (p); 1574#else /* __FreeBSD_version >= 500000 */ 1575 error = suser (td); 1576#endif /* __FreeBSD_version >= 500000 */ 1577 if (error) 1578 return error; 1579 if (c->mode == M_E1 || c->mode == M_G703) 1580 return EINVAL; 1581 s = splimp (); 1582 ct_set_dpll (c, *(int*)data); 1583 splx (s); 1584 return 0; 1585 1586 case SERIAL_GETNRZI: 1587 if (c->mode == M_E1 || c->mode == M_G703) 1588 return EINVAL; 1589 *(int*)data = ct_get_nrzi (c); 1590 return 0; 1591 1592 case SERIAL_SETNRZI: 1593 /* Only for superuser! */ 1594#if __FreeBSD_version < 400000 1595 error = suser (p->p_ucred, &p->p_acflag); 1596#elif __FreeBSD_version < 500000 1597 error = suser (p); 1598#else /* __FreeBSD_version >= 500000 */ 1599 error = suser (td); 1600#endif /* __FreeBSD_version >= 500000 */ 1601 if (error) 1602 return error; 1603 if (c->mode == M_E1 || c->mode == M_G703) 1604 return EINVAL; 1605 s = splimp (); 1606 ct_set_nrzi (c, *(int*)data); 1607 splx (s); 1608 return 0; 1609 1610 case SERIAL_GETDEBUG: 1611 *(int*)data = c->debug; 1612 return 0; 1613 1614 case SERIAL_SETDEBUG: 1615 /* Only for superuser! */ 1616#if __FreeBSD_version < 400000 1617 error = suser (p->p_ucred, &p->p_acflag); 1618#elif __FreeBSD_version < 500000 1619 error = suser (p); 1620#else /* __FreeBSD_version >= 500000 */ 1621 error = suser (td); 1622#endif /* __FreeBSD_version >= 500000 */ 1623 if (error) 1624 return error; 1625 c->debug = *(int*)data; 1626#ifndef NETGRAPH 1627 if (d->chan->debug) 1628 d->pp.pp_if.if_flags |= IFF_DEBUG; 1629 else 1630 d->pp.pp_if.if_flags &= (~IFF_DEBUG); 1631#endif 1632 return 0; 1633 1634 case SERIAL_GETHIGAIN: 1635 if (c->mode != M_E1) 1636 return EINVAL; 1637 *(int*)data = ct_get_higain (c); 1638 return 0; 1639 1640 case SERIAL_SETHIGAIN: 1641 /* Only for superuser! */ 1642#if __FreeBSD_version < 400000 1643 error = suser (p->p_ucred, &p->p_acflag); 1644#elif __FreeBSD_version < 500000 1645 error = suser (p); 1646#else /* __FreeBSD_version >= 500000 */ 1647 error = suser (td); 1648#endif /* __FreeBSD_version >= 500000 */ 1649 if (error) 1650 return error; 1651 s = splimp (); 1652 ct_set_higain (c, *(int*)data); 1653 splx (s); 1654 return 0; 1655 1656 case SERIAL_GETPHONY: 1657 CT_DEBUG2 (d, ("ioctl: getphony\n")); 1658 if (c->mode != M_E1) 1659 return EINVAL; 1660 *(int*)data = c->gopt.phony; 1661 return 0; 1662 1663 case SERIAL_SETPHONY: 1664 CT_DEBUG2 (d, ("ioctl: setphony\n")); 1665 if (c->mode != M_E1) 1666 return EINVAL; 1667 /* Only for superuser! */ 1668#if __FreeBSD_version < 400000 1669 error = suser (p->p_ucred, &p->p_acflag); 1670#elif __FreeBSD_version < 500000 1671 error = suser (p); 1672#else /* __FreeBSD_version >= 500000 */ 1673 error = suser (td); 1674#endif /* __FreeBSD_version >= 500000 */ 1675 if (error) 1676 return error; 1677 s = splimp (); 1678 ct_set_phony (c, *(int*)data); 1679 splx (s); 1680 return 0; 1681 1682 case SERIAL_GETCLK: 1683 if (c->mode != M_E1 && c->mode != M_G703) 1684 return EINVAL; 1685 switch (ct_get_clk(c)) { 1686 default: *(int*)data = E1CLK_INTERNAL; break; 1687 case GCLK_RCV: *(int*)data = E1CLK_RECEIVE; break; 1688 case GCLK_RCLKO: *(int*)data = c->num ? 1689 E1CLK_RECEIVE_CHAN0 : E1CLK_RECEIVE_CHAN1; break; 1690 } 1691 return 0; 1692 1693 case SERIAL_SETCLK: 1694 /* Only for superuser! */ 1695#if __FreeBSD_version < 400000 1696 error = suser (p->p_ucred, &p->p_acflag); 1697#elif __FreeBSD_version < 500000 1698 error = suser (p); 1699#else /* __FreeBSD_version >= 500000 */ 1700 error = suser (td); 1701#endif /* __FreeBSD_version >= 500000 */ 1702 if (error) 1703 return error; 1704 s = splimp (); 1705 switch (*(int*)data) { 1706 default: ct_set_clk (c, GCLK_INT); break; 1707 case E1CLK_RECEIVE: ct_set_clk (c, GCLK_RCV); break; 1708 case E1CLK_RECEIVE_CHAN0: 1709 case E1CLK_RECEIVE_CHAN1: 1710 ct_set_clk (c, GCLK_RCLKO); break; 1711 } 1712 splx (s); 1713 return 0; 1714 1715 case SERIAL_GETTIMESLOTS: 1716 if (c->mode != M_E1) 1717 return EINVAL; 1718 *(long*)data = ct_get_ts (c); 1719 return 0; 1720 1721 case SERIAL_SETTIMESLOTS: 1722 /* Only for superuser! */ 1723#if __FreeBSD_version < 400000 1724 error = suser (p->p_ucred, &p->p_acflag); 1725#elif __FreeBSD_version < 500000 1726 error = suser (p); 1727#else /* __FreeBSD_version >= 500000 */ 1728 error = suser (td); 1729#endif /* __FreeBSD_version >= 500000 */ 1730 if (error) 1731 return error; 1732 s = splimp (); 1733 ct_set_ts (c, *(long*)data); 1734 splx (s); 1735 return 0; 1736 1737 case SERIAL_GETSUBCHAN: 1738 if (c->mode != M_E1) 1739 return EINVAL; 1740 *(long*)data = ct_get_subchan (c->board); 1741 return 0; 1742 1743 case SERIAL_SETSUBCHAN: 1744 /* Only for superuser! */ 1745#if __FreeBSD_version < 400000 1746 error = suser (p->p_ucred, &p->p_acflag); 1747#elif __FreeBSD_version < 500000 1748 error = suser (p); 1749#else /* __FreeBSD_version >= 500000 */ 1750 error = suser (td); 1751#endif /* __FreeBSD_version >= 500000 */ 1752 if (error) 1753 return error; 1754 s = splimp (); 1755 ct_set_subchan (c->board, *(long*)data); 1756 splx (s); 1757 return 0; 1758 1759 case SERIAL_GETINVCLK: 1760 case SERIAL_GETINVTCLK: 1761 if (c->mode == M_E1 || c->mode == M_G703) 1762 return EINVAL; 1763 *(int*)data = ct_get_invtxc (c); 1764 return 0; 1765 1766 case SERIAL_GETINVRCLK: 1767 if (c->mode == M_E1 || c->mode == M_G703) 1768 return EINVAL; 1769 *(int*)data = ct_get_invrxc (c); 1770 return 0; 1771 1772 case SERIAL_SETINVCLK: 1773 case SERIAL_SETINVTCLK: 1774 /* Only for superuser! */ 1775#if __FreeBSD_version < 400000 1776 error = suser (p->p_ucred, &p->p_acflag); 1777#elif __FreeBSD_version < 500000 1778 error = suser (p); 1779#else /* __FreeBSD_version >= 500000 */ 1780 error = suser (td); 1781#endif /* __FreeBSD_version >= 500000 */ 1782 if (error) 1783 return error; 1784 if (c->mode == M_E1 || c->mode == M_G703) 1785 return EINVAL; 1786 s = splimp (); 1787 ct_set_invtxc (c, *(int*)data); 1788 splx (s); 1789 return 0; 1790 1791 case SERIAL_SETINVRCLK: 1792 /* Only for superuser! */ 1793#if __FreeBSD_version < 400000 1794 error = suser (p->p_ucred, &p->p_acflag); 1795#elif __FreeBSD_version < 500000 1796 error = suser (p); 1797#else /* __FreeBSD_version >= 500000 */ 1798 error = suser (td); 1799#endif /* __FreeBSD_version >= 500000 */ 1800 if (error) 1801 return error; 1802 if (c->mode == M_E1 || c->mode == M_G703) 1803 return EINVAL; 1804 s = splimp (); 1805 ct_set_invrxc (c, *(int*)data); 1806 splx (s); 1807 return 0; 1808 1809 case SERIAL_GETLEVEL: 1810 if (c->mode != M_G703) 1811 return EINVAL; 1812 s = splimp (); 1813 *(int*)data = ct_get_lq (c); 1814 splx (s); 1815 return 0; 1816 1817 case TIOCSDTR: /* Set DTR */ 1818 s = splimp (); 1819 ct_set_dtr (c, 1); 1820 splx (s); 1821 return 0; 1822 1823 case TIOCCDTR: /* Clear DTR */ 1824 s = splimp (); 1825 ct_set_dtr (c, 0); 1826 splx (s); 1827 return 0; 1828 1829 case TIOCMSET: /* Set DTR/RTS */ 1830 s = splimp (); 1831 ct_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1832 ct_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1833 splx (s); 1834 return 0; 1835 1836 case TIOCMBIS: /* Add DTR/RTS */ 1837 s = splimp (); 1838 if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 1); 1839 if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 1); 1840 splx (s); 1841 return 0; 1842 1843 case TIOCMBIC: /* Clear DTR/RTS */ 1844 s = splimp (); 1845 if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 0); 1846 if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 0); 1847 splx (s); 1848 return 0; 1849 1850 case TIOCMGET: /* Get modem status */ 1851 *(int*)data = ct_modem_status (c); 1852 return 0; 1853 } 1854 return ENOTTY; 1855} 1856 1857#if __FreeBSD_version < 400000 1858struct isa_driver ctdriver = { ct_probe, ct_attach, "ct" }; 1859static struct cdevsw ct_cdevsw = { 1860 ct_open, ct_close, noread, nowrite, 1861 ct_ioctl, nostop, noreset, nodevtotty, 1862 seltrue, nommap, NULL, "ct", 1863 NULL, -1, 1864}; 1865#elif __FreeBSD_version < 500000 1866static struct cdevsw ct_cdevsw = { 1867 ct_open, ct_close, noread, nowrite, 1868 ct_ioctl, nopoll, nommap, nostrategy, 1869 "ct", CDEV_MAJOR, nodump, nopsize, 1870 D_NAGGED, -1 1871}; 1872#elif __FreeBSD_version == 500000 1873static struct cdevsw ct_cdevsw = { 1874 ct_open, ct_close, noread, nowrite, 1875 ct_ioctl, nopoll, nommap, nostrategy, 1876 "ct", CDEV_MAJOR, nodump, nopsize, 1877 D_NAGGED, 1878 }; 1879#elif __FreeBSD_version <= 501000 1880static struct cdevsw ct_cdevsw = { 1881 .d_open = ct_open, 1882 .d_close = ct_close, 1883 .d_read = noread, 1884 .d_write = nowrite, 1885 .d_ioctl = ct_ioctl, 1886 .d_poll = nopoll, 1887 .d_mmap = nommap, 1888 .d_strategy = nostrategy, 1889 .d_name = "ct", 1890 .d_maj = CDEV_MAJOR, 1891 .d_dump = nodump, 1892 .d_flags = D_NAGGED, 1893}; 1894#elif __FreeBSD_version < 502103 1895static struct cdevsw ct_cdevsw = { 1896 .d_open = ct_open, 1897 .d_close = ct_close, 1898 .d_ioctl = ct_ioctl, 1899 .d_name = "ct", 1900 .d_maj = CDEV_MAJOR, 1901 .d_flags = D_NAGGED, 1902}; 1903#else /* __FreeBSD_version >= 502103 */ 1904static struct cdevsw ct_cdevsw = { 1905 .d_version = D_VERSION, 1906 .d_open = ct_open, 1907 .d_close = ct_close, 1908 .d_ioctl = ct_ioctl, 1909 .d_name = "ct", 1910 .d_maj = CDEV_MAJOR, 1911 .d_flags = D_NEEDGIANT, 1912}; 1913#endif /* __FreeBSD_version > 501000 */ 1914 1915#ifdef NETGRAPH 1916#if __FreeBSD_version >= 500000 1917static int ng_ct_constructor (node_p node) 1918{ 1919 drv_t *d = NG_NODE_PRIVATE (node); 1920#else 1921static int ng_ct_constructor (node_p *node) 1922{ 1923 drv_t *d = (*node)->private; 1924#endif 1925 CT_DEBUG (d, ("Constructor\n")); 1926 return EINVAL; 1927} 1928 1929static int ng_ct_newhook (node_p node, hook_p hook, const char *name) 1930{ 1931 int s; 1932#if __FreeBSD_version >= 500000 1933 drv_t *d = NG_NODE_PRIVATE (node); 1934#else 1935 drv_t *d = node->private; 1936#endif 1937 1938 if (!d) 1939 return EINVAL; 1940 1941 /* Attach debug hook */ 1942 if (strcmp (name, NG_CT_HOOK_DEBUG) == 0) { 1943#if __FreeBSD_version >= 500000 1944 NG_HOOK_SET_PRIVATE (hook, NULL); 1945#else 1946 hook->private = 0; 1947#endif 1948 d->debug_hook = hook; 1949 return 0; 1950 } 1951 1952 /* Check for raw hook */ 1953 if (strcmp (name, NG_CT_HOOK_RAW) != 0) 1954 return EINVAL; 1955 1956#if __FreeBSD_version >= 500000 1957 NG_HOOK_SET_PRIVATE (hook, d); 1958#else 1959 hook->private = d; 1960#endif 1961 d->hook = hook; 1962 s = splimp (); 1963 ct_up (d); 1964 splx (s); 1965 return 0; 1966} 1967 1968static char *format_timeslots (u_long s) 1969{ 1970 static char buf [100]; 1971 char *p = buf; 1972 int i; 1973 1974 for (i=1; i<32; ++i) 1975 if ((s >> i) & 1) { 1976 int prev = (i > 1) & (s >> (i-1)); 1977 int next = (i < 31) & (s >> (i+1)); 1978 1979 if (prev) { 1980 if (next) 1981 continue; 1982 *p++ = '-'; 1983 } else if (p > buf) 1984 *p++ = ','; 1985 1986 if (i >= 10) 1987 *p++ = '0' + i / 10; 1988 *p++ = '0' + i % 10; 1989 } 1990 *p = 0; 1991 return buf; 1992} 1993 1994static int print_modems (char *s, ct_chan_t *c, int need_header) 1995{ 1996 int status = ct_modem_status (c); 1997 int length = 0; 1998 1999 if (need_header) 2000 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 2001 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 2002 status & TIOCM_LE ? "On" : "-", 2003 status & TIOCM_DTR ? "On" : "-", 2004 status & TIOCM_DSR ? "On" : "-", 2005 status & TIOCM_RTS ? "On" : "-", 2006 status & TIOCM_CTS ? "On" : "-", 2007 status & TIOCM_CD ? "On" : "-"); 2008 return length; 2009} 2010 2011static int print_stats (char *s, ct_chan_t *c, int need_header) 2012{ 2013 struct serial_statistics st; 2014 int length = 0; 2015 2016 st.rintr = c->rintr; 2017 st.tintr = c->tintr; 2018 st.mintr = c->mintr; 2019 st.ibytes = c->ibytes; 2020 st.ipkts = c->ipkts; 2021 st.ierrs = c->ierrs; 2022 st.obytes = c->obytes; 2023 st.opkts = c->opkts; 2024 st.oerrs = c->oerrs; 2025 if (need_header) 2026 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 2027 length += sprintf (s + length, "%7ld %7ld %7ld %8ld %7ld %7ld %8ld %7ld %7ld\n", 2028 st.rintr, st.tintr, st.mintr, st.ibytes, st.ipkts, 2029 st.ierrs, st.obytes, st.opkts, st.oerrs); 2030 return length; 2031} 2032 2033static char *format_e1_status (u_char status) 2034{ 2035 static char buf [80]; 2036 2037 if (status & E1_NOALARM) 2038 return "Ok"; 2039 buf[0] = 0; 2040 if (status & E1_LOS) strcat (buf, ",LOS"); 2041 if (status & E1_AIS) strcat (buf, ",AIS"); 2042 if (status & E1_LOF) strcat (buf, ",LOF"); 2043 if (status & E1_LOMF) strcat (buf, ",LOMF"); 2044 if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 2045 if (status & E1_AIS16) strcat (buf, ",AIS16"); 2046 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 2047 if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 2048 if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 2049 if (buf[0] == ',') 2050 return buf+1; 2051 return "Unknown"; 2052} 2053 2054static int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 2055{ 2056 int n, length = 0; 2057 2058 if (numerator < 1 || divider < 1) { 2059 length += sprintf (s+length, leftalign ? "/- " : " -"); 2060 return length; 2061 } 2062 n = (int) (0.5 + 1000.0 * numerator / divider); 2063 if (n < 1000) { 2064 length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 2065 return length; 2066 } 2067 *(s + length) = leftalign ? '/' : ' '; 2068 length ++; 2069 2070 if (n >= 1000000) n = (n+500) / 1000 * 1000; 2071 else if (n >= 100000) n = (n+50) / 100 * 100; 2072 else if (n >= 10000) n = (n+5) / 10 * 10; 2073 2074 switch (n) { 2075 case 1000: length += printf (s+length, ".999"); return length; 2076 case 10000: n = 9990; break; 2077 case 100000: n = 99900; break; 2078 case 1000000: n = 999000; break; 2079 } 2080 if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 2081 else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 2082 else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 2083 else length += sprintf (s+length, "%d", n/1000); 2084 2085 return length; 2086} 2087 2088static int print_e1_stats (char *s, ct_chan_t *c) 2089{ 2090 struct e1_counters total; 2091 u_long totsec; 2092 int length = 0; 2093 2094 totsec = c->totsec + c->cursec; 2095 total.bpv = c->total.bpv + c->currnt.bpv; 2096 total.fse = c->total.fse + c->currnt.fse; 2097 total.crce = c->total.crce + c->currnt.crce; 2098 total.rcrce = c->total.rcrce + c->currnt.rcrce; 2099 total.uas = c->total.uas + c->currnt.uas; 2100 total.les = c->total.les + c->currnt.les; 2101 total.es = c->total.es + c->currnt.es; 2102 total.bes = c->total.bes + c->currnt.bes; 2103 total.ses = c->total.ses + c->currnt.ses; 2104 total.oofs = c->total.oofs + c->currnt.oofs; 2105 total.css = c->total.css + c->currnt.css; 2106 total.dm = c->total.dm + c->currnt.dm; 2107 2108 length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 2109 2110 /* Unavailable seconds, degraded minutes */ 2111 length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 2112 length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 2113 2114 /* Bipolar violations, frame sync errors */ 2115 length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 2116 length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 2117 2118 /* CRC errors, remote CRC errors (E-bit) */ 2119 length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 2120 length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 2121 2122 /* Errored seconds, line errored seconds */ 2123 length += print_frac (s + length, 0, c->currnt.es, c->cursec); 2124 length += print_frac (s + length, 1, c->currnt.les, c->cursec); 2125 2126 /* Severely errored seconds, burst errored seconds */ 2127 length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 2128 length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 2129 2130 /* Out of frame seconds, controlled slip seconds */ 2131 length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 2132 length += print_frac (s + length, 1, c->currnt.css, c->cursec); 2133 2134 length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 2135 2136 /* Print total statistics. */ 2137 length += print_frac (s + length, 0, total.uas, totsec); 2138 length += print_frac (s + length, 1, 60 * total.dm, totsec); 2139 2140 length += print_frac (s + length, 0, total.bpv, totsec); 2141 length += print_frac (s + length, 1, total.fse, totsec); 2142 2143 length += print_frac (s + length, 0, total.crce, totsec); 2144 length += print_frac (s + length, 1, total.rcrce, totsec); 2145 2146 length += print_frac (s + length, 0, total.es, totsec); 2147 length += print_frac (s + length, 1, total.les, totsec); 2148 2149 length += print_frac (s + length, 0, total.ses, totsec); 2150 length += print_frac (s + length, 1, total.bes, totsec); 2151 2152 length += print_frac (s + length, 0, total.oofs, totsec); 2153 length += print_frac (s + length, 1, total.css, totsec); 2154 2155 length += sprintf (s + length, " -- Total\n"); 2156 return length; 2157} 2158 2159static int print_chan (char *s, ct_chan_t *c) 2160{ 2161 drv_t *d = c->sys; 2162 int length = 0; 2163 2164 length += sprintf (s + length, "ct%d", c->board->num * NCHAN + c->num); 2165 if (d->chan->debug) 2166 length += sprintf (s + length, " debug=%d", d->chan->debug); 2167 2168 switch (ct_get_config (c->board)) { 2169 case CFG_A: length += sprintf (s + length, " cfg=A"); break; 2170 case CFG_B: length += sprintf (s + length, " cfg=B"); break; 2171 case CFG_C: length += sprintf (s + length, " cfg=C"); break; 2172 default: length += sprintf (s + length, " cfg=unknown"); break; 2173 } 2174 2175 if (ct_get_baud (c)) 2176 length += sprintf (s + length, " %ld", ct_get_baud (c)); 2177 else 2178 length += sprintf (s + length, " extclock"); 2179 2180 if (c->mode == M_E1 || c->mode == M_G703) 2181 switch (ct_get_clk(c)) { 2182 case GCLK_INT : length += sprintf (s + length, " syn=int"); break; 2183 case GCLK_RCV : length += sprintf (s + length, " syn=rcv"); break; 2184 case GCLK_RCLKO : length += sprintf (s + length, " syn=xrcv"); break; 2185 } 2186 if (c->mode == M_HDLC) { 2187 length += sprintf (s + length, " dpll=%s", ct_get_dpll (c) ? "on" : "off"); 2188 length += sprintf (s + length, " nrzi=%s", ct_get_nrzi (c) ? "on" : "off"); 2189 length += sprintf (s + length, " invtclk=%s", ct_get_invtxc (c) ? "on" : "off"); 2190 length += sprintf (s + length, " invrclk=%s", ct_get_invrxc (c) ? "on" : "off"); 2191 } 2192 if (c->mode == M_E1) 2193 length += sprintf (s + length, " higain=%s", ct_get_higain (c)? "on" : "off"); 2194 2195 length += sprintf (s + length, " loop=%s", ct_get_loop (c) ? "on" : "off"); 2196 2197 if (c->mode == M_E1) 2198 length += sprintf (s + length, " ts=%s", format_timeslots (ct_get_ts(c))); 2199 if (c->mode == M_E1 && ct_get_config (c->board) != CFG_A) 2200 length += sprintf (s + length, " pass=%s", format_timeslots (ct_get_subchan(c->board))); 2201 if (c->mode == M_G703) { 2202 int lq, x; 2203 2204 x = splimp (); 2205 lq = ct_get_lq (c); 2206 splx (x); 2207 length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2208 } 2209 length += sprintf (s + length, "\n"); 2210 return length; 2211} 2212 2213#if __FreeBSD_version >= 500000 2214static int ng_ct_rcvmsg (node_p node, item_p item, hook_p lasthook) 2215{ 2216 drv_t *d = NG_NODE_PRIVATE (node); 2217 struct ng_mesg *msg; 2218#else 2219static int ng_ct_rcvmsg (node_p node, struct ng_mesg *msg, 2220 const char *retaddr, struct ng_mesg **rptr) 2221{ 2222 drv_t *d = node->private; 2223#endif 2224 struct ng_mesg *resp = NULL; 2225 int error = 0; 2226 2227 if (!d) 2228 return EINVAL; 2229 2230 CT_DEBUG (d, ("Rcvmsg\n")); 2231#if __FreeBSD_version >= 500000 2232 NGI_GET_MSG (item, msg); 2233#endif 2234 switch (msg->header.typecookie) { 2235 default: 2236 error = EINVAL; 2237 break; 2238 2239 case NGM_CT_COOKIE: 2240 printf ("Don't forget to implement\n"); 2241 error = EINVAL; 2242 break; 2243 2244 case NGM_GENERIC_COOKIE: 2245 switch (msg->header.cmd) { 2246 default: 2247 error = EINVAL; 2248 break; 2249 2250 case NGM_TEXT_STATUS: { 2251 char *s; 2252 int l = 0; 2253 int dl = sizeof (struct ng_mesg) + 730; 2254 2255#if __FreeBSD_version >= 500000 2256 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2257 if (! resp) { 2258 error = ENOMEM; 2259 break; 2260 } 2261#else 2262 MALLOC (resp, struct ng_mesg *, dl, 2263 M_NETGRAPH, M_NOWAIT); 2264 if (! resp) { 2265 error = ENOMEM; 2266 break; 2267 } 2268 bzero (resp, dl); 2269#endif 2270 s = (resp)->data; 2271 l += print_chan (s + l, d->chan); 2272 l += print_stats (s + l, d->chan, 1); 2273 l += print_modems (s + l, d->chan, 1); 2274 l += print_e1_stats (s + l, d->chan); 2275#if __FreeBSD_version < 500000 2276 (resp)->header.version = NG_VERSION; 2277 (resp)->header.arglen = strlen (s) + 1; 2278 (resp)->header.token = msg->header.token; 2279 (resp)->header.typecookie = NGM_CT_COOKIE; 2280 (resp)->header.cmd = msg->header.cmd; 2281#endif 2282 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 2283 } 2284 break; 2285 } 2286 break; 2287 } 2288#if __FreeBSD_version >= 500000 2289 NG_RESPOND_MSG (error, node, item, resp); 2290 NG_FREE_MSG (msg); 2291#else 2292 *rptr = resp; 2293 FREE (msg, M_NETGRAPH); 2294#endif 2295 return error; 2296} 2297 2298#if __FreeBSD_version >= 500000 2299static int ng_ct_rcvdata (hook_p hook, item_p item) 2300{ 2301 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2302 struct mbuf *m; 2303 meta_p meta; 2304#else 2305static int ng_ct_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) 2306{ 2307 drv_t *d = hook->node->private; 2308#endif 2309 struct ifqueue *q; 2310 int s; 2311 2312 if (!d) 2313 return ENETDOWN; 2314 2315#if __FreeBSD_version >= 500000 2316 NGI_GET_M (item, m); 2317 NGI_GET_META (item, meta); 2318 NG_FREE_ITEM (item); 2319 if (! NG_HOOK_PRIVATE (hook) || ! d) { 2320 NG_FREE_M (m); 2321 NG_FREE_META (meta); 2322#else 2323 if (! hook->private || ! d) { 2324 NG_FREE_DATA (m,meta); 2325#endif 2326 return ENETDOWN; 2327 } 2328 q = (meta && meta->priority > 0) ? &d->hi_queue : &d->queue; 2329 s = splimp (); 2330#if __FreeBSD_version >= 500000 2331 IF_LOCK (q); 2332 if (_IF_QFULL (q)) { 2333 _IF_DROP (q); 2334 IF_UNLOCK (q); 2335 splx (s); 2336 NG_FREE_M (m); 2337 NG_FREE_META (meta); 2338 return ENOBUFS; 2339 } 2340 _IF_ENQUEUE (q, m); 2341 IF_UNLOCK (q); 2342#else 2343 if (IF_QFULL (q)) { 2344 IF_DROP (q); 2345 splx (s); 2346 NG_FREE_DATA (m, meta); 2347 return ENOBUFS; 2348 } 2349 IF_ENQUEUE (q, m); 2350#endif 2351 ct_start (d); 2352 splx (s); 2353 return 0; 2354} 2355 2356static int ng_ct_rmnode (node_p node) 2357{ 2358#if __FreeBSD_version >= 500000 2359 drv_t *d = NG_NODE_PRIVATE (node); 2360 2361 CT_DEBUG (d, ("Rmnode\n")); 2362 if (d && d->running) { 2363 int s = splimp (); 2364 ct_down (d); 2365 splx (s); 2366 } 2367#ifdef KLD_MODULE 2368 if (node->nd_flags & NG_REALLY_DIE) { 2369 NG_NODE_SET_PRIVATE (node, NULL); 2370 NG_NODE_UNREF (node); 2371 } 2372 node->nd_flags &= ~NG_INVALID; 2373#endif 2374#else /* __FreeBSD_version < 500000 */ 2375 drv_t *d = node->private; 2376 int s; 2377 2378 if (!d) 2379 return 0; 2380 2381 s = splimp (); 2382 ct_down (d); 2383 splx (s); 2384 node->flags |= NG_INVALID; 2385 ng_cutlinks (node); 2386#ifdef KLD_MODULE 2387 ng_unname (node); 2388 ng_unref (node); 2389#else 2390 node->flags &= ~NG_INVALID; 2391#endif 2392#endif 2393 return 0; 2394} 2395 2396static void ng_ct_watchdog (void *arg) 2397{ 2398 drv_t *d = arg; 2399 2400 if (!d) 2401 return; 2402 2403 if (d->timeout == 1) 2404 ct_watchdog (d); 2405 if (d->timeout) 2406 d->timeout--; 2407 d->timeout_handle = timeout (ng_ct_watchdog, d, hz); 2408} 2409 2410static int ng_ct_connect (hook_p hook) 2411{ 2412#if __FreeBSD_version >= 500000 2413 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2414#else 2415 drv_t *d = hook->node->private; 2416#endif 2417 2418 if (!d) 2419 return 0; 2420 2421 d->timeout_handle = timeout (ng_ct_watchdog, d, hz); 2422 return 0; 2423} 2424 2425static int ng_ct_disconnect (hook_p hook) 2426{ 2427#if __FreeBSD_version >= 500000 2428 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2429#else 2430 drv_t *d = hook->node->private; 2431#endif 2432 2433 if (!d) 2434 return 0; 2435 2436#if __FreeBSD_version >= 500000 2437 if (NG_HOOK_PRIVATE (hook)) 2438#else 2439 if (hook->private) 2440#endif 2441 ct_down (d); 2442 untimeout (ng_ct_watchdog, d, d->timeout_handle); 2443 return 0; 2444} 2445#endif 2446 2447#ifdef KLD_MODULE 2448#if __FreeBSD_version < 400000 2449/* 2450 * Function called when loading the driver. 2451 */ 2452static int ct_load (void) 2453{ 2454 int i; 2455 2456 for (i=0;i<NCTAU; ++i) { 2457 struct isa_device id = {-1, &ctdriver, -1, 0, -1, 0, 0, (inthand2_t *)ct_intr, i, 0, 0, 0, 0 ,0 ,1 ,0 ,0}; 2458 disable_intr(); 2459 if (!ct_probe (&id)) { 2460 enable_intr(); 2461 break; 2462 } 2463 ct_attach (&id); 2464 register_intr ((adapter [i])->irq, 0, 0, (inthand2_t*) ct_intr, 2465 &net_imask, id.id_unit); 2466 enable_intr(); 2467 } 2468 if (!i) { 2469 /* Deactivate the timeout routine. */ 2470 untimeout (ct_timeout, 0, timeout_handle); 2471 2472 return ENXIO; 2473 } 2474 return 0; 2475} 2476 2477/* 2478 * Function called when unloading the driver. 2479 */ 2480static int ct_unload (void) 2481{ 2482 int i, s; 2483 2484 /* Check if the device is busy (open). */ 2485 for (i=0; i<NCTAU*NCHAN; ++i) { 2486 drv_t *d = channel[i]; 2487 2488 if (!d) 2489 continue; 2490 if (d->running) 2491 return EBUSY; 2492 } 2493 2494 /* OK to unload the driver, unregister the interrupt first. */ 2495 s = splimp (); 2496 2497 /* Deactivate the timeout routine. */ 2498 for (i=0; i<NCTAU; ++i) { 2499 if (!adapter [i]) 2500 continue; 2501 untimeout (ct_timeout, 0, timeout_handle); 2502 break; 2503 } 2504 2505 for (i=0; i<NCTAU; ++i) { 2506 ct_board_t *b = adapter [i]; 2507 2508 if (!b || ! b->port) 2509 continue; 2510 2511 ct_close_board (b); 2512 } 2513 2514 for (i=0; i<NCTAU; ++i) { 2515 ct_board_t *b = adapter [i]; 2516 2517 if (!b || ! b->port) 2518 continue; 2519 2520 if (led_timo[i].callout) 2521 untimeout (ct_led_off, b, led_timo[i]); 2522 } 2523 2524 for (i=0; i<NCTAU; ++i) { 2525 ct_board_t *b = adapter [i]; 2526 2527 if (!b || ! b->port) 2528 continue; 2529 2530 /* Disable the interrupt request. */ 2531 disable_intr(); 2532 unregister_intr (b->irq, (inthand2_t *)ct_intr); 2533 isa_dma_release (b->dma); 2534 enable_intr(); 2535 } 2536 2537 /* Detach the interfaces, free buffer memory. */ 2538 for (i=0; i<NCTAU*NCHAN; ++i) { 2539 drv_t *d = channel[i]; 2540 2541 if (!d) 2542 continue; 2543 2544#ifndef NETGRAPH 2545#if NBPFILTER > 0 2546 /* Detach from the packet filter list of interfaces. */ 2547 { 2548 struct bpf_if *q, **b = &bpf_iflist; 2549 2550 while ((q = *b)) { 2551 if (q->bif_ifp == d->pp.pp_if) { 2552 *b = q->bif_next; 2553 free (q, M_DEVBUF); 2554 } 2555 b = &(q->bif_next); 2556 } 2557 } 2558#endif /* NBPFILTER > 0 */ 2559 /* Detach from the sync PPP list. */ 2560 sppp_detach (&d->pp.pp_if); 2561 2562 /* Detach from the system list of interfaces. */ 2563 { 2564 struct ifaddr *ifa; 2565 TAILQ_FOREACH (ifa, &d->pp.pp_if.if_addrhead, ifa_link) { 2566 TAILQ_REMOVE (&d->pp.pp_if.if_addrhead, ifa, ifa_link); 2567 free (ifa, M_IFADDR); 2568 } 2569 TAILQ_REMOVE (&ifnet, &d->pp.pp_if, if_link); 2570 } 2571#endif /* !NETGRAPH */ 2572 /* Deallocate buffers. */ 2573/* free (d, M_DEVBUF);*/ 2574 } 2575 for (i=0; i<NCTAU; ++i) { 2576 ct_board_t *b = adapter [i]; 2577 if (!b) 2578 continue; 2579 adapter [i] = 0; 2580 free (b, M_DEVBUF); 2581 } 2582 splx(s); 2583 2584 return 0; 2585} 2586 2587#define devsw(a) cdevsw[major((a))] 2588#endif /* __FreeBSD_version < 400000 */ 2589#endif /* KLD_MODULE */ 2590 2591#if __FreeBSD_version < 400000 2592#ifdef KLD_MODULE 2593static int ct_modevent (module_t mod, int type, void *unused) 2594{ 2595 dev_t dev; 2596 int result; 2597 static int load_count = 0; 2598 2599 dev = makedev (CDEV_MAJOR, 0); 2600 switch (type) { 2601 case MOD_LOAD: 2602 if (devsw(dev)) 2603 return (ENXIO); 2604 load_count ++; 2605 cdevsw_add (&dev, &ct_cdevsw, NULL); 2606 timeout_handle = timeout (ct_timeout, 0, hz*5); 2607 result = ct_load (); 2608 return result; 2609 case MOD_UNLOAD: 2610 result = ct_unload (); 2611 if (result) 2612 return result; 2613 if (devsw(dev)&&!(load_count-1)) { 2614 cdevsw_add (&dev, NULL, NULL); 2615 } 2616 load_count --; 2617 return result; 2618 case MOD_SHUTDOWN: 2619 break; 2620 } 2621 return 0; 2622} 2623#endif /* KLD_MODULE */ 2624#else /* __FreeBSD_version >= 400000 */ 2625static int ct_modevent (module_t mod, int type, void *unused) 2626{ 2627 dev_t dev; 2628 static int load_count = 0; 2629 struct cdevsw *cdsw; 2630 2631#if __FreeBSD_version >= 502103 2632 dev = udev2dev (makeudev(CDEV_MAJOR, 0)); 2633#else 2634 dev = makedev (CDEV_MAJOR, 0); 2635#endif 2636 switch (type) { 2637 case MOD_LOAD: 2638 if (dev != NODEV && 2639 (cdsw = devsw (dev)) && 2640 cdsw->d_maj == CDEV_MAJOR) { 2641 printf ("Tau-ISA driver is already in system\n"); 2642 return (ENXIO); 2643 } 2644#if __FreeBSD_version >= 500000 && defined NETGRAPH 2645 if (ng_newtype (&typestruct)) 2646 printf ("Failed to register ng_ct\n"); 2647#endif 2648 ++load_count; 2649#if __FreeBSD_version <= 500000 2650 cdevsw_add (&ct_cdevsw); 2651#endif 2652 timeout_handle = timeout (ct_timeout, 0, hz*5); 2653 break; 2654 case MOD_UNLOAD: 2655 if (load_count == 1) { 2656 printf ("Removing device entry for Tau-ISA\n"); 2657#if __FreeBSD_version <= 500000 2658 cdevsw_remove (&ct_cdevsw); 2659#endif 2660#if __FreeBSD_version >= 500000 && defined NETGRAPH 2661 ng_rmtype (&typestruct); 2662#endif 2663 } 2664 if (timeout_handle.callout) 2665 untimeout (ct_timeout, 0, timeout_handle); 2666 --load_count; 2667 break; 2668 case MOD_SHUTDOWN: 2669 break; 2670 } 2671 return 0; 2672} 2673#endif /* __FreeBSD_version >= 400000 */ 2674 2675#ifdef NETGRAPH 2676static struct ng_type typestruct = { 2677 .version = NG_ABI_VERSION, 2678 .name = NG_CT_NODE_TYPE, 2679 .constructor = ng_ct_constructor, 2680 .rcvmsg = ng_ct_rcvmsg, 2681 .shutdown = ng_ct_rmnode, 2682 .newhook = ng_ct_newhook, 2683 .connect = ng_ct_connect, 2684 .rcvdata = ng_ct_rcvdata, 2685 .disconnect = ng_ct_disconnect 2686}; 2687 2688#if __FreeBSD_version < 400000 2689NETGRAPH_INIT_ORDERED (ct, &typestruct, SI_SUB_DRIVERS,\ 2690 SI_ORDER_MIDDLE + CDEV_MAJOR); 2691#endif 2692#endif /*NETGRAPH*/ 2693 2694#if __FreeBSD_version >= 500000 2695#ifdef NETGRAPH 2696MODULE_DEPEND (ng_ct, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2697#else 2698MODULE_DEPEND (ct, sppp, 1, 1, 1); 2699#endif 2700#ifdef KLD_MODULE 2701DRIVER_MODULE (ctmod, isa, ct_isa_driver, ct_devclass, ct_modevent, NULL); 2702#else 2703DRIVER_MODULE (ct, isa, ct_isa_driver, ct_devclass, ct_modevent, NULL); 2704#endif 2705#elif __FreeBSD_version >= 400000 2706#ifdef NETGRAPH 2707DRIVER_MODULE(ct, isa, ct_isa_driver, ct_devclass, ng_mod_event, &typestruct); 2708#else 2709DRIVER_MODULE(ct, isa, ct_isa_driver, ct_devclass, ct_modevent, 0); 2710#endif 2711#else /* __FreeBSD_version < 400000 */ 2712#ifdef KLD_MODULE 2713#ifndef NETGRAPH 2714static moduledata_t ctmod = { "ct", ct_modevent, }; 2715DECLARE_MODULE (ct, ctmod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR); 2716#endif /* !NETGRAPH */ 2717#else /* KLD_MODULE */ 2718 2719/* 2720 * Now for some driver initialisation. 2721 * Occurs ONCE during boot (very early). 2722 * This is if we are NOT a loadable module. 2723 */ 2724static void ct_drvinit (void *unused) 2725{ 2726 dev_t dev; 2727 2728 dev = makedev (CDEV_MAJOR, 0); 2729 cdevsw_add (&dev, &ct_cdevsw, NULL); 2730 2731 /* Activate the timeout routine. */ 2732 timeout_handle = timeout (ct_timeout, 0, hz); 2733#ifdef NETGRAPH 2734#if 0 2735 /* Register our node type in netgraph */ 2736 if (ng_newtype (&typestruct)) 2737 printf ("Failed to register ng_ct\n"); 2738#endif 2739#endif 2740} 2741 2742SYSINIT (ctdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, ct_drvinit, 0) 2743#endif /* KLD_MODULE */ 2744#endif /* __FreeBSD_version < 400000 */ 2745#endif /* NCTAU */ 2746