Add __DragonFly__
[dragonfly.git] / sys / net / i4b / layer2 / i4b_iframe.c
1 /*
2  * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b_iframe.c - i frame handling routines
28  *      ------------------------------------------
29  *
30  *      $Id: i4b_iframe.c,v 1.25 2000/08/24 11:48:57 hm Exp $ 
31  *
32  * $FreeBSD: src/sys/i4b/layer2/i4b_iframe.c,v 1.6.2.1 2001/08/10 14:08:41 obrien Exp $
33  * $DragonFly: src/sys/net/i4b/layer2/i4b_iframe.c,v 1.4 2004/02/13 17:45:50 joerg Exp $
34  *
35  *      last edit-date: [Thu Aug 24 12:49:18 2000]
36  *
37  *---------------------------------------------------------------------------*/
38
39 #if defined(__DragonFly__) || defined(__FreeBSD__)
40 #include "use_i4bq921.h"
41 #else
42 #define NI4BQ921        1
43 #endif
44 #if NI4BQ921 > 0
45
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/systm.h>
49 #include <sys/mbuf.h>
50 #include <sys/socket.h>
51 #include <net/if.h>
52
53 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
54 #include <sys/callout.h>
55 #endif
56
57 #if defined(__DragonFly__) || defined(__FreeBSD__)
58 #include <net/i4b/include/machine/i4b_debug.h>
59 #include <net/i4b/include/machine/i4b_trace.h>
60 #else
61 #include <i4b/i4b_debug.h>
62 #include <i4b/i4b_ioctl.h>
63 #include <i4b/i4b_trace.h>
64 #endif
65
66 #include "../include/i4b_global.h"
67 #include "../include/i4b_l1l2.h"
68 #include "../include/i4b_l2l3.h"
69 #include "../include/i4b_mbuf.h"
70
71 #include "i4b_l2.h"
72 #include "i4b_l2fsm.h"
73
74 /*---------------------------------------------------------------------------*
75  *      process i frame
76  *      implements the routine "I COMMAND" Q.921 03/93 pp 68 and pp 77
77  *---------------------------------------------------------------------------*/
78 void
79 i4b_rxd_i_frame(int unit, struct mbuf *m)
80 {
81         l2_softc_t *l2sc = &l2_softc[unit];
82         u_char *ptr = m->m_data;
83         int nr;
84         int ns;
85         int p;
86         CRIT_VAR;
87         
88         if(!((l2sc->tei_valid == TEI_VALID) &&
89              (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))))
90         {
91                 i4b_Dfreembuf(m);
92                 return;
93         }
94
95         if((l2sc->Q921_state != ST_MULTIFR) && (l2sc->Q921_state != ST_TIMREC))
96         {
97                 i4b_Dfreembuf(m);
98                 NDBGL2(L2_I_ERR, "ERROR, state != (MF || TR)!");
99                 return;
100         }
101
102         CRIT_BEG;
103
104         l2sc->stat.rx_i++;              /* update frame count */
105         
106         nr = GETINR(*(ptr + OFF_INR));
107         ns = GETINS(*(ptr + OFF_INS));
108         p = GETIP(*(ptr + OFF_INR));
109         
110         i4b_rxd_ack(l2sc, nr);          /* last packet ack */
111
112         if(l2sc->own_busy)              /* own receiver busy ? */
113         {       
114                 i4b_Dfreembuf(m);       /* yes, discard information */
115
116                 if(p == 1)              /* P bit == 1 ? */
117                 {
118                         i4b_tx_rnr_response(l2sc, p); /* yes, tx RNR */
119                         l2sc->ack_pend = 0;     /* clear ACK pending */
120                 }
121         }
122         else    /* own receiver ready */
123         {
124                 if(ns == l2sc->vr)      /* expected sequence number ? */
125                 {
126                         M128INC(l2sc->vr);      /* yes, update */
127                         
128                         l2sc->rej_excpt = 0;    /* clr reject exception */
129
130                         m_adj(m, I_HDR_LEN);    /* strip i frame header */
131
132                         l2sc->iframe_sent = 0;  /* reset i acked already */
133
134                         DL_Data_Ind(l2sc->unit, m);     /* pass data up */
135
136                         if(!l2sc->iframe_sent)
137                         {
138                                 i4b_tx_rr_response(l2sc, p); /* yes, tx RR */
139                                 l2sc->ack_pend = 0;     /* clr ACK pending */
140                         }
141                 }
142                 else    /* ERROR, sequence number NOT expected */
143                 {
144                         i4b_Dfreembuf(m);       /* discard information */
145
146                         if(l2sc->rej_excpt == 1)  /* already exception ? */
147                         {
148                                 if(p == 1)      /* immediate response ? */
149                                 {
150                                         i4b_tx_rr_response(l2sc, p); /* yes, tx RR */
151                                         l2sc->ack_pend = 0; /* clr ack pend */
152                                 }
153                         }
154                         else    /* not in exception cond */
155                         {
156                                 l2sc->rej_excpt = 1;    /* set exception */
157                                 i4b_tx_rej_response(l2sc, p);   /* tx REJ */
158                                 l2sc->ack_pend = 0;     /* clr ack pending */
159                         }
160                 }
161         }
162
163         /* sequence number ranges as expected ? */
164         
165         if(i4b_l2_nr_ok(nr, l2sc->va, l2sc->vs))
166         {
167                 if(l2sc->Q921_state == ST_TIMREC)
168                 {
169                         l2sc->va = nr;
170
171                         CRIT_END;
172
173                         return;
174                 }
175
176                 if(l2sc->peer_busy)     /* yes, other side busy ? */
177                 {
178                         l2sc->va = nr;  /* yes, update ack count */
179                 }
180                 else    /* other side ready */
181                 {
182                         if(nr == l2sc->vs)      /* count expected ? */
183                         {
184                                 l2sc->va = nr;  /* update ack */
185                                 i4b_T200_stop(l2sc);
186                                 i4b_T203_restart(l2sc);
187                         }
188                         else
189                         {
190                                 if(nr != l2sc->va)
191                                 {
192                                         l2sc->va = nr;
193                                         i4b_T200_restart(l2sc);
194                                 }
195                         }
196                 }
197         }
198         else
199         {
200                 i4b_nr_error_recovery(l2sc);    /* sequence error */
201                 l2sc->Q921_state = ST_AW_EST; 
202         }
203
204         CRIT_END;
205 }
206
207 /*---------------------------------------------------------------------------*
208  *      internal I FRAME QUEUED UP routine (Q.921 03/93 p 61)
209  *---------------------------------------------------------------------------*/
210 void
211 i4b_i_frame_queued_up(l2_softc_t *l2sc)
212 {
213         struct mbuf *m;
214         u_char *ptr;
215         CRIT_VAR;
216
217         CRIT_BEG;
218         
219         if((l2sc->peer_busy) || (l2sc->vs == ((l2sc->va + MAX_K_VALUE) & 127)))
220         {
221                 if(l2sc->peer_busy)
222                 {
223                         NDBGL2(L2_I_MSG, "regen IFQUP, cause: peer busy!");
224                 }
225
226                 if(l2sc->vs == ((l2sc->va + MAX_K_VALUE) & 127))
227                 {
228                         NDBGL2(L2_I_MSG, "regen IFQUP, cause: vs=va+k!");
229                 }       
230
231                 /*
232                  * XXX see: Q.921, page 36, 5.6.1 ".. may retransmit an I
233                  * frame ...", shall we retransmit the last i frame ?
234                  */
235
236                 if(!(IF_QEMPTY(&l2sc->i_queue)))
237                 {
238                         NDBGL2(L2_I_MSG, "re-scheduling IFQU call!");
239                         START_TIMER(l2sc->IFQU_callout, i4b_i_frame_queued_up, l2sc, IFQU_DLY);
240                 }
241                 CRIT_END;
242                 return;
243         }
244
245         IF_DEQUEUE(&l2sc->i_queue, m);    /* fetch next frame to tx */
246
247         if(!m)
248         {
249                 NDBGL2(L2_I_ERR, "ERROR, mbuf NULL after IF_DEQUEUE");
250                 CRIT_END;
251                 return;
252         }
253
254         ptr = m->m_data;
255         
256         PUTSAPI(SAPI_CCP, CR_CMD_TO_NT, *(ptr + OFF_SAPI));
257         PUTTEI(l2sc->tei, *(ptr + OFF_TEI));
258
259         *(ptr + OFF_INS) = (l2sc->vs << 1) & 0xfe; /* bit 0 = 0 */
260         *(ptr + OFF_INR) = (l2sc->vr << 1) & 0xfe; /* P bit = 0 */
261
262         l2sc->stat.tx_i++;      /* update frame counter */
263         
264         PH_Data_Req(l2sc->unit, m, MBUF_DONTFREE); /* free'd when ack'd ! */
265
266         l2sc->iframe_sent = 1;          /* in case we ack an I frame with another I frame */
267         
268         if(l2sc->ua_num != UA_EMPTY)    /* failsafe */
269         {
270                 NDBGL2(L2_I_ERR, "ERROR, l2sc->ua_num: %d != UA_EMPTY", l2sc->ua_num);
271                 i4b_print_l2var(l2sc);
272                 i4b_Dfreembuf(l2sc->ua_frame);
273         }
274
275         l2sc->ua_frame = m;             /* save unacked frame */
276         l2sc->ua_num = l2sc->vs;        /* save frame number */
277
278         M128INC(l2sc->vs);
279         
280         l2sc->ack_pend = 0;
281
282         CRIT_END;
283
284         if(l2sc->T200 == TIMER_IDLE)
285         {
286                 i4b_T203_stop(l2sc);
287                 i4b_T200_start(l2sc);
288         }
289 }
290  
291 #endif /* NI4BQ921 > 0 */