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.16 2003/08/12 19:49:27 martin 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.16 2003/08/12 19:49:27 martin 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 #include "bpfilter.h"
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__
152 PDEVSTATIC void ipppattach(void *);
153 PSEUDO_SET(ipppattach, i4b_isppp);
154 #else
155 PDEVSTATIC 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
164 struct 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
192 static int i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data);
193
194 #if 0
195 static void i4bisppp_send(struct ifnet *ifp);
196 #endif
197
198 static void i4bisppp_start(struct ifnet *ifp);
199
200 #if 0 /* never used ??? */
201 static void i4bisppp_timeout(void *cookie);
202 #endif
203
204 static void i4bisppp_tls(struct sppp *sp);
205 static void i4bisppp_tlf(struct sppp *sp);
206 static void i4bisppp_state_changed(struct sppp *sp, int new_state);
207 static void i4bisppp_negotiation_complete(struct sppp *sp);
208 static void i4bisppp_watchdog(struct ifnet *ifp);
209 time_t i4bisppp_idletime(void *softc);
210 static void i4bisppp_rx_data_rdy(void *softc);
211 static void i4bisppp_tx_queue_empty(void *softc);
212 static void i4bisppp_activity(void *softc, int rxtx);
213 static void i4bisppp_connect(void *softc, void *cdp);
214 static void i4bisppp_disconnect(void *softc, void *cdp);
215 static void i4bisppp_dialresponse(void *softc, int status, cause_t cause);
216 static void i4bisppp_updown(void *softc, int updown);
217 static void* i4bisppp_ret_softc(int unit);
218 static void i4bisppp_set_linktab(void *softc, isdn_link_t *ilt);
219
220 static const struct isdn_l4_driver_functions
221 ippp_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
236 static int ippp_drvr_id = -1;
237
238 enum 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 *---------------------------------------------------------------------------*/
251 PDEVSTATIC void
252 #ifdef __FreeBSD__
253 ipppattach(void *dummy)
254 #else
255 ipppattach()
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 sprintf(sc->sc_sp.pp_if.if_xname, "ippp%d", i);
275 sc->sc_unit = i;
276 #endif
277
278 sc->sc_sp.pp_if.if_mtu = PP_MTU;
279
280 #ifdef __NetBSD__
281 sc->sc_sp.pp_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT |
282 IFF_MULTICAST;
283 #else
284 sc->sc_sp.pp_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT;
285 #endif
286
287 sc->sc_sp.pp_if.if_type = IFT_ISDNBASIC;
288 sc->sc_state = ST_IDLE;
289
290 sc->sc_sp.pp_if.if_ioctl = i4bisppp_ioctl;
291
292 /* actually initialized by sppp_attach() */
293 /* sc->sc_sp.pp_if.if_output = sppp_output; */
294
295 sc->sc_sp.pp_if.if_start = i4bisppp_start;
296
297 sc->sc_sp.pp_if.if_hdrlen = 0;
298 sc->sc_sp.pp_if.if_addrlen = 0;
299 IFQ_SET_MAXLEN(&sc->sc_sp.pp_if.if_snd, IFQ_MAXLEN);
300 IFQ_SET_READY(&sc->sc_sp.pp_if.if_snd);
301
302 sc->sc_sp.pp_if.if_ipackets = 0;
303 sc->sc_sp.pp_if.if_ierrors = 0;
304 sc->sc_sp.pp_if.if_opackets = 0;
305 sc->sc_sp.pp_if.if_oerrors = 0;
306 sc->sc_sp.pp_if.if_collisions = 0;
307 sc->sc_sp.pp_if.if_ibytes = 0;
308 sc->sc_sp.pp_if.if_obytes = 0;
309 sc->sc_sp.pp_if.if_imcasts = 0;
310 sc->sc_sp.pp_if.if_omcasts = 0;
311 sc->sc_sp.pp_if.if_iqdrops = 0;
312 sc->sc_sp.pp_if.if_noproto = 0;
313
314 #if I4BISPPPACCT
315 sc->sc_sp.pp_if.if_timer = 0;
316 sc->sc_sp.pp_if.if_watchdog = i4bisppp_watchdog;
317 sc->sc_iinb = 0;
318 sc->sc_ioutb = 0;
319 sc->sc_inb = 0;
320 sc->sc_outb = 0;
321 sc->sc_linb = 0;
322 sc->sc_loutb = 0;
323 sc->sc_fn = 1;
324 #endif
325
326 sc->sc_sp.pp_tls = i4bisppp_tls;
327 sc->sc_sp.pp_tlf = i4bisppp_tlf;
328 sc->sc_sp.pp_con = i4bisppp_negotiation_complete;
329 sc->sc_sp.pp_chg = i4bisppp_state_changed;
330 sc->sc_sp.pp_framebytes = 0; /* no framing added by hardware */
331
332 #if defined(__FreeBSD_version) && ((__FreeBSD_version >= 500009) || (410000 <= __FreeBSD_version && __FreeBSD_version < 500000))
333 /* do not call bpfattach in ether_ifattach */
334 ether_ifattach(&sc->sc_sp.pp_if, 0);
335 #else
336 if_attach(&sc->sc_sp.pp_if);
337 #endif
338 #ifndef USE_ISPPP
339 sppp_attach(&sc->sc_sp.pp_if);
340 #else
341 isppp_attach(&sc->sc_sp.pp_if);
342 #endif
343
344 #if NBPFILTER > 0 || NBPF > 0
345 #ifdef __FreeBSD__
346 bpfattach(&sc->sc_sp.pp_if, DLT_PPP, PPP_HDRLEN);
347 CALLOUT_INIT(&sc->sc_ch);
348 #endif /* __FreeBSD__ */
349 #ifdef __NetBSD__
350 bpfattach(&sc->sc_sp.pp_if, DLT_PPP, sizeof(u_int));
351 #endif
352 #endif
353 }
354 }
355
356 /*---------------------------------------------------------------------------*
357 * process ioctl
358 *---------------------------------------------------------------------------*/
359 static int
360 i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data)
361 {
362 struct i4bisppp_softc *sc = ifp->if_softc;
363 int error;
364
365 #ifndef USE_ISPPP
366 error = sppp_ioctl(&sc->sc_sp.pp_if, cmd, data);
367 #else
368 error = isppp_ioctl(&sc->sc_sp.pp_if, cmd, data);
369 #endif
370 if (error)
371 return error;
372
373 switch(cmd) {
374 case SIOCSIFFLAGS:
375 #if 0 /* never used ??? */
376 x = splnet();
377 if ((ifp->if_flags & IFF_UP) == 0)
378 UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
379 splx(x);
380 #endif
381 break;
382 }
383
384 return 0;
385 }
386
387 /*---------------------------------------------------------------------------*
388 * start output to ISDN B-channel
389 *---------------------------------------------------------------------------*/
390 static void
391 i4bisppp_start(struct ifnet *ifp)
392 {
393 struct i4bisppp_softc *sc = ifp->if_softc;
394 struct mbuf *m;
395
396 #ifndef USE_ISPPP
397 if (sppp_isempty(ifp))
398 #else
399 if (isppp_isempty(ifp))
400 #endif
401 return;
402
403 if(sc->sc_state != ST_CONNECTED)
404 return;
405
406 /*
407 * s = splnet();
408 * ifp->if_flags |= IFF_OACTIVE; // - need to clear this somewhere
409 * splx(s);
410 */
411
412 #ifndef USE_ISPPP
413 while ((m = sppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
414 #else
415 while ((m = isppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
416 #endif
417 {
418
419 #if NBPFILTER > 0 || NBPF > 0
420 #ifdef __FreeBSD__
421 if (ifp->if_bpf)
422 bpf_mtap(ifp, m);
423 #endif /* __FreeBSD__ */
424
425 #ifdef __NetBSD__
426 if (ifp->if_bpf)
427 bpf_mtap(ifp->if_bpf, m);
428 #endif
429 #endif /* NBPFILTER > 0 || NBPF > 0 */
430
431 if(IF_QFULL(sc->sc_ilt->tx_queue))
432 {
433 NDBGL4(L4_ISPDBG, "%s, tx queue full!", sc->sc_sp.pp_if.if_xname);
434 m_freem(m);
435 }
436 else
437 {
438 IF_ENQUEUE(sc->sc_ilt->tx_queue, m);
439 #if 0
440 sc->sc_sp.pp_if.if_obytes += m->m_pkthdr.len;
441 #endif
442 sc->sc_outb += m->m_pkthdr.len;
443 sc->sc_sp.pp_if.if_opackets++;
444 }
445 }
446 sc->sc_ilt->bchannel_driver->bch_tx_start(sc->sc_ilt->l1token,
447 sc->sc_ilt->channel);
448 }
449
450 #ifdef I4BISPPPACCT
451 /*---------------------------------------------------------------------------*
452 * watchdog routine
453 *---------------------------------------------------------------------------*/
454 static void
455 i4bisppp_watchdog(struct ifnet *ifp)
456 {
457 struct i4bisppp_softc *sc = ifp->if_softc;
458 bchan_statistics_t bs;
459
460 (*sc->sc_ilt->bchannel_driver->bch_stat)
461 (sc->sc_ilt->l1token, sc->sc_ilt->channel, &bs);
462
463 sc->sc_ioutb += bs.outbytes;
464 sc->sc_iinb += bs.inbytes;
465
466 if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn)
467 {
468 int ri = (sc->sc_iinb - sc->sc_linb)/I4BISPPPACCTINTVL;
469 int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BISPPPACCTINTVL;
470
471 if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb))
472 sc->sc_fn = 0;
473 else
474 sc->sc_fn = 1;
475
476 sc->sc_linb = sc->sc_iinb;
477 sc->sc_loutb = sc->sc_ioutb;
478
479 if (sc->sc_cdp)
480 i4b_l4_accounting(sc->sc_cdp->cdid, ACCT_DURING,
481 sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb);
482 }
483 sc->sc_sp.pp_if.if_timer = I4BISPPPACCTINTVL;
484
485 #if 0 /* old stuff, keep it around */
486 printf(ISPPP_FMT "transmit timeout\n", ISPPP_ARG(sc));
487 i4bisppp_start(ifp);
488 #endif
489 }
490 #endif /* I4BISPPPACCT */
491
492 /*
493 *===========================================================================*
494 * SyncPPP layer interface routines
495 *===========================================================================*
496 */
497
498 /*---------------------------------------------------------------------------*
499 * PPP this-layer-started action
500 *---------------------------------------------------------------------------*
501 */
502 static void
503 i4bisppp_tls(struct sppp *sp)
504 {
505 struct i4bisppp_softc *sc = sp->pp_if.if_softc;
506
507 if(sc->sc_state == ST_CONNECTED)
508 return;
509
510 i4b_l4_dialout(ippp_drvr_id, sc->sc_unit);
511 }
512
513 /*---------------------------------------------------------------------------*
514 * PPP this-layer-finished action
515 *---------------------------------------------------------------------------*
516 */
517 static void
518 i4bisppp_tlf(struct sppp *sp)
519 {
520 struct i4bisppp_softc *sc = sp->pp_if.if_softc;
521
522 if(sc->sc_state != ST_CONNECTED)
523 return;
524
525 i4b_l4_drvrdisc(sc->sc_cdp->cdid);
526 }
527 /*---------------------------------------------------------------------------*
528 * PPP interface phase change
529 *---------------------------------------------------------------------------*
530 */
531 static void
532 i4bisppp_state_changed(struct sppp *sp, int new_state)
533 {
534 struct i4bisppp_softc *sc = sp->pp_if.if_softc;
535
536 i4b_l4_ifstate_changed(sc->sc_cdp, new_state);
537 }
538
539 /*---------------------------------------------------------------------------*
540 * PPP control protocol negotiation complete (run ip-up script now)
541 *---------------------------------------------------------------------------*
542 */
543 static void
544 i4bisppp_negotiation_complete(struct sppp *sp)
545 {
546 struct i4bisppp_softc *sc = sp->pp_if.if_softc;
547
548 i4b_l4_negcomplete(sc->sc_cdp);
549 }
550
551 /*===========================================================================*
552 * ISDN INTERFACE ROUTINES
553 *===========================================================================*/
554
555 /*---------------------------------------------------------------------------*
556 * this routine is called from L4 handler at connect time
557 *---------------------------------------------------------------------------*/
558 static void
559 i4bisppp_connect(void *softc, void *cdp)
560 {
561 struct i4bisppp_softc *sc = softc;
562 struct sppp *sp = &sc->sc_sp;
563 int s = splnet();
564
565 sc->sc_cdp = (call_desc_t *)cdp;
566 sc->sc_state = ST_CONNECTED;
567
568 #if I4BISPPPACCT
569 sc->sc_iinb = 0;
570 sc->sc_ioutb = 0;
571 sc->sc_inb = 0;
572 sc->sc_outb = 0;
573 sc->sc_linb = 0;
574 sc->sc_loutb = 0;
575 sc->sc_sp.pp_if.if_timer = I4BISPPPACCTINTVL;
576 #endif
577
578 #if 0 /* never used ??? */
579 UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
580 #endif
581
582 sp->pp_up(sp); /* tell PPP we are ready */
583 #ifndef __NetBSD__
584 sp->pp_last_sent = sp->pp_last_recv = SECOND;
585 #endif
586 splx(s);
587 }
588
589 /*---------------------------------------------------------------------------*
590 * this routine is called from L4 handler at disconnect time
591 *---------------------------------------------------------------------------*/
592 static void
593 i4bisppp_disconnect(void *softc, void *cdp)
594 {
595 call_desc_t *cd = (call_desc_t *)cdp;
596 struct i4bisppp_softc *sc = softc;
597 struct sppp *sp = &sc->sc_sp;
598
599 int s = splnet();
600
601 /* new stuff to check that the active channel is being closed */
602 if (cd != sc->sc_cdp)
603 {
604 NDBGL4(L4_ISPDBG, "%s: channel%d not active!", sp->pp_if.if_xname,
605 cd->channelid);
606 splx(s);
607 return;
608 }
609
610 #if I4BISPPPACCT
611 sc->sc_sp.pp_if.if_timer = 0;
612 #endif
613
614 i4b_l4_accounting(cd->cdid, ACCT_FINAL,
615 sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb);
616
617 if (sc->sc_state == ST_CONNECTED)
618 {
619 #if 0 /* never used ??? */
620 UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
621 #endif
622 sc->sc_cdp = (call_desc_t *)0;
623 /* do thhis here because pp_down calls i4bisppp_tlf */
624 sc->sc_state = ST_IDLE;
625 sp->pp_down(sp); /* tell PPP we have hung up */
626 }
627
628 splx(s);
629 }
630
631 /*---------------------------------------------------------------------------*
632 * this routine is used to give a feedback from userland demon
633 * in case of dial problems
634 *---------------------------------------------------------------------------*/
635 static void
636 i4bisppp_dialresponse(void *softc, int status, cause_t cause)
637 {
638 struct i4bisppp_softc *sc = softc;
639
640 NDBGL4(L4_ISPDBG, "%s: status=%d, cause=%d", sc->sc_sp.pp_if.if_xname, status, cause);
641
642 if(status != DSTAT_NONE)
643 {
644 struct mbuf *m;
645
646 NDBGL4(L4_ISPDBG, "%s: clearing queues", sc->sc_sp.pp_if.if_xname);
647
648 #ifndef USE_ISPPP
649 if(!(sppp_isempty(&sc->sc_sp.pp_if)))
650 #else
651 if(!(isppp_isempty(&sc->sc_sp.pp_if)))
652 #endif
653 {
654 #ifndef USE_ISPPP
655 while((m = sppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
656 #else
657 while((m = isppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
658 #endif
659 m_freem(m);
660 }
661 }
662 }
663
664 /*---------------------------------------------------------------------------*
665 * interface up/down
666 *---------------------------------------------------------------------------*/
667 static void
668 i4bisppp_updown(void *softc, int updown)
669 {
670 /* could probably do something useful here */
671 }
672
673 /*---------------------------------------------------------------------------*
674 * this routine is called from the HSCX interrupt handler
675 * when a new frame (mbuf) has been received and was put on
676 * the rx queue.
677 *---------------------------------------------------------------------------*/
678 static void
679 i4bisppp_rx_data_rdy(void *softc)
680 {
681 struct i4bisppp_softc *sc = softc;
682 struct mbuf *m;
683 int s;
684
685 if((m = *sc->sc_ilt->rx_mbuf) == NULL)
686 return;
687
688 m->m_pkthdr.rcvif = &sc->sc_sp.pp_if;
689 m->m_pkthdr.len = m->m_len;
690
691 sc->sc_sp.pp_if.if_ipackets++;
692
693 #if I4BISPPPACCT
694 sc->sc_inb += m->m_pkthdr.len;
695 #endif
696
697 #ifdef I4BISPPPDEBUG
698 printf("i4bisppp_rx_data_ready: received packet!\n");
699 #endif
700
701 #if NBPFILTER > 0 || NBPF > 0
702
703 #ifdef __FreeBSD__
704 if(sc->sc_sp.pp_if.if_bpf)
705 bpf_mtap(&sc->sc_sp.pp_if, m);
706 #endif /* __FreeBSD__ */
707
708 #ifdef __NetBSD__
709 if(sc->sc_sp.pp_if.if_bpf)
710 bpf_mtap(sc->sc_sp.pp_if.if_bpf, m);
711 #endif
712
713 #endif /* NBPFILTER > 0 || NBPF > 0 */
714
715 s = splnet();
716
717 #ifndef USE_ISPPP
718 sppp_input(&sc->sc_sp.pp_if, m);
719 #else
720 isppp_input(&sc->sc_sp.pp_if, m);
721 #endif
722
723 splx(s);
724 }
725
726 /*---------------------------------------------------------------------------*
727 * this routine is called from the HSCX interrupt handler
728 * when the last frame has been sent out and there is no
729 * further frame (mbuf) in the tx queue.
730 *---------------------------------------------------------------------------*/
731 static void
732 i4bisppp_tx_queue_empty(void *softc)
733 {
734 struct sppp *sp = &((struct i4bisppp_softc *)softc)->sc_sp;
735 i4bisppp_start(&sp->pp_if);
736 }
737
738 /*---------------------------------------------------------------------------*
739 * THIS should be used instead of last_active_time to implement
740 * an activity timeout mechanism.
741 *
742 * Sending back the time difference unneccessarily complicates the
743 * idletime checks in i4b_l4.c. Return the largest time instead.
744 * That way the code in i4b_l4.c needs only minimal changes.
745 *---------------------------------------------------------------------------*/
746 time_t
747 i4bisppp_idletime(void *softc)
748 {
749 struct sppp *sp = &((struct i4bisppp_softc *)softc)->sc_sp;
750
751 return sp->pp_last_activity;
752 }
753
754 /*---------------------------------------------------------------------------*
755 * this routine is called from the HSCX interrupt handler
756 * each time a packet is received or transmitted. It should
757 * be used to implement an activity timeout mechanism.
758 *---------------------------------------------------------------------------*/
759 static void
760 i4bisppp_activity(void *softc, int rxtx)
761 {
762 struct i4bisppp_softc *sc = softc;
763 sc->sc_cdp->last_active_time = SECOND;
764 }
765
766 /*---------------------------------------------------------------------------*
767 * return this drivers linktab address
768 *---------------------------------------------------------------------------*/
769 static void *
770 i4bisppp_ret_softc(int unit)
771 {
772 return &i4bisppp_softc[unit];
773 }
774
775 /*---------------------------------------------------------------------------*
776 * setup the isdn_linktab for this driver
777 *---------------------------------------------------------------------------*/
778 static void
779 i4bisppp_set_linktab(void *softc, isdn_link_t *ilt)
780 {
781 struct i4bisppp_softc *sc = softc;
782 sc->sc_ilt = ilt;
783 }
784
785 /*===========================================================================*/
Cache object: c555b8546327402d73de78d48fbe38df
|