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