fa002b3f1f8753df62f217f5a9ba230d57fb1180
[dragonfly.git] / sys / net / i4b / layer2 / i4b_l2.c
1 /*
2  * Copyright (c) 1997, 2001 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_l2.c - ISDN layer 2 (Q.921)
28  *      -------------------------------
29  *
30  * $FreeBSD: src/sys/i4b/layer2/i4b_l2.c,v 1.6.2.1 2001/08/10 14:08:41 obrien Exp $
31  * $DragonFly: src/sys/net/i4b/layer2/i4b_l2.c,v 1.9 2005/06/14 21:19:19 joerg Exp $
32  *
33  *      last edit-date: [Fri Jan 12 16:43:31 2001]
34  *
35  *---------------------------------------------------------------------------*/
36
37 #include "use_i4bq921.h"
38 #if NI4BQ921 > 0
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/mbuf.h>
43 #include <sys/socket.h>
44 #include <sys/thread2.h>
45 #include <net/if.h>
46
47 #include <net/i4b/include/machine/i4b_debug.h>
48
49 #include "../include/i4b_l1l2.h"
50 #include "../include/i4b_l2l3.h"
51 #include "../include/i4b_mbuf.h"
52 #include "../include/i4b_global.h"
53
54 #include "i4b_l2.h"
55 #include "i4b_l2fsm.h"
56
57 int i4b_dl_establish_ind(int);
58 int i4b_dl_establish_cnf(int);
59 int i4b_dl_release_ind(int);
60 int i4b_dl_release_cnf(int);
61 int i4b_dl_data_ind(int, struct mbuf *);
62 int i4b_dl_unit_data_ind(int, struct mbuf *);
63
64 static int i4b_mdl_command_req(int, int, void *);
65
66 /* from layer 2 */
67
68 extern int i4b_mdl_status_ind(int, int, int);
69
70 /* this layers debug level */
71
72 unsigned int i4b_l2_debug = L2_DEBUG_DEFAULT;
73
74 struct i4b_l2l3_func i4b_l2l3_func = {
75
76         /* Layer 2 --> Layer 3 */
77         
78         (int (*)(int))                          i4b_dl_establish_ind,
79         (int (*)(int))                          i4b_dl_establish_cnf,
80         (int (*)(int))                          i4b_dl_release_ind,
81         (int (*)(int))                          i4b_dl_release_cnf,
82         (int (*)(int, struct mbuf *))           i4b_dl_data_ind,
83         (int (*)(int, struct mbuf *))           i4b_dl_unit_data_ind,
84
85         /* Layer 3 --> Layer 2 */
86
87         (int (*)(int))                          i4b_dl_establish_req,
88         (int (*)(int))                          i4b_dl_release_req,
89         (int (*)(int, struct mbuf *))           i4b_dl_data_req,
90         (int (*)(int, struct mbuf *))           i4b_dl_unit_data_req,
91
92         /* Layer 2 --> Layer 3 management */
93         
94         (int (*)(int, int, int))                i4b_mdl_status_ind,
95
96         /* Layer 3  --> Layer 2 management */
97         
98         (int (*)(int, int, void *))             i4b_mdl_command_req     
99 };
100
101 /*---------------------------------------------------------------------------*
102  *      DL_ESTABLISH_REQ from layer 3
103  *---------------------------------------------------------------------------*/
104 int i4b_dl_establish_req(int unit)
105 {
106         l2_softc_t *l2sc = &l2_softc[unit];
107         
108         NDBGL2(L2_PRIM, "unit %d",unit);
109         i4b_l1_activate(l2sc);
110         i4b_next_l2state(l2sc, EV_DLESTRQ);
111         return(0);
112 }
113
114 /*---------------------------------------------------------------------------*
115  *      DL_RELEASE_REQ from layer 3
116  *---------------------------------------------------------------------------*/
117 int i4b_dl_release_req(int unit)
118 {
119         l2_softc_t *l2sc = &l2_softc[unit];
120
121         NDBGL2(L2_PRIM, "unit %d",unit);        
122         i4b_next_l2state(l2sc, EV_DLRELRQ);
123         return(0);      
124 }
125
126 /*---------------------------------------------------------------------------*
127  *      DL UNIT DATA REQUEST from Layer 3
128  *---------------------------------------------------------------------------*/
129 int i4b_dl_unit_data_req(int unit, struct mbuf *m)
130 {
131 #ifdef NOTDEF
132         NDBGL2(L2_PRIM, "unit %d",unit);
133 #endif
134         return(0);
135 }
136
137 /*---------------------------------------------------------------------------*
138  *      DL DATA REQUEST from Layer 3
139  *---------------------------------------------------------------------------*/
140 int i4b_dl_data_req(int unit, struct mbuf *m)
141 {
142         l2_softc_t *l2sc = &l2_softc[unit];
143
144 #ifdef NOTDEF
145         NDBGL2(L2_PRIM, "unit %d",unit);
146 #endif
147         switch(l2sc->Q921_state)
148         {
149                 case ST_AW_EST:
150                 case ST_MULTIFR:
151                 case ST_TIMREC:
152                 
153                         if(IF_QFULL(&l2sc->i_queue))
154                         {
155                                 NDBGL2(L2_ERROR, "i_queue full!!");
156                                 i4b_Dfreembuf(m);
157                         }
158                         else
159                         {
160                                 CRIT_VAR;
161
162                                 CRIT_BEG;
163                                 IF_ENQUEUE(&l2sc->i_queue, m);
164                                 CRIT_END;
165
166                                 i4b_i_frame_queued_up(l2sc);
167                         }
168                         break;
169                         
170                 default:
171                         NDBGL2(L2_ERROR, "unit %d ERROR in state [%s], freeing mbuf", unit, i4b_print_l2state(l2sc));
172                         i4b_Dfreembuf(m);
173                         break;
174         }               
175         return(0);
176 }
177
178 /*---------------------------------------------------------------------------*
179  *      i4b_ph_activate_ind - link activation indication from layer 1
180  *---------------------------------------------------------------------------*/
181 int
182 i4b_ph_activate_ind(int unit)
183 {
184         l2_softc_t *l2sc = &l2_softc[unit];
185
186         NDBGL1(L1_PRIM, "unit %d",unit);
187         l2sc->ph_active = PH_ACTIVE;
188         return(0);
189 }
190
191 /*---------------------------------------------------------------------------*
192  *      i4b_ph_deactivate_ind - link deactivation indication from layer 1
193  *---------------------------------------------------------------------------*/
194 int
195 i4b_ph_deactivate_ind(int unit)
196 {
197         l2_softc_t *l2sc = &l2_softc[unit];
198
199         NDBGL1(L1_PRIM, "unit %d",unit);
200         l2sc->ph_active = PH_INACTIVE;
201         return(0);
202 }
203
204
205 /*---------------------------------------------------------------------------*
206  *      i4b_l2_unit_init - place layer 2 unit into known state
207  *---------------------------------------------------------------------------*/
208 static void
209 i4b_l2_unit_init(int unit)
210 {
211         l2_softc_t *l2sc = &l2_softc[unit];
212         CRIT_VAR;
213
214         CRIT_BEG;
215         l2sc->Q921_state = ST_TEI_UNAS;
216         l2sc->tei_valid = TEI_INVALID;
217         l2sc->vr = 0;
218         l2sc->vs = 0;
219         l2sc->va = 0;
220         l2sc->ack_pend = 0;
221         l2sc->rej_excpt = 0;
222         l2sc->peer_busy = 0;
223         l2sc->own_busy = 0;
224         l2sc->l3initiated = 0;
225
226         l2sc->rxd_CR = 0;
227         l2sc->rxd_PF = 0;
228         l2sc->rxd_NR = 0;
229         l2sc->RC = 0;
230         l2sc->iframe_sent = 0;
231                 
232         l2sc->postfsmfunc = NULL;
233
234         if(l2sc->ua_num != UA_EMPTY)
235         {
236                 i4b_Dfreembuf(l2sc->ua_frame);
237                 l2sc->ua_num = UA_EMPTY;
238                 l2sc->ua_frame = NULL;
239         }
240
241         i4b_T200_stop(l2sc);
242         i4b_T202_stop(l2sc);
243         i4b_T203_stop(l2sc);
244
245         CRIT_END;       
246 }
247
248 /*---------------------------------------------------------------------------*
249  *      i4b_mph_status_ind - status indication upward
250  *---------------------------------------------------------------------------*/
251 int
252 i4b_mph_status_ind(int unit, int status, int parm)
253 {
254         l2_softc_t *l2sc = &l2_softc[unit];
255         int sendup = 1;
256         CRIT_VAR;
257         
258         CRIT_BEG;
259
260         NDBGL1(L1_PRIM, "unit %d, status=%d, parm=%d", unit, status, parm);
261
262         switch(status)
263         {
264                 case STI_ATTACH:
265                         l2sc->unit = unit;
266                         l2sc->i_queue.ifq_maxlen = IQUEUE_MAXLEN;
267
268                         l2sc->ua_frame = NULL;
269                         bzero(&l2sc->stat, sizeof(lapdstat_t));                 
270                         i4b_l2_unit_init(unit);
271                         
272                         /* initialize the callout handles for timeout routines */
273                         callout_init(&l2sc->T200_timeout);
274                         callout_init(&l2sc->T202_timeout);
275                         callout_init(&l2sc->T203_timeout);
276                         callout_init(&l2sc->IFQU_timeout);
277
278                         break;
279
280                 case STI_L1STAT:        /* state of layer 1 */
281                         break;
282                 
283                 case STI_PDEACT:        /* Timer 4 expired */
284 /*XXX*/                 if((l2sc->Q921_state >= ST_AW_EST) &&
285                            (l2sc->Q921_state <= ST_TIMREC))
286                         {
287                                 NDBGL2(L2_ERROR, "unit %d, persistent deactivation!", unit);
288                                 i4b_l2_unit_init(unit);
289                         }
290                         else
291                         {
292                                 sendup = 0;
293                         }
294                         break;
295
296                 case STI_NOL1ACC:
297                         i4b_l2_unit_init(unit);
298                         NDBGL2(L2_ERROR, "unit %d, cannot access S0 bus!", unit);
299                         break;
300                         
301                 default:
302                         NDBGL2(L2_ERROR, "ERROR, unit %d, unknown status message!", unit);
303                         break;
304         }
305         
306         if(sendup)
307                 MDL_Status_Ind(unit, status, parm);  /* send up to layer 3 */
308
309         CRIT_END;
310         
311         return(0);
312 }
313
314 /*---------------------------------------------------------------------------*
315  *      MDL_COMMAND_REQ from layer 3
316  *---------------------------------------------------------------------------*/
317 int i4b_mdl_command_req(int unit, int command, void * parm)
318 {
319         NDBGL2(L2_PRIM, "unit %d, command=%d, parm=%d", unit, command, (unsigned int)parm);
320
321         switch(command)
322         {
323                 case CMR_DOPEN:
324                         i4b_l2_unit_init(unit);
325                         break;
326         }               
327
328         MPH_Command_Req(unit, command, parm);
329         
330         return(0);
331 }
332
333 /*---------------------------------------------------------------------------*
334  *      i4b_ph_data_ind - process a rx'd frame got from layer 1
335  *---------------------------------------------------------------------------*/
336 int
337 i4b_ph_data_ind(int unit, struct mbuf *m)
338 {
339         l2_softc_t *l2sc = &l2_softc[unit];
340 #ifdef NOTDEF
341         NDBGL1(L1_PRIM, "unit %d", unit);
342 #endif
343         u_char *ptr = m->m_data;
344
345         if ( (*(ptr + OFF_CNTL) & 0x01) == 0 )
346         {
347                 if(m->m_len < 4)        /* 6 oct - 2 chksum oct */
348                 {
349                         l2sc->stat.err_rx_len++;
350                         NDBGL2(L2_ERROR, "ERROR, I-frame < 6 octetts!");
351                         i4b_Dfreembuf(m);
352                         return(0);
353                 }
354                 i4b_rxd_i_frame(unit, m);
355         }
356         else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x01 )
357         {
358                 if(m->m_len < 4)        /* 6 oct - 2 chksum oct */
359                 {
360                         l2sc->stat.err_rx_len++;
361                         NDBGL2(L2_ERROR, "ERROR, S-frame < 6 octetts!");
362                         i4b_Dfreembuf(m);
363                         return(0);
364                 }
365                 i4b_rxd_s_frame(unit, m);
366         }
367         else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x03 )
368         {
369                 if(m->m_len < 3)        /* 5 oct - 2 chksum oct */
370                 {
371                         l2sc->stat.err_rx_len++;
372                         NDBGL2(L2_ERROR, "ERROR, U-frame < 5 octetts!");
373                         i4b_Dfreembuf(m);
374                         return(0);
375                 }
376                 i4b_rxd_u_frame(unit, m);
377         }
378         else
379         {
380                 l2sc->stat.err_rx_badf++;
381                 NDBGL2(L2_ERROR, "ERROR, bad frame rx'd - ");
382                 i4b_print_frame(m->m_len, m->m_data);
383                 i4b_Dfreembuf(m);
384         }
385         return(0);
386 }
387
388 #endif /* NI4BQ921 > 0 */