2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * i4b_iframe.c - i frame handling routines
28 * ------------------------------------------
30 * $Id: i4b_iframe.c,v 1.8 2005/12/11 12:25:06 christos Exp $
34 * last edit-date: [Fri Jan 5 11:33:47 2001]
36 *---------------------------------------------------------------------------*/
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: i4b_iframe.c,v 1.6.8.1 2005/03/04 16:53:44 skrll Exp $");
48 #include <sys/param.h>
49 #include <sys/kernel.h>
50 #include <sys/systm.h>
52 #include <sys/socket.h>
55 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
56 #include <sys/callout.h>
60 #include <machine/i4b_debug.h>
61 #include <machine/i4b_ioctl.h>
62 #include <machine/i4b_trace.h>
64 #include <netisdn/i4b_debug.h>
65 #include <netisdn/i4b_ioctl.h>
66 #include <netisdn/i4b_trace.h>
69 #include <netisdn/i4b_global.h>
70 #include <netisdn/i4b_l2.h>
71 #include <netisdn/i4b_l1l2.h>
72 #include <netisdn/i4b_isdnq931.h>
73 #include <netisdn/i4b_mbuf.h>
74 #include <netisdn/i4b_l2fsm.h>
76 /*---------------------------------------------------------------------------*
78 * implements the routine "I COMMAND" Q.921 03/93 pp 68 and pp 77
79 *---------------------------------------------------------------------------*/
81 i4b_rxd_i_frame(l2_softc_t
*l2sc
, struct isdn_l3_driver
*drv
, struct mbuf
*m
)
83 u_char
*ptr
= m
->m_data
;
89 if(!((l2sc
->tei_valid
== TEI_VALID
) &&
90 (l2sc
->tei
== GETTEI(*(ptr
+OFF_TEI
)))))
96 if((l2sc
->Q921_state
!= ST_MULTIFR
) && (l2sc
->Q921_state
!= ST_TIMREC
))
99 NDBGL2(L2_I_ERR
, "ERROR, state != (MF || TR)!");
105 l2sc
->stat
.rx_i
++; /* update frame count */
107 nr
= GETINR(*(ptr
+ OFF_INR
));
108 ns
= GETINS(*(ptr
+ OFF_INS
));
109 p
= GETIP(*(ptr
+ OFF_INR
));
111 i4b_rxd_ack(l2sc
, drv
, nr
); /* last packet ack */
113 if(l2sc
->own_busy
) /* own receiver busy ? */
115 i4b_Dfreembuf(m
); /* yes, discard information */
117 if(p
== 1) /* P bit == 1 ? */
119 i4b_tx_rnr_response(l2sc
, p
); /* yes, tx RNR */
120 l2sc
->ack_pend
= 0; /* clear ACK pending */
123 else /* own receiver ready */
125 if(ns
== l2sc
->vr
) /* expected sequence number ? */
127 M128INC(l2sc
->vr
); /* yes, update */
129 l2sc
->rej_excpt
= 0; /* clr reject exception */
131 m_adj(m
, I_HDR_LEN
); /* strip i frame header */
133 l2sc
->iframe_sent
= 0; /* reset i acked already */
135 i4b_dl_data_ind(drv
, m
); /* pass data up */
137 if(!l2sc
->iframe_sent
)
139 i4b_tx_rr_response(l2sc
, p
); /* yes, tx RR */
140 l2sc
->ack_pend
= 0; /* clr ACK pending */
143 else /* ERROR, sequence number NOT expected */
145 i4b_Dfreembuf(m
); /* discard information */
147 if(l2sc
->rej_excpt
== 1) /* already exception ? */
149 if(p
== 1) /* immediate response ? */
151 i4b_tx_rr_response(l2sc
, p
); /* yes, tx RR */
152 l2sc
->ack_pend
= 0; /* clr ack pend */
155 else /* not in exception cond */
157 l2sc
->rej_excpt
= 1; /* set exception */
158 i4b_tx_rej_response(l2sc
, p
); /* tx REJ */
159 l2sc
->ack_pend
= 0; /* clr ack pending */
164 /* sequence number ranges as expected ? */
166 if(i4b_l2_nr_ok(nr
, l2sc
->va
, l2sc
->vs
))
168 if(l2sc
->Q921_state
== ST_TIMREC
)
177 if(l2sc
->peer_busy
) /* yes, other side busy ? */
179 l2sc
->va
= nr
; /* yes, update ack count */
181 else /* other side ready */
183 if(nr
== l2sc
->vs
) /* count expected ? */
185 l2sc
->va
= nr
; /* update ack */
187 i4b_T203_restart(l2sc
);
194 i4b_T200_restart(l2sc
);
201 i4b_nr_error_recovery(l2sc
); /* sequence error */
202 l2sc
->Q921_state
= ST_AW_EST
;
208 /*---------------------------------------------------------------------------*
209 * internal I FRAME QUEUED UP routine (Q.921 03/93 p 61)
210 *---------------------------------------------------------------------------*/
212 i4b_i_frame_queued_up(l2_softc_t
*l2sc
)
220 if((l2sc
->peer_busy
) || (l2sc
->vs
== ((l2sc
->va
+ MAX_K_VALUE
) & 127)))
224 NDBGL2(L2_I_MSG
, "regen IFQUP, cause: peer busy!");
227 if(l2sc
->vs
== ((l2sc
->va
+ MAX_K_VALUE
) & 127))
229 NDBGL2(L2_I_MSG
, "regen IFQUP, cause: vs=va+k!");
233 * XXX see: Q.921, page 36, 5.6.1 ".. may retransmit an I
234 * frame ...", shall we retransmit the last i frame ?
237 if(!(IF_QEMPTY(&l2sc
->i_queue
)))
239 NDBGL2(L2_I_MSG
, "re-scheduling IFQU call!");
240 START_TIMER(l2sc
->IFQU_callout
, i4b_i_frame_queued_up
, l2sc
, IFQU_DLY
);
246 IF_DEQUEUE(&l2sc
->i_queue
, m
); /* fetch next frame to tx */
250 NDBGL2(L2_I_ERR
, "ERROR, mbuf NULL after IF_DEQUEUE");
257 PUTSAPI(SAPI_CCP
, CR_CMD_TO_NT
, *(ptr
+ OFF_SAPI
));
258 PUTTEI(l2sc
->tei
, *(ptr
+ OFF_TEI
));
260 *(ptr
+ OFF_INS
) = (l2sc
->vs
<< 1) & 0xfe; /* bit 0 = 0 */
261 *(ptr
+ OFF_INR
) = (l2sc
->vr
<< 1) & 0xfe; /* P bit = 0 */
263 l2sc
->stat
.tx_i
++; /* update frame counter */
265 l2sc
->driver
->ph_data_req(l2sc
->l1_token
, m
, MBUF_DONTFREE
); /* free'd when ack'd ! */
267 l2sc
->iframe_sent
= 1; /* in case we ack an I frame with another I frame */
269 if(l2sc
->ua_num
!= UA_EMPTY
) /* failsafe */
271 NDBGL2(L2_I_ERR
, "ERROR, l2sc->ua_num: %d != UA_EMPTY", l2sc
->ua_num
);
272 i4b_print_l2var(l2sc
);
273 i4b_Dfreembuf(l2sc
->ua_frame
);
276 l2sc
->ua_frame
= m
; /* save unacked frame */
277 l2sc
->ua_num
= l2sc
->vs
; /* save frame number */
285 if(l2sc
->T200
== TIMER_IDLE
)
288 i4b_T200_start(l2sc
);
292 #endif /* NI4BQ921 > 0 */