1/* 2 * Copyright (c) 1997 Joerg Wunsch. All rights reserved. 3 * 4 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 *--------------------------------------------------------------------------- 29 * 30 * i4b_isppp.c - isdn4bsd kernel SyncPPP driver 31 * -------------------------------------------- 32 * 33 * Uses Serge Vakulenko's sppp backend (originally contributed with 34 * the "cx" driver for Cronyx's HDLC-in-hardware device). This driver 35 * is only the glue between sppp and i4b. 36 * 37 * $Id: i4b_isppp.c,v 1.27 2010/04/05 07:22:50 joerg Exp $ 38 * 39 * $FreeBSD$ 40 * 41 * last edit-date: [Fri Jan 5 11:33:47 2001] 42 * 43 *---------------------------------------------------------------------------*/ 44 45#include <sys/cdefs.h> 46__KERNEL_RCSID(0, "$NetBSD: i4b_isppp.c,v 1.26 2010/01/19 22:08:17 pooka Exp $"); 47 48#ifndef __NetBSD__ 49#define USE_ISPPP 50#endif 51#include "ippp.h" 52 53#ifndef USE_ISPPP 54 55#ifdef __FreeBSD__ 56#include "sppp.h" 57#endif 58 59#ifndef __NetBSD__ 60#if NI4BISPPP == 0 61# error "You need to define `pseudo-device sppp <N>' with options ISPPP" 62#endif 63#endif 64 65#endif 66 67#include <sys/param.h> 68/* 69 * XXX - sys/param.h on alpha (indirectly) includes sys/signal.h, which 70 * defines sc_sp - interfering with our use of this identifier. 71 * Just undef it for now. 72 */ 73#undef sc_sp 74 75#include <sys/systm.h> 76#include <sys/mbuf.h> 77#include <sys/socket.h> 78#include <sys/errno.h> 79#include <sys/ioccom.h> 80#include <sys/sockio.h> 81#include <sys/kernel.h> 82#include <sys/protosw.h> 83#include <sys/callout.h> 84 85#include <net/if.h> 86#include <net/if_types.h> 87#include <net/netisr.h> 88#include <net/route.h> 89 90#include <netinet/in.h> 91#include <netinet/in_systm.h> 92#include <netinet/in_var.h> 93#include <netinet/ip.h> 94 95#include <net/slcompress.h> 96 97#include <net/if_spppvar.h> 98 99#if defined(__FreeBSD_version) && __FreeBSD_version >= 400008 100#include "bpf.h" 101#else 102#define NBPFILTER 1 103#endif 104#if NBPFILTER > 0 || NBPF > 0 105#include <sys/time.h> 106#include <net/bpf.h> 107#endif 108 109#ifdef __FreeBSD__ 110#include <machine/i4b_ioctl.h> 111#include <machine/i4b_cause.h> 112#include <machine/i4b_debug.h> 113#else 114#include <netisdn/i4b_ioctl.h> 115#include <netisdn/i4b_cause.h> 116#include <netisdn/i4b_debug.h> 117#endif 118 119#include <netisdn/i4b_global.h> 120#include <netisdn/i4b_mbuf.h> 121#include <netisdn/i4b_l3l4.h> 122 123#include <netisdn/i4b_l4.h> 124 125#ifdef __FreeBSD__ 126#define ISPPP_FMT "ippp%d: " 127#define ISPPP_ARG(sc) ((sc)->sc_if.if_unit) 128#define PDEVSTATIC static 129 130# if __FreeBSD_version >= 300001 131# define CALLOUT_INIT(chan) callout_handle_init(chan) 132# define TIMEOUT(fun, arg, chan, tick) chan = timeout(fun, arg, tick) 133# define UNTIMEOUT(fun, arg, chan) untimeout(fun, arg, chan) 134# define IOCTL_CMD_T u_long 135# else 136# define CALLOUT_INIT(chan) do {} while(0) 137# define TIMEOUT(fun, arg, chan, tick) timeout(fun, arg, tick) 138# define UNTIMEOUT(fun, arg, chan) untimeout(fun, arg) 139# define IOCTL_CMD_T int 140# endif 141 142#elif defined __NetBSD__ || defined __OpenBSD__ 143#define ISPPP_FMT "%s: " 144#define ISPPP_ARG(sc) ((sc)->sc_sp.pp_if.if_xname) 145#define PDEVSTATIC /* not static */ 146#define IOCTL_CMD_T u_long 147#else 148# error "What system are you using?" 149#endif 150 151#ifdef __FreeBSD__ 152PDEVSTATIC void ipppattach(void *); 153PSEUDO_SET(ipppattach, i4b_isppp); 154#else 155PDEVSTATIC void ipppattach(void); 156#endif 157 158#define I4BISPPPACCT 1 /* enable accounting messages */ 159#define I4BISPPPACCTINTVL 2 /* accounting msg interval in secs */ 160#define I4BISPPPDISCDEBUG 1 161 162#define PPP_HDRLEN 4 /* 4 octetts PPP header length */ 163 164struct i4bisppp_softc { 165 struct sppp sc_sp; /* we are derived from struct sppp */ 166 167 int sc_state; /* state of the interface */ 168 169#ifndef __FreeBSD__ 170 int sc_unit; /* unit number for Net/OpenBSD */ 171#endif 172 173 call_desc_t *sc_cdp; /* ptr to call descriptor */ 174 isdn_link_t *sc_ilt; /* B channel driver and state */ 175 176#ifdef I4BISPPPACCT 177 int sc_iinb; /* isdn driver # of inbytes */ 178 int sc_ioutb; /* isdn driver # of outbytes */ 179 int sc_inb; /* # of bytes rx'd */ 180 int sc_outb; /* # of bytes tx'd */ 181 int sc_linb; /* last # of bytes rx'd */ 182 int sc_loutb; /* last # of bytes tx'd */ 183 int sc_fn; /* flag, first null acct */ 184#endif 185 186#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 187 struct callout_handle sc_ch; 188#endif 189 190} i4bisppp_softc[NIPPP]; 191 192static int i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data); 193 194#if 0 195static void i4bisppp_send(struct ifnet *ifp); 196#endif 197 198static void i4bisppp_start(struct ifnet *ifp); 199 200#if 0 /* never used ??? */ 201static void i4bisppp_timeout(void *cookie); 202#endif 203 204static void i4bisppp_tls(struct sppp *sp); 205static void i4bisppp_tlf(struct sppp *sp); 206static void i4bisppp_state_changed(struct sppp *sp, int new_state); 207static void i4bisppp_negotiation_complete(struct sppp *sp); 208static void i4bisppp_watchdog(struct ifnet *ifp); 209time_t i4bisppp_idletime(void *softc); 210static void i4bisppp_rx_data_rdy(void *softc); 211static void i4bisppp_tx_queue_empty(void *softc); 212static void i4bisppp_activity(void *softc, int rxtx); 213static void i4bisppp_connect(void *softc, void *cdp); 214static void i4bisppp_disconnect(void *softc, void *cdp); 215static void i4bisppp_dialresponse(void *softc, int status, cause_t cause); 216static void i4bisppp_updown(void *softc, int updown); 217static void* i4bisppp_ret_softc(int unit); 218static void i4bisppp_set_linktab(void *softc, isdn_link_t *ilt); 219 220static const struct isdn_l4_driver_functions 221ippp_l4_functions = { 222 /* L4<->B-channel functions */ 223 i4bisppp_rx_data_rdy, 224 i4bisppp_tx_queue_empty, 225 i4bisppp_activity, 226 i4bisppp_connect, 227 i4bisppp_disconnect, 228 i4bisppp_dialresponse, 229 i4bisppp_updown, 230 /* Management functions */ 231 i4bisppp_ret_softc, 232 i4bisppp_set_linktab, 233 i4bisppp_idletime 234}; 235 236static int ippp_drvr_id = -1; 237 238enum i4bisppp_states { 239 ST_IDLE, /* initialized, ready, idle */ 240 ST_DIALING, /* dialling out to remote */ 241 ST_CONNECTED, /* connected to remote */ 242}; 243 244/*===========================================================================* 245 * DEVICE DRIVER ROUTINES 246 *===========================================================================*/ 247 248/*---------------------------------------------------------------------------* 249 * interface attach routine at kernel boot time 250 *---------------------------------------------------------------------------*/ 251PDEVSTATIC void 252#ifdef __FreeBSD__ 253ipppattach(void *dummy) 254#else 255ipppattach(void) 256#endif 257{ 258 struct i4bisppp_softc *sc = i4bisppp_softc; 259 int i; 260 261 ippp_drvr_id = isdn_l4_driver_attach("ippp", NIPPP, &ippp_l4_functions); 262 263 for(i = 0; i < NIPPP; sc++, i++) { 264 sc->sc_sp.pp_if.if_softc = sc; 265 sc->sc_ilt = NULL; 266 267#ifdef __FreeBSD__ 268 sc->sc_sp.pp_if.if_name = "ippp"; 269#if defined(__FreeBSD_version) && __FreeBSD_version < 300001 270 sc->sc_sp.pp_if.if_next = NULL; 271#endif 272 sc->sc_sp.pp_if.if_unit = i; 273#else 274 snprintf(sc->sc_sp.pp_if.if_xname, 275 sizeof(sc->sc_sp.pp_if.if_xname), "ippp%d", i); 276 sc->sc_unit = i; 277#endif 278 279 sc->sc_sp.pp_if.if_mtu = PP_MTU; 280 281#ifdef __NetBSD__ 282 sc->sc_sp.pp_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | 283 IFF_MULTICAST; 284#else 285 sc->sc_sp.pp_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT; 286#endif 287 288 sc->sc_sp.pp_if.if_type = IFT_ISDNBASIC; 289 sc->sc_state = ST_IDLE; 290 291 sc->sc_sp.pp_if.if_ioctl = i4bisppp_ioctl; 292 293 /* actually initialized by sppp_attach() */ 294 /* sc->sc_sp.pp_if.if_output = sppp_output; */ 295 296 sc->sc_sp.pp_if.if_start = i4bisppp_start; 297 298 sc->sc_sp.pp_if.if_hdrlen = 0; 299 sc->sc_sp.pp_if.if_addrlen = 0; 300 IFQ_SET_MAXLEN(&sc->sc_sp.pp_if.if_snd, IFQ_MAXLEN); 301 IFQ_SET_READY(&sc->sc_sp.pp_if.if_snd); 302 303 sc->sc_sp.pp_if.if_ipackets = 0; 304 sc->sc_sp.pp_if.if_ierrors = 0; 305 sc->sc_sp.pp_if.if_opackets = 0; 306 sc->sc_sp.pp_if.if_oerrors = 0; 307 sc->sc_sp.pp_if.if_collisions = 0; 308 sc->sc_sp.pp_if.if_ibytes = 0; 309 sc->sc_sp.pp_if.if_obytes = 0; 310 sc->sc_sp.pp_if.if_imcasts = 0; 311 sc->sc_sp.pp_if.if_omcasts = 0; 312 sc->sc_sp.pp_if.if_iqdrops = 0; 313 sc->sc_sp.pp_if.if_noproto = 0; 314 315#if I4BISPPPACCT 316 sc->sc_sp.pp_if.if_timer = 0; 317 sc->sc_sp.pp_if.if_watchdog = i4bisppp_watchdog; 318 sc->sc_iinb = 0; 319 sc->sc_ioutb = 0; 320 sc->sc_inb = 0; 321 sc->sc_outb = 0; 322 sc->sc_linb = 0; 323 sc->sc_loutb = 0; 324 sc->sc_fn = 1; 325#endif 326 327 sc->sc_sp.pp_tls = i4bisppp_tls; 328 sc->sc_sp.pp_tlf = i4bisppp_tlf; 329 sc->sc_sp.pp_con = i4bisppp_negotiation_complete; 330 sc->sc_sp.pp_chg = i4bisppp_state_changed; 331 sc->sc_sp.pp_framebytes = 0; /* no framing added by hardware */ 332 333#if defined(__FreeBSD_version) && ((__FreeBSD_version >= 500009) || (410000 <= __FreeBSD_version && __FreeBSD_version < 500000)) 334 /* do not call bpfattach in ether_ifattach */ 335 ether_ifattach(&sc->sc_sp.pp_if, 0); 336#else 337 if_attach(&sc->sc_sp.pp_if); 338#endif 339#ifndef USE_ISPPP 340 sppp_attach(&sc->sc_sp.pp_if); 341#else 342 isppp_attach(&sc->sc_sp.pp_if); 343#endif 344 345#if NBPFILTER > 0 || NBPF > 0 346#ifdef __FreeBSD__ 347 bpfattach(&sc->sc_sp.pp_if, DLT_PPP, PPP_HDRLEN); 348 CALLOUT_INIT(&sc->sc_ch); 349#endif /* __FreeBSD__ */ 350#ifdef __NetBSD__ 351 bpf_attach(&sc->sc_sp.pp_if, DLT_PPP, sizeof(u_int)); 352#endif 353#endif 354 } 355} 356 357/*---------------------------------------------------------------------------* 358 * process ioctl 359 *---------------------------------------------------------------------------*/ 360static int 361i4bisppp_ioctl(struct ifnet *ifp, unsigned long cmd, void *data) 362{ 363 struct i4bisppp_softc *sc = ifp->if_softc; 364 365#ifndef USE_ISPPP 366 return sppp_ioctl(&sc->sc_sp.pp_if, cmd, data); 367#else 368 return isppp_ioctl(&sc->sc_sp.pp_if, cmd, data); 369#endif 370} 371 372/*---------------------------------------------------------------------------* 373 * start output to ISDN B-channel 374 *---------------------------------------------------------------------------*/ 375static void 376i4bisppp_start(struct ifnet *ifp) 377{ 378 struct i4bisppp_softc *sc = ifp->if_softc; 379 struct mbuf *m; 380 381#ifndef USE_ISPPP 382 if (sppp_isempty(ifp)) 383#else 384 if (isppp_isempty(ifp)) 385#endif 386 return; 387 388 if(sc->sc_state != ST_CONNECTED) 389 return; 390 391 /* 392 * s = splnet(); 393 * ifp->if_flags |= IFF_OACTIVE; // - need to clear this somewhere 394 * splx(s); 395 */ 396 397#ifndef USE_ISPPP 398 while ((m = sppp_dequeue(&sc->sc_sp.pp_if)) != NULL) 399#else 400 while ((m = isppp_dequeue(&sc->sc_sp.pp_if)) != NULL) 401#endif 402 { 403 404#if NBPFILTER > 0 || NBPF > 0 405#ifdef __FreeBSD__ 406 if (ifp->if_bpf) 407 bpf_mtap(ifp, m); 408#endif /* __FreeBSD__ */ 409 410#ifdef __NetBSD__ 411 bpf_mtap(ifp, m); 412#endif 413#endif /* NBPFILTER > 0 || NBPF > 0 */ 414 415 if(IF_QFULL(sc->sc_ilt->tx_queue)) 416 { 417 NDBGL4(L4_ISPDBG, "%s, tx queue full!", sc->sc_sp.pp_if.if_xname); 418 m_freem(m); 419 } 420 else 421 { 422 IF_ENQUEUE(sc->sc_ilt->tx_queue, m); 423#if 0 424 sc->sc_sp.pp_if.if_obytes += m->m_pkthdr.len; 425#endif 426 sc->sc_outb += m->m_pkthdr.len; 427 sc->sc_sp.pp_if.if_opackets++; 428 } 429 } 430 sc->sc_ilt->bchannel_driver->bch_tx_start(sc->sc_ilt->l1token, 431 sc->sc_ilt->channel); 432} 433 434#ifdef I4BISPPPACCT 435/*---------------------------------------------------------------------------* 436 * watchdog routine 437 *---------------------------------------------------------------------------*/ 438static void 439i4bisppp_watchdog(struct ifnet *ifp) 440{ 441 struct i4bisppp_softc *sc = ifp->if_softc; 442 bchan_statistics_t bs; 443 444 (*sc->sc_ilt->bchannel_driver->bch_stat) 445 (sc->sc_ilt->l1token, sc->sc_ilt->channel, &bs); 446 447 sc->sc_ioutb += bs.outbytes; 448 sc->sc_iinb += bs.inbytes; 449 450 if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn) 451 { 452 int ri = (sc->sc_iinb - sc->sc_linb)/I4BISPPPACCTINTVL; 453 int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BISPPPACCTINTVL; 454 455 if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb)) 456 sc->sc_fn = 0; 457 else 458 sc->sc_fn = 1; 459 460 sc->sc_linb = sc->sc_iinb; 461 sc->sc_loutb = sc->sc_ioutb; 462 463 if (sc->sc_cdp) 464 i4b_l4_accounting(sc->sc_cdp->cdid, ACCT_DURING, 465 sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb); 466 } 467 sc->sc_sp.pp_if.if_timer = I4BISPPPACCTINTVL; 468 469#if 0 /* old stuff, keep it around */ 470 printf(ISPPP_FMT "transmit timeout\n", ISPPP_ARG(sc)); 471 i4bisppp_start(ifp); 472#endif 473} 474#endif /* I4BISPPPACCT */ 475 476/* 477 *===========================================================================* 478 * SyncPPP layer interface routines 479 *===========================================================================* 480 */ 481 482/*---------------------------------------------------------------------------* 483 * PPP this-layer-started action 484 *---------------------------------------------------------------------------* 485 */ 486static void 487i4bisppp_tls(struct sppp *sp) 488{ 489 struct i4bisppp_softc *sc = sp->pp_if.if_softc; 490 491 if(sc->sc_state == ST_CONNECTED) 492 return; 493 494 i4b_l4_dialout(ippp_drvr_id, sc->sc_unit); 495} 496 497/*---------------------------------------------------------------------------* 498 * PPP this-layer-finished action 499 *---------------------------------------------------------------------------* 500 */ 501static void 502i4bisppp_tlf(struct sppp *sp) 503{ 504 struct i4bisppp_softc *sc = sp->pp_if.if_softc; 505 506 if(sc->sc_state != ST_CONNECTED) 507 return; 508 509 i4b_l4_drvrdisc(sc->sc_cdp->cdid); 510} 511/*---------------------------------------------------------------------------* 512 * PPP interface phase change 513 *---------------------------------------------------------------------------* 514 */ 515static void 516i4bisppp_state_changed(struct sppp *sp, int new_state) 517{ 518 struct i4bisppp_softc *sc = sp->pp_if.if_softc; 519 520 i4b_l4_ifstate_changed(sc->sc_cdp, new_state); 521} 522 523/*---------------------------------------------------------------------------* 524 * PPP control protocol negotiation complete (run ip-up script now) 525 *---------------------------------------------------------------------------* 526 */ 527static void 528i4bisppp_negotiation_complete(struct sppp *sp) 529{ 530 struct i4bisppp_softc *sc = sp->pp_if.if_softc; 531 532 i4b_l4_negcomplete(sc->sc_cdp); 533} 534 535/*===========================================================================* 536 * ISDN INTERFACE ROUTINES 537 *===========================================================================*/ 538 539/*---------------------------------------------------------------------------* 540 * this routine is called from L4 handler at connect time 541 *---------------------------------------------------------------------------*/ 542static void 543i4bisppp_connect(void *softc, void *cdp) 544{ 545 struct i4bisppp_softc *sc = softc; 546 struct sppp *sp = &sc->sc_sp; 547 int s = splnet(); 548 549 sc->sc_cdp = (call_desc_t *)cdp; 550 sc->sc_state = ST_CONNECTED; 551 552#if I4BISPPPACCT 553 sc->sc_iinb = 0; 554 sc->sc_ioutb = 0; 555 sc->sc_inb = 0; 556 sc->sc_outb = 0; 557 sc->sc_linb = 0; 558 sc->sc_loutb = 0; 559 sc->sc_sp.pp_if.if_timer = I4BISPPPACCTINTVL; 560#endif 561 562#if 0 /* never used ??? */ 563 UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch); 564#endif 565 566 sp->pp_up(sp); /* tell PPP we are ready */ 567#ifndef __NetBSD__ 568 sp->pp_last_sent = sp->pp_last_recv = SECOND; 569#endif 570 splx(s); 571} 572 573/*---------------------------------------------------------------------------* 574 * this routine is called from L4 handler at disconnect time 575 *---------------------------------------------------------------------------*/ 576static void 577i4bisppp_disconnect(void *softc, void *cdp) 578{ 579 call_desc_t *cd = (call_desc_t *)cdp; 580 struct i4bisppp_softc *sc = softc; 581 struct sppp *sp = &sc->sc_sp; 582 583 int s = splnet(); 584 585 /* new stuff to check that the active channel is being closed */ 586 if (cd != sc->sc_cdp) 587 { 588 NDBGL4(L4_ISPDBG, "%s: channel%d not active!", sp->pp_if.if_xname, 589 cd->channelid); 590 splx(s); 591 return; 592 } 593 594#if I4BISPPPACCT 595 sc->sc_sp.pp_if.if_timer = 0; 596#endif 597 598 i4b_l4_accounting(cd->cdid, ACCT_FINAL, 599 sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb); 600 601 if (sc->sc_state == ST_CONNECTED) 602 { 603#if 0 /* never used ??? */ 604 UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch); 605#endif 606 sc->sc_cdp = (call_desc_t *)0; 607 /* do thhis here because pp_down calls i4bisppp_tlf */ 608 sc->sc_state = ST_IDLE; 609 sp->pp_down(sp); /* tell PPP we have hung up */ 610 } 611 612 splx(s); 613} 614 615/*---------------------------------------------------------------------------* 616 * this routine is used to give a feedback from userland demon 617 * in case of dial problems 618 *---------------------------------------------------------------------------*/ 619static void 620i4bisppp_dialresponse(void *softc, int status, cause_t cause) 621{ 622 struct i4bisppp_softc *sc = softc; 623 624 NDBGL4(L4_ISPDBG, "%s: status=%d, cause=%d", sc->sc_sp.pp_if.if_xname, status, cause); 625 626 if(status != DSTAT_NONE) 627 { 628 struct mbuf *m; 629 630 NDBGL4(L4_ISPDBG, "%s: clearing queues", sc->sc_sp.pp_if.if_xname); 631 632#ifndef USE_ISPPP 633 if(!(sppp_isempty(&sc->sc_sp.pp_if))) 634#else 635 if(!(isppp_isempty(&sc->sc_sp.pp_if))) 636#endif 637 { 638#ifndef USE_ISPPP 639 while((m = sppp_dequeue(&sc->sc_sp.pp_if)) != NULL) 640#else 641 while((m = isppp_dequeue(&sc->sc_sp.pp_if)) != NULL) 642#endif 643 m_freem(m); 644 } 645 } 646} 647 648/*---------------------------------------------------------------------------* 649 * interface up/down 650 *---------------------------------------------------------------------------*/ 651static void 652i4bisppp_updown(void *softc, int updown) 653{ 654 (void)softc; 655 (void)updown; 656 /* could probably do something useful here */ 657} 658 659/*---------------------------------------------------------------------------* 660 * this routine is called from the HSCX interrupt handler 661 * when a new frame (mbuf) has been received and was put on 662 * the rx queue. 663 *---------------------------------------------------------------------------*/ 664static void 665i4bisppp_rx_data_rdy(void *softc) 666{ 667 struct i4bisppp_softc *sc = softc; 668 struct mbuf *m; 669 int s; 670 671 if((m = *sc->sc_ilt->rx_mbuf) == NULL) 672 return; 673 674 m->m_pkthdr.rcvif = &sc->sc_sp.pp_if; 675 m->m_pkthdr.len = m->m_len; 676 677 sc->sc_sp.pp_if.if_ipackets++; 678 679#if I4BISPPPACCT 680 sc->sc_inb += m->m_pkthdr.len; 681#endif 682 683#ifdef I4BISPPPDEBUG 684 printf("i4bisppp_rx_data_ready: received packet!\n"); 685#endif 686 687#if NBPFILTER > 0 || NBPF > 0 688 689#ifdef __FreeBSD__ 690 if(sc->sc_sp.pp_if.if_bpf) 691 bpf_mtap(&sc->sc_sp.pp_if, m); 692#endif /* __FreeBSD__ */ 693 694#ifdef __NetBSD__ 695 bpf_mtap(&sc->sc_sp.pp_if, m); 696#endif 697 698#endif /* NBPFILTER > 0 || NBPF > 0 */ 699 700 s = splnet(); 701 702#ifndef USE_ISPPP 703 sppp_input(&sc->sc_sp.pp_if, m); 704#else 705 isppp_input(&sc->sc_sp.pp_if, m); 706#endif 707 708 splx(s); 709} 710 711/*---------------------------------------------------------------------------* 712 * this routine is called from the HSCX interrupt handler 713 * when the last frame has been sent out and there is no 714 * further frame (mbuf) in the tx queue. 715 *---------------------------------------------------------------------------*/ 716static void 717i4bisppp_tx_queue_empty(void *softc) 718{ 719 struct sppp *sp = &((struct i4bisppp_softc *)softc)->sc_sp; 720 i4bisppp_start(&sp->pp_if); 721} 722 723/*---------------------------------------------------------------------------* 724 * THIS should be used instead of last_active_time to implement 725 * an activity timeout mechanism. 726 * 727 * Sending back the time difference unneccessarily complicates the 728 * idletime checks in i4b_l4.c. Return the largest time instead. 729 * That way the code in i4b_l4.c needs only minimal changes. 730 *---------------------------------------------------------------------------*/ 731time_t 732i4bisppp_idletime(void *softc) 733{ 734 struct sppp *sp = &((struct i4bisppp_softc *)softc)->sc_sp; 735 736 return sp->pp_last_activity; 737} 738 739/*---------------------------------------------------------------------------* 740 * this routine is called from the HSCX interrupt handler 741 * each time a packet is received or transmitted. It should 742 * be used to implement an activity timeout mechanism. 743 *---------------------------------------------------------------------------*/ 744static void 745i4bisppp_activity(void *softc, int rxtx) 746{ 747 struct i4bisppp_softc *sc = softc; 748 sc->sc_cdp->last_active_time = SECOND; 749} 750 751/*---------------------------------------------------------------------------* 752 * return this drivers linktab address 753 *---------------------------------------------------------------------------*/ 754static void * 755i4bisppp_ret_softc(int unit) 756{ 757 return &i4bisppp_softc[unit]; 758} 759 760/*---------------------------------------------------------------------------* 761 * setup the isdn_linktab for this driver 762 *---------------------------------------------------------------------------*/ 763static void 764i4bisppp_set_linktab(void *softc, isdn_link_t *ilt) 765{ 766 struct i4bisppp_softc *sc = softc; 767 sc->sc_ilt = ilt; 768} 769 770/*===========================================================================*/ 771