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