Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / net / i4b / layer2 / i4b_util.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_util.c - layer 2 utility routines
28  *      -------------------------------------
29  *
30  *      $Id: i4b_util.c,v 1.26 2000/08/24 11:48:58 hm Exp $ 
31  *
32  * $FreeBSD: src/sys/i4b/layer2/i4b_util.c,v 1.6.2.1 2001/08/10 14:08:41 obrien Exp $
33  *
34  *      last edit-date: [Mon May 29 16:55:35 2000]
35  *
36  *---------------------------------------------------------------------------*/
37
38 #ifdef __FreeBSD__
39 #include "i4bq921.h"
40 #else
41 #define NI4BQ921        1
42 #endif
43 #if NI4BQ921 > 0
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/mbuf.h>
48 #include <sys/socket.h>
49 #include <net/if.h>
50
51 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
52 #include <sys/callout.h>
53 #endif
54
55 #ifdef __FreeBSD__
56 #include <machine/i4b_debug.h>
57 #else
58 #include <i4b/i4b_debug.h>
59 #include <i4b/i4b_ioctl.h>
60 #endif
61
62 #include <i4b/include/i4b_global.h>
63 #include <i4b/include/i4b_l1l2.h>
64 #include <i4b/include/i4b_mbuf.h>
65
66 #include <i4b/layer2/i4b_l2.h>
67
68 /*---------------------------------------------------------------------------*
69  *      routine ESTABLISH DATA LINK (Q.921 03/93 page 83)
70  *---------------------------------------------------------------------------*/
71 void
72 i4b_establish_data_link(l2_softc_t *l2sc)
73 {
74         i4b_l1_activate(l2sc);  
75
76         i4b_clear_exception_conditions(l2sc);
77
78         l2sc->RC = 0;
79
80         i4b_tx_sabme(l2sc, P1);
81
82         i4b_T200_restart(l2sc);
83
84         i4b_T203_stop(l2sc);    
85 }
86
87 /*---------------------------------------------------------------------------*
88  *      routine CLEAR EXCEPTION CONDITIONS (Q.921 03/93 page 83)
89  *---------------------------------------------------------------------------*/
90 void
91 i4b_clear_exception_conditions(l2_softc_t *l2sc)
92 {
93         CRIT_VAR;
94
95         CRIT_BEG;
96         
97 /*XXX -------------------------------------------------------------- */
98 /*XXX is this really appropriate here or should it moved elsewhere ? */
99
100         i4b_Dcleanifq(&l2sc->i_queue);
101         
102         if(l2sc->ua_num != UA_EMPTY)
103         {
104                 i4b_Dfreembuf(l2sc->ua_frame);
105                 l2sc->ua_num = UA_EMPTY;
106         }
107 /*XXX -------------------------------------------------------------- */
108
109         l2sc->peer_busy = 0;
110
111         l2sc->rej_excpt = 0;
112
113         l2sc->own_busy = 0;
114
115         l2sc->ack_pend = 0;     
116
117         CRIT_END;       
118 }
119
120 /*---------------------------------------------------------------------------*
121  *      routine TRANSMIT ENQUIRE (Q.921 03/93 page 83)
122  *---------------------------------------------------------------------------*/
123 void
124 i4b_transmit_enquire(l2_softc_t *l2sc)
125 {
126         if(l2sc->own_busy)
127                 i4b_tx_rnr_command(l2sc, P1);
128         else
129                 i4b_tx_rr_command(l2sc, P1);
130
131         l2sc->ack_pend = 0;
132
133         i4b_T200_start(l2sc);
134 }
135
136 /*---------------------------------------------------------------------------*
137  *      routine NR ERROR RECOVERY (Q.921 03/93 page 83)
138  *---------------------------------------------------------------------------*/
139 void
140 i4b_nr_error_recovery(l2_softc_t *l2sc)
141 {
142         i4b_mdl_error_ind(l2sc, "i4b_nr_error_recovery", MDL_ERR_J);
143
144         i4b_establish_data_link(l2sc);
145         
146         l2sc->l3initiated = 0;
147 }
148
149 /*---------------------------------------------------------------------------*
150  *      routine ENQUIRY RESPONSE (Q.921 03/93 page 84)
151  *---------------------------------------------------------------------------*/
152 void
153 i4b_enquiry_response(l2_softc_t *l2sc)
154 {
155         if(l2sc->own_busy)
156                 i4b_tx_rnr_response(l2sc, F1);
157         else
158                 i4b_tx_rr_response(l2sc, F1);
159
160         l2sc->ack_pend = 0;
161 }
162
163 /*---------------------------------------------------------------------------*
164  *      routine INVOKE RETRANSMISSION (Q.921 03/93 page 84)
165  *---------------------------------------------------------------------------*/
166 void
167 i4b_invoke_retransmission(l2_softc_t *l2sc, int nr)
168 {
169         CRIT_VAR;
170
171         CRIT_BEG;
172
173         NDBGL2(L2_ERROR, "nr = %d", nr );
174         
175         while(l2sc->vs != nr)
176         {
177                 NDBGL2(L2_ERROR, "nr(%d) != vs(%d)", nr, l2sc->vs);
178
179                 M128DEC(l2sc->vs);
180
181 /* XXXXXXXXXXXXXXXXX */
182
183                 if((l2sc->ua_num != UA_EMPTY) && (l2sc->vs == l2sc->ua_num))
184                 {
185                         if(_IF_QFULL(&l2sc->i_queue))
186                         {
187                                 NDBGL2(L2_ERROR, "ERROR, I-queue full!");
188                         }
189                         else
190                         {
191                                 IF_ENQUEUE(&l2sc->i_queue, l2sc->ua_frame);
192                                 l2sc->ua_num = UA_EMPTY;
193                         }
194                 }
195                 else
196                 {
197                         NDBGL2(L2_ERROR, "ERROR, l2sc->vs = %d, l2sc->ua_num = %d ",l2sc->vs, l2sc->ua_num);
198                 }
199
200 /* XXXXXXXXXXXXXXXXX */
201                         
202                 i4b_i_frame_queued_up(l2sc);
203         }
204
205         CRIT_END;
206 }
207
208 /*---------------------------------------------------------------------------*
209  *      routine ACKNOWLEDGE PENDING (Q.921 03/93 p 70)
210  *---------------------------------------------------------------------------*/
211 void
212 i4b_acknowledge_pending(l2_softc_t *l2sc)
213 {
214         if(l2sc->ack_pend)
215         {
216                 l2sc->ack_pend = 0;
217                 i4b_tx_rr_response(l2sc, F0);
218         }
219 }
220
221 /*---------------------------------------------------------------------------*
222  *      i4b_print_frame - just print the hex contents of a frame
223  *---------------------------------------------------------------------------*/
224 void
225 i4b_print_frame(int len, u_char *buf)
226 {
227 #if DO_I4B_DEBUG
228         int i;
229
230         if (!(i4b_l2_debug & L2_ERROR))         /* XXXXXXXXXXXXXXXXXXXXX */
231                 return;
232
233         for(i = 0; i < len; i++)
234                 printf(" 0x%x", buf[i]);
235         printf("\n");
236 #endif
237 }
238
239 /*---------------------------------------------------------------------------*
240  *      i4b_print_l2var - print some l2softc vars
241  *---------------------------------------------------------------------------*/
242 void
243 i4b_print_l2var(l2_softc_t *l2sc)
244 {
245         NDBGL2(L2_ERROR, "unit%d V(R)=%d, V(S)=%d, V(A)=%d,ACKP=%d,PBSY=%d,OBSY=%d",
246                 l2sc->unit,
247                 l2sc->vr,
248                 l2sc->vs,
249                 l2sc->va,
250                 l2sc->ack_pend,
251                 l2sc->peer_busy,
252                 l2sc->own_busy);
253 }
254
255 /*---------------------------------------------------------------------------*
256  *      got s or i frame, check if valid ack for last sent frame
257  *---------------------------------------------------------------------------*/
258 void
259 i4b_rxd_ack(l2_softc_t *l2sc, int nr)
260 {
261
262 #ifdef NOTDEF
263         NDBGL2(L2_ERROR, "N(R)=%d, UA=%d, V(R)=%d, V(S)=%d, V(A)=%d",
264                 nr,
265                 l2sc->ua_num,
266                 l2sc->vr,
267                 l2sc->vs,
268                 l2sc->va);
269 #endif
270
271         if(l2sc->ua_num != UA_EMPTY)
272         {
273                 CRIT_VAR;
274
275                 CRIT_BEG;
276                 
277                 M128DEC(nr);
278
279                 if(l2sc->ua_num != nr)
280                         NDBGL2(L2_ERROR, "((N(R)-1)=%d) != (UA=%d) !!!", nr, l2sc->ua_num);
281                         
282                 i4b_Dfreembuf(l2sc->ua_frame);
283                 l2sc->ua_num = UA_EMPTY;
284                 
285                 CRIT_END;
286         }
287 }
288
289 /*---------------------------------------------------------------------------*
290  *      if not already active, activate layer 1
291  *---------------------------------------------------------------------------*/
292 void
293 i4b_l1_activate(l2_softc_t *l2sc)
294 {
295         if(l2sc->ph_active == PH_INACTIVE)
296         {
297                 l2sc->ph_active = PH_ACTIVEPEND;
298                 PH_Act_Req(l2sc->unit);
299         }
300 };
301
302 /*---------------------------------------------------------------------------*
303  *      check for v(a) <= n(r) <= v(s)
304  *      nr = receive sequence frame counter, va = acknowledge sequence frame
305  *      counter and vs = transmit sequence frame counter
306  *---------------------------------------------------------------------------*/
307 int
308 i4b_l2_nr_ok(int nr, int va, int vs)
309 {
310         if((va > nr) && ((nr != 0) || (va != 127)))
311         {
312                 NDBGL2(L2_ERROR, "ERROR, va = %d, nr = %d, vs = %d [1]", va, nr, vs);
313                 return 0;       /* fail */
314         }
315
316         if((nr > vs) && ((vs != 0) || (nr != 127)))
317         {
318                 NDBGL2(L2_ERROR, "ERROR, va = %d, nr = %d, vs = %d [2]", va, nr, vs);
319                 return 0;       /* fail */
320         }
321         return 1;               /* good */
322 }
323         
324 #endif /* NI4BQ921 > 0 */
325