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.1 2003/04/06 04:37:48 tg 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 #include "ippp.h"
49 
50 #include <sys/param.h>
51 /*
52  * XXX - sys/param.h on alpha (indirectly) includes sys/signal.h, which
53  *	 defines sc_sp - interfering with our use of this identifier.
54  *	 Just undef it for now.
55  */
56 #undef sc_sp
57 
58 #include <sys/systm.h>
59 #include <sys/mbuf.h>
60 #include <sys/socket.h>
61 #include <sys/errno.h>
62 #include <sys/ioccom.h>
63 #include <sys/sockio.h>
64 #include <sys/kernel.h>
65 #include <sys/protosw.h>
66 #include <sys/timeout.h>
67 #include <net/if.h>
68 #include <net/if_types.h>
69 #include <net/netisr.h>
70 #include <net/route.h>
71 
72 #include <netinet/in.h>
73 #include <netinet/in_systm.h>
74 #include <netinet/in_var.h>
75 #include <netinet/ip.h>
76 
77 #include <net/slcompress.h>
78 
79 #include <net/if_sppp.h>
80 
81 #include "bpfilter.h"
82 #if NBPFILTER > 0 || NBPF > 0
83 #include <sys/time.h>
84 #include <net/bpf.h>
85 #endif
86 
87 #include <netisdn/i4b_ioctl.h>
88 #include <netisdn/i4b_cause.h>
89 #include <netisdn/i4b_debug.h>
90 #include <netisdn/i4b_global.h>
91 #include <netisdn/i4b_mbuf.h>
92 #include <netisdn/i4b_l3l4.h>
93 #include <netisdn/i4b_l4.h>
94 
95 #define	ISPPP_FMT	"%s: "
96 #define	ISPPP_ARG(sc)	((sc)->sc_sp.pp_if.if_xname)
97 #define	PDEVSTATIC	/* not static */
98 #define IOCTL_CMD_T	u_long
99 
100 PDEVSTATIC void ipppattach(void);
101 
102 #define I4BISPPPACCT		1	/* enable accounting messages */
103 #define	I4BISPPPACCTINTVL	2	/* accounting msg interval in secs */
104 #define I4BISPPPDISCDEBUG	1
105 
106 #define PPP_HDRLEN   		4	/* 4 octetts PPP header length	*/
107 
108 struct i4bisppp_softc {
109 	struct sppp sc_sp;	/* we are derived from struct sppp */
110 
111 	int	sc_state;	/* state of the interface	*/
112 
113 	int	sc_unit;	/* unit number for Net/OpenBSD	*/
114 
115 	call_desc_t *sc_cdp;	/* ptr to call descriptor	*/
116 	isdn_link_t *sc_ilt;	/* B channel driver and state	*/
117 
118 #ifdef I4BISPPPACCT
119 	int sc_iinb;		/* isdn driver # of inbytes	*/
120 	int sc_ioutb;		/* isdn driver # of outbytes	*/
121 	int sc_inb;		/* # of bytes rx'd		*/
122 	int sc_outb;		/* # of bytes tx'd	 	*/
123 	int sc_linb;		/* last # of bytes rx'd		*/
124 	int sc_loutb;		/* last # of bytes tx'd 	*/
125 	int sc_fn;		/* flag, first null acct	*/
126 #endif
127 
128 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
129 	struct callout_handle sc_ch;
130 #endif
131 
132 } i4bisppp_softc[NIPPP];
133 
134 static int	i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data);
135 
136 #if 0
137 static void	i4bisppp_send(struct ifnet *ifp);
138 #endif
139 
140 static void	i4bisppp_start(struct ifnet *ifp);
141 
142 #if 0 /* never used ??? */
143 static void	i4bisppp_timeout(void *cookie);
144 #endif
145 
146 static void	i4bisppp_tls(struct sppp *sp);
147 static void	i4bisppp_tlf(struct sppp *sp);
148 static void	i4bisppp_state_changed(struct sppp *sp, int new_state);
149 static void	i4bisppp_negotiation_complete(struct sppp *sp);
150 static void	i4bisppp_watchdog(struct ifnet *ifp);
151 time_t   	i4bisppp_idletime(void *softc);
152 static void	i4bisppp_rx_data_rdy(void *softc);
153 static void	i4bisppp_tx_queue_empty(void *softc);
154 static void	i4bisppp_activity(void *softc, int rxtx);
155 static void	i4bisppp_connect(void *softc, void *cdp);
156 static void	i4bisppp_disconnect(void *softc, void *cdp);
157 static void	i4bisppp_dialresponse(void *softc, int status, cause_t cause);
158 static void	i4bisppp_updown(void *softc, int updown);
159 static void*	i4bisppp_ret_softc(int unit);
160 static void	i4bisppp_set_linktab(void *softc, isdn_link_t *ilt);
161 
162 static const struct isdn_l4_driver_functions
163 ippp_l4_functions = {
164 	/* L4<->B-channel functions */
165 	i4bisppp_rx_data_rdy,
166 	i4bisppp_tx_queue_empty,
167 	i4bisppp_activity,
168 	i4bisppp_connect,
169 	i4bisppp_disconnect,
170 	i4bisppp_dialresponse,
171 	i4bisppp_updown,
172 	/* Management functions */
173 	i4bisppp_ret_softc,
174 	i4bisppp_set_linktab,
175 	i4bisppp_idletime
176 };
177 
178 static int ippp_drvr_id = -1;
179 
180 enum i4bisppp_states {
181 	ST_IDLE,			/* initialized, ready, idle	*/
182 	ST_DIALING,			/* dialling out to remote	*/
183 	ST_CONNECTED,			/* connected to remote		*/
184 };
185 
186 /*===========================================================================*
187  *			DEVICE DRIVER ROUTINES
188  *===========================================================================*/
189 
190 /*---------------------------------------------------------------------------*
191  *	interface attach routine at kernel boot time
192  *---------------------------------------------------------------------------*/
193 PDEVSTATIC void
194 #ifdef __FreeBSD__
ipppattach(void * dummy)195 ipppattach(void *dummy)
196 #else
197 ipppattach()
198 #endif
199 {
200 	struct i4bisppp_softc *sc = i4bisppp_softc;
201 	int i;
202 
203 	ippp_drvr_id = isdn_l4_driver_attach("ippp", NIPPP, &ippp_l4_functions);
204 
205 	for(i = 0; i < NIPPP; sc++, i++) {
206 		sc->sc_sp.pp_if.if_softc = sc;
207 		sc->sc_ilt = NULL;
208 
209 		snprintf(sc->sc_sp.pp_if.if_xname,
210 		    sizeof sc->sc_sp.pp_if.if_xname, "ippp%d", i);
211 		sc->sc_unit = i;
212 
213 		sc->sc_sp.pp_if.if_mtu = PP_MTU;
214 
215 		sc->sc_sp.pp_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT;
216 
217 		sc->sc_sp.pp_if.if_type = IFT_ISDNBASIC;
218 		sc->sc_state = ST_IDLE;
219 
220 		sc->sc_sp.pp_if.if_ioctl = i4bisppp_ioctl;
221 
222 		/* actually initialized by sppp_attach() */
223 		/* sc->sc_sp.pp_if.if_output = sppp_output; */
224 
225 		sc->sc_sp.pp_if.if_start = i4bisppp_start;
226 
227 		sc->sc_sp.pp_if.if_hdrlen = 0;
228 		sc->sc_sp.pp_if.if_addrlen = 0;
229 		IFQ_SET_MAXLEN(&sc->sc_sp.pp_if.if_snd, IFQ_MAXLEN);
230 		IFQ_SET_READY(&sc->sc_sp.pp_if.if_snd);
231 
232 		sc->sc_sp.pp_if.if_ipackets = 0;
233 		sc->sc_sp.pp_if.if_ierrors = 0;
234 		sc->sc_sp.pp_if.if_opackets = 0;
235 		sc->sc_sp.pp_if.if_oerrors = 0;
236 		sc->sc_sp.pp_if.if_collisions = 0;
237 		sc->sc_sp.pp_if.if_ibytes = 0;
238 		sc->sc_sp.pp_if.if_obytes = 0;
239 		sc->sc_sp.pp_if.if_imcasts = 0;
240 		sc->sc_sp.pp_if.if_omcasts = 0;
241 		sc->sc_sp.pp_if.if_iqdrops = 0;
242 		sc->sc_sp.pp_if.if_noproto = 0;
243 
244 #if I4BISPPPACCT
245 		sc->sc_sp.pp_if.if_timer = 0;
246 		sc->sc_sp.pp_if.if_watchdog = i4bisppp_watchdog;
247 		sc->sc_iinb = 0;
248 		sc->sc_ioutb = 0;
249 		sc->sc_inb = 0;
250 		sc->sc_outb = 0;
251 		sc->sc_linb = 0;
252 		sc->sc_loutb = 0;
253 		sc->sc_fn = 1;
254 #endif
255 
256 		sc->sc_sp.pp_tls = i4bisppp_tls;
257 		sc->sc_sp.pp_tlf = i4bisppp_tlf;
258 		sc->sc_sp.pp_con = i4bisppp_negotiation_complete;
259 		sc->sc_sp.pp_chg = i4bisppp_state_changed;
260 		sc->sc_sp.pp_framebytes = 0;	/* no framing added by hardware */
261 
262 		if_attach(&sc->sc_sp.pp_if);
263 #ifndef USE_ISPPP
264 		sppp_attach(&sc->sc_sp.pp_if);
265 #else
266 		isppp_attach(&sc->sc_sp.pp_if);
267 #endif
268 	}
269 }
270 
271 /*---------------------------------------------------------------------------*
272  *	process ioctl
273  *---------------------------------------------------------------------------*/
274 static int
i4bisppp_ioctl(struct ifnet * ifp,IOCTL_CMD_T cmd,caddr_t data)275 i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data)
276 {
277 	struct i4bisppp_softc *sc = ifp->if_softc;
278 	int error;
279 
280 #ifndef USE_ISPPP
281 	error = sppp_ioctl(&sc->sc_sp.pp_if, cmd, data);
282 #else
283 	error = isppp_ioctl(&sc->sc_sp.pp_if, cmd, data);
284 #endif
285 	if (error)
286 		return error;
287 
288 	switch(cmd) {
289 	case SIOCSIFFLAGS:
290 #if 0 /* never used ??? */
291 		x = splnet();
292 		if ((ifp->if_flags & IFF_UP) == 0)
293 			UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
294 		splx(x);
295 #endif
296 		break;
297 	}
298 
299 	return 0;
300 }
301 
302 /*---------------------------------------------------------------------------*
303  *	start output to ISDN B-channel
304  *---------------------------------------------------------------------------*/
305 static void
i4bisppp_start(struct ifnet * ifp)306 i4bisppp_start(struct ifnet *ifp)
307 {
308 	struct i4bisppp_softc *sc = ifp->if_softc;
309 	struct mbuf *m;
310 
311 #ifndef USE_ISPPP
312 	if (sppp_isempty(ifp))
313 #else
314 	if (isppp_isempty(ifp))
315 #endif
316 		return;
317 
318 	if(sc->sc_state != ST_CONNECTED)
319 		return;
320 
321 	/*
322 	 * s = splnet();
323 	 * ifp->if_flags |= IFF_OACTIVE; // - need to clear this somewhere
324 	 * splx(s);
325 	 */
326 
327 #ifndef USE_ISPPP
328 	while ((m = sppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
329 #else
330 	while ((m = isppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
331 #endif
332 	{
333 
334 #if NBPFILTER > 0 || NBPF > 0
335 		if (ifp->if_bpf)
336 			bpf_mtap(ifp->if_bpf, m);
337 #endif /* NBPFILTER > 0 || NBPF > 0 */
338 
339 		if(IF_QFULL(sc->sc_ilt->tx_queue))
340 		{
341 			NDBGL4(L4_ISPDBG, "%s, tx queue full!", sc->sc_sp.pp_if.if_xname);
342 			m_freem(m);
343 		}
344 		else
345 		{
346 			IF_ENQUEUE(sc->sc_ilt->tx_queue, m);
347 #if 0
348 			sc->sc_sp.pp_if.if_obytes += m->m_pkthdr.len;
349 #endif
350 			sc->sc_outb += m->m_pkthdr.len;
351 			sc->sc_sp.pp_if.if_opackets++;
352 		}
353 	}
354 	sc->sc_ilt->bchannel_driver->bch_tx_start(sc->sc_ilt->l1token,
355 	    sc->sc_ilt->channel);
356 }
357 
358 #ifdef I4BISPPPACCT
359 /*---------------------------------------------------------------------------*
360  *	watchdog routine
361  *---------------------------------------------------------------------------*/
362 static void
i4bisppp_watchdog(struct ifnet * ifp)363 i4bisppp_watchdog(struct ifnet *ifp)
364 {
365 	struct i4bisppp_softc *sc = ifp->if_softc;
366 	bchan_statistics_t bs;
367 
368 	(*sc->sc_ilt->bchannel_driver->bch_stat)
369 		(sc->sc_ilt->l1token, sc->sc_ilt->channel, &bs);
370 
371 	sc->sc_ioutb += bs.outbytes;
372 	sc->sc_iinb += bs.inbytes;
373 
374 	if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn)
375 	{
376 		int ri = (sc->sc_iinb - sc->sc_linb)/I4BISPPPACCTINTVL;
377 		int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BISPPPACCTINTVL;
378 
379 		if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb))
380 			sc->sc_fn = 0;
381 		else
382 			sc->sc_fn = 1;
383 
384 		sc->sc_linb = sc->sc_iinb;
385 		sc->sc_loutb = sc->sc_ioutb;
386 
387 		if (sc->sc_cdp)
388 			i4b_l4_accounting(sc->sc_cdp->cdid, ACCT_DURING,
389 			    sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb);
390  	}
391 	sc->sc_sp.pp_if.if_timer = I4BISPPPACCTINTVL;
392 
393 #if 0 /* old stuff, keep it around */
394 	printf(ISPPP_FMT "transmit timeout\n", ISPPP_ARG(sc));
395 	i4bisppp_start(ifp);
396 #endif
397 }
398 #endif /* I4BISPPPACCT */
399 
400 /*
401  *===========================================================================*
402  *			SyncPPP layer interface routines
403  *===========================================================================*
404  */
405 
406 /*---------------------------------------------------------------------------*
407  *	PPP this-layer-started action
408  *---------------------------------------------------------------------------*
409  */
410 static void
i4bisppp_tls(struct sppp * sp)411 i4bisppp_tls(struct sppp *sp)
412 {
413 	struct i4bisppp_softc *sc = sp->pp_if.if_softc;
414 
415 	if(sc->sc_state == ST_CONNECTED)
416 		return;
417 
418 	i4b_l4_dialout(ippp_drvr_id, sc->sc_unit);
419 }
420 
421 /*---------------------------------------------------------------------------*
422  *	PPP this-layer-finished action
423  *---------------------------------------------------------------------------*
424  */
425 static void
i4bisppp_tlf(struct sppp * sp)426 i4bisppp_tlf(struct sppp *sp)
427 {
428 	struct i4bisppp_softc *sc = sp->pp_if.if_softc;
429 
430 	if(sc->sc_state != ST_CONNECTED)
431 		return;
432 
433 	i4b_l4_drvrdisc(sc->sc_cdp->cdid);
434 }
435 /*---------------------------------------------------------------------------*
436  *	PPP interface phase change
437  *---------------------------------------------------------------------------*
438  */
439 static void
i4bisppp_state_changed(struct sppp * sp,int new_state)440 i4bisppp_state_changed(struct sppp *sp, int new_state)
441 {
442 	struct i4bisppp_softc *sc = sp->pp_if.if_softc;
443 
444 	i4b_l4_ifstate_changed(sc->sc_cdp, new_state);
445 }
446 
447 /*---------------------------------------------------------------------------*
448  *	PPP control protocol negotiation complete (run ip-up script now)
449  *---------------------------------------------------------------------------*
450  */
451 static void
i4bisppp_negotiation_complete(struct sppp * sp)452 i4bisppp_negotiation_complete(struct sppp *sp)
453 {
454 	struct i4bisppp_softc *sc = sp->pp_if.if_softc;
455 
456 	i4b_l4_negcomplete(sc->sc_cdp);
457 }
458 
459 /*===========================================================================*
460  *			ISDN INTERFACE ROUTINES
461  *===========================================================================*/
462 
463 /*---------------------------------------------------------------------------*
464  *	this routine is called from L4 handler at connect time
465  *---------------------------------------------------------------------------*/
466 static void
i4bisppp_connect(void * softc,void * cdp)467 i4bisppp_connect(void *softc, void *cdp)
468 {
469 	struct i4bisppp_softc *sc = softc;
470 	struct sppp *sp = &sc->sc_sp;
471 	int s = splnet();
472 
473 	sc->sc_cdp = (call_desc_t *)cdp;
474 	sc->sc_state = ST_CONNECTED;
475 
476 #if I4BISPPPACCT
477 	sc->sc_iinb = 0;
478 	sc->sc_ioutb = 0;
479 	sc->sc_inb = 0;
480 	sc->sc_outb = 0;
481 	sc->sc_linb = 0;
482 	sc->sc_loutb = 0;
483 	sc->sc_sp.pp_if.if_timer = I4BISPPPACCTINTVL;
484 #endif
485 
486 #if 0 /* never used ??? */
487 	UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
488 #endif
489 
490 	sp->pp_up(sp);		/* tell PPP we are ready */
491 #ifndef __NetBSD__
492 	sp->pp_last_sent = sp->pp_last_recv = SECOND;
493 #endif
494 	splx(s);
495 }
496 
497 /*---------------------------------------------------------------------------*
498  *	this routine is called from L4 handler at disconnect time
499  *---------------------------------------------------------------------------*/
500 static void
i4bisppp_disconnect(void * softc,void * cdp)501 i4bisppp_disconnect(void *softc, void *cdp)
502 {
503 	call_desc_t *cd = (call_desc_t *)cdp;
504 	struct i4bisppp_softc *sc = softc;
505 	struct sppp *sp = &sc->sc_sp;
506 
507 	int s = splnet();
508 
509 	/* new stuff to check that the active channel is being closed */
510 	if (cd != sc->sc_cdp)
511 	{
512 		NDBGL4(L4_ISPDBG, "%s: channel%d not active!", sp->pp_if.if_xname,
513 		    cd->channelid);
514 		splx(s);
515 		return;
516 	}
517 
518 #if I4BISPPPACCT
519 	sc->sc_sp.pp_if.if_timer = 0;
520 #endif
521 
522 	i4b_l4_accounting(cd->cdid, ACCT_FINAL,
523 		 sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb);
524 
525 	if (sc->sc_state == ST_CONNECTED)
526 	{
527 #if 0 /* never used ??? */
528 		UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
529 #endif
530 		sc->sc_cdp = (call_desc_t *)0;
531 		/* do thhis here because pp_down calls i4bisppp_tlf */
532 		sc->sc_state = ST_IDLE;
533 		sp->pp_down(sp);	/* tell PPP we have hung up */
534 	}
535 
536 	splx(s);
537 }
538 
539 /*---------------------------------------------------------------------------*
540  *	this routine is used to give a feedback from userland demon
541  *	in case of dial problems
542  *---------------------------------------------------------------------------*/
543 static void
i4bisppp_dialresponse(void * softc,int status,cause_t cause)544 i4bisppp_dialresponse(void *softc, int status, cause_t cause)
545 {
546 	struct i4bisppp_softc *sc = softc;
547 
548 	NDBGL4(L4_ISPDBG, "%s: status=%d, cause=%d", sc->sc_sp.pp_if.if_xname, status, cause);
549 
550 	if(status != DSTAT_NONE)
551 	{
552 		struct mbuf *m;
553 
554 		NDBGL4(L4_ISPDBG, "%s: clearing queues", sc->sc_sp.pp_if.if_xname);
555 
556 #ifndef USE_ISPPP
557 		if(!(sppp_isempty(&sc->sc_sp.pp_if)))
558 #else
559 		if(!(isppp_isempty(&sc->sc_sp.pp_if)))
560 #endif
561 		{
562 #ifndef USE_ISPPP
563 			while((m = sppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
564 #else
565 			while((m = isppp_dequeue(&sc->sc_sp.pp_if)) != NULL)
566 #endif
567 				m_freem(m);
568 		}
569 	}
570 }
571 
572 /*---------------------------------------------------------------------------*
573  *	interface up/down
574  *---------------------------------------------------------------------------*/
575 static void
i4bisppp_updown(void * softc,int updown)576 i4bisppp_updown(void *softc, int updown)
577 {
578 	/* could probably do something useful here */
579 }
580 
581 /*---------------------------------------------------------------------------*
582  *	this routine is called from the HSCX interrupt handler
583  *	when a new frame (mbuf) has been received and was put on
584  *	the rx queue.
585  *---------------------------------------------------------------------------*/
586 static void
i4bisppp_rx_data_rdy(void * softc)587 i4bisppp_rx_data_rdy(void *softc)
588 {
589 	struct i4bisppp_softc *sc = softc;
590 	struct mbuf *m;
591 	int s;
592 
593 	if((m = *sc->sc_ilt->rx_mbuf) == NULL)
594 		return;
595 
596 	m->m_pkthdr.rcvif = &sc->sc_sp.pp_if;
597 	m->m_pkthdr.len = m->m_len;
598 
599 	sc->sc_sp.pp_if.if_ipackets++;
600 
601 #if I4BISPPPACCT
602 	sc->sc_inb += m->m_pkthdr.len;
603 #endif
604 
605 #ifdef I4BISPPPDEBUG
606 	printf("i4bisppp_rx_data_ready: received packet!\n");
607 #endif
608 
609 #if NBPFILTER > 0 || NBPF > 0
610 
611 #ifdef __FreeBSD__
612 	if(sc->sc_sp.pp_if.if_bpf)
613 		bpf_mtap(&sc->sc_sp.pp_if, m);
614 #endif /* __FreeBSD__ */
615 
616 #ifdef __NetBSD__
617 	if(sc->sc_sp.pp_if.if_bpf)
618 		bpf_mtap(sc->sc_sp.pp_if.if_bpf, m);
619 #endif
620 
621 #endif /* NBPFILTER > 0  || NBPF > 0 */
622 
623 	s = splnet();
624 
625 #ifndef USE_ISPPP
626 	sppp_input(&sc->sc_sp.pp_if, m);
627 #else
628 	isppp_input(&sc->sc_sp.pp_if, m);
629 #endif
630 
631 	splx(s);
632 }
633 
634 /*---------------------------------------------------------------------------*
635  *	this routine is called from the HSCX interrupt handler
636  *	when the last frame has been sent out and there is no
637  *	further frame (mbuf) in the tx queue.
638  *---------------------------------------------------------------------------*/
639 static void
i4bisppp_tx_queue_empty(void * softc)640 i4bisppp_tx_queue_empty(void *softc)
641 {
642 	struct sppp *sp = &((struct i4bisppp_softc *)softc)->sc_sp;
643 	i4bisppp_start(&sp->pp_if);
644 }
645 
646 /*---------------------------------------------------------------------------*
647  *	THIS should be used instead of last_active_time to implement
648  *	an activity timeout mechanism.
649  *
650  *	Sending back the time difference unneccessarily complicates the
651  *	idletime checks in i4b_l4.c. Return the largest time instead.
652  *	That way the code in i4b_l4.c needs only minimal changes.
653  *---------------------------------------------------------------------------*/
654 time_t
i4bisppp_idletime(void * softc)655 i4bisppp_idletime(void *softc)
656 {
657 	struct sppp *sp = &((struct i4bisppp_softc *)softc)->sc_sp;
658 
659 	return sp->pp_last_activity;
660 }
661 
662 /*---------------------------------------------------------------------------*
663  *	this routine is called from the HSCX interrupt handler
664  *	each time a packet is received or transmitted. It should
665  *	be used to implement an activity timeout mechanism.
666  *---------------------------------------------------------------------------*/
667 static void
i4bisppp_activity(void * softc,int rxtx)668 i4bisppp_activity(void *softc, int rxtx)
669 {
670 	struct i4bisppp_softc *sc = softc;
671 	sc->sc_cdp->last_active_time = SECOND;
672 }
673 
674 /*---------------------------------------------------------------------------*
675  *	return this drivers linktab address
676  *---------------------------------------------------------------------------*/
677 static void *
i4bisppp_ret_softc(int unit)678 i4bisppp_ret_softc(int unit)
679 {
680 	return &i4bisppp_softc[unit];
681 }
682 
683 /*---------------------------------------------------------------------------*
684  *	setup the isdn_linktab for this driver
685  *---------------------------------------------------------------------------*/
686 static void
i4bisppp_set_linktab(void * softc,isdn_link_t * ilt)687 i4bisppp_set_linktab(void *softc, isdn_link_t *ilt)
688 {
689 	struct i4bisppp_softc *sc = softc;
690 	sc->sc_ilt = ilt;
691 }
692 
693 /*===========================================================================*/
694